Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornlf <quitlahok@gmail.com>2022-07-11 23:35:53 +0300
committerGitHub <noreply@github.com>2022-07-11 23:35:53 +0300
commite9b4214e1ddb1ad79fe6826cf2ce7ba385f0c274 (patch)
treeefeb24009144c9da100fc10561ac32f937031a52 /workspaces/arborist
parent25b305830be0892bbbf0245aee2eebdb76ee2ce3 (diff)
feat(arborist): add support for dependencies script (#5094)
feat: add support for dependencies script this is a new feature that will run the `dependencies` (as well as the `pre` and `post` versions) script any time an npm action makes a change to the installed dependency tree, whether it's adding a new dependency, removing one, or just shuffling things around to dedupe/optimize
Diffstat (limited to 'workspaces/arborist')
-rw-r--r--workspaces/arborist/lib/arborist/reify.js25
-rw-r--r--workspaces/arborist/test/arborist/reify.js58
2 files changed, 82 insertions, 1 deletions
diff --git a/workspaces/arborist/lib/arborist/reify.js b/workspaces/arborist/lib/arborist/reify.js
index 4932c17d0..faf016c70 100644
--- a/workspaces/arborist/lib/arborist/reify.js
+++ b/workspaces/arborist/lib/arborist/reify.js
@@ -22,6 +22,7 @@ const moveFile = require('@npmcli/move-file')
const rimraf = promisify(require('rimraf'))
const PackageJson = require('@npmcli/package-json')
const packageContents = require('@npmcli/installed-package-contents')
+const runScript = require('@npmcli/run-script')
const { checkEngine, checkPlatform } = require('npm-install-checks')
const _force = Symbol.for('force')
@@ -1516,6 +1517,30 @@ module.exports = cls => class Reifier extends cls {
if (!this[_global]) {
await this.actualTree.meta.save()
+ const ignoreScripts = !!this.options.ignoreScripts
+ // if we aren't doing a dry run or ignoring scripts and we actually made changes to the dep
+ // tree, then run the dependencies scripts
+ if (!this[_dryRun] && !ignoreScripts && this.diff && this.diff.children.length) {
+ const { path, package: pkg } = this.actualTree.target
+ const stdio = this.options.foregroundScripts ? 'inherit' : 'pipe'
+ const { scripts = {} } = pkg
+ for (const event of ['predependencies', 'dependencies', 'postdependencies']) {
+ if (Object.prototype.hasOwnProperty.call(scripts, event)) {
+ const timer = `reify:run:${event}`
+ process.emit('time', timer)
+ log.info('run', pkg._id, event, scripts[event])
+ await runScript({
+ event,
+ path,
+ pkg,
+ stdioString: true,
+ stdio,
+ scriptShell: this.options.scriptShell,
+ })
+ process.emit('timeEnd', timer)
+ }
+ }
+ }
}
}
}
diff --git a/workspaces/arborist/test/arborist/reify.js b/workspaces/arborist/test/arborist/reify.js
index a77b0fbb2..406b4281d 100644
--- a/workspaces/arborist/test/arborist/reify.js
+++ b/workspaces/arborist/test/arborist/reify.js
@@ -1,4 +1,4 @@
-const { resolve, basename } = require('path')
+const { join, resolve, basename } = require('path')
const t = require('tap')
const runScript = require('@npmcli/run-script')
const localeCompare = require('@isaacs/string-locale-compare')('en')
@@ -2467,6 +2467,62 @@ t.test('add local dep with existing dev + peer/optional', async t => {
t.equal(tree.children.size, 1, 'children')
})
+t.test('runs dependencies script if tree changes', async (t) => {
+ const path = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'root',
+ version: '1.0.0',
+ dependencies: {
+ abbrev: '^1.1.1',
+ },
+ scripts: {
+ predependencies: `node -e "require('fs').writeFileSync('ran-predependencies', '')"`,
+ dependencies: `node -e "require('fs').writeFileSync('ran-dependencies', '')"`,
+ postdependencies: `node -e "require('fs').writeFileSync('ran-postdependencies', '')"`,
+ },
+ }),
+ })
+
+ await reify(path)
+
+ for (const script of ['predependencies', 'dependencies', 'postdependencies']) {
+ const expectedPath = join(path, `ran-${script}`)
+ t.ok(fs.existsSync(expectedPath), `ran ${script}`)
+ // delete the files after we assert they exist
+ fs.unlinkSync(expectedPath)
+ }
+
+ // reify again without changing dependencies
+ await reify(path)
+
+ for (const script of ['predependencies', 'dependencies', 'postdependencies']) {
+ const expectedPath = join(path, `ran-${script}`)
+ // and this time we assert that they do _not_ exist
+ t.not(fs.existsSync(expectedPath), `did not run ${script}`)
+ }
+
+ // take over console.log as run-script is going to print a banner for these because
+ // they're running in the foreground
+ const _log = console.log
+ t.teardown(() => {
+ console.log = _log
+ })
+ const logs = []
+ console.log = (msg) => logs.push(msg)
+ // reify again, this time adding a new dependency
+ await reify(path, { foregroundScripts: true, add: ['once@^1.4.0'] })
+ console.log = _log
+
+ t.match(logs, [/predependencies/, /dependencies/, /postdependencies/], 'logged banners')
+
+ // files should exist again
+ for (const script of ['predependencies', 'dependencies', 'postdependencies']) {
+ const expectedPath = join(path, `ran-${script}`)
+ t.ok(fs.existsSync(expectedPath), `ran ${script}`)
+ fs.unlinkSync(expectedPath)
+ }
+})
+
t.test('save package.json on update', t => {
t.test('should save many deps in multiple package.json when using save=true', async t => {
const path = fixture(t, 'workspaces-need-update')