From 028d1d31705dda9cb7395c85acfd3165bfea2fcd Mon Sep 17 00:00:00 2001 From: Mark Lee Date: Wed, 2 Jan 2019 01:15:59 -0800 Subject: [PATCH 1/5] feat(core): add basic Forge v5 to v6 importer --- packages/api/core/src/api/import.ts | 63 ++++++- .../api/core/src/api/init-scripts/init-npm.ts | 2 +- .../api/core/src/util/upgrade-forge-config.ts | 142 ++++++++++++++ .../test/fast/upgrade-forge-config_spec.ts | 173 ++++++++++++++++++ 4 files changed, 370 insertions(+), 10 deletions(-) create mode 100644 packages/api/core/src/util/upgrade-forge-config.ts create mode 100644 packages/api/core/test/fast/upgrade-forge-config_spec.ts diff --git a/packages/api/core/src/api/import.ts b/packages/api/core/src/api/import.ts index fc131b0b1c..9dfdc8e074 100644 --- a/packages/api/core/src/api/import.ts +++ b/packages/api/core/src/api/import.ts @@ -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'; @@ -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 @@ -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', @@ -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); @@ -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(); diff --git a/packages/api/core/src/api/init-scripts/init-npm.ts b/packages/api/core/src/api/init-scripts/init-npm.ts index d9cfb60f0f..03cb23e0f3 100644 --- a/packages/api/core/src/api/init-scripts/init-npm.ts +++ b/packages/api/core/src/api/init-scripts/init-npm.ts @@ -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}`; } diff --git a/packages/api/core/src/util/upgrade-forge-config.ts b/packages/api/core/src/util/upgrade-forge-config.ts new file mode 100644 index 0000000000..174b280f75 --- /dev/null +++ b/packages/api/core/src/util/upgrade-forge-config.ts @@ -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 { + const makeTargets = new Map(); + 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([ + ['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([ + ['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; +} diff --git a/packages/api/core/test/fast/upgrade-forge-config_spec.ts b/packages/api/core/test/fast/upgrade-forge-config_spec.ts new file mode 100644 index 0000000000..55c766437b --- /dev/null +++ b/packages/api/core/test/fast/upgrade-forge-config_spec.ts @@ -0,0 +1,173 @@ +import _merge from 'lodash.merge'; +import { IForgeResolvableMaker, IForgeResolvablePublisher } from '@electron-forge/shared-types'; +import { expect } from 'chai'; +import path from 'path'; + +import upgradeForgeConfig, { updateUpgradedForgeDevDeps } from '../../src/util/upgrade-forge-config'; + +describe('upgradeForgeConfig', () => { + it('converts Electron Packager config', () => { + const oldConfig = { + electronPackagerConfig: { + asar: true, + packageManager: 'npm', + }, + }; + const expected = { asar: true }; + + const newConfig = upgradeForgeConfig(oldConfig); + expect(newConfig.packagerConfig).to.deep.equal(expected); + }); + + it('converts electron-rebuild config', () => { + const rebuildConfig = { types: ['prod'] }; + const oldConfig = { electronRebuildConfig: _merge({}, rebuildConfig) }; + + const newConfig = upgradeForgeConfig(oldConfig); + expect(newConfig.electronRebuildConfig).to.deep.equal(rebuildConfig); + }); + + it('converts maker config', () => { + const oldConfig = { + makeTargets: { + linux: ['deb'], + }, + electronInstallerDebian: { + depends: ['liboath0'], + }, + }; + const expected = [ + { + name: '@electron-forge/maker-deb', + config: { + depends: ['liboath0'], + }, + platforms: ['linux'], + }, + ] as IForgeResolvableMaker[]; + + const newConfig = upgradeForgeConfig(oldConfig); + expect(newConfig.makers).to.deep.equal(expected); + }); + + it('adds the zip maker when specified in makeTargets', () => { + const oldConfig = { + makeTargets: { + darwin: ['zip'], + linux: ['zip'], + }, + }; + const expected = [ + { + name: '@electron-forge/maker-zip', + platforms: ['darwin', 'linux'], + }, + ] as IForgeResolvableMaker[]; + + const newConfig = upgradeForgeConfig(oldConfig); + expect(newConfig.makers).to.deep.equal(expected); + }); + + it('converts publisher config', () => { + const oldConfig = { + snapStore: { + release: 'beta', + }, + }; + const expected = [ + { + name: '@electron-forge/publisher-snapcraft', + config: { + release: 'beta', + }, + platforms: null, + }, + ] as IForgeResolvablePublisher[]; + + const newConfig = upgradeForgeConfig(oldConfig); + expect(newConfig.publishers).to.deep.equal(expected); + }); + + it('converts GitHub publisher config', () => { + const octokitOptions = { + timeout: 0, + }; + const repo = { + name: 'myapp', + owner: 'user', + }; + const oldConfig = { + github_repository: Object.assign({ + options: octokitOptions, + draft: true, + }, repo), + }; + const newConfig = upgradeForgeConfig(oldConfig); + expect(newConfig.publishers).to.have.lengthOf(1); + const publisherConfig = (newConfig.publishers[0] as IForgeResolvablePublisher).config; + expect(publisherConfig.repository).to.deep.equal(repo); + expect(publisherConfig.octokitOptions).to.deep.equal(octokitOptions); + expect(publisherConfig.draft).to.equal(true); + }); +}); + +describe('updateUpgradedForgeDevDeps', () => { + const skeletonPackageJSON = { + config: { + forge: { + makers: [] as IForgeResolvableMaker[], + publishers: [] as IForgeResolvablePublisher[], + }, + }, + devDependencies: {}, + }; + + it('removes unused makers from devDependencies', () => { + const packageJSON = _merge({}, skeletonPackageJSON); + const devDeps = updateUpgradedForgeDevDeps(packageJSON, ['@electron-forge/maker-squirrel']); + expect(devDeps).to.deep.equal([]); + }); + + it('adds makers to devDependencies', () => { + const packageJSON = _merge({}, skeletonPackageJSON); + packageJSON.config.forge.makers = [ + { + name: '@electron-forge/maker-zip', + platforms: ['darwin', 'linux'], + }, + { + name: '@electron-forge/maker-squirrel', + config: {}, + platforms: ['win32'], + }, + ] as IForgeResolvableMaker[]; + + const actual = updateUpgradedForgeDevDeps(packageJSON, []); + expect(actual).to.have.lengthOf(2); + expect(actual.find(dep => dep.startsWith('@electron-forge/maker-zip'))).to.not.equal(undefined); + expect(actual.find(dep => dep.startsWith('@electron-forge/maker-squirrel'))).to.not.equal(undefined); + }); + + it('adds publishers to devDependencies', () => { + const packageJSON = _merge({}, skeletonPackageJSON); + packageJSON.config.forge.publishers = [ + { name: '@electron-forge/publisher-github' }, + { name: '@electron-forge/publisher-snapcraft' }, + ]; + + const actual = updateUpgradedForgeDevDeps(packageJSON, []); + expect(actual).to.have.lengthOf(2); + expect(actual.find(dep => dep.startsWith('@electron-forge/publisher-github'))).to.not.equal(undefined); + expect(actual.find(dep => dep.startsWith('@electron-forge/publisher-snapcraft'))).to.not.equal(undefined); + }); + + it('adds electron-compile plugin to devDependencies when electron-prebuilt-compile is in devDependencies', () => { + const packageJSON = _merge({}, skeletonPackageJSON, { + devDependencies: { 'electron-prebuilt-compile': '2.0.0' }, + }); + + const actual = updateUpgradedForgeDevDeps(packageJSON, []); + expect(actual, JSON.stringify(actual)).to.have.lengthOf(1); + expect(actual[0]).to.match(/^@electron-forge\/plugin-compile/); + }); +}); From 51a783b191433fd305eef1d6bc1eb11013601ef0 Mon Sep 17 00:00:00 2001 From: Mark Lee Date: Thu, 3 Jan 2019 00:43:46 -0800 Subject: [PATCH 2/5] test(core): add tests for updateElectronDependency and getElectronVersion Also refactor src/util/electron-version --- packages/api/core/src/api/import.ts | 20 +----- packages/api/core/src/api/make.ts | 2 +- packages/api/core/src/api/package.ts | 2 +- packages/api/core/src/api/start.ts | 2 +- .../api/core/src/util/electron-version.ts | 44 +++++++++++-- packages/api/core/src/util/resolve-dir.ts | 2 +- .../core/test/fast/electron-version_spec.ts | 61 +++++++++++++++++++ 7 files changed, 105 insertions(+), 28 deletions(-) create mode 100644 packages/api/core/test/fast/electron-version_spec.ts diff --git a/packages/api/core/src/api/import.ts b/packages/api/core/src/api/import.ts index 9dfdc8e074..4631753b4a 100644 --- a/packages/api/core/src/api/import.ts +++ b/packages/api/core/src/api/import.ts @@ -7,6 +7,7 @@ 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'; @@ -15,25 +16,6 @@ import upgradeForgeConfig, { updateUpgradedForgeDevDeps } from'../util/upgrade-f 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 diff --git a/packages/api/core/src/api/make.ts b/packages/api/core/src/api/make.ts index e4d2d0ec32..5f6617872c 100644 --- a/packages/api/core/src/api/make.ts +++ b/packages/api/core/src/api/make.ts @@ -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'; diff --git a/packages/api/core/src/api/package.ts b/packages/api/core/src/api/package.ts index 34b45306e1..b60ed0bb4b 100644 --- a/packages/api/core/src/api/package.ts +++ b/packages/api/core/src/api/package.ts @@ -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'); diff --git a/packages/api/core/src/api/start.ts b/packages/api/core/src/api/start.ts index ce8e9a47fa..34a0a1f784 100644 --- a/packages/api/core/src/api/start.ts +++ b/packages/api/core/src/api/start.ts @@ -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 }; diff --git a/packages/api/core/src/util/electron-version.ts b/packages/api/core/src/util/electron-version.ts index 28c8dacc3f..bca17ab889 100644 --- a/packages/api/core/src/util/electron-version.ts +++ b/packages/api/core/src/util/electron-version.ts @@ -1,6 +1,40 @@ -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', +]; + +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]; +} diff --git a/packages/api/core/src/util/resolve-dir.ts b/packages/api/core/src/util/resolve-dir.ts index 985885dbc1..4eea41f9ea 100644 --- a/packages/api/core/src/util/resolve-dir.ts +++ b/packages/api/core/src/util/resolve-dir.ts @@ -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'); diff --git a/packages/api/core/test/fast/electron-version_spec.ts b/packages/api/core/test/fast/electron-version_spec.ts new file mode 100644 index 0000000000..8ba2ca1f51 --- /dev/null +++ b/packages/api/core/test/fast/electron-version_spec.ts @@ -0,0 +1,61 @@ +import { expect } from 'chai'; +import { getElectronVersion, updateElectronDependency } from '../../src/util/electron-version'; +import { deps, devDeps, exactDevDeps } from '../../src/api/init-scripts/init-npm'; + +describe('updateElectronDependency', () => { + it('adds an Electron dep if one does not already exist', () => { + const packageJSON = { dependencies: {}, devDependencies: {} }; + const [dev, exact] = updateElectronDependency(packageJSON, devDeps, exactDevDeps); + expect(dev).to.deep.equal(devDeps); + expect(exact).to.deep.equal(exactDevDeps); + }); + it('does not add an Electron dep if one already exists', () => { + const packageJSON = { + dependencies: {}, + devDependencies: { electron: '0.37.0' }, + }; + const [dev, exact] = updateElectronDependency(packageJSON, devDeps, exactDevDeps); + expect(dev).to.deep.equal(devDeps); + expect(exact).to.deep.equal([]); + }); + it('moves an Electron dependency from dependencies to devDependencies', () => { + const packageJSON = { + dependencies: { electron: '0.37.0'}, + devDependencies: { }, + }; + const [dev, exact] = updateElectronDependency(packageJSON, devDeps, exactDevDeps); + expect(dev.includes('electron@0.37.0')).to.equal(true); + expect(exact).to.deep.equal([]); + }); +}); + +describe('getElectronVersion', () => { + it('fails without devDependencies', () => { + expect(() => getElectronVersion({})).to.throw('does not have any devDependencies'); + }); + + it('fails without electron devDependencies', () => { + expect(() => getElectronVersion({ devDependencies: {} })).to.throw('Electron packages in devDependencies'); + }); + + it('works with electron-prebuilt-compile', () => { + const packageJSON = { + devDependencies: { 'electron-prebuilt-compile': '1.0.0' }, + }; + expect(getElectronVersion(packageJSON)).to.be.equal('1.0.0'); + }); + + it('works with electron-prebuilt', () => { + const packageJSON = { + devDependencies: { 'electron-prebuilt': '1.0.0' }, + }; + expect(getElectronVersion(packageJSON)).to.be.equal('1.0.0'); + }); + + it('works with electron', () => { + const packageJSON = { + devDependencies: { 'electron': '1.0.0' }, + }; + expect(getElectronVersion(packageJSON)).to.be.equal('1.0.0'); + }); +}); From 21b76bb3f9c8e23a48af68e0f4696c85fff33fc8 Mon Sep 17 00:00:00 2001 From: Mark Lee Date: Thu, 3 Jan 2019 00:57:32 -0800 Subject: [PATCH 3/5] Fix linting problems --- packages/api/core/src/util/electron-version.ts | 4 ++-- packages/api/core/test/fast/electron-version_spec.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/api/core/src/util/electron-version.ts b/packages/api/core/src/util/electron-version.ts index bca17ab889..aa7ef5ad9c 100644 --- a/packages/api/core/src/util/electron-version.ts +++ b/packages/api/core/src/util/electron-version.ts @@ -12,7 +12,7 @@ function findElectronDep(dep: string): boolean { return electronPackageNames.includes(dep); } -export function getElectronVersion (packageJSON: any) { +export function getElectronVersion(packageJSON: any) { if (!packageJSON.devDependencies) { throw new Error('package.json for app does not have any devDependencies'.red); } @@ -21,7 +21,7 @@ export function getElectronVersion (packageJSON: any) { 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)) { diff --git a/packages/api/core/test/fast/electron-version_spec.ts b/packages/api/core/test/fast/electron-version_spec.ts index 8ba2ca1f51..8905f8bf45 100644 --- a/packages/api/core/test/fast/electron-version_spec.ts +++ b/packages/api/core/test/fast/electron-version_spec.ts @@ -20,7 +20,7 @@ describe('updateElectronDependency', () => { }); it('moves an Electron dependency from dependencies to devDependencies', () => { const packageJSON = { - dependencies: { electron: '0.37.0'}, + dependencies: { electron: '0.37.0' }, devDependencies: { }, }; const [dev, exact] = updateElectronDependency(packageJSON, devDeps, exactDevDeps); @@ -54,7 +54,7 @@ describe('getElectronVersion', () => { it('works with electron', () => { const packageJSON = { - devDependencies: { 'electron': '1.0.0' }, + devDependencies: { electron: '1.0.0' }, }; expect(getElectronVersion(packageJSON)).to.be.equal('1.0.0'); }); From 35077a964fa2fd1259609082d641916be81c6aaa Mon Sep 17 00:00:00 2001 From: Mark Lee Date: Tue, 8 Jan 2019 08:32:49 -0800 Subject: [PATCH 4/5] feat(core): add support for electron-nightly --- packages/api/core/src/util/electron-version.ts | 1 + packages/api/core/test/fast/electron-version_spec.ts | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/packages/api/core/src/util/electron-version.ts b/packages/api/core/src/util/electron-version.ts index aa7ef5ad9c..a44dfdd831 100644 --- a/packages/api/core/src/util/electron-version.ts +++ b/packages/api/core/src/util/electron-version.ts @@ -5,6 +5,7 @@ const d = debug('electron-forge:electron-version'); const electronPackageNames = [ 'electron-prebuilt-compile', 'electron-prebuilt', + 'electron-nightly', 'electron', ]; diff --git a/packages/api/core/test/fast/electron-version_spec.ts b/packages/api/core/test/fast/electron-version_spec.ts index 8905f8bf45..5ec799bde3 100644 --- a/packages/api/core/test/fast/electron-version_spec.ts +++ b/packages/api/core/test/fast/electron-version_spec.ts @@ -52,6 +52,13 @@ describe('getElectronVersion', () => { expect(getElectronVersion(packageJSON)).to.be.equal('1.0.0'); }); + it('works with electron-nightly', () => { + const packageJSON = { + devDependencies: { 'electron-nightly': '5.0.0-nightly.20190107' }, + }; + expect(getElectronVersion(packageJSON)).to.be.equal('5.0.0-nightly.20190107'); + }); + it('works with electron', () => { const packageJSON = { devDependencies: { electron: '1.0.0' }, From 6ae0ec41d05ee9e3f8c0ec09c71d39fc038dafcb Mon Sep 17 00:00:00 2001 From: Mark Lee Date: Tue, 8 Jan 2019 22:00:59 -0800 Subject: [PATCH 5/5] Make copies of the dep lists instead of altering in-place --- packages/api/core/src/util/electron-version.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/api/core/src/util/electron-version.ts b/packages/api/core/src/util/electron-version.ts index a44dfdd831..038a9596bf 100644 --- a/packages/api/core/src/util/electron-version.ts +++ b/packages/api/core/src/util/electron-version.ts @@ -25,17 +25,19 @@ export function getElectronVersion(packageJSON: any) { } export function updateElectronDependency(packageJSON: any, dev: string[], exact: string[]): [string[], string[]] { + const alteredDev = ([] as string[]).concat(dev); + let alteredExact = ([] as string[]).concat(exact); if (Object.keys(packageJSON.devDependencies).find(findElectronDep)) { - exact = exact.filter(dep => dep !== 'electron'); + alteredExact = alteredExact.filter(dep => dep !== 'electron'); } else { const electronKey = Object.keys(packageJSON.dependencies).find(findElectronDep); if (electronKey) { - exact = exact.filter(dep => dep !== 'electron'); + alteredExact = alteredExact.filter(dep => dep !== 'electron'); d(`Moving ${electronKey} from dependencies to devDependencies`); - dev.push(`${electronKey}@${packageJSON.dependencies[electronKey]}`); + alteredDev.push(`${electronKey}@${packageJSON.dependencies[electronKey]}`); delete packageJSON.dependencies[electronKey]; } } - return [dev, exact]; + return [alteredDev, alteredExact]; }