(
packageName: string,
targetPath: string,
options: { registry?: string; version?: string } = {},
)
| 490 | * Install a plugin from npm using a global cache (exported for testing) |
| 491 | */ |
| 492 | export async function installFromNpm( |
| 493 | packageName: string, |
| 494 | targetPath: string, |
| 495 | options: { registry?: string; version?: string } = {}, |
| 496 | ): Promise<void> { |
| 497 | const npmCachePath = join(getPluginsDirectory(), 'npm-cache') |
| 498 | |
| 499 | await getFsImplementation().mkdir(npmCachePath) |
| 500 | |
| 501 | const packageSpec = options.version |
| 502 | ? `${packageName}@${options.version}` |
| 503 | : packageName |
| 504 | const packagePath = join(npmCachePath, 'node_modules', packageName) |
| 505 | const needsInstall = !(await pathExists(packagePath)) |
| 506 | |
| 507 | if (needsInstall) { |
| 508 | logForDebugging(`Installing npm package ${packageSpec} to cache`) |
| 509 | const args = ['install', packageSpec, '--prefix', npmCachePath] |
| 510 | if (options.registry) { |
| 511 | args.push('--registry', options.registry) |
| 512 | } |
| 513 | const result = await execFileNoThrow('npm', args, { useCwd: false }) |
| 514 | |
| 515 | if (result.code !== 0) { |
| 516 | throw new Error(`Failed to install npm package: ${result.stderr}`) |
| 517 | } |
| 518 | } |
| 519 | |
| 520 | await copyDir(packagePath, targetPath) |
| 521 | logForDebugging( |
| 522 | `Copied npm package ${packageName} from cache to ${targetPath}`, |
| 523 | ) |
| 524 | } |
| 525 | |
| 526 | /** |
| 527 | * Clone a git repository (exported for testing) |
no test coverage detected