1 | import { Errors, ux } from '@oclif/core';
|
2 | import makeDebug from 'debug';
|
3 | import { readFile } from 'node:fs/promises';
|
4 | import { createRequire } from 'node:module';
|
5 | import { join, sep } from 'node:path';
|
6 | import { spawn } from './spawn.js';
|
7 | const debug = makeDebug('@oclif/plugin-plugins:npm');
|
8 | export class NPM {
|
9 | bin;
|
10 | config;
|
11 | logLevel;
|
12 | constructor({ config, logLevel }) {
|
13 | this.config = config;
|
14 | this.logLevel = logLevel;
|
15 | }
|
16 | async exec(args = [], options) {
|
17 | const bin = await this.findNpm();
|
18 | debug('npm binary path', bin);
|
19 | args.push(`--loglevel=${this.logLevel}`, '--no-fund');
|
20 | if (this.config.npmRegistry)
|
21 | args.push(`--registry=${this.config.npmRegistry}`);
|
22 | if (options.logLevel !== 'notice' && options.logLevel !== 'silent') {
|
23 | ux.stderr(`${options.cwd}: ${bin} ${args.join(' ')}`);
|
24 | }
|
25 | debug(`${options.cwd}: ${bin} ${args.join(' ')}`);
|
26 | try {
|
27 | const output = await spawn(bin, args, options);
|
28 | debug('npm done');
|
29 | return output;
|
30 | }
|
31 | catch (error) {
|
32 | debug('npm error', error);
|
33 | throw error;
|
34 | }
|
35 | }
|
36 | async install(args, opts) {
|
37 | const prod = opts.prod ? ['--omit', 'dev'] : [];
|
38 | return this.exec(['install', ...args, ...prod, '--no-audit'], opts);
|
39 | }
|
40 | async uninstall(args, opts) {
|
41 | return this.exec(['uninstall', ...args], opts);
|
42 | }
|
43 | async update(args, opts) {
|
44 | return this.exec(['update', ...args], opts);
|
45 | }
|
46 | async view(args, opts) {
|
47 | return this.exec(['view', ...args], { ...opts, logLevel: 'silent' });
|
48 | }
|
49 | |
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | async findNpm() {
|
57 | if (this.bin)
|
58 | return this.bin;
|
59 | try {
|
60 | const npmPjsonPath = createRequire(import.meta.url).resolve('npm/package.json');
|
61 | const npmPjson = JSON.parse(await readFile(npmPjsonPath, { encoding: 'utf8' }));
|
62 | const npmPath = npmPjsonPath.slice(0, Math.max(0, npmPjsonPath.lastIndexOf(sep)));
|
63 | this.bin = join(npmPath, npmPjson.bin.npm);
|
64 | }
|
65 | catch {
|
66 | const { default: which } = await import('which');
|
67 | this.bin = await which('npm');
|
68 | }
|
69 | if (!this.bin) {
|
70 | throw new Errors.CLIError('npm not found');
|
71 | }
|
72 | return this.bin;
|
73 | }
|
74 | }
|