{"version":3,"file":"npm.mjs","names":["path"],"sources":["../../../src/packagers/npm.ts"],"sourcesContent":["import { Predicate } from 'effect';\nimport { any, isEmpty, replace, split, startsWith, takeWhile } from 'ramda';\nimport * as path from 'path';\n\nimport type { DependenciesResult, DependencyMap, JSONObject, PackagerOptions } from '../types';\nimport { SpawnError, spawnProcess } from '../utils';\nimport type { Packager } from './packager';\n\ntype NpmV7Map = Record<string, NpmV7Tree>;\n\nexport interface NpmV7Tree {\n  version: string;\n  resolved: string;\n  name: string;\n  integrity: string;\n  _id: string;\n  extraneous: boolean;\n  path: string;\n  _dependencies: Record<string, string>;\n  devDependencies: Record<string, string>;\n  peerDependencies: Record<string, string>;\n  dependencies?: NpmV7Map;\n}\n\nexport interface NpmV7Deps {\n  version: string;\n  name: string;\n  description: string;\n  private: boolean;\n  scripts: Record<string, string>;\n  _id: string;\n  extraneous: boolean;\n  path: string;\n  _dependencies: Record<string, string>;\n  devDependencies: Record<string, string>;\n  peerDependencies: Record<string, string>;\n  dependencies: NpmV7Map;\n}\n\nexport type NpmV6Map = Record<string, NpmV6Tree>;\n\nexport interface NpmV6Tree {\n  _args: string[][] | string;\n  _from: string;\n  _id: string;\n  _integrity: string;\n  _location: string;\n  _phantomChildren: Record<string, string> | string;\n  _requested: Record<string, unknown>;\n  _requiredBy: string[] | string;\n  _resolved: string;\n  _spec: string;\n  _where: string;\n  author: string;\n  license: string;\n  main: string;\n  name: string;\n  scripts: Record<string, string> | string;\n  version: string;\n  readme: string;\n  dependencies: NpmV6Map;\n  devDependencies: Record<string, string> | string;\n  optionalDependencies: Record<string, string> | string;\n  _dependencies: Record<string, string> | string;\n  path: string;\n  error: string | Error;\n  extraneous: boolean;\n  _deduped?: string;\n}\n\nexport interface NpmV6Deps {\n  name: string;\n  version: string;\n  description: string;\n  private: boolean;\n  scripts: Record<string, string>;\n  dependencies?: NpmV6Map;\n  readme?: string;\n  _id: string;\n  _shrinkwrap: Record<string, unknown>;\n  devDependencies: Record<string, string>;\n  optionalDependencies: Record<string, string>;\n  _dependencies: Record<string, string>;\n  path: string;\n  error: string | Error;\n  extraneous: boolean;\n}\n\n/**\n * NPM packager.\n */\nexport class NPM implements Packager {\n  private packagerOptions: PackagerOptions;\n\n  constructor(packagerOptions: PackagerOptions) {\n    this.packagerOptions = packagerOptions;\n  }\n\n  get lockfileName() {\n    return 'package-lock.json';\n  }\n\n  get copyPackageSectionNames() {\n    return [];\n  }\n\n  get mustCopyModules() {\n    return true;\n  }\n\n  private async getNpmMajorVersion(cwd: string): Promise<number> {\n    const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';\n    const args = ['--version'];\n\n    const processOutput = await spawnProcess(command, args, { cwd });\n    const version = processOutput.stdout.trim();\n\n    const [major] = version.split('.');\n\n    if (major) {\n      return parseInt(major, 10);\n    }\n\n    throw new Error('Unable to get major npm version');\n  }\n\n  async getProdDependencies(cwd: string, depth?: number): Promise<DependenciesResult> {\n    const npmMajorVersion = await this.getNpmMajorVersion(cwd);\n    const prodFlag = npmMajorVersion >= 7 ? '--omit=dev' : '-prod';\n    const noDepthFlag = npmMajorVersion >= 7 ? '-all' : null;\n\n    // Get first level dependency graph\n    const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';\n    const args = [\n      'ls',\n      '-json',\n      prodFlag, // Only prod dependencies\n      '-long',\n      depth ? `-depth=${depth}` : noDepthFlag,\n    ].filter(Predicate.isString);\n\n    const ignoredNpmErrors: Array<{\n      npmError: string;\n      log: boolean;\n    }> = [\n      { npmError: 'extraneous', log: false },\n      { npmError: 'missing', log: false },\n      { npmError: 'peer dep missing', log: true },\n      { npmError: 'code ELSPROBLEMS', log: false },\n    ];\n\n    let parsedDeps: NpmV6Deps | NpmV7Deps;\n\n    try {\n      const processOutput = await spawnProcess(command, args, { cwd });\n\n      parsedDeps = JSON.parse(processOutput.stdout) as NpmV6Deps | NpmV7Deps;\n    } catch (err) {\n      if (err instanceof SpawnError) {\n        // Only exit with an error if we have critical npm errors for 2nd level inside\n        // Split the stderr by \\n character to get the npm ERR! plaintext lines, ignore additional JSON blob (emitted by npm >=7)\n        // see https://github.com/serverless-heaven/serverless-webpack/pull/782 and https://github.com/floydspace/serverless-swc/issues/288\n        const lines = split('\\n', err.stderr);\n        const npmErrors = takeWhile((line) => line !== '{', lines);\n\n        const hasThrowableErrors = npmErrors.every(\n          (error) =>\n            !isEmpty(error) &&\n            !any((ignoredError) => startsWith(`npm ERR! ${ignoredError.npmError}`, error), ignoredNpmErrors)\n        );\n\n        if (!hasThrowableErrors && !isEmpty(err.stdout)) {\n          return { stdout: err.stdout };\n        }\n      }\n\n      throw err;\n    }\n\n    const basePath = parsedDeps.path;\n\n    const convertTrees = (\n      currentTree: NpmV6Map | NpmV7Map,\n      rootDeps: DependencyMap,\n      currentDeps: DependencyMap = rootDeps\n    ): DependencyMap => {\n      return Object.entries(currentTree).reduce<DependencyMap>((deps, [name, tree]) => {\n        if (tree.path === path.join(basePath, 'node_modules', name)) {\n          // Module path is in the root folder\n\n          // If this isn't the root of the tree\n          if (rootDeps !== deps) {\n            // Set it as resolved\n            // eslint-disable-next-line no-param-reassign\n            deps[name] ??= {\n              version: tree.version,\n              isRootDep: true,\n            };\n          }\n          if (tree._deduped || (!isEmpty(tree._dependencies) && !tree.dependencies)) {\n            // Edge case - When it is de-duped this record will not contain the dependency tree.\n            // _deduped is for v6 (Object.keys(tree._dependencies).length && !tree.dependencies) for v7\n            // We can just ignore storing this at the root because it does not contain the tree we are after\n            // \"samchungy-dep-b\": {\n            //   \"version\": \"3.0.0\",\n            //   \"name\": \"samchungy-dep-b\",\n            //   \"resolved\": \"https://registry.npmjs.org/samchungy-dep-b/-/samchungy-dep-b-3.0.0.tgz\",\n            //   \"integrity\": \"sha512-fy6RAnofLSnLHgOUmgsFz0ZFnJcJeNHT+qUfHJ7daIFlBaciRDR6v5sdWm7mAM2EzQ1KFf2hmKJVFZgthVeCAw==\",\n            //   \"_id\": \"samchungy-dep-b@3.0.0\",\n            //   \"extraneous\": false,\n            //   \"path\": \"/Users/schung/me/serverless-swc/examples/individually/node_modules/samchungy-dep-b\",\n            //   \"_dependencies\": {\n            //     \"samchungy-dep-c\": \"^1.0.0\",\n            //     \"samchungy-dep-d\": \"^1.0.0\"\n            //   },\n            //   \"devDependencies\": {},\n            //   \"peerDependencies\": {}\n            // }\n          } else {\n            // This is a root node_modules dependency\n            // eslint-disable-next-line no-param-reassign\n            rootDeps[name] ??= {\n              version: tree.version,\n              ...(tree.dependencies &&\n                !isEmpty(tree.dependencies) && {\n                  dependencies: convertTrees(tree.dependencies, rootDeps, {}),\n                }),\n            };\n          }\n\n          return deps;\n        }\n\n        // Module is only installed within the node_modules of this dep. Iterate through it's dep tree\n        // eslint-disable-next-line no-param-reassign\n        deps[name] ??= {\n          version: tree.version,\n          ...(tree.dependencies &&\n            !isEmpty(tree.dependencies) && {\n              dependencies: convertTrees(tree.dependencies, rootDeps, {}),\n            }),\n        };\n\n        return deps;\n      }, currentDeps);\n    };\n\n    return {\n      ...(parsedDeps.dependencies &&\n        !isEmpty(parsedDeps.dependencies) && {\n          dependencies: convertTrees(parsedDeps.dependencies, {}),\n        }),\n    };\n  }\n\n  /**\n   * We should not be modifying 'package-lock.json'\n   * because this file should be treated as internal to npm.\n   *\n   * Rebase package-lock is a temporary workaround and must be\n   * removed as soon as https://github.com/npm/npm/issues/19183 gets fixed.\n   */\n  rebaseLockfile(pathToPackageRoot: string, lockfile: JSONObject) {\n    if (lockfile.version) {\n      // eslint-disable-next-line no-param-reassign\n      lockfile.version = this._rebaseFileReferences(pathToPackageRoot, lockfile.version);\n    }\n\n    if (lockfile.dependencies) {\n      for (const lockedDependency in lockfile.dependencies) {\n        this.rebaseLockfile(pathToPackageRoot, lockedDependency);\n      }\n    }\n\n    return lockfile;\n  }\n\n  async install(cwd: string, extraArgs: Array<string>, useLockfile: boolean) {\n    const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';\n\n    const args = [!this.packagerOptions.ignoreLockfile && useLockfile ? 'ci' : 'install', ...extraArgs];\n\n    await spawnProcess(command, args, { cwd });\n  }\n\n  async prune(cwd: string) {\n    const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';\n    const args = ['prune'];\n\n    await spawnProcess(command, args, { cwd });\n  }\n\n  async runScripts(cwd: string, scriptNames: string[]) {\n    const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';\n\n    await Promise.all(\n      scriptNames.map((scriptName) => {\n        const args = ['run', scriptName];\n\n        return spawnProcess(command, args, { cwd });\n      })\n    );\n  }\n\n  private _rebaseFileReferences(pathToPackageRoot: string, moduleVersion: string) {\n    if (/^file:[^/]{2}/.test(moduleVersion)) {\n      const filePath = replace(/^file:/, '', moduleVersion);\n\n      return replace(/\\\\/g, '/', `file:${pathToPackageRoot}/${filePath}`);\n    }\n\n    return moduleVersion;\n  }\n}\n"],"mappings":"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"}