Skip to content

Commit

Permalink
feat(core): add basic Forge v5 to v6 importer
Browse files Browse the repository at this point in the history
  • Loading branch information
malept committed Jan 9, 2019
1 parent 73fc58c commit 648ef33
Show file tree
Hide file tree
Showing 4 changed files with 370 additions and 10 deletions.
63 changes: 54 additions & 9 deletions packages/api/core/src/api/import.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _merge from 'lodash.merge';
import { asyncOra } from '@electron-forge/async-ora';
import debug from 'debug';
import fs from 'fs-extra';
Expand All @@ -10,9 +11,29 @@ import { setInitialForgeConfig } from '../util/forge-config';
import { info, warn } from '../util/messages';
import installDepList, { DepType, DepVersionRestriction } from '../util/install-dependencies';
import { readRawPackageJson } from '../util/read-package-json';
import upgradeForgeConfig, { updateUpgradedForgeDevDeps } from'../util/upgrade-forge-config';

const d = debug('electron-forge:import');

function findElectronDep(dep: string): boolean {
return ['electron', 'electron-prebuilt', 'electron-prebuilt-compile'].includes(dep);
}

function updateElectronDependency(packageJSON: any, dev: string[], exact: string[]): [string[], string[]] {
if (Object.keys(packageJSON.devDependencies).find(findElectronDep)) {
exact = exact.filter(dep => dep !== 'electron');
} else {
const electronKey = Object.keys(packageJSON.dependencies).find(findElectronDep);
if (electronKey) {
d(`Moving ${electronKey} from dependencies to devDependencies`);
dev.push(`${electronKey}@${packageJSON.dependencies[electronKey]}`);
delete packageJSON.dependencies[electronKey];
}
}

return [dev, exact];
}

export interface ImportOptions {
/**
* The path to the app to be imported
Expand Down Expand Up @@ -72,25 +93,40 @@ export default async ({

await initGit(dir);

const importDeps = ([] as string[]).concat(deps);
let importDevDeps = ([] as string[]).concat(devDeps);
let importExactDevDeps = ([] as string[]).concat(exactDevDeps);

let packageJSON = await readRawPackageJson(dir);
if (packageJSON.config && packageJSON.config.forge) {
warn(interactive, 'It looks like this project is already configured for "electron-forge"'.green);
if (typeof shouldContinueOnExisting === 'function') {
if (!await shouldContinueOnExisting()) {
process.exit(0);
if (packageJSON.config.forge.makers) {
warn(interactive, 'It looks like this project is already configured for Electron Forge'.green);
if (typeof shouldContinueOnExisting === 'function') {
if (!await shouldContinueOnExisting()) {
process.exit(0);
}
}
} else if (typeof packageJSON.config.forge === 'string') {
warn(interactive, "We can't tell if the Electron Forge config is compatible because it's in an external JavaScript file, not trying to convert it and continuing anyway".yellow);
} else {
d('Upgrading an Electron Forge < 6 project');
packageJSON.config.forge = upgradeForgeConfig(packageJSON.config.forge);
importDevDeps = updateUpgradedForgeDevDeps(packageJSON, importDevDeps);
}
}

packageJSON.dependencies = packageJSON.dependencies || {};
packageJSON.devDependencies = packageJSON.devDependencies || {};

[importDevDeps, importExactDevDeps] = updateElectronDependency(packageJSON, importDevDeps, importExactDevDeps);

const keys = Object.keys(packageJSON.dependencies).concat(Object.keys(packageJSON.devDependencies));
const buildToolPackages: {
[key: string]: string | undefined;
} = {
'electron-builder': 'provides mostly equivalent functionality',
'electron-download': 'already uses this module as a transitive dependency',
'electron-forge': 'replaced with @electron-forge/cli',
'electron-installer-debian': 'already uses this module as a transitive dependency',
'electron-installer-dmg': 'already uses this module as a transitive dependency',
'electron-installer-flatpak': 'already uses this module as a transitive dependency',
Expand Down Expand Up @@ -152,13 +188,13 @@ export default async ({
await fs.remove(path.resolve(dir, 'node_modules/.bin/electron.cmd'));

d('installing dependencies');
await installDepList(dir, deps);
await installDepList(dir, importDeps);

d('installing devDependencies');
await installDepList(dir, devDeps, DepType.DEV);
await installDepList(dir, importDevDeps, DepType.DEV);

d('installing exactDevDependencies');
await installDepList(dir, exactDevDeps, DepType.DEV, DepVersionRestriction.EXACT);
await installDepList(dir, importExactDevDeps, DepType.DEV, DepVersionRestriction.EXACT);
});

packageJSON = await readRawPackageJson(dir);
Expand All @@ -169,8 +205,17 @@ export default async ({

packageJSON.config = packageJSON.config || {};
const templatePackageJSON = await readRawPackageJson(path.resolve(__dirname, '../../tmpl'));
packageJSON.config.forge = templatePackageJSON.config.forge;
setInitialForgeConfig(packageJSON);
if (packageJSON.config.forge) {
if (typeof packageJSON.config.forge !== 'string') {
packageJSON.config.forge = _merge(templatePackageJSON.config.forge, packageJSON.config.forge);
}
} else {
packageJSON.config.forge = templatePackageJSON.config.forge;
}

if (typeof packageJSON.config.forge !== 'string') {
setInitialForgeConfig(packageJSON);
}

await writeChanges();

Expand Down
2 changes: 1 addition & 1 deletion packages/api/core/src/api/init-scripts/init-npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { readRawPackageJson } from '../../util/read-package-json';
const d = debug('electron-forge:init:npm');
const corePackage = fs.readJsonSync(path.resolve(__dirname, '../../../package.json'));

function siblingDep(name: string) {
export function siblingDep(name: string) {
return `@electron-forge/${name}@${corePackage.version}`;
}

Expand Down
142 changes: 142 additions & 0 deletions packages/api/core/src/util/upgrade-forge-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import {
ForgeConfig,
ForgePlatform,
IForgeResolvableMaker,
IForgeResolvablePublisher,
} from '@electron-forge/shared-types';
import path from 'path';
import { siblingDep } from '../api/init-scripts/init-npm';

function mapMakeTargets(forge5Config: any): Map<string, ForgePlatform[]> {
const makeTargets = new Map<string, ForgePlatform[]>();
if (forge5Config.makeTargets) {
// TODO: Use object.entries when dropping Node 6
for (const platform in forge5Config.makeTargets) {
for (const target of forge5Config.makeTargets[platform]) {
let platforms = makeTargets.get(target);
if (platforms === undefined) {
platforms = [];
makeTargets.set(target, platforms);
}
platforms.push(platform as ForgePlatform);
}
}
}

return makeTargets;
}

const forge5MakerMappings = new Map<string, string>([
['electronInstallerDebian', 'deb'],
['electronInstallerDMG', 'dmg'],
['electronInstallerFlatpak', 'flatpak'],
['electronInstallerRedhat', 'rpm'],
['electronInstallerSnap', 'snap'],
['electronWinstallerConfig', 'squirrel'],
['electronWixMSIConfig', 'wix'],
['windowsStoreConfig', 'appx'],
]);

/**
* Converts Forge v5 maker config to v6.
*/
function generateForgeMakerConfig(forge5Config: any): IForgeResolvableMaker[] {
const makeTargets = mapMakeTargets(forge5Config);
const makers: IForgeResolvableMaker[] = [];

for (const [forge5Key, makerType] of forge5MakerMappings) {
const config = forge5Config[forge5Key];
if (config) {
makers.push({
name: `@electron-forge/maker-${makerType}`,
config: forge5Config[forge5Key],
platforms: makeTargets.get(makerType) || null,
} as IForgeResolvableMaker);
}
}

const zipPlatforms = makeTargets.get('zip');
if (zipPlatforms) {
makers.push({
name: '@electron-forge/maker-zip',
platforms: zipPlatforms,
} as IForgeResolvableMaker);
}

return makers;
}

const forge5PublisherMappings = new Map<string, string>([
['github_repository', 'github'],
['s3', 's3'],
['electron-release-server', 'electron-release-server'],
['snapStore', 'snapcraft'],
]);

/**
* Converts Forge v5 publisher config to v6.
*/
function generateForgePublisherConfig(forge5Config: any): IForgeResolvablePublisher[] {
const publishers: IForgeResolvablePublisher[] = [];

for (const [forge5Key, publisherType] of forge5PublisherMappings) {
let config = forge5Config[forge5Key];
if (config) {
if (publisherType === 'github') {
config = transformGitHubPublisherConfig(config);
}
publishers.push({
config,
name: `@electron-forge/publisher-${publisherType}`,
platforms: null,
} as IForgeResolvableMaker);
}
}

return publishers;
}

/**
* Transforms v5 GitHub publisher config to v6 syntax.
*/
function transformGitHubPublisherConfig(config: any) {
const { name, owner, options, ...gitHubConfig } = config;
gitHubConfig.repository = { name, owner };
if (options) {
gitHubConfig.octokitOptions = options;
}

return gitHubConfig;
}

/**
* Upgrades Forge v5 config to v6.
*/
export default function upgradeForgeConfig(forge5Config: any): ForgeConfig {
const forgeConfig: ForgeConfig = ({} as ForgeConfig);

if (forge5Config.electronPackagerConfig) {
delete forge5Config.electronPackagerConfig.packageManager;
forgeConfig.packagerConfig = forge5Config.electronPackagerConfig;
}
if (forge5Config.electronRebuildConfig) {
forgeConfig.electronRebuildConfig = forge5Config.electronRebuildConfig;
}
forgeConfig.makers = generateForgeMakerConfig(forge5Config);
forgeConfig.publishers = generateForgePublisherConfig(forge5Config);

return forgeConfig;
}

export function updateUpgradedForgeDevDeps(packageJSON: any, devDeps: string[]): string[] {
const forgeConfig = packageJSON.config.forge;
devDeps = devDeps.filter(dep => !dep.startsWith('@electron-forge/maker-'));
devDeps = devDeps.concat(forgeConfig.makers.map((maker: IForgeResolvableMaker) => siblingDep(path.basename(maker.name))));
devDeps = devDeps.concat(forgeConfig.publishers.map((publisher: IForgeResolvablePublisher) => siblingDep(path.basename(publisher.name))));

if (Object.keys(packageJSON.devDependencies).find((dep: string) => dep === 'electron-prebuilt-compile')) {
devDeps = devDeps.concat(siblingDep('plugin-compile'));
}

return devDeps;
}
Loading

0 comments on commit 648ef33

Please sign in to comment.