mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #4180 from node-red/4168-make-module-install-synchronous
Ensure external modules are installed synchronously
This commit is contained in:
commit
b904c23e4d
@ -242,63 +242,68 @@ async function ensureModuleDir() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let installLock = Promise.resolve()
|
||||||
async function installModule(moduleDetails) {
|
async function installModule(moduleDetails) {
|
||||||
let installSpec = moduleDetails.module;
|
const result = installLock.then(async () => {
|
||||||
if (!registryUtil.checkModuleAllowed( moduleDetails.module, moduleDetails.version,installAllowList,installDenyList)) {
|
let installSpec = moduleDetails.module;
|
||||||
const e = new Error("Install not allowed");
|
if (!registryUtil.checkModuleAllowed( moduleDetails.module, moduleDetails.version,installAllowList,installDenyList)) {
|
||||||
e.code = "install_not_allowed";
|
const e = new Error("Install not allowed");
|
||||||
throw e;
|
e.code = "install_not_allowed";
|
||||||
}
|
|
||||||
if (moduleDetails.version) {
|
|
||||||
installSpec = installSpec+"@"+moduleDetails.version;
|
|
||||||
}
|
|
||||||
log.info(log._("server.install.installing",{name: moduleDetails.module,version: moduleDetails.version||"latest"}));
|
|
||||||
const installDir = getInstallDir();
|
|
||||||
|
|
||||||
await ensureModuleDir();
|
|
||||||
|
|
||||||
let triggerPayload = {
|
|
||||||
"module": moduleDetails.module,
|
|
||||||
"version": moduleDetails.version,
|
|
||||||
"dir": installDir,
|
|
||||||
"args": ["--production","--engine-strict"]
|
|
||||||
}
|
|
||||||
return hooks.trigger("preInstall", triggerPayload).then((result) => {
|
|
||||||
// preInstall passed
|
|
||||||
// - run install
|
|
||||||
if (result !== false) {
|
|
||||||
let extraArgs = triggerPayload.args || [];
|
|
||||||
let args = ['install', ...extraArgs, installSpec]
|
|
||||||
log.trace(NPM_COMMAND + JSON.stringify(args));
|
|
||||||
return exec.run(NPM_COMMAND, args, { cwd: installDir },true)
|
|
||||||
} else {
|
|
||||||
log.trace("skipping npm install");
|
|
||||||
}
|
|
||||||
}).then(() => {
|
|
||||||
return hooks.trigger("postInstall", triggerPayload)
|
|
||||||
}).then(() => {
|
|
||||||
log.info(log._("server.install.installed", { name: installSpec }));
|
|
||||||
const runtimeInstalledModules = settings.get("modules") || {};
|
|
||||||
runtimeInstalledModules[moduleDetails.module] = moduleDetails;
|
|
||||||
settings.set("modules",runtimeInstalledModules)
|
|
||||||
}).catch(result => {
|
|
||||||
var output = result.stderr || result.toString();
|
|
||||||
var e;
|
|
||||||
if (/E404/.test(output) || /ETARGET/.test(output)) {
|
|
||||||
log.error(log._("server.install.install-failed-not-found",{name:installSpec}));
|
|
||||||
e = new Error("Module not found");
|
|
||||||
e.code = 404;
|
|
||||||
throw e;
|
|
||||||
} else {
|
|
||||||
log.error(log._("server.install.install-failed-long",{name:installSpec}));
|
|
||||||
log.error("------------------------------------------");
|
|
||||||
log.error(output);
|
|
||||||
log.error("------------------------------------------");
|
|
||||||
e = new Error(log._("server.install.install-failed"));
|
|
||||||
e.code = "unexpected_error";
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
if (moduleDetails.version) {
|
||||||
|
installSpec = installSpec+"@"+moduleDetails.version;
|
||||||
|
}
|
||||||
|
log.info(log._("server.install.installing",{name: moduleDetails.module,version: moduleDetails.version||"latest"}));
|
||||||
|
const installDir = getInstallDir();
|
||||||
|
|
||||||
|
await ensureModuleDir();
|
||||||
|
|
||||||
|
let triggerPayload = {
|
||||||
|
"module": moduleDetails.module,
|
||||||
|
"version": moduleDetails.version,
|
||||||
|
"dir": installDir,
|
||||||
|
"args": ["--production","--engine-strict"]
|
||||||
|
}
|
||||||
|
return hooks.trigger("preInstall", triggerPayload).then((result) => {
|
||||||
|
// preInstall passed
|
||||||
|
// - run install
|
||||||
|
if (result !== false) {
|
||||||
|
let extraArgs = triggerPayload.args || [];
|
||||||
|
let args = ['install', ...extraArgs, installSpec]
|
||||||
|
log.trace(NPM_COMMAND + JSON.stringify(args));
|
||||||
|
return exec.run(NPM_COMMAND, args, { cwd: installDir },true)
|
||||||
|
} else {
|
||||||
|
log.trace("skipping npm install");
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
return hooks.trigger("postInstall", triggerPayload)
|
||||||
|
}).then(() => {
|
||||||
|
log.info(log._("server.install.installed", { name: installSpec }));
|
||||||
|
const runtimeInstalledModules = settings.get("modules") || {};
|
||||||
|
runtimeInstalledModules[moduleDetails.module] = moduleDetails;
|
||||||
|
settings.set("modules",runtimeInstalledModules)
|
||||||
|
}).catch(result => {
|
||||||
|
var output = result.stderr || result.toString();
|
||||||
|
var e;
|
||||||
|
if (/E404/.test(output) || /ETARGET/.test(output)) {
|
||||||
|
log.error(log._("server.install.install-failed-not-found",{name:installSpec}));
|
||||||
|
e = new Error("Module not found");
|
||||||
|
e.code = 404;
|
||||||
|
throw e;
|
||||||
|
} else {
|
||||||
|
log.error(log._("server.install.install-failed-long",{name:installSpec}));
|
||||||
|
log.error("------------------------------------------");
|
||||||
|
log.error(output);
|
||||||
|
log.error("------------------------------------------");
|
||||||
|
e = new Error(log._("server.install.install-failed"));
|
||||||
|
e.code = "unexpected_error";
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
installLock = result.catch(() => {})
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
Loading…
Reference in New Issue
Block a user