Skip to content

Commit

Permalink
fix(core): find electron when app is in a yarn workspace (#1450)
Browse files Browse the repository at this point in the history
Fixes #1377.
  • Loading branch information
malept authored Jan 29, 2020
1 parent cf725c5 commit 8613386
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 11 deletions.
4 changes: 2 additions & 2 deletions packages/api/core/src/api/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,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 { getElectronModulePath, getElectronVersion } from '../util/electron-version';

export { StartOptions };

Expand Down Expand Up @@ -78,7 +78,7 @@ export default async ({

if (!electronExecPath) {
// eslint-disable-next-line import/no-dynamic-require, global-require
electronExecPath = require(path.resolve(dir, 'node_modules/electron'));
electronExecPath = require((await getElectronModulePath(dir, packageJSON)) || path.resolve(dir, 'node_modules/electron'));
}

const spawnOpts = {
Expand Down
46 changes: 39 additions & 7 deletions packages/api/core/src/util/electron-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,55 @@ export class PackageNotFoundError extends Error {
}
}

export async function getElectronVersion(dir: string, packageJSON: any): Promise<string> {
function getElectronModuleName(packageJSON: any): string {
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 packageName;
}

async function getElectronPackageJSONPath(
dir: string,
packageName: string,
): Promise<string | undefined> {
const nodeModulesPath = await determineNodeModulesPath(dir);
if (!nodeModulesPath) {
throw new PackageNotFoundError(packageName, dir);
}
const electronPackageJSONPath = path.join(nodeModulesPath, packageName, 'package.json');
if (await fs.pathExists(electronPackageJSONPath)) {
return electronPackageJSONPath;
}

return undefined;
}

export async function getElectronModulePath(
dir: string,
packageJSON: any,
): Promise<string | undefined> {
const moduleName = await getElectronModuleName(packageJSON);
const packageJSONPath = await getElectronPackageJSONPath(dir, moduleName);
if (packageJSONPath) {
return path.dirname(packageJSONPath);
}

return undefined;
}

export async function getElectronVersion(dir: string, packageJSON: any): Promise<string> {
const packageName = getElectronModuleName(packageJSON);

let version = packageJSON.devDependencies[packageName];
if (!semver.valid(version)) { // It's not an exact version, find it in the actual module
const nodeModulesPath = await determineNodeModulesPath(dir);
if (!nodeModulesPath) {
throw new PackageNotFoundError(packageName, dir);
}
const electronPackageJSONPath = path.join(nodeModulesPath, packageName, 'package.json');
if (await fs.pathExists(electronPackageJSONPath)) {
const electronPackageJSONPath = await getElectronPackageJSONPath(dir, packageName);
if (electronPackageJSONPath) {
const electronPackageJSON = await fs.readJson(electronPackageJSONPath);
// eslint-disable-next-line prefer-destructuring
version = electronPackageJSON.version;
Expand Down
43 changes: 42 additions & 1 deletion packages/api/core/test/fast/electron-version_spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { expect } from 'chai';
import fs from 'fs-extra';
import os from 'os';
import path from 'path';
import { getElectronVersion, updateElectronDependency } from '../../src/util/electron-version';
import { getElectronModulePath, getElectronVersion, updateElectronDependency } from '../../src/util/electron-version';
import { devDeps, exactDevDeps } from '../../src/api/init-scripts/init-npm';
import { hasYarn } from '../../src/util/yarn-or-npm';

Expand Down Expand Up @@ -86,3 +88,42 @@ describe('getElectronVersion', () => {
}
});
});

describe('getElectronModulePath', () => {
let tempDir: string;
before(async () => {
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'electron-forge-test-'));
});

it('fails without devDependencies', () => expect(getElectronModulePath('', {})).to.eventually.be.rejectedWith('does not have any devDependencies'));

it('fails without electron devDependencies', () => expect(getElectronModulePath('', { devDependencies: {} })).to.eventually.be.rejectedWith('Electron packages in devDependencies'));

it('fails with no electron installed', async () => {
const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'dummy_app');
await fs.copy(fixtureDir, tempDir);
return expect(getElectronModulePath(tempDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.be.rejectedWith('Cannot find the package');
});

it('works with electron', () => {
const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'non-exact');
return expect(getElectronModulePath(fixtureDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.equal(path.join(fixtureDir, 'node_modules', 'electron'));
});

it('works with yarn workspaces', async () => {
const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace');
const fixtureDir = path.join(workspaceDir, 'packages', 'subpackage');
const packageJSON = {
devDependencies: { electron: '^4.0.4' },
};
if (hasYarn()) {
expect(await getElectronModulePath(fixtureDir, packageJSON)).to.be.equal(path.join(workspaceDir, 'node_modules', 'electron'));
} else {
expect(getElectronModulePath(fixtureDir, packageJSON)).to.eventually.be.rejectedWith('Cannot find the package');
}
});

after(async () => {
await fs.remove(tempDir);
});
});
7 changes: 6 additions & 1 deletion packages/api/core/test/fast/start_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ describe('start', () => {
spawnStub = sinon.stub();
shouldOverride = false;
packageJSON = require('../fixture/dummy_app/package.json');
const electronPath = path.resolve(__dirname, 'node_modules/electron');

start = proxyquire.noCallThru().load('../../src/api/start', {
'../util/electron-version': {
getElectronModulePath: () => Promise.resolve(electronPath),
getElectronVersion: () => Promise.resolve('1.0.0'),
},
'../util/forge-config': async () => ({
pluginInterface: {
overrideStartLogic: async () => shouldOverride,
triggerHook: async () => false,
},
}),
[path.resolve(__dirname, 'node_modules/electron')]: 'fake_electron_path',
[electronPath]: 'fake_electron_path',
'../util/resolve-dir': async (dir: string) => resolveStub(dir),
'../util/read-package-json': {
readMutatedPackageJson: () => Promise.resolve(packageJSON),
Expand Down

0 comments on commit 8613386

Please sign in to comment.