MCPcopy Create free account
hub / github.com/npm/cli / exec

Method exec

lib/commands/ci.js:40–135  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

38 ]
39
40 async exec () {
41 if (this.npm.global) {
42 throw Object.assign(new Error('`npm ci` does not work for global packages'), {
43 code: 'ECIGLOBAL',
44 })
45 }
46
47 const dryRun = this.npm.config.get('dry-run')
48 const ignoreScripts = this.npm.config.get('ignore-scripts')
49 const where = this.npm.prefix
50 const Arborist = require('@npmcli/arborist')
51 const { policy: allowScriptsPolicy } = await resolveAllowScripts(this.npm)
52 const opts = {
53 ...this.npm.flatOptions,
54 packageLock: true, // npm ci should never skip lock files
55 path: where,
56 save: false, // npm ci should never modify the lockfile or package.json
57 workspaces: this.workspaceNames,
58 allowScripts: allowScriptsPolicy,
59 }
60
61 // generate an inventory from the virtual tree in the lockfile
62 const virtualArb = new Arborist(opts)
63 try {
64 await virtualArb.loadVirtual()
65 } catch (err) {
66 log.verbose('loadVirtual', err.stack)
67 const msg =
68 'The `npm ci` command can only install with an existing package-lock.json or\n' +
69 'npm-shrinkwrap.json with lockfileVersion >= 1. Run an install with npm@5 or\n' +
70 'later to generate a package-lock.json file, then try again.'
71 throw this.usageError(msg)
72 }
73 const virtualInventory = new Map(virtualArb.virtualTree.inventory)
74
75 // Now we make our real Arborist.
76 // We need a new one because the virtual tree fromt the lockfile can have extraneous dependencies in it that won't install on this platform
77 const arb = new Arborist(opts)
78 await arb.buildIdealTree()
79 await strictAllowScriptsPreflight({ arb, npm: this.npm, idealTreeOpts: opts })
80
81 // Verifies that the packages from the ideal tree will match the same versions that are present in the virtual tree (lock file).
82 const errors = validateLockfile(virtualInventory, arb.idealTree.inventory)
83 if (errors.length) {
84 throw this.usageError(
85 '`npm ci` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. ' +
86 'Please update your lock file with `npm install` before continuing.\n\n' +
87 errors.join('\n')
88 )
89 }
90
91 if (!dryRun) {
92 const workspacePaths = await getWorkspaces([], {
93 path: this.npm.localPrefix,
94 includeWorkspaceRoot: true,
95 })
96
97 // Only remove node_modules after we've successfully loaded the virtual tree and validated the lockfile

Callers

nothing calls this directly

Calls 12

reifyMethod · 0.95
resolveAllowScriptsFunction · 0.85
validateLockfileFunction · 0.85
getWorkspacesFunction · 0.85
runScriptFunction · 0.85
reifyFinishFunction · 0.85
loadVirtualMethod · 0.80
usageErrorMethod · 0.80
buildIdealTreeMethod · 0.80
getMethod · 0.45
rmMethod · 0.45

Tested by

no test coverage detected