chore: ensure yarn is installed before launching fiddle (#452)
This commit is contained in:
+24
-8
@@ -10,7 +10,8 @@ export interface PMOperationOptions {
|
||||
packageManager: IPackageManager;
|
||||
}
|
||||
|
||||
export let isInstalled: boolean | null = null;
|
||||
export let isNpmInstalled: boolean | null = null;
|
||||
export let isYarnInstalled: boolean | null = null;
|
||||
|
||||
/* add other modules to automatically ignore here */
|
||||
/* perhaps we can expose this to the settings module?*/
|
||||
@@ -33,22 +34,37 @@ const isUnique = (item: any, idx: number, arr: Array<any>): boolean => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if npm is installed by checking if a binary
|
||||
* Checks if package manager is installed by checking if a binary
|
||||
* with that name can be found.
|
||||
*/
|
||||
export async function getIsNpmInstalled(
|
||||
export async function getIsPackageManagerInstalled(
|
||||
packageManager: IPackageManager,
|
||||
ignoreCache?: boolean,
|
||||
): Promise<boolean> {
|
||||
if (isInstalled !== null && !ignoreCache) return isInstalled;
|
||||
if (packageManager === 'npm' && isNpmInstalled !== null && !ignoreCache)
|
||||
return isNpmInstalled;
|
||||
if (packageManager === 'yarn' && isYarnInstalled !== null && !ignoreCache)
|
||||
return isYarnInstalled;
|
||||
|
||||
const command = process.platform === 'win32' ? 'where.exe npm' : 'which npm';
|
||||
const command =
|
||||
process.platform === 'win32'
|
||||
? `where.exe ${packageManager}`
|
||||
: `which ${packageManager}`;
|
||||
|
||||
try {
|
||||
await exec(process.cwd(), command);
|
||||
return (isInstalled = true);
|
||||
if (packageManager === 'npm') {
|
||||
return (isNpmInstalled = true);
|
||||
} else {
|
||||
return (isYarnInstalled = true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`getIsNpmInstalled: "${command}" failed.`, error);
|
||||
return (isInstalled = false);
|
||||
console.warn(`getIsPackageManagerInstalled: "${command}" failed.`, error);
|
||||
if (packageManager === 'npm') {
|
||||
return (isNpmInstalled = false);
|
||||
} else {
|
||||
return (isYarnInstalled = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-9
@@ -9,7 +9,7 @@ import { getElectronBinaryPath, getIsDownloaded } from './binary';
|
||||
import { ipcRendererManager } from './ipc';
|
||||
import {
|
||||
findModulesInEditors,
|
||||
getIsNpmInstalled,
|
||||
getIsPackageManagerInstalled,
|
||||
installModules,
|
||||
packageRun,
|
||||
PMOperationOptions,
|
||||
@@ -124,10 +124,13 @@ export class Runner {
|
||||
this.appState.isConsoleShowing = true;
|
||||
pushOutput(`📦 ${strings[0]} current Fiddle...`);
|
||||
|
||||
if (!(await getIsNpmInstalled())) {
|
||||
let message = `Error: Could not find npm. Fiddle requires Node.js and npm `;
|
||||
const packageManager = this.appState.packageManager;
|
||||
const pmInstalled = await getIsPackageManagerInstalled(packageManager);
|
||||
if (!pmInstalled) {
|
||||
let message = `Error: Could not find ${packageManager}. Fiddle requires Node.js and npm or yarn `;
|
||||
message += `to compile packages. Please visit https://nodejs.org to install `;
|
||||
message += `Node.js and npm.`;
|
||||
message += `Node.js and npm, or https://classic.yarnpkg.com/lang/en/ `;
|
||||
message += `to install Yarn`;
|
||||
|
||||
this.appState.pushOutput(message, { isNotPre: true });
|
||||
return false;
|
||||
@@ -141,8 +144,6 @@ export class Runner {
|
||||
);
|
||||
if (!dir) return false;
|
||||
|
||||
const packageManager = this.appState.packageManager;
|
||||
|
||||
// Files are now saved to temp, let's install Forge and dependencies
|
||||
if (!(await this.packageInstall({ dir, packageManager }))) return false;
|
||||
|
||||
@@ -177,14 +178,16 @@ export class Runner {
|
||||
const { pushOutput } = this.appState;
|
||||
|
||||
if (modules && modules.length > 0) {
|
||||
if (!(await getIsNpmInstalled())) {
|
||||
const packageManager = pmOptions.packageManager;
|
||||
const pmInstalled = await getIsPackageManagerInstalled(packageManager);
|
||||
if (!pmInstalled) {
|
||||
let message = `The ${maybePlural(`module`, modules)} ${modules.join(
|
||||
', ',
|
||||
)} need to be installed, `;
|
||||
message += `but we could not find npm. Fiddle requires Node.js and npm `;
|
||||
message += `but we could not find ${packageManager}. Fiddle requires Node.js and npm `;
|
||||
message += `to support the installation of modules not included in `;
|
||||
message += `Electron. Please visit https://nodejs.org to install Node.js `;
|
||||
message += `and npm.`;
|
||||
message += `and npm, or https://classic.yarnpkg.com/lang/en/ to install Yarn`;
|
||||
|
||||
pushOutput(message, { isNotPre: true });
|
||||
return;
|
||||
|
||||
+105
-42
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
findModulesInEditors,
|
||||
getIsNpmInstalled,
|
||||
getIsPackageManagerInstalled,
|
||||
installModules,
|
||||
packageRun,
|
||||
} from '../../src/renderer/npm';
|
||||
@@ -26,64 +26,127 @@ describe('npm', () => {
|
||||
}
|
||||
`;
|
||||
|
||||
describe('getIsNpmInstalled()', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModuleRegistry();
|
||||
describe('getIsPackageManagerInstalled()', () => {
|
||||
describe('npm()', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModuleRegistry();
|
||||
});
|
||||
|
||||
afterEach(() => resetPlatform());
|
||||
|
||||
it('returns true if npm installed', async () => {
|
||||
overridePlatform('darwin');
|
||||
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-npm'),
|
||||
);
|
||||
|
||||
const result = await getIsPackageManagerInstalled('npm');
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('which npm');
|
||||
});
|
||||
|
||||
it('returns true if npm installed', async () => {
|
||||
overridePlatform('win32');
|
||||
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-npm'),
|
||||
);
|
||||
|
||||
const result = await getIsPackageManagerInstalled('npm', true);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('where.exe npm');
|
||||
});
|
||||
|
||||
it('returns false if npm not installed', async () => {
|
||||
overridePlatform('darwin');
|
||||
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.reject('/usr/bin/fake-npm'),
|
||||
);
|
||||
|
||||
const result = await getIsPackageManagerInstalled('npm', true);
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('which npm');
|
||||
});
|
||||
|
||||
it('uses the cache', async () => {
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-npm'),
|
||||
);
|
||||
|
||||
const one = await getIsPackageManagerInstalled('npm', true);
|
||||
expect(one).toBe(true);
|
||||
expect(exec as jest.Mock).toHaveBeenCalledTimes(1);
|
||||
|
||||
const two = await getIsPackageManagerInstalled('npm');
|
||||
expect(two).toBe(true);
|
||||
expect(exec as jest.Mock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => resetPlatform());
|
||||
describe('yarn()', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModuleRegistry();
|
||||
});
|
||||
|
||||
it('returns true if npm installed', async () => {
|
||||
overridePlatform('darwin');
|
||||
afterEach(() => resetPlatform());
|
||||
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-npm'),
|
||||
);
|
||||
it('returns true if yarn installed', async () => {
|
||||
overridePlatform('darwin');
|
||||
|
||||
const result = await getIsNpmInstalled();
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-yarn'),
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('which npm');
|
||||
});
|
||||
const result = await getIsPackageManagerInstalled('yarn');
|
||||
|
||||
it('returns true if npm installed', async () => {
|
||||
overridePlatform('win32');
|
||||
expect(result).toBe(true);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('which yarn');
|
||||
});
|
||||
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-npm'),
|
||||
);
|
||||
it('returns true if yarn installed', async () => {
|
||||
overridePlatform('win32');
|
||||
|
||||
const result = await getIsNpmInstalled(true);
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-yarn'),
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('where.exe npm');
|
||||
});
|
||||
const result = await getIsPackageManagerInstalled('yarn', true);
|
||||
|
||||
it('returns false if npm not installed', async () => {
|
||||
overridePlatform('darwin');
|
||||
expect(result).toBe(true);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('where.exe yarn');
|
||||
});
|
||||
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.reject('/usr/bin/fake-npm'),
|
||||
);
|
||||
it('returns false if yarn not installed', async () => {
|
||||
overridePlatform('darwin');
|
||||
|
||||
const result = await getIsNpmInstalled(true);
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.reject('/usr/bin/fake-yarn'),
|
||||
);
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('which npm');
|
||||
});
|
||||
const result = await getIsPackageManagerInstalled('yarn', true);
|
||||
|
||||
it('uses the cache', async () => {
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-npm'),
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
expect((exec as jest.Mock).mock.calls[0][1]).toBe('which yarn');
|
||||
});
|
||||
|
||||
const one = await getIsNpmInstalled(true);
|
||||
expect(one).toBe(true);
|
||||
expect(exec as jest.Mock).toHaveBeenCalledTimes(1);
|
||||
it('uses the cache', async () => {
|
||||
(exec as jest.Mock).mockReturnValueOnce(
|
||||
Promise.resolve('/usr/bin/fake-yarn'),
|
||||
);
|
||||
|
||||
const two = await getIsNpmInstalled();
|
||||
expect(two).toBe(true);
|
||||
expect(exec as jest.Mock).toHaveBeenCalledTimes(1);
|
||||
const one = await getIsPackageManagerInstalled('yarn', true);
|
||||
expect(one).toBe(true);
|
||||
expect(exec as jest.Mock).toHaveBeenCalledTimes(1);
|
||||
|
||||
const two = await getIsPackageManagerInstalled('yarn');
|
||||
expect(two).toBe(true);
|
||||
expect(exec as jest.Mock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { getIsDownloaded } from '../../src/renderer/binary';
|
||||
import { ipcRendererManager } from '../../src/renderer/ipc';
|
||||
import {
|
||||
findModulesInEditors,
|
||||
getIsNpmInstalled,
|
||||
getIsPackageManagerInstalled,
|
||||
installModules,
|
||||
packageRun,
|
||||
} from '../../src/renderer/npm';
|
||||
@@ -35,7 +35,7 @@ describe('Runner component', () => {
|
||||
mockChild = new MockChildProcess();
|
||||
ipcRendererManager.removeAllListeners();
|
||||
|
||||
(getIsNpmInstalled as jest.Mock).mockReturnValue(true);
|
||||
(getIsPackageManagerInstalled as jest.Mock).mockReturnValue(true);
|
||||
|
||||
store = {
|
||||
version: '2.0.2',
|
||||
@@ -45,6 +45,7 @@ describe('Runner component', () => {
|
||||
pushOutput: jest.fn(),
|
||||
clearConsole: jest.fn(),
|
||||
pushError: jest.fn(),
|
||||
packageManager: 'npm',
|
||||
get currentElectronVersion() {
|
||||
return mockVersions['2.0.2'];
|
||||
},
|
||||
@@ -270,7 +271,7 @@ describe('Runner component', () => {
|
||||
});
|
||||
|
||||
it('does attempt a forge operation if npm is not installed', async () => {
|
||||
(getIsNpmInstalled as jest.Mock).mockReturnValueOnce(false);
|
||||
(getIsPackageManagerInstalled as jest.Mock).mockReturnValueOnce(false);
|
||||
|
||||
expect(await instance.performForgeOperation(ForgeCommands.MAKE)).toBe(
|
||||
false,
|
||||
@@ -280,7 +281,7 @@ describe('Runner component', () => {
|
||||
|
||||
describe('installModulesForEditor()', () => {
|
||||
it('does not attempt installation if npm is not installed', async () => {
|
||||
(getIsNpmInstalled as jest.Mock).mockReturnValueOnce(false);
|
||||
(getIsPackageManagerInstalled as jest.Mock).mockReturnValueOnce(false);
|
||||
(findModulesInEditors as jest.Mock).mockReturnValueOnce(['fake-module']);
|
||||
|
||||
await instance.installModulesForEditor(
|
||||
@@ -298,7 +299,7 @@ describe('Runner component', () => {
|
||||
});
|
||||
|
||||
it('does attempt installation if npm is installed', async () => {
|
||||
(getIsNpmInstalled as jest.Mock).mockReturnValueOnce(true);
|
||||
(getIsPackageManagerInstalled as jest.Mock).mockReturnValueOnce(true);
|
||||
(findModulesInEditors as jest.Mock).mockReturnValueOnce(['fake-module']);
|
||||
|
||||
await instance.installModulesForEditor(
|
||||
|
||||
Reference in New Issue
Block a user