UNPKG

8.23 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9Object.defineProperty(exports, "__esModule", { value: true });
10exports.runTempPackageBin = exports.installTempPackage = exports.installPackage = exports.installAllPackages = void 0;
11const child_process_1 = require("child_process");
12const fs_1 = require("fs");
13const os_1 = require("os");
14const path_1 = require("path");
15const rimraf = require("rimraf");
16const workspace_schema_1 = require("../lib/config/workspace-schema");
17const spinner_1 = require("./spinner");
18async function installAllPackages(packageManager = workspace_schema_1.PackageManager.Npm, extraArgs = [], cwd = process.cwd()) {
19 const packageManagerArgs = getPackageManagerArguments(packageManager);
20 const installArgs = [];
21 if (packageManagerArgs.installAll) {
22 installArgs.push(packageManagerArgs.installAll);
23 }
24 installArgs.push(packageManagerArgs.silent);
25 const spinner = new spinner_1.Spinner();
26 spinner.start('Installing packages...');
27 const bufferedOutput = [];
28 return new Promise((resolve, reject) => {
29 var _a, _b;
30 const childProcess = child_process_1.spawn(packageManager, [...installArgs, ...extraArgs], {
31 stdio: 'pipe',
32 shell: true,
33 cwd,
34 }).on('close', (code) => {
35 if (code === 0) {
36 spinner.succeed('Packages successfully installed.');
37 resolve(0);
38 }
39 else {
40 spinner.stop();
41 bufferedOutput.forEach(({ stream, data }) => stream.write(data));
42 spinner.fail('Package install failed, see above.');
43 reject(1);
44 }
45 });
46 (_a = childProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => bufferedOutput.push({ stream: process.stdout, data: data }));
47 (_b = childProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => bufferedOutput.push({ stream: process.stderr, data: data }));
48 });
49}
50exports.installAllPackages = installAllPackages;
51async function installPackage(packageName, packageManager = workspace_schema_1.PackageManager.Npm, save = true, extraArgs = [], cwd = process.cwd()) {
52 const packageManagerArgs = getPackageManagerArguments(packageManager);
53 const installArgs = [
54 packageManagerArgs.install,
55 packageName,
56 packageManagerArgs.silent,
57 ];
58 const spinner = new spinner_1.Spinner();
59 spinner.start('Installing package...');
60 if (save === 'devDependencies') {
61 installArgs.push(packageManagerArgs.saveDev);
62 }
63 const bufferedOutput = [];
64 return new Promise((resolve, reject) => {
65 var _a, _b;
66 const childProcess = child_process_1.spawn(packageManager, [...installArgs, ...extraArgs], {
67 stdio: 'pipe',
68 shell: true,
69 cwd,
70 }).on('close', (code) => {
71 if (code === 0) {
72 spinner.succeed('Package successfully installed.');
73 resolve(0);
74 }
75 else {
76 spinner.stop();
77 bufferedOutput.forEach(({ stream, data }) => stream.write(data));
78 spinner.fail('Package install failed, see above.');
79 reject(1);
80 }
81 });
82 (_a = childProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => bufferedOutput.push({ stream: process.stdout, data: data }));
83 (_b = childProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => bufferedOutput.push({ stream: process.stderr, data: data }));
84 });
85}
86exports.installPackage = installPackage;
87async function installTempPackage(packageName, packageManager = workspace_schema_1.PackageManager.Npm, extraArgs) {
88 const tempPath = fs_1.mkdtempSync(path_1.join(fs_1.realpathSync(os_1.tmpdir()), 'angular-cli-packages-'));
89 // clean up temp directory on process exit
90 process.on('exit', () => {
91 try {
92 rimraf.sync(tempPath);
93 }
94 catch { }
95 });
96 // NPM will warn when a `package.json` is not found in the install directory
97 // Example:
98 // npm WARN enoent ENOENT: no such file or directory, open '/tmp/.ng-temp-packages-84Qi7y/package.json'
99 // npm WARN .ng-temp-packages-84Qi7y No description
100 // npm WARN .ng-temp-packages-84Qi7y No repository field.
101 // npm WARN .ng-temp-packages-84Qi7y No license field.
102 // While we can use `npm init -y` we will end up needing to update the 'package.json' anyways
103 // because of missing fields.
104 fs_1.writeFileSync(path_1.join(tempPath, 'package.json'), JSON.stringify({
105 name: 'temp-cli-install',
106 description: 'temp-cli-install',
107 repository: 'temp-cli-install',
108 license: 'MIT',
109 }));
110 // setup prefix/global modules path
111 const packageManagerArgs = getPackageManagerArguments(packageManager);
112 const tempNodeModules = path_1.join(tempPath, 'node_modules');
113 // Yarn will not append 'node_modules' to the path
114 const prefixPath = packageManager === workspace_schema_1.PackageManager.Yarn ? tempNodeModules : tempPath;
115 const installArgs = [
116 ...(extraArgs || []),
117 `${packageManagerArgs.prefix}="${prefixPath}"`,
118 packageManagerArgs.noLockfile,
119 ];
120 return {
121 status: await installPackage(packageName, packageManager, true, installArgs, tempPath),
122 tempNodeModules,
123 };
124}
125exports.installTempPackage = installTempPackage;
126async function runTempPackageBin(packageName, packageManager = workspace_schema_1.PackageManager.Npm, args = []) {
127 const { status: code, tempNodeModules } = await installTempPackage(packageName, packageManager);
128 if (code !== 0) {
129 return code;
130 }
131 // Remove version/tag etc... from package name
132 // Ex: @angular/cli@latest -> @angular/cli
133 const packageNameNoVersion = packageName.substring(0, packageName.lastIndexOf('@'));
134 const pkgLocation = path_1.join(tempNodeModules, packageNameNoVersion);
135 const packageJsonPath = path_1.join(pkgLocation, 'package.json');
136 // Get a binary location for this package
137 let binPath;
138 if (fs_1.existsSync(packageJsonPath)) {
139 const content = fs_1.readFileSync(packageJsonPath, 'utf-8');
140 if (content) {
141 const { bin = {} } = JSON.parse(content);
142 const binKeys = Object.keys(bin);
143 if (binKeys.length) {
144 binPath = path_1.resolve(pkgLocation, bin[binKeys[0]]);
145 }
146 }
147 }
148 if (!binPath) {
149 throw new Error(`Cannot locate bin for temporary package: ${packageNameNoVersion}.`);
150 }
151 const argv = [`'${binPath}'`, ...args];
152 const { status, error } = child_process_1.spawnSync('node', argv, {
153 stdio: 'inherit',
154 shell: true,
155 env: {
156 ...process.env,
157 NG_DISABLE_VERSION_CHECK: 'true',
158 NG_CLI_ANALYTICS: 'false',
159 },
160 });
161 if (status === null && error) {
162 throw error;
163 }
164 return status || 0;
165}
166exports.runTempPackageBin = runTempPackageBin;
167function getPackageManagerArguments(packageManager) {
168 switch (packageManager) {
169 case workspace_schema_1.PackageManager.Yarn:
170 return {
171 silent: '--silent',
172 saveDev: '--dev',
173 install: 'add',
174 prefix: '--modules-folder',
175 noLockfile: '--no-lockfile',
176 };
177 case workspace_schema_1.PackageManager.Pnpm:
178 return {
179 silent: '--silent',
180 saveDev: '--save-dev',
181 install: 'add',
182 installAll: 'install',
183 prefix: '--prefix',
184 noLockfile: '--no-lockfile',
185 };
186 default:
187 return {
188 silent: '--quiet',
189 saveDev: '--save-dev',
190 install: 'install',
191 installAll: 'install',
192 prefix: '--prefix',
193 noLockfile: '--no-package-lock',
194 };
195 }
196}