From c8d00d2c2527128bc7b75674c6930095d1821a0e Mon Sep 17 00:00:00 2001 From: ylemkimon Date: Sat, 23 Oct 2021 16:41:36 +0900 Subject: [PATCH] feat(reify): add an ability to add a hook --- README.md | 6 ++++++ lib/arborist/reify.js | 7 +++++++ tap-snapshots/test/arborist/reify.js.test.cjs | 10 ++++++++++ test/arborist/reify.js | 13 +++++++++++++ 4 files changed, 36 insertions(+) diff --git a/README.md b/README.md index cda5f8b90..4ef9af5cb 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,12 @@ arb.reify({ // write the lockfile(s) back to disk, and package.json with any updates // defaults to 'true' save: true, + + // experimental hooks + hooks: { + // hook that runs after building the idealTree but before saving it + [Symbol.for('beforeReify')]: Arborist => ... + } }).then(() => { // node modules has been written to match the idealTree }) diff --git a/lib/arborist/reify.js b/lib/arborist/reify.js index 658ece7a9..c1688a0d1 100644 --- a/lib/arborist/reify.js +++ b/lib/arborist/reify.js @@ -99,6 +99,9 @@ const _resolvedAdd = Symbol.for('resolvedAdd') const _usePackageLock = Symbol.for('usePackageLock') const _formatPackageLock = Symbol.for('formatPackageLock') +// hooks +const _beforeReify = Symbol.for('beforeReify') + module.exports = cls => class Reifier extends cls { constructor (options) { super(options) @@ -148,6 +151,10 @@ module.exports = cls => class Reifier extends cls { await this[_validatePath]() await this[_loadTrees](options) await this[_diffTrees]() + if (options.hooks + && typeof options.hooks[_beforeReify] === 'function') { + options.hooks[_beforeReify](this) + } await this[_reifyPackages]() await this[_saveIdealTree](options) await this[_copyIdealToActual]() diff --git a/tap-snapshots/test/arborist/reify.js.test.cjs b/tap-snapshots/test/arborist/reify.js.test.cjs index d784549c7..50305c8f2 100644 --- a/tap-snapshots/test/arborist/reify.js.test.cjs +++ b/tap-snapshots/test/arborist/reify.js.test.cjs @@ -32315,6 +32315,16 @@ ArboristNode { } ` +exports[`test/arborist/reify.js TAP run hooks > must match snapshot 1`] = ` +ArboristNode { + "isProjectRoot": true, + "location": "", + "name": "tap-testdir-reify-run-hooks", + "packageName": "hook-test-modified", + "path": "{CWD}/test/arborist/tap-testdir-reify-run-hooks", +} +` + exports[`test/arborist/reify.js TAP running lifecycle scripts of unchanged link nodes on reify > result 1`] = ` ArboristNode { "children": Map { diff --git a/test/arborist/reify.js b/test/arborist/reify.js index fc1aa7af5..ec561af62 100644 --- a/test/arborist/reify.js +++ b/test/arborist/reify.js @@ -2397,3 +2397,16 @@ t.test('no workspace', async t => { t.equal(tree.inventory.query('name', 'abbrev').size, 0) t.equal(tree.inventory.query('name', 'once').size, 1) }) + +t.test('run hooks', async t => { + const path = t.testdir({ + 'package.json': JSON.stringify({ + name: 'hook-test', + }), + }) + const tree = await reify(path, { hooks: { + [Symbol.for('beforeReify')]: (arborist) => { + arborist.idealTree.package.name = 'hook-test-modified' + } } }) + t.matchSnapshot(printTree(tree)) +})