Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple Importer from Forge 5.x to 6.x #653

Merged
merged 5 commits into from
Jan 9, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 36 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 @@ -6,10 +7,12 @@ import path from 'path';
import initGit from './init-scripts/init-git';
import { deps, devDeps, exactDevDeps } from './init-scripts/init-npm';

import { updateElectronDependency } from '../util/electron-version';
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');

Expand Down Expand Up @@ -72,25 +75,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 +170,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 +187,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
2 changes: 1 addition & 1 deletion packages/api/core/src/api/make.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import parseArchs from '../util/parse-archs';
import { readMutatedPackageJson } from '../util/read-package-json';
import resolveDir from '../util/resolve-dir';
import getCurrentOutDir from '../util/out-dir';
import getElectronVersion from '../util/electron-version';
import { getElectronVersion } from '../util/electron-version';
import requireSearch from '../util/require-search';

import packager from './package';
Expand Down
2 changes: 1 addition & 1 deletion packages/api/core/src/api/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import rebuildHook from '../util/rebuild';
import requireSearch from '../util/require-search';
import resolveDir from '../util/resolve-dir';
import getCurrentOutDir from '../util/out-dir';
import getElectronVersion from '../util/electron-version';
import { getElectronVersion } from '../util/electron-version';

const { host: hostArch }: { host: () => ForgeArch | 'all' } = require('electron-download/lib/arch');

Expand Down
2 changes: 1 addition & 1 deletion packages/api/core/src/api/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import rebuild from '../util/rebuild';
import resolveDir from '../util/resolve-dir';
import getForgeConfig from '../util/forge-config';
import { runHook } from '../util/hook';
import getElectronVersion from '../util/electron-version';
import { getElectronVersion } from '../util/electron-version';

export { StartOptions };

Expand Down
47 changes: 41 additions & 6 deletions packages/api/core/src/util/electron-version.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
export default (packageJSON: any) => {
if (!packageJSON.devDependencies) return null;
return (packageJSON.devDependencies['electron-prebuilt-compile']
|| packageJSON.devDependencies['electron-prebuilt']
|| packageJSON.devDependencies.electron);
};
import debug from 'debug';

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

const electronPackageNames = [
'electron-prebuilt-compile',
'electron-prebuilt',
'electron-nightly',
'electron',
];

function findElectronDep(dep: string): boolean {
return electronPackageNames.includes(dep);
}

export function getElectronVersion(packageJSON: any) {
if (!packageJSON.devDependencies) {
throw new Error('package.json for app does not have any devDependencies'.red);
}
const packageName = electronPackageNames.find(pkg => packageJSON.devDependencies[pkg]);
if (packageName === undefined) {
throw new Error('Could not find any Electron packages in devDependencies');
}
return packageJSON.devDependencies[packageName];
}

export 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) {
exact = exact.filter(dep => dep !== 'electron');
d(`Moving ${electronKey} from dependencies to devDependencies`);
dev.push(`${electronKey}@${packageJSON.dependencies[electronKey]}`);
delete packageJSON.dependencies[electronKey];
}
}

return [dev, exact];
}
2 changes: 1 addition & 1 deletion packages/api/core/src/util/resolve-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import debug from 'debug';
import fs from 'fs-extra';
import path from 'path';
import { readRawPackageJson } from './read-package-json';
import getElectronVersion from './electron-version';
import { getElectronVersion } from './electron-version';

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

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