mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-18 20:02:40 +08:00
The `esModuleInterop` option is recommended to be enable by TypeScript and corrects several assumptions TypeScript would otherwise make when importing CommonJS files. This option change helps ensure compatibility as packages move towards ESM. Reference: https://www.typescriptlang.org/tsconfig#esModuleInterop
145 lines
4.4 KiB
TypeScript
145 lines
4.4 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import { BaseException } from '@angular-devkit/core';
|
|
import { SpawnOptions, spawn } from 'child_process';
|
|
import ora from 'ora';
|
|
import * as path from 'path';
|
|
import { Observable } from 'rxjs';
|
|
import { TaskExecutor, UnsuccessfulWorkflowExecution } from '../../src';
|
|
import { NodePackageTaskFactoryOptions, NodePackageTaskOptions } from './options';
|
|
|
|
interface PackageManagerProfile {
|
|
quietArgument?: string;
|
|
commands: {
|
|
installAll?: string;
|
|
installPackage: string;
|
|
};
|
|
}
|
|
|
|
const packageManagers: { [name: string]: PackageManagerProfile } = {
|
|
'npm': {
|
|
quietArgument: '--quiet',
|
|
commands: {
|
|
installAll: 'install',
|
|
installPackage: 'install',
|
|
},
|
|
},
|
|
'cnpm': {
|
|
commands: {
|
|
installAll: 'install',
|
|
installPackage: 'install',
|
|
},
|
|
},
|
|
'yarn': {
|
|
quietArgument: '--silent',
|
|
commands: {
|
|
installPackage: 'add',
|
|
},
|
|
},
|
|
'pnpm': {
|
|
quietArgument: '--silent',
|
|
commands: {
|
|
installAll: 'install',
|
|
installPackage: 'install',
|
|
},
|
|
},
|
|
};
|
|
|
|
export class UnknownPackageManagerException extends BaseException {
|
|
constructor(name: string) {
|
|
super(`Unknown package manager "${name}".`);
|
|
}
|
|
}
|
|
|
|
export default function (
|
|
factoryOptions: NodePackageTaskFactoryOptions = {},
|
|
): TaskExecutor<NodePackageTaskOptions> {
|
|
const packageManagerName = factoryOptions.packageManager || 'npm';
|
|
const packageManagerProfile = packageManagers[packageManagerName];
|
|
if (!packageManagerProfile) {
|
|
throw new UnknownPackageManagerException(packageManagerName);
|
|
}
|
|
|
|
const rootDirectory = factoryOptions.rootDirectory || process.cwd();
|
|
|
|
return (options: NodePackageTaskOptions = { command: 'install' }) => {
|
|
let taskPackageManagerProfile = packageManagerProfile;
|
|
let taskPackageManagerName = packageManagerName;
|
|
if (factoryOptions.allowPackageManagerOverride && options.packageManager) {
|
|
taskPackageManagerProfile = packageManagers[options.packageManager];
|
|
if (!taskPackageManagerProfile) {
|
|
throw new UnknownPackageManagerException(options.packageManager);
|
|
}
|
|
taskPackageManagerName = options.packageManager;
|
|
}
|
|
|
|
const bufferedOutput: { stream: NodeJS.WriteStream; data: Buffer }[] = [];
|
|
const spawnOptions: SpawnOptions = {
|
|
stdio: options.hideOutput ? 'pipe' : 'inherit',
|
|
shell: true,
|
|
cwd: path.join(rootDirectory, options.workingDirectory || ''),
|
|
};
|
|
const args: string[] = [];
|
|
|
|
if (options.packageName) {
|
|
if (options.command === 'install') {
|
|
args.push(taskPackageManagerProfile.commands.installPackage);
|
|
}
|
|
args.push(options.packageName);
|
|
} else if (options.command === 'install' && taskPackageManagerProfile.commands.installAll) {
|
|
args.push(taskPackageManagerProfile.commands.installAll);
|
|
}
|
|
|
|
if (options.quiet && taskPackageManagerProfile.quietArgument) {
|
|
args.push(taskPackageManagerProfile.quietArgument);
|
|
}
|
|
|
|
if (factoryOptions.registry) {
|
|
args.push(`--registry="${factoryOptions.registry}"`);
|
|
}
|
|
|
|
if (factoryOptions.force) {
|
|
args.push('--force');
|
|
}
|
|
|
|
return new Observable((obs) => {
|
|
const spinner = ora({
|
|
text: `Installing packages (${taskPackageManagerName})...`,
|
|
// Workaround for https://github.com/sindresorhus/ora/issues/136.
|
|
discardStdin: process.platform != 'win32',
|
|
}).start();
|
|
const childProcess = spawn(taskPackageManagerName, args, spawnOptions).on(
|
|
'close',
|
|
(code: number) => {
|
|
if (code === 0) {
|
|
spinner.succeed('Packages installed successfully.');
|
|
spinner.stop();
|
|
obs.next();
|
|
obs.complete();
|
|
} else {
|
|
if (options.hideOutput) {
|
|
bufferedOutput.forEach(({ stream, data }) => stream.write(data));
|
|
}
|
|
spinner.fail('Package install failed, see above.');
|
|
obs.error(new UnsuccessfulWorkflowExecution());
|
|
}
|
|
},
|
|
);
|
|
if (options.hideOutput) {
|
|
childProcess.stdout?.on('data', (data: Buffer) =>
|
|
bufferedOutput.push({ stream: process.stdout, data: data }),
|
|
);
|
|
childProcess.stderr?.on('data', (data: Buffer) =>
|
|
bufferedOutput.push({ stream: process.stderr, data: data }),
|
|
);
|
|
}
|
|
});
|
|
};
|
|
}
|