Allow npm install args to be customised by preInstall trigger

This commit is contained in:
Nick O'Leary 2021-04-20 22:55:06 +01:00
parent b4a03a56b4
commit 250005ad16
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
4 changed files with 15 additions and 8 deletions

View File

@ -190,16 +190,18 @@ async function installModule(moduleDetails) {
await ensureModuleDir(); await ensureModuleDir();
var args = ["install", installSpec, "--production"];
let triggerPayload = { let triggerPayload = {
"module": moduleDetails.module, "module": moduleDetails.module,
"version": moduleDetails.version, "version": moduleDetails.version,
"dir": installDir, "dir": installDir,
"args": ["--production"]
} }
return hooks.trigger("preInstall", triggerPayload).then((result) => { return hooks.trigger("preInstall", triggerPayload).then((result) => {
// preInstall passed // preInstall passed
// - run install // - run install
if (result !== false) { if (result !== false) {
let extraArgs = triggerPayload.args || [];
let args = ['install', ...extraArgs, installSpec]
log.trace(NPM_COMMAND + JSON.stringify(args)); log.trace(NPM_COMMAND + JSON.stringify(args));
return exec.run(NPM_COMMAND, args, { cwd: installDir },true) return exec.run(NPM_COMMAND, args, { cwd: installDir },true)
} else { } else {

View File

@ -168,20 +168,22 @@ async function installModule(module,version,url) {
} }
var installDir = settings.userDir || process.env.NODE_RED_HOME || "."; var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
var args = ['install','--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--production',installName];
let triggerPayload = { let triggerPayload = {
"module": module, "module": module,
"version": version, "version": version,
"url": url, "url": url,
"dir": installDir, "dir": installDir,
"isExisting": isExisting, "isExisting": isExisting,
"isUpgrade": isUpgrade "isUpgrade": isUpgrade,
"args": ['--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--production']
} }
return hooks.trigger("preInstall", triggerPayload).then((result) => { return hooks.trigger("preInstall", triggerPayload).then((result) => {
// preInstall passed // preInstall passed
// - run install // - run install
if (result !== false) { if (result !== false) {
let extraArgs = triggerPayload.args || [];
let args = ['install', ...extraArgs, installName]
log.trace(npmCommand + JSON.stringify(args)); log.trace(npmCommand + JSON.stringify(args));
return exec.run(npmCommand,args,{ cwd: installDir}, true) return exec.run(npmCommand,args,{ cwd: installDir}, true)
} else { } else {

View File

@ -48,13 +48,13 @@ describe("externalModules api", function() {
beforeEach(function() { beforeEach(function() {
sinon.stub(exec,"run").callsFake(async function(cmd, args, options) { sinon.stub(exec,"run").callsFake(async function(cmd, args, options) {
let error; let error;
if (args[1] === "moduleNotFound") { if (args[2] === "moduleNotFound") {
error = new Error(); error = new Error();
error.stderr = "E404"; error.stderr = "E404";
} else if (args[1] === "moduleVersionNotFound") { } else if (args[2] === "moduleVersionNotFound") {
error = new Error(); error = new Error();
error.stderr = "ETARGET"; error.stderr = "ETARGET";
} else if (args[1] === "moduleFail") { } else if (args[2] === "moduleFail") {
error = new Error(); error = new Error();
error.stderr = "Some unexpected install error"; error.stderr = "Some unexpected install error";
} }
@ -109,13 +109,14 @@ describe("externalModules api", function() {
externalModules.init({userDir: homeDir}); externalModules.init({userDir: homeDir});
externalModules.register("function", "libs"); externalModules.register("function", "libs");
let receivedPreEvent,receivedPostEvent; let receivedPreEvent,receivedPostEvent;
hooks.add("preInstall", function(event) { receivedPreEvent = event; }) hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
hooks.add("postInstall", function(event) { receivedPostEvent = event; }) hooks.add("postInstall", function(event) { receivedPostEvent = event; })
await externalModules.checkFlowDependencies([ await externalModules.checkFlowDependencies([
{type: "function", libs:[{module: "foo"}]} {type: "function", libs:[{module: "foo"}]}
]) ])
exec.run.called.should.be.true(); exec.run.called.should.be.true();
// exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'foo' ]);
receivedPreEvent.should.have.property("module","foo") receivedPreEvent.should.have.property("module","foo")
receivedPreEvent.should.have.property("version") receivedPreEvent.should.have.property("version")
receivedPreEvent.should.have.property("dir") receivedPreEvent.should.have.property("dir")

View File

@ -254,7 +254,7 @@ describe('nodes/registry/installer', function() {
it("triggers preInstall and postInstall hooks", function(done) { it("triggers preInstall and postInstall hooks", function(done) {
let receivedPreEvent,receivedPostEvent; let receivedPreEvent,receivedPostEvent;
hooks.add("preInstall", function(event) { receivedPreEvent = event; }) hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
hooks.add("postInstall", function(event) { receivedPostEvent = event; }) hooks.add("postInstall", function(event) { receivedPostEvent = event; })
var nodeInfo = {nodes:{module:"foo",types:["a"]}}; var nodeInfo = {nodes:{module:"foo",types:["a"]}};
var res = {code: 0,stdout:"",stderr:""} var res = {code: 0,stdout:"",stderr:""}
@ -267,6 +267,8 @@ describe('nodes/registry/installer', function() {
}); });
installer.installModule("this_wont_exist","1.2.3").then(function(info) { installer.installModule("this_wont_exist","1.2.3").then(function(info) {
exec.run.called.should.be.true();
exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'this_wont_exist@1.2.3' ]);
info.should.eql(nodeInfo); info.should.eql(nodeInfo);
should.exist(receivedPreEvent) should.exist(receivedPreEvent)
receivedPreEvent.should.have.property("module","this_wont_exist") receivedPreEvent.should.have.property("module","this_wont_exist")