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) {
|
||||
let installSpec = moduleDetails.module;
|
||||
if (!registryUtil.checkModuleAllowed( moduleDetails.module, moduleDetails.version,installAllowList,installDenyList)) {
|
||||
const e = new Error("Install not allowed");
|
||||
e.code = "install_not_allowed";
|
||||
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";
|
||||
const result = installLock.then(async () => {
|
||||
let installSpec = moduleDetails.module;
|
||||
if (!registryUtil.checkModuleAllowed( moduleDetails.module, moduleDetails.version,installAllowList,installDenyList)) {
|
||||
const e = new Error("Install not allowed");
|
||||
e.code = "install_not_allowed";
|
||||
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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user