mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add event log to editor
Shows output from git pull/push and npm install in the editor
This commit is contained in:
parent
2816b3edae
commit
b2516117f5
@ -156,6 +156,7 @@ module.exports = function(grunt) {
|
|||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editor.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/editor.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
|
||||||
|
"packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tray.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/tray.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js",
|
||||||
"packages/node_modules/@node-red/editor-client/src/js/ui/library.js",
|
"packages/node_modules/@node-red/editor-client/src/js/ui/library.js",
|
||||||
|
@ -215,6 +215,10 @@
|
|||||||
"plusNMore": "+ __count__ more"
|
"plusNMore": "+ __count__ more"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eventLog": {
|
||||||
|
"title": "Event log",
|
||||||
|
"view": "View log"
|
||||||
|
},
|
||||||
"diff": {
|
"diff": {
|
||||||
"unresolvedCount": "__count__ unresolved conflict",
|
"unresolvedCount": "__count__ unresolved conflict",
|
||||||
"unresolvedCount_plural": "__count__ unresolved conflicts",
|
"unresolvedCount_plural": "__count__ unresolved conflicts",
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
"ctrl-alt-r": "core:show-remote-diff",
|
"ctrl-alt-r": "core:show-remote-diff",
|
||||||
"ctrl-alt-n": "core:new-project",
|
"ctrl-alt-n": "core:new-project",
|
||||||
"ctrl-alt-o": "core:open-project",
|
"ctrl-alt-o": "core:open-project",
|
||||||
"ctrl-g v": "core:show-version-control-tab"
|
"ctrl-g v": "core:show-version-control-tab",
|
||||||
|
"ctrl-shift-l": "core:show-event-log"
|
||||||
},
|
},
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"backspace": "core:delete-selection",
|
"backspace": "core:delete-selection",
|
||||||
|
@ -398,6 +398,10 @@ var RED = (function() {
|
|||||||
// Refresh flow library to ensure any examples are updated
|
// Refresh flow library to ensure any examples are updated
|
||||||
RED.library.loadFlowLibrary();
|
RED.library.loadFlowLibrary();
|
||||||
});
|
});
|
||||||
|
RED.comms.subscribe("event-log/#", function(topic,payload) {
|
||||||
|
var id = topic.substring(9);
|
||||||
|
RED.eventLog.log(id,payload);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAbout() {
|
function showAbout() {
|
||||||
@ -436,6 +440,7 @@ var RED = (function() {
|
|||||||
// null,
|
// null,
|
||||||
{id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true},
|
{id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true},
|
||||||
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
|
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
|
||||||
|
{id:"menu-item-event-log",label:RED._("eventLog.title"),onselect:"core:show-event-log"},
|
||||||
null
|
null
|
||||||
]});
|
]});
|
||||||
menuOptions.push(null);
|
menuOptions.push(null);
|
||||||
@ -483,6 +488,7 @@ var RED = (function() {
|
|||||||
RED.library.init();
|
RED.library.init();
|
||||||
RED.keyboard.init();
|
RED.keyboard.init();
|
||||||
RED.palette.init();
|
RED.palette.init();
|
||||||
|
RED.eventLog.init();
|
||||||
if (RED.settings.theme('palette.editable') !== false) {
|
if (RED.settings.theme('palette.editable') !== false) {
|
||||||
RED.palette.editor.init();
|
RED.palette.editor.init();
|
||||||
} else {
|
} else {
|
||||||
|
121
packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js
vendored
Normal file
121
packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js
vendored
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
RED.eventLog = (function() {
|
||||||
|
|
||||||
|
var template = '<script type="text/x-red" data-template-name="_eventLog"><div class="form-row node-text-editor-row"><div style="height: 100%;min-height: 150px;" class="node-text-editor" id="event-log-editor"></div></div></script>';
|
||||||
|
|
||||||
|
var eventLogEditor;
|
||||||
|
var backlog = [];
|
||||||
|
var shown = false;
|
||||||
|
|
||||||
|
function appendLogLine(line) {
|
||||||
|
backlog.push(line);
|
||||||
|
if (backlog.length > 500) {
|
||||||
|
backlog = backlog.slice(-500);
|
||||||
|
}
|
||||||
|
if (eventLogEditor) {
|
||||||
|
eventLogEditor.getSession().insert({
|
||||||
|
row: eventLogEditor.getSession().getLength(),
|
||||||
|
column: 0
|
||||||
|
}, "\n" + line);
|
||||||
|
eventLogEditor.scrollToLine(eventLogEditor.getSession().getLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
init: function() {
|
||||||
|
$(template).appendTo(document.body);
|
||||||
|
RED.actions.add("core:show-event-log",RED.eventLog.show);
|
||||||
|
},
|
||||||
|
show: function() {
|
||||||
|
if (shown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
shown = true;
|
||||||
|
var type = "_eventLog"
|
||||||
|
|
||||||
|
var trayOptions = {
|
||||||
|
title: RED._("eventLog.title"),
|
||||||
|
width: Infinity,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
id: "node-dialog-close",
|
||||||
|
text: RED._("common.label.close"),
|
||||||
|
click: function() {
|
||||||
|
RED.tray.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
resize: function(dimensions) {
|
||||||
|
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||||
|
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||||
|
var height = $("#dialog-form").height();
|
||||||
|
for (var i=0;i<rows.size();i++) {
|
||||||
|
height -= $(rows[i]).outerHeight(true);
|
||||||
|
}
|
||||||
|
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||||
|
$(".node-text-editor").css("height",height+"px");
|
||||||
|
eventLogEditor.resize();
|
||||||
|
},
|
||||||
|
open: function(tray) {
|
||||||
|
var trayBody = tray.find('.editor-tray-body');
|
||||||
|
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||||
|
eventLogEditor = RED.editor.createEditor({
|
||||||
|
id: 'event-log-editor',
|
||||||
|
value: backlog.join("\n"),
|
||||||
|
lineNumbers: false,
|
||||||
|
readOnly: true,
|
||||||
|
options: {
|
||||||
|
showPrintMargin: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTimeout(function() {
|
||||||
|
eventLogEditor.scrollToLine(eventLogEditor.getSession().getLength());
|
||||||
|
},200);
|
||||||
|
dialogForm.i18n();
|
||||||
|
},
|
||||||
|
close: function() {
|
||||||
|
eventLogEditor.destroy();
|
||||||
|
eventLogEditor = null;
|
||||||
|
shown = false;
|
||||||
|
},
|
||||||
|
show: function() {}
|
||||||
|
}
|
||||||
|
RED.tray.show(trayOptions);
|
||||||
|
},
|
||||||
|
log: function(id,payload) {
|
||||||
|
var ts = (new Date(payload.ts)).toISOString()+" ";
|
||||||
|
if (payload.type) {
|
||||||
|
ts += "["+payload.type+"] "
|
||||||
|
}
|
||||||
|
if (payload.data) {
|
||||||
|
var data = payload.data;
|
||||||
|
if (data.endsWith('\n')) {
|
||||||
|
data = data.substring(0,data.length-1);
|
||||||
|
}
|
||||||
|
var lines = data.split(/\n/);
|
||||||
|
lines.forEach(function(line) {
|
||||||
|
appendLogLine(ts+line);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
startEvent: function(name) {
|
||||||
|
backlog.push("");
|
||||||
|
backlog.push("-----------------------------------------------------------");
|
||||||
|
backlog.push((new Date()).toISOString()+" "+name);
|
||||||
|
backlog.push("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
@ -863,11 +863,35 @@ RED.palette.editor = (function() {
|
|||||||
class: "primary palette-module-install-confirm-button-update",
|
class: "primary palette-module-install-confirm-button-update",
|
||||||
click: function() {
|
click: function() {
|
||||||
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
||||||
|
var buttonRow = $('<div style="position: relative;bottom: calc(50% + 17px); padding-right: 10px;text-align: right;"></div>').appendTo(spinner);
|
||||||
|
$('<button class="editor-button"></button>').text(RED._("eventLog.view")).appendTo(buttonRow).click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
RED.actions.invoke("core:show-event-log");
|
||||||
|
});
|
||||||
|
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install")+" : "+entry.name+" "+version);
|
||||||
installNodeModule(entry.name,version,function(xhr) {
|
installNodeModule(entry.name,version,function(xhr) {
|
||||||
spinner.remove();
|
spinner.remove();
|
||||||
if (xhr) {
|
if (xhr) {
|
||||||
if (xhr.responseJSON) {
|
if (xhr.responseJSON) {
|
||||||
RED.notify(RED._('palette.editor.errors.updateFailed',{module: entry.name,message:xhr.responseJSON.message}));
|
var notification = RED.notify(RED._('palette.editor.errors.updateFailed',{module: entry.name,message:xhr.responseJSON.message}),{
|
||||||
|
type: 'error',
|
||||||
|
modal: true,
|
||||||
|
fixed: true,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: RED._("common.label.close"),
|
||||||
|
click: function() {
|
||||||
|
notification.close();
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
text: RED._("eventLog.view"),
|
||||||
|
click: function() {
|
||||||
|
notification.close();
|
||||||
|
RED.actions.invoke("core:show-event-log");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done(xhr);
|
done(xhr);
|
||||||
@ -898,12 +922,35 @@ RED.palette.editor = (function() {
|
|||||||
class: "primary palette-module-install-confirm-button-remove",
|
class: "primary palette-module-install-confirm-button-remove",
|
||||||
click: function() {
|
click: function() {
|
||||||
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
||||||
|
var buttonRow = $('<div style="position: relative;bottom: calc(50% + 17px); padding-right: 10px;text-align: right;"></div>').appendTo(spinner);
|
||||||
|
$('<button class="editor-button"></button>').text(RED._("eventLog.view")).appendTo(buttonRow).click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
RED.actions.invoke("core:show-event-log");
|
||||||
|
});
|
||||||
|
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.remove")+" : "+entry.name);
|
||||||
removeNodeModule(entry.name, function(xhr) {
|
removeNodeModule(entry.name, function(xhr) {
|
||||||
spinner.remove();
|
spinner.remove();
|
||||||
if (xhr) {
|
if (xhr) {
|
||||||
if (xhr.responseJSON) {
|
if (xhr.responseJSON) {
|
||||||
RED.notify(RED._('palette.editor.errors.removeFailed',{module: entry.name,message:xhr.responseJSON.message}));
|
var notification = RED.notify(RED._('palette.editor.errors.removeFailed',{module: entry.name,message:xhr.responseJSON.message}),{
|
||||||
}
|
type: 'error',
|
||||||
|
modal: true,
|
||||||
|
fixed: true,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: RED._("common.label.close"),
|
||||||
|
click: function() {
|
||||||
|
notification.close();
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
text: RED._("eventLog.view"),
|
||||||
|
click: function() {
|
||||||
|
notification.close();
|
||||||
|
RED.actions.invoke("core:show-event-log");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}); }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
notification.close();
|
notification.close();
|
||||||
@ -940,11 +987,36 @@ RED.palette.editor = (function() {
|
|||||||
class: "primary palette-module-install-confirm-button-install",
|
class: "primary palette-module-install-confirm-button-install",
|
||||||
click: function() {
|
click: function() {
|
||||||
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
||||||
|
|
||||||
|
var buttonRow = $('<div style="position: relative;bottom: calc(50% + 17px); padding-right: 10px;text-align: right;"></div>').appendTo(spinner);
|
||||||
|
$('<button class="editor-button"></button>').text(RED._("eventLog.view")).appendTo(buttonRow).click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
RED.actions.invoke("core:show-event-log");
|
||||||
|
});
|
||||||
|
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install")+" : "+entry.id+" "+entry.version);
|
||||||
installNodeModule(entry.id,entry.version,function(xhr) {
|
installNodeModule(entry.id,entry.version,function(xhr) {
|
||||||
spinner.remove();
|
spinner.remove();
|
||||||
if (xhr) {
|
if (xhr) {
|
||||||
if (xhr.responseJSON) {
|
if (xhr.responseJSON) {
|
||||||
RED.notify(RED._('palette.editor.errors.installFailed',{module: entry.id,message:xhr.responseJSON.message}));
|
var notification = RED.notify(RED._('palette.editor.errors.installFailed',{module: entry.id,message:xhr.responseJSON.message}),{
|
||||||
|
type: 'error',
|
||||||
|
modal: true,
|
||||||
|
fixed: true,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: RED._("common.label.close"),
|
||||||
|
click: function() {
|
||||||
|
notification.close();
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
text: RED._("eventLog.view"),
|
||||||
|
click: function() {
|
||||||
|
notification.close();
|
||||||
|
RED.actions.invoke("core:show-event-log");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done(xhr);
|
done(xhr);
|
||||||
|
@ -870,7 +870,13 @@ RED.sidebar.versionControl = (function() {
|
|||||||
.click(function(e) {
|
.click(function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain");
|
var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain");
|
||||||
|
var buttonRow = $('<div style="position: relative; bottom: 60px;"></div>').appendTo(spinner);
|
||||||
|
$('<button class="editor-button"></button>').text(RED._("eventLog.view")).appendTo(buttonRow).click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
RED.actions.invoke("core:show-event-log");
|
||||||
|
});
|
||||||
var activeProject = RED.projects.getActiveProject();
|
var activeProject = RED.projects.getActiveProject();
|
||||||
|
RED.eventLog.startEvent("Push changes"+(activeProject.git.branches.remoteAlt?(" : "+activeProject.git.branches.remoteAlt):""));
|
||||||
var url = "projects/"+activeProject.name+"/push";
|
var url = "projects/"+activeProject.name+"/push";
|
||||||
if (activeProject.git.branches.remoteAlt) {
|
if (activeProject.git.branches.remoteAlt) {
|
||||||
url+="/"+activeProject.git.branches.remoteAlt;
|
url+="/"+activeProject.git.branches.remoteAlt;
|
||||||
@ -914,7 +920,13 @@ RED.sidebar.versionControl = (function() {
|
|||||||
var pullRemote = function(options) {
|
var pullRemote = function(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain");
|
var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain");
|
||||||
|
var buttonRow = $('<div style="position: relative; bottom: 60px;"></div>').appendTo(spinner);
|
||||||
|
$('<button class="editor-button"></button>').text(RED._("eventLog.view")).appendTo(buttonRow).click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
RED.actions.invoke("core:show-event-log");
|
||||||
|
});
|
||||||
var activeProject = RED.projects.getActiveProject();
|
var activeProject = RED.projects.getActiveProject();
|
||||||
|
RED.eventLog.startEvent("Pull changes"+(activeProject.git.branches.remoteAlt?(" : "+activeProject.git.branches.remoteAlt):""));
|
||||||
var url = "projects/"+activeProject.name+"/pull";
|
var url = "projects/"+activeProject.name+"/pull";
|
||||||
if (activeProject.git.branches.remoteAlt) {
|
if (activeProject.git.branches.remoteAlt) {
|
||||||
url+="/"+activeProject.git.branches.remoteAlt;
|
url+="/"+activeProject.git.branches.remoteAlt;
|
||||||
|
@ -6,3 +6,16 @@
|
|||||||
border-top-right-radius: 4px;
|
border-top-right-radius: 4px;
|
||||||
border-bottom-right-radius: 4px;
|
border-bottom-right-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#event-log-editor {
|
||||||
|
.ace_scroller {
|
||||||
|
background: #444;
|
||||||
|
color: #dd9;
|
||||||
|
}
|
||||||
|
.ace_active-line {
|
||||||
|
background: #666 !important;
|
||||||
|
}
|
||||||
|
.ace_selection {
|
||||||
|
background: #999 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ var fs = require("fs");
|
|||||||
var registry = require("./registry");
|
var registry = require("./registry");
|
||||||
var library = require("./library");
|
var library = require("./library");
|
||||||
var log;
|
var log;
|
||||||
|
var exec;
|
||||||
|
|
||||||
var events;
|
var events;
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ function init(runtime) {
|
|||||||
events = runtime.events;
|
events = runtime.events;
|
||||||
settings = runtime.settings;
|
settings = runtime.settings;
|
||||||
log = runtime.log;
|
log = runtime.log;
|
||||||
|
exec = runtime.exec;
|
||||||
}
|
}
|
||||||
|
|
||||||
var activePromise = Promise.resolve();
|
var activePromise = Promise.resolve();
|
||||||
@ -104,50 +106,40 @@ function installModule(module,version) {
|
|||||||
var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
|
var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
|
||||||
var args = ['install','--save','--save-prefix="~"','--production',installName];
|
var args = ['install','--save','--save-prefix="~"','--production',installName];
|
||||||
log.trace(npmCommand + JSON.stringify(args));
|
log.trace(npmCommand + JSON.stringify(args));
|
||||||
var child = child_process.spawn(npmCommand,args,{
|
exec.run(npmCommand,args,{
|
||||||
cwd: installDir,
|
cwd: installDir
|
||||||
shell: true
|
}, true).then(result => {
|
||||||
});
|
if (!isUpgrade) {
|
||||||
var output = "";
|
log.info(log._("server.install.installed",{name:module}));
|
||||||
child.stdout.on('data', (data) => {
|
resolve(require("./index").addModule(module).then(reportAddedModules));
|
||||||
output += data;
|
|
||||||
});
|
|
||||||
child.stderr.on('data', (data) => {
|
|
||||||
output += data;
|
|
||||||
});
|
|
||||||
child.on('close', (code) => {
|
|
||||||
if (code !== 0) {
|
|
||||||
var e;
|
|
||||||
var lookFor404 = new RegExp(" 404 .*"+module,"m");
|
|
||||||
var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
|
|
||||||
if (lookFor404.test(output)) {
|
|
||||||
log.warn(log._("server.install.install-failed-not-found",{name:module}));
|
|
||||||
e = new Error("Module not found");
|
|
||||||
e.code = 404;
|
|
||||||
reject(e);
|
|
||||||
} else if (isUpgrade && lookForVersionNotFound.test(output)) {
|
|
||||||
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
|
|
||||||
e = new Error("Module not found");
|
|
||||||
e.code = 404;
|
|
||||||
reject(e);
|
|
||||||
} else {
|
|
||||||
log.warn(log._("server.install.install-failed-long",{name:module}));
|
|
||||||
log.warn("------------------------------------------");
|
|
||||||
log.warn(output);
|
|
||||||
log.warn("------------------------------------------");
|
|
||||||
reject(new Error(log._("server.install.install-failed")));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!isUpgrade) {
|
log.info(log._("server.install.upgraded",{name:module, version:version}));
|
||||||
log.info(log._("server.install.installed",{name:module}));
|
events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
|
||||||
resolve(require("./index").addModule(module).then(reportAddedModules));
|
resolve(require("./registry").setModulePendingUpdated(module,version));
|
||||||
} else {
|
|
||||||
log.info(log._("server.install.upgraded",{name:module, version:version}));
|
|
||||||
events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
|
|
||||||
resolve(require("./registry").setModulePendingUpdated(module,version));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}).catch(result => {
|
||||||
|
var output = result.stderr;
|
||||||
|
var e;
|
||||||
|
var lookFor404 = new RegExp(" 404 .*"+module,"m");
|
||||||
|
var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
|
||||||
|
if (lookFor404.test(output)) {
|
||||||
|
log.warn(log._("server.install.install-failed-not-found",{name:module}));
|
||||||
|
e = new Error("Module not found");
|
||||||
|
e.code = 404;
|
||||||
|
reject(e);
|
||||||
|
} else if (isUpgrade && lookForVersionNotFound.test(output)) {
|
||||||
|
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
|
||||||
|
e = new Error("Module not found");
|
||||||
|
e.code = 404;
|
||||||
|
reject(e);
|
||||||
|
} else {
|
||||||
|
log.warn(log._("server.install.install-failed-long",{name:module}));
|
||||||
|
log.warn("------------------------------------------");
|
||||||
|
log.warn(output);
|
||||||
|
log.warn("------------------------------------------");
|
||||||
|
reject(new Error(log._("server.install.install-failed")));
|
||||||
|
}
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
// In case of error, reset activePromise to be resolvable
|
// In case of error, reset activePromise to be resolvable
|
||||||
@ -208,25 +200,21 @@ function uninstallModule(module) {
|
|||||||
var args = ['remove','--save',module];
|
var args = ['remove','--save',module];
|
||||||
log.trace(npmCommand + JSON.stringify(args));
|
log.trace(npmCommand + JSON.stringify(args));
|
||||||
|
|
||||||
var child = child_process.execFile(npmCommand,args,
|
exec.run(npmCommand,args,{
|
||||||
{
|
cwd: installDir,
|
||||||
cwd: installDir
|
},true).then(result => {
|
||||||
},
|
log.info(log._("server.install.uninstalled",{name:module}));
|
||||||
function(err, stdin, stdout) {
|
reportRemovedModules(list);
|
||||||
if (err) {
|
library.removeExamplesDir(module);
|
||||||
log.warn(log._("server.install.uninstall-failed-long",{name:module}));
|
resolve(list);
|
||||||
log.warn("------------------------------------------");
|
}).catch(result => {
|
||||||
log.warn(err.toString());
|
var output = result.stderr;
|
||||||
log.warn("------------------------------------------");
|
log.warn(log._("server.install.uninstall-failed-long",{name:module}));
|
||||||
reject(new Error(log._("server.install.uninstall-failed",{name:module})));
|
log.warn("------------------------------------------");
|
||||||
} else {
|
log.warn(output.toString());
|
||||||
log.info(log._("server.install.uninstalled",{name:module}));
|
log.warn("------------------------------------------");
|
||||||
reportRemovedModules(list);
|
reject(new Error(log._("server.install.uninstall-failed",{name:module})));
|
||||||
library.removeExamplesDir(module);
|
});
|
||||||
resolve(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
// In case of error, reset activePromise to be resolvable
|
// In case of error, reset activePromise to be resolvable
|
||||||
|
@ -42,6 +42,21 @@ function handleRuntimeEvent(event) {
|
|||||||
runtime.log.trace("runtime event: "+JSON.stringify(event));
|
runtime.log.trace("runtime event: "+JSON.stringify(event));
|
||||||
publish("notification/"+event.id,event.payload||{},event.retain);
|
publish("notification/"+event.id,event.payload||{},event.retain);
|
||||||
}
|
}
|
||||||
|
function handleEventLog(event) {
|
||||||
|
var type = event.payload.type;
|
||||||
|
var id = event.id;
|
||||||
|
if (event.payload.data) {
|
||||||
|
var data = event.payload.data;
|
||||||
|
if (data.endsWith('\n')) {
|
||||||
|
data = data.substring(0,data.length-1);
|
||||||
|
}
|
||||||
|
var lines = data.split(/\n/);
|
||||||
|
lines.forEach(line => {
|
||||||
|
runtime.log.debug((type?("["+type+"] "):"")+line)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
publish("event-log/"+event.id,event.payload||{});
|
||||||
|
}
|
||||||
|
|
||||||
function publish(topic,data,retain) {
|
function publish(topic,data,retain) {
|
||||||
if (retain) {
|
if (retain) {
|
||||||
@ -64,6 +79,8 @@ var api = module.exports = {
|
|||||||
runtime.events.on("runtime-event",handleRuntimeEvent);
|
runtime.events.on("runtime-event",handleRuntimeEvent);
|
||||||
runtime.events.removeListener("comms",handleCommsEvent);
|
runtime.events.removeListener("comms",handleCommsEvent);
|
||||||
runtime.events.on("comms",handleCommsEvent);
|
runtime.events.on("comms",handleCommsEvent);
|
||||||
|
runtime.events.removeListener("event-log",handleEventLog);
|
||||||
|
runtime.events.on("event-log",handleEventLog);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
69
packages/node_modules/@node-red/runtime/lib/exec.js
vendored
Normal file
69
packages/node_modules/@node-red/runtime/lib/exec.js
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
const child_process = require('child_process');
|
||||||
|
const { util } = require('@node-red/util');
|
||||||
|
|
||||||
|
var events;
|
||||||
|
|
||||||
|
function logLines(id,type,data) {
|
||||||
|
events.emit("event-log", {id:id,payload:{ts: Date.now(),data:data,type:type}});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: function(_runtime) {
|
||||||
|
events = _runtime.events;
|
||||||
|
},
|
||||||
|
run: function(command,args,options,emit) {
|
||||||
|
var invocationId = util.generateId();
|
||||||
|
|
||||||
|
emit && events.emit("event-log", {ts: Date.now(),id:invocationId,payload:{ts: Date.now(),data:command+" "+args.join(" ")}});
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let stdout = "";
|
||||||
|
let stderr = "";
|
||||||
|
const child = child_process.spawn(command,args,options);
|
||||||
|
child.stdout.on('data', (data) => {
|
||||||
|
const str = ""+data;
|
||||||
|
stdout += str;
|
||||||
|
emit && logLines(invocationId,"out",str);
|
||||||
|
});
|
||||||
|
child.stderr.on('data', (data) => {
|
||||||
|
const str = ""+data;
|
||||||
|
stderr += str;
|
||||||
|
emit && logLines(invocationId,"err",str);
|
||||||
|
});
|
||||||
|
child.on('error', function(err) {
|
||||||
|
stderr = err.toString();
|
||||||
|
emit && logLines(invocationId,"err",stderr);
|
||||||
|
})
|
||||||
|
child.on('close', (code) => {
|
||||||
|
let result = {
|
||||||
|
code: code,
|
||||||
|
stdout: stdout,
|
||||||
|
stderr: stderr
|
||||||
|
}
|
||||||
|
emit && events.emit("event-log", {id:invocationId,payload:{ts: Date.now(),data:"rc="+code}});
|
||||||
|
|
||||||
|
if (code === 0) {
|
||||||
|
resolve(result)
|
||||||
|
} else {
|
||||||
|
reject(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ var storage = require("./storage");
|
|||||||
var library = require("./library");
|
var library = require("./library");
|
||||||
var events = require("./events");
|
var events = require("./events");
|
||||||
var settings = require("./settings");
|
var settings = require("./settings");
|
||||||
|
var exec = require("./exec");
|
||||||
|
|
||||||
var express = require("express");
|
var express = require("express");
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
@ -71,6 +72,7 @@ function init(userSettings,_redUtil,_adminApi) {
|
|||||||
redNodes.init(runtime);
|
redNodes.init(runtime);
|
||||||
library.init(runtime);
|
library.init(runtime);
|
||||||
externalAPI.init(runtime);
|
externalAPI.init(runtime);
|
||||||
|
exec.init(runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
var version;
|
var version;
|
||||||
@ -248,6 +250,7 @@ var runtime = {
|
|||||||
events: events,
|
events: events,
|
||||||
nodes: redNodes,
|
nodes: redNodes,
|
||||||
library: library,
|
library: library,
|
||||||
|
exec: exec,
|
||||||
util: require("@node-red/util").util,
|
util: require("@node-red/util").util,
|
||||||
get adminApi() { return adminApi },
|
get adminApi() { return adminApi },
|
||||||
get nodeApp() { return nodeApp },
|
get nodeApp() { return nodeApp },
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
var exec = require('child_process').exec;
|
|
||||||
var spawn = require('child_process').spawn;
|
var exec = require("../../../../exec");
|
||||||
|
|
||||||
var authResponseServer = require('./authServer').ResponseServer;
|
var authResponseServer = require('./authServer').ResponseServer;
|
||||||
var sshResponseServer = require('./authServer').ResponseSSHServer;
|
var sshResponseServer = require('./authServer').ResponseSSHServer;
|
||||||
var clone = require('clone');
|
var clone = require('clone');
|
||||||
@ -26,83 +27,70 @@ var gitCommand = "git";
|
|||||||
var gitVersion;
|
var gitVersion;
|
||||||
var log;
|
var log;
|
||||||
|
|
||||||
function runGitCommand(args,cwd,env) {
|
function runGitCommand(args,cwd,env,emit) {
|
||||||
log.trace(gitCommand + JSON.stringify(args));
|
log.trace(gitCommand + JSON.stringify(args));
|
||||||
return when.promise(function(resolve,reject) {
|
args.unshift("credential.helper=")
|
||||||
args.unshift("credential.helper=")
|
args.unshift("-c");
|
||||||
args.unshift("-c");
|
return exec.run(gitCommand, args, {cwd:cwd, env:env}, emit).then(result => {
|
||||||
var child = spawn(gitCommand, args, {cwd:cwd, detached:true, env:env});
|
return result.stdout;
|
||||||
var stdout = "";
|
}).catch(result => {
|
||||||
var stderr = "";
|
var err = new Error(stderr);
|
||||||
child.stdout.on('data', function(data) {
|
var stdout = result.stdout;
|
||||||
stdout += data;
|
var stderr = result.stderr;
|
||||||
});
|
err.stdout = stdout;
|
||||||
child.stderr.on('data', function(data) {
|
err.stderr = stderr;
|
||||||
stderr += data;
|
if (/Connection refused/i.test(stderr)) {
|
||||||
});
|
err.code = "git_connection_failed";
|
||||||
child.on('error', function(err) {
|
} else if (/Connection timed out/i.test(stderr)) {
|
||||||
stderr = err.toString();
|
err.code = "git_connection_failed";
|
||||||
})
|
} else if (/fatal: could not read/i.test(stderr)) {
|
||||||
child.on('close', function(code) {
|
// Username/Password
|
||||||
if (code !== 0) {
|
err.code = "git_auth_failed";
|
||||||
var err = new Error(stderr);
|
} else if(/HTTP Basic: Access denied/i.test(stderr)) {
|
||||||
err.stdout = stdout;
|
err.code = "git_auth_failed";
|
||||||
err.stderr = stderr;
|
} else if(/Permission denied \(publickey\)/i.test(stderr)) {
|
||||||
if (/Connection refused/i.test(stderr)) {
|
err.code = "git_auth_failed";
|
||||||
err.code = "git_connection_failed";
|
} else if(/Host key verification failed/i.test(stderr)) {
|
||||||
} else if (/Connection timed out/i.test(stderr)) {
|
// TODO: handle host key verification errors separately
|
||||||
err.code = "git_connection_failed";
|
err.code = "git_auth_failed";
|
||||||
} else if (/fatal: could not read/i.test(stderr)) {
|
} else if (/commit your changes or stash/i.test(stderr)) {
|
||||||
// Username/Password
|
err.code = "git_local_overwrite";
|
||||||
err.code = "git_auth_failed";
|
} else if (/CONFLICT/.test(err.stdout)) {
|
||||||
} else if(/HTTP Basic: Access denied/i.test(stderr)) {
|
err.code = "git_pull_merge_conflict";
|
||||||
err.code = "git_auth_failed";
|
} else if (/not fully merged/i.test(stderr)) {
|
||||||
} else if(/Permission denied \(publickey\)/i.test(stderr)) {
|
err.code = "git_delete_branch_unmerged";
|
||||||
err.code = "git_auth_failed";
|
} else if (/remote .* already exists/i.test(stderr)) {
|
||||||
} else if(/Host key verification failed/i.test(stderr)) {
|
err.code = "git_remote_already_exists";
|
||||||
// TODO: handle host key verification errors separately
|
} else if (/does not appear to be a git repository/i.test(stderr)) {
|
||||||
err.code = "git_auth_failed";
|
err.code = "git_not_a_repository";
|
||||||
} else if (/commit your changes or stash/i.test(stderr)) {
|
} else if (/Repository not found/i.test(stderr)) {
|
||||||
err.code = "git_local_overwrite";
|
err.code = "git_repository_not_found";
|
||||||
} else if (/CONFLICT/.test(err.stdout)) {
|
} else if (/repository '.*' does not exist/i.test(stderr)) {
|
||||||
err.code = "git_pull_merge_conflict";
|
err.code = "git_repository_not_found";
|
||||||
} else if (/not fully merged/i.test(stderr)) {
|
} else if (/refusing to merge unrelated histories/i.test(stderr)) {
|
||||||
err.code = "git_delete_branch_unmerged";
|
err.code = "git_pull_unrelated_history"
|
||||||
} else if (/remote .* already exists/i.test(stderr)) {
|
} else if (/Please tell me who you are/i.test(stderr)) {
|
||||||
err.code = "git_remote_already_exists";
|
err.code = "git_missing_user";
|
||||||
} else if (/does not appear to be a git repository/i.test(stderr)) {
|
} else if (/name consists only of disallowed characters/i.test(stderr)) {
|
||||||
err.code = "git_not_a_repository";
|
err.code = "git_missing_user";
|
||||||
} else if (/Repository not found/i.test(stderr)) {
|
}
|
||||||
err.code = "git_repository_not_found";
|
throw err;
|
||||||
} else if (/repository '.*' does not exist/i.test(stderr)) {
|
})
|
||||||
err.code = "git_repository_not_found";
|
|
||||||
} else if (/refusing to merge unrelated histories/i.test(stderr)) {
|
|
||||||
err.code = "git_pull_unrelated_history"
|
|
||||||
} else if (/Please tell me who you are/i.test(stderr)) {
|
|
||||||
err.code = "git_missing_user";
|
|
||||||
} else if (/name consists only of disallowed characters/i.test(stderr)) {
|
|
||||||
err.code = "git_missing_user";
|
|
||||||
}
|
|
||||||
return reject(err);
|
|
||||||
}
|
|
||||||
resolve(stdout);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
function runGitCommandWithAuth(args,cwd,auth) {
|
function runGitCommandWithAuth(args,cwd,auth,emit) {
|
||||||
return authResponseServer(auth).then(function(rs) {
|
return authResponseServer(auth).then(function(rs) {
|
||||||
var commandEnv = clone(process.env);
|
var commandEnv = clone(process.env);
|
||||||
commandEnv.GIT_ASKPASS = path.join(__dirname,"node-red-ask-pass.sh");
|
commandEnv.GIT_ASKPASS = path.join(__dirname,"node-red-ask-pass.sh");
|
||||||
commandEnv.NODE_RED_GIT_NODE_PATH = process.execPath;
|
commandEnv.NODE_RED_GIT_NODE_PATH = process.execPath;
|
||||||
commandEnv.NODE_RED_GIT_SOCK_PATH = rs.path;
|
commandEnv.NODE_RED_GIT_SOCK_PATH = rs.path;
|
||||||
commandEnv.NODE_RED_GIT_ASKPASS_PATH = path.join(__dirname,"authWriter.js");
|
commandEnv.NODE_RED_GIT_ASKPASS_PATH = path.join(__dirname,"authWriter.js");
|
||||||
return runGitCommand(args,cwd,commandEnv).finally(function() {
|
return runGitCommand(args,cwd,commandEnv,emit).finally(function() {
|
||||||
rs.close();
|
rs.close();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function runGitCommandWithSSHCommand(args,cwd,auth) {
|
function runGitCommandWithSSHCommand(args,cwd,auth,emit) {
|
||||||
return sshResponseServer(auth).then(function(rs) {
|
return sshResponseServer(auth).then(function(rs) {
|
||||||
var commandEnv = clone(process.env);
|
var commandEnv = clone(process.env);
|
||||||
commandEnv.SSH_ASKPASS = path.join(__dirname,"node-red-ask-pass.sh");
|
commandEnv.SSH_ASKPASS = path.join(__dirname,"node-red-ask-pass.sh");
|
||||||
@ -116,7 +104,7 @@ function runGitCommandWithSSHCommand(args,cwd,auth) {
|
|||||||
// GIT_SSH_COMMAND - added in git 2.3.0
|
// GIT_SSH_COMMAND - added in git 2.3.0
|
||||||
commandEnv.GIT_SSH_COMMAND = "ssh -i " + auth.key_path + " -F /dev/null";
|
commandEnv.GIT_SSH_COMMAND = "ssh -i " + auth.key_path + " -F /dev/null";
|
||||||
// console.log('commandEnv:', commandEnv);
|
// console.log('commandEnv:', commandEnv);
|
||||||
return runGitCommand(args,cwd,commandEnv).finally(function() {
|
return runGitCommand(args,cwd,commandEnv,emit).finally(function() {
|
||||||
rs.close();
|
rs.close();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@ -448,13 +436,13 @@ module.exports = {
|
|||||||
var promise;
|
var promise;
|
||||||
if (auth) {
|
if (auth) {
|
||||||
if ( auth.key_path ) {
|
if ( auth.key_path ) {
|
||||||
promise = runGitCommandWithSSHCommand(args,cwd,auth);
|
promise = runGitCommandWithSSHCommand(args,cwd,auth,true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
promise = runGitCommandWithAuth(args,cwd,auth);
|
promise = runGitCommandWithAuth(args,cwd,auth,true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
promise = runGitCommand(args,cwd)
|
promise = runGitCommand(args,cwd,undefined,true)
|
||||||
}
|
}
|
||||||
return promise;
|
return promise;
|
||||||
// .catch(function(err) {
|
// .catch(function(err) {
|
||||||
@ -485,13 +473,13 @@ module.exports = {
|
|||||||
var promise;
|
var promise;
|
||||||
if (auth) {
|
if (auth) {
|
||||||
if ( auth.key_path ) {
|
if ( auth.key_path ) {
|
||||||
promise = runGitCommandWithSSHCommand(args,cwd,auth);
|
promise = runGitCommandWithSSHCommand(args,cwd,auth,true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
promise = runGitCommandWithAuth(args,cwd,auth);
|
promise = runGitCommandWithAuth(args,cwd,auth,true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
promise = runGitCommand(args,cwd)
|
promise = runGitCommand(args,cwd,undefined,true)
|
||||||
}
|
}
|
||||||
return promise.catch(function(err) {
|
return promise.catch(function(err) {
|
||||||
if (err.code === 'git_error') {
|
if (err.code === 'git_error') {
|
||||||
@ -517,13 +505,13 @@ module.exports = {
|
|||||||
args.push(".");
|
args.push(".");
|
||||||
if (auth) {
|
if (auth) {
|
||||||
if ( auth.key_path ) {
|
if ( auth.key_path ) {
|
||||||
return runGitCommandWithSSHCommand(args,cwd,auth);
|
return runGitCommandWithSSHCommand(args,cwd,auth,true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return runGitCommandWithAuth(args,cwd,auth);
|
return runGitCommandWithAuth(args,cwd,auth,true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return runGitCommand(args,cwd);
|
return runGitCommand(args,cwd,undefined,true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getStatus: getStatus,
|
getStatus: getStatus,
|
||||||
|
@ -30,19 +30,22 @@ module.exports = {
|
|||||||
log.init(settings);
|
log.init(settings);
|
||||||
i18n.init();
|
i18n.init();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logging utilities
|
* Logging utilities
|
||||||
* @see module:@node-red/util.module:log
|
* @see module:@node-red/util.module:log
|
||||||
*/
|
*/
|
||||||
log: log,
|
log: log,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internationalization utilities
|
* Internationalization utilities
|
||||||
* @see module:@node-red/util.module:i18n
|
* @see module:@node-red/util.module:i18n
|
||||||
*/
|
*/
|
||||||
i18n: i18n,
|
i18n: i18n,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General utilities
|
* General utilities
|
||||||
* @see module:@node-red/util.module:util
|
* @see module:@node-red/util.module:util
|
||||||
*/
|
*/
|
||||||
util: util
|
util: util,
|
||||||
}
|
}
|
||||||
|
13
packages/node_modules/node-red/lib/red.js
vendored
13
packages/node_modules/node-red/lib/red.js
vendored
@ -38,18 +38,6 @@ function checkVersion(userSettings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkBuild() {
|
|
||||||
console.log("Skipping red.js/checkBuild");
|
|
||||||
// var editorFile = path.resolve(path.join(__dirname,"..","..","..","..","public","red","red.min.js"));
|
|
||||||
// try {
|
|
||||||
// var stats = fs.statSync(editorFile);
|
|
||||||
// } catch(err) {
|
|
||||||
// var e = new Error("Node-RED not built");
|
|
||||||
// e.code = "not_built";
|
|
||||||
// throw e;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(httpServer,userSettings) {
|
init: function(httpServer,userSettings) {
|
||||||
if (!userSettings) {
|
if (!userSettings) {
|
||||||
@ -59,7 +47,6 @@ module.exports = {
|
|||||||
|
|
||||||
if (!userSettings.SKIP_BUILD_CHECK) {
|
if (!userSettings.SKIP_BUILD_CHECK) {
|
||||||
checkVersion(userSettings);
|
checkVersion(userSettings);
|
||||||
checkBuild();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!userSettings.coreNodesDir) {
|
if (!userSettings.coreNodesDir) {
|
||||||
|
@ -21,9 +21,6 @@ var path = require("path");
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var EventEmitter = require('events');
|
var EventEmitter = require('events');
|
||||||
|
|
||||||
var child_process = require('child_process');
|
|
||||||
|
|
||||||
|
|
||||||
var NR_TEST_UTILS = require("nr-test-utils");
|
var NR_TEST_UTILS = require("nr-test-utils");
|
||||||
|
|
||||||
var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer");
|
var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer");
|
||||||
@ -42,16 +39,21 @@ describe('nodes/registry/installer', function() {
|
|||||||
_: function() { return "abc"}
|
_: function() { return "abc"}
|
||||||
}
|
}
|
||||||
|
|
||||||
before(function() {
|
beforeEach(function() {
|
||||||
installer.init({log:mockLog, settings:{}, events: new EventEmitter()});
|
installer.init({log:mockLog, settings:{}, events: new EventEmitter(), exec: {
|
||||||
|
run: function() {
|
||||||
|
return Promise.resolve("");
|
||||||
|
}
|
||||||
|
}});
|
||||||
});
|
});
|
||||||
|
function initInstaller(execResult) {
|
||||||
|
installer.init({log:mockLog, settings:{}, events: new EventEmitter(), exec: {
|
||||||
|
run: function() {
|
||||||
|
return execResult;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
}
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
if (child_process.spawn.restore) {
|
|
||||||
child_process.spawn.restore();
|
|
||||||
}
|
|
||||||
if (child_process.execFile.restore) {
|
|
||||||
child_process.execFile.restore();
|
|
||||||
}
|
|
||||||
if (registry.addModule.restore) {
|
if (registry.addModule.restore) {
|
||||||
registry.addModule.restore();
|
registry.addModule.restore();
|
||||||
}
|
}
|
||||||
@ -76,39 +78,33 @@ describe('nodes/registry/installer', function() {
|
|||||||
|
|
||||||
describe("installs module", function() {
|
describe("installs module", function() {
|
||||||
it("rejects when npm returns a 404", function(done) {
|
it("rejects when npm returns a 404", function(done) {
|
||||||
sinon.stub(child_process,"spawn",function(cmd,args,opt) {
|
var res = {
|
||||||
var ee = new EventEmitter();
|
code: 1,
|
||||||
ee.stdout = new EventEmitter();
|
stdout:"",
|
||||||
ee.stderr = new EventEmitter();
|
stderr:" 404 this_wont_exist"
|
||||||
setTimeout(function() {
|
}
|
||||||
ee.stderr.emit('data'," 404 this_wont_exist");
|
var p = Promise.reject(res);
|
||||||
ee.emit('close',1);
|
p.catch((err)=>{});
|
||||||
},10)
|
initInstaller(p)
|
||||||
return ee;
|
|
||||||
});
|
|
||||||
|
|
||||||
installer.installModule("this_wont_exist").catch(function(err) {
|
installer.installModule("this_wont_exist").catch(function(err) {
|
||||||
err.should.have.property("code",404);
|
err.should.have.property("code",404);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("rejects when npm does not find specified version", function(done) {
|
it("rejects when npm does not find specified version", function(done) {
|
||||||
sinon.stub(child_process,"spawn",function(cmd,args,opt) {
|
var res = {
|
||||||
var ee = new EventEmitter();
|
code: 1,
|
||||||
ee.stdout = new EventEmitter();
|
stdout:"",
|
||||||
ee.stderr = new EventEmitter();
|
stderr:" version not found: this_wont_exist@0.1.2"
|
||||||
setTimeout(function() {
|
}
|
||||||
ee.stderr.emit('data'," version not found: this_wont_exist@0.1.2");
|
var p = Promise.reject(res);
|
||||||
ee.emit('close',1);
|
p.catch((err)=>{});
|
||||||
},10)
|
initInstaller(p)
|
||||||
return ee;
|
|
||||||
});
|
|
||||||
sinon.stub(typeRegistry,"getModuleInfo", function() {
|
sinon.stub(typeRegistry,"getModuleInfo", function() {
|
||||||
return {
|
return {
|
||||||
version: "0.1.1"
|
version: "0.1.1"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||||
err.code.should.be.eql(404);
|
err.code.should.be.eql(404);
|
||||||
done();
|
done();
|
||||||
@ -126,17 +122,14 @@ describe('nodes/registry/installer', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("rejects with generic error", function(done) {
|
it("rejects with generic error", function(done) {
|
||||||
sinon.stub(child_process,"spawn",function(cmd,args,opt,cb) {
|
var res = {
|
||||||
var ee = new EventEmitter();
|
code: 1,
|
||||||
ee.stdout = new EventEmitter();
|
stdout:"",
|
||||||
ee.stderr = new EventEmitter();
|
stderr:" kaboom!"
|
||||||
setTimeout(function() {
|
}
|
||||||
ee.stderr.emit('data'," kaboom!");
|
var p = Promise.reject(res);
|
||||||
ee.emit('close',1);
|
p.catch((err)=>{});
|
||||||
},10)
|
initInstaller(p)
|
||||||
return ee;
|
|
||||||
});
|
|
||||||
|
|
||||||
installer.installModule("this_wont_exist").then(function() {
|
installer.installModule("this_wont_exist").then(function() {
|
||||||
done(new Error("Unexpected success"));
|
done(new Error("Unexpected success"));
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
@ -145,15 +138,16 @@ describe('nodes/registry/installer', function() {
|
|||||||
});
|
});
|
||||||
it("succeeds when module is found", function(done) {
|
it("succeeds when module is found", function(done) {
|
||||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||||
sinon.stub(child_process,"spawn",function(cmd,args,opt) {
|
|
||||||
var ee = new EventEmitter();
|
var res = {
|
||||||
ee.stdout = new EventEmitter();
|
code: 0,
|
||||||
ee.stderr = new EventEmitter();
|
stdout:"",
|
||||||
setTimeout(function() {
|
stderr:""
|
||||||
ee.emit('close',0);
|
}
|
||||||
},10)
|
var p = Promise.resolve(res);
|
||||||
return ee;
|
p.catch((err)=>{});
|
||||||
});
|
initInstaller(p)
|
||||||
|
|
||||||
var addModule = sinon.stub(registry,"addModule",function(md) {
|
var addModule = sinon.stub(registry,"addModule",function(md) {
|
||||||
return when.resolve(nodeInfo);
|
return when.resolve(nodeInfo);
|
||||||
});
|
});
|
||||||
@ -191,15 +185,15 @@ describe('nodes/registry/installer', function() {
|
|||||||
return when.resolve(nodeInfo);
|
return when.resolve(nodeInfo);
|
||||||
});
|
});
|
||||||
var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","TestNodeModule"));
|
var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","TestNodeModule"));
|
||||||
sinon.stub(child_process,"spawn",function(cmd,args,opt) {
|
|
||||||
var ee = new EventEmitter();
|
var res = {
|
||||||
ee.stdout = new EventEmitter();
|
code: 0,
|
||||||
ee.stderr = new EventEmitter();
|
stdout:"",
|
||||||
setTimeout(function() {
|
stderr:""
|
||||||
ee.emit('close',0);
|
}
|
||||||
},10)
|
var p = Promise.resolve(res);
|
||||||
return ee;
|
p.catch((err)=>{});
|
||||||
});
|
initInstaller(p)
|
||||||
installer.installModule(resourcesDir).then(function(info) {
|
installer.installModule(resourcesDir).then(function(info) {
|
||||||
info.should.eql(nodeInfo);
|
info.should.eql(nodeInfo);
|
||||||
done();
|
done();
|
||||||
@ -226,9 +220,14 @@ describe('nodes/registry/installer', function() {
|
|||||||
var removeModule = sinon.stub(registry,"removeModule",function(md) {
|
var removeModule = sinon.stub(registry,"removeModule",function(md) {
|
||||||
return when.resolve(nodeInfo);
|
return when.resolve(nodeInfo);
|
||||||
});
|
});
|
||||||
sinon.stub(child_process,"execFile",function(cmd,args,opt,cb) {
|
var res = {
|
||||||
cb(new Error("test_error"),"","");
|
code: 1,
|
||||||
});
|
stdout:"",
|
||||||
|
stderr:"error"
|
||||||
|
}
|
||||||
|
var p = Promise.reject(res);
|
||||||
|
p.catch((err)=>{});
|
||||||
|
initInstaller(p)
|
||||||
|
|
||||||
installer.uninstallModule("this_wont_exist").then(function() {
|
installer.uninstallModule("this_wont_exist").then(function() {
|
||||||
done(new Error("Unexpected success"));
|
done(new Error("Unexpected success"));
|
||||||
@ -244,9 +243,14 @@ describe('nodes/registry/installer', function() {
|
|||||||
var getModuleInfo = sinon.stub(registry,"getModuleInfo",function(md) {
|
var getModuleInfo = sinon.stub(registry,"getModuleInfo",function(md) {
|
||||||
return {nodes:[]};
|
return {nodes:[]};
|
||||||
});
|
});
|
||||||
sinon.stub(child_process,"execFile",function(cmd,args,opt,cb) {
|
var res = {
|
||||||
cb(null,"","");
|
code: 0,
|
||||||
});
|
stdout:"",
|
||||||
|
stderr:""
|
||||||
|
}
|
||||||
|
var p = Promise.resolve(res);
|
||||||
|
p.catch((err)=>{});
|
||||||
|
initInstaller(p)
|
||||||
|
|
||||||
sinon.stub(fs,"statSync", function(fn) { return {}; });
|
sinon.stub(fs,"statSync", function(fn) { return {}; });
|
||||||
|
|
||||||
|
22
test/unit/@node-red/runtime/lib/exec_spec.js
Normal file
22
test/unit/@node-red/runtime/lib/exec_spec.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
var path = require("path");
|
||||||
|
|
||||||
|
var NR_TEST_UTILS = require("nr-test-utils");
|
||||||
|
|
||||||
|
var exec = NR_TEST_UTILS.require("@node-red/runtime/lib/exec");
|
Loading…
Reference in New Issue
Block a user