🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

node-red-debugger

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-red-debugger - npm Package Compare versions

Comparing version

to
1.1.0

CHANGELOG.md

35

dist/flow-debugger.js

@@ -11,4 +11,4 @@ "use strict";

const routeAuthHandler = RED.auth.needsPermission("flow-debugger.write");
RED.comms.publish("flow-debugger/connected", true, true);
function publishState() {
// Do not retain as we don't want stale state to be saved
RED.comms.publish("flow-debugger/state", flowDebugger.getState());

@@ -23,9 +23,7 @@ }

flowDebugger.on("messageQueued", (event) => {
// msg = RED.util.encodeObject(msg,{maxLength:debuglength});
// RED.comms.publish("debug",msg);
event.msg = RED.util.encodeObject({ msg: event.msg }, { maxLength: 100 });
// Don't include the full message on the event
// event.msg = RED.util.encodeObject({msg:event.msg}, {maxLength: 100});
RED.comms.publish("flow-debugger/messageQueued", event);
});
flowDebugger.on("messageDispatched", (event) => {
event.msg = RED.util.encodeObject({ msg: event.msg }, { maxLength: 100 });
RED.comms.publish("flow-debugger/messageDispatched", event);

@@ -36,22 +34,25 @@ });

// });
RED.httpAdmin.get(`${apiRoot}/state`, (_, res) => {
RED.httpAdmin.get(`${apiRoot}`, (_, res) => {
res.json(flowDebugger.getState());
});
RED.httpAdmin.put(`${apiRoot}/state`, routeAuthHandler, (req, res) => {
RED.httpAdmin.put(`${apiRoot}`, routeAuthHandler, (req, res) => {
let stateChanged = false;
if (req.body.hasOwnProperty("enabled")) {
const enabled = !!req.body.enabled;
let stateChanged = false;
if (enabled && flowDebugger.state === debugger_1.State.DISABLED) {
if (enabled && !flowDebugger.enabled) {
flowDebugger.enable();
stateChanged = true;
}
else if (!enabled && flowDebugger.state !== debugger_1.State.DISABLED) {
else if (!enabled && flowDebugger.enabled) {
flowDebugger.disable();
stateChanged = true;
}
if (stateChanged) {
publishState();
}
}
res.sendStatus(200);
if (req.body.hasOwnProperty("config")) {
stateChanged = flowDebugger.setConfig(req.body.config);
}
if (stateChanged) {
publishState();
}
res.json(flowDebugger.getState());
});

@@ -63,8 +64,6 @@ RED.httpAdmin.get(`${apiRoot}/breakpoints`, routeAuthHandler, (_, res) => {

flowDebugger.setBreakpointActive(req.params.id, req.body.active);
publishState();
res.sendStatus(200);
res.json(flowDebugger.getBreakpoint(req.params.id));
});
RED.httpAdmin.delete(`${apiRoot}/breakpoints/:id`, routeAuthHandler, (req, res) => {
flowDebugger.clearBreakpoint(req.params.id);
publishState();
res.sendStatus(200);

@@ -81,3 +80,3 @@ });

id: m.id,
location: m.location,
location: m.location.toString(),
destination: undefined,

@@ -84,0 +83,0 @@ msg: RED.util.encodeObject({ msg: m.event.msg }, { maxLength: 100 })

@@ -22,12 +22,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Debugger = exports.State = void 0;
exports.Debugger = void 0;
const Location = __importStar(require("./location"));
const MessageQueue_1 = require("./MessageQueue");
const events_1 = require("events");
var State;
(function (State) {
State[State["DISABLED"] = 0] = "DISABLED";
State[State["ENABLED"] = 1] = "ENABLED";
State[State["PAUSED"] = 2] = "PAUSED";
})(State = exports.State || (exports.State = {}));
const DEBUGGER_PAUSED = Symbol("node-red-debugger: paused");
let BREAKPOINT_ID = 1;

@@ -39,5 +34,9 @@ class Debugger extends events_1.EventEmitter {

super();
this.config = {
breakpointAction: "pause-all"
};
this.RED = RED;
this.state = State.DISABLED;
this.enabled = false;
this.breakpoints = new Map();
this.pausedLocations = new Set();
this.breakpointsByLocation = new Map();

@@ -53,23 +52,32 @@ this.queuesByLocation = {};

const breakpointId = location.getBreakpointLocation();
const locationId = location.toString();
if (this.state === State.ENABLED) {
const bp = this.breakpointsByLocation.get(breakpointId);
if (bp && bp.active) {
if (this.isNodePaused(location.id)) {
this.queueEvent(location, event, done);
}
else {
if (event.msg && event.msg[DEBUGGER_PAUSED]) {
this.pause({
reason: "breakpoint",
breakpoint: bp.id
reason: "step",
node: location.id
});
this.queueEvent(locationId, event, done);
this.queueEvent(location, event, done);
}
else {
done();
const bp = this.breakpointsByLocation.get(breakpointId);
if (bp && bp.active) {
this.pause({
reason: "breakpoint",
node: location.id,
breakpoint: bp.id
});
this.queueEvent(location, event, done);
}
else {
done();
}
}
}
else if (this.state === State.PAUSED) {
this.queueEvent(locationId, event, done);
}
}
enable() {
this.log("Enabled");
this.state = State.ENABLED;
this.enabled = true;
this.RED.hooks.add("preRoute.flow-debugger", (sendEvent, done) => {

@@ -97,4 +105,4 @@ if (isNodeInSubflowModule(sendEvent.source.node)) {

this.RED.hooks.add("onReceive.flow-debugger", (receiveEvent, done) => {
if (this.state === State.PAUSED && receiveEvent.destination.node.type === "inject") {
// Inside a subflow module - don't pause the event
if (receiveEvent.destination.node.type === "inject") {
// Never pause an Inject node's internal receive event
done();

@@ -104,2 +112,3 @@ return;

if (isNodeInSubflowModule(receiveEvent.destination.node)) {
// Inside a subflow module - don't pause the event
done();

@@ -115,21 +124,54 @@ return;

this.log("Disabled");
this.state = State.DISABLED;
this.enabled = false;
this.RED.hooks.remove("*.flow-debugger");
this.pausedLocations.clear();
this.drainQueues(true);
}
pause(event) {
if (this.state === State.ENABLED) {
this.state = State.PAUSED;
const logReason = event ? ("@" + this.breakpoints.get(event.breakpoint).location.toString()) : "manual";
if (this.enabled) {
let logReason;
if (event) {
if (this.config.breakpointAction === "pause-all") {
this.pausedLocations.clear();
this.pausedLocations.add("*");
}
else {
this.pausedLocations.add(event.node);
}
if (event.reason === "breakpoint") {
logReason = "@" + this.breakpoints.get(event.breakpoint).location.toString();
}
else if (event.reason === "step") {
logReason = "@" + event.node;
}
event.pausedLocations = [...this.pausedLocations];
}
else {
// Manual pause
this.pausedLocations.clear();
this.pausedLocations.add("*");
logReason = "manual";
}
this.log(`Flows paused: ${logReason}`);
this.emit("paused", event || { reason: "manual", breakpoint: null });
this.emit("paused", event || { reason: "manual" });
}
}
resume() {
if (this.state === State.PAUSED) {
this.log("Flows resumed");
this.state = State.ENABLED;
this.emit("resumed", {});
this.drainQueues();
resume(nodeId) {
if (this.pausedLocations.size === 0) {
return;
}
if (!nodeId || nodeId === "*") {
console.log("resume - clear all locations");
this.pausedLocations.clear();
}
else if (nodeId && this.pausedLocations.has(nodeId)) {
this.pausedLocations.delete(nodeId);
}
else {
// Nothing has been unpaused
return;
}
this.log("Flows resumed");
this.emit("resumed", { node: nodeId });
this.drainQueues();
}

@@ -140,8 +182,9 @@ deleteMessage(messageId) {

this.messageQueue.remove(nextEvent);
this.queuesByLocation[nextEvent.location].remove(nextEvent);
const queueDepth = this.queuesByLocation[nextEvent.location].length;
const nextEventLocation = nextEvent.location.toString();
this.queuesByLocation[nextEventLocation].remove(nextEvent);
const queueDepth = this.queuesByLocation[nextEventLocation].length;
if (queueDepth === 0) {
delete this.queuesByLocation[nextEvent.location];
delete this.queuesByLocation[nextEventLocation];
}
this.emit("messageDispatched", { id: nextEvent.id, location: nextEvent.location, depth: queueDepth });
this.emit("messageDispatched", { id: nextEvent.id, location: nextEventLocation, depth: queueDepth });
// Call done with false to prevent any further processing

@@ -151,18 +194,25 @@ nextEvent.done(false);

}
isNodePaused(nodeId) {
return this.pausedLocations.has("*") || this.pausedLocations.has(nodeId);
}
drainQueues(quiet) {
let nextEvent;
do {
nextEvent = this.messageQueue.next();
if (nextEvent) {
this.queuesByLocation[nextEvent.location].remove(nextEvent);
const queueDepth = this.queuesByLocation[nextEvent.location].length;
for (const nextEvent of this.messageQueue) {
const eventNodeId = nextEvent.location.id;
if (!this.isNodePaused(eventNodeId)) {
const nextEventLocation = nextEvent.location.toString();
this.queuesByLocation[nextEventLocation].remove(nextEvent);
const queueDepth = this.queuesByLocation[nextEventLocation].length;
if (queueDepth === 0) {
delete this.queuesByLocation[nextEvent.location];
delete this.queuesByLocation[nextEventLocation];
}
if (!quiet) {
this.emit("messageDispatched", { id: nextEvent.id, location: nextEvent.location, depth: queueDepth });
this.emit("messageDispatched", { id: nextEvent.id, location: nextEventLocation, depth: queueDepth });
}
if (nextEvent.event.msg[DEBUGGER_PAUSED]) {
delete nextEvent.event.msg[DEBUGGER_PAUSED];
}
nextEvent.done();
this.messageQueue.remove(nextEvent);
}
} while (this.state !== State.PAUSED && nextEvent);
}
}

@@ -173,3 +223,4 @@ setBreakpoint(location) {

location,
active: true
active: true,
mode: "all"
};

@@ -200,3 +251,3 @@ this.breakpoints.set(bp.id, bp);

step(messageId) {
if (this.state === State.PAUSED) {
if (this.enabled) {
let nextEvent;

@@ -213,9 +264,11 @@ if (messageId) {

if (nextEvent) {
this.log("Step: " + nextEvent.location.toString());
this.queuesByLocation[nextEvent.location].remove(nextEvent);
const queueDepth = this.queuesByLocation[nextEvent.location].length;
const nextEventLocation = nextEvent.location.toString();
this.log("Step: " + nextEventLocation);
this.queuesByLocation[nextEventLocation].remove(nextEvent);
const queueDepth = this.queuesByLocation[nextEventLocation].length;
if (queueDepth === 0) {
delete this.queuesByLocation[nextEvent.location];
delete this.queuesByLocation[nextEventLocation];
}
this.emit("messageDispatched", { id: nextEvent.id, location: nextEvent.location, depth: queueDepth });
nextEvent.event.msg[DEBUGGER_PAUSED] = true;
this.emit("messageDispatched", { id: nextEvent.id, location: nextEventLocation, depth: queueDepth });
nextEvent.done();

@@ -225,4 +278,14 @@ }

}
setConfig(newConfig) {
let changed = false;
for (const key in this.config) {
if (newConfig.hasOwnProperty(key) && this.config[key] !== newConfig[key]) {
changed = true;
this.config[key] = newConfig[key];
}
}
return changed;
}
getState() {
if (this.state === State.DISABLED) {
if (!this.enabled) {
return { enabled: false };

@@ -232,3 +295,4 @@ }

enabled: true,
paused: this.state === State.PAUSED,
pausedLocations: [...this.pausedLocations],
config: this.config,
breakpoints: this.getBreakpoints(),

@@ -250,3 +314,3 @@ queues: this.getMessageQueueDepths()

getMessageQueueDepths() {
if (this.state === State.DISABLED) {
if (!this.enabled) {
return {};

@@ -274,3 +338,4 @@ }

}
queueEvent(locationId, event, done) {
queueEvent(location, event, done) {
const locationId = location.toString();
if (!this.queuesByLocation[locationId]) {

@@ -282,3 +347,3 @@ this.queuesByLocation[locationId] = new MessageQueue_1.MessageQueue("Location");

event,
location: locationId,
location,
done,

@@ -285,0 +350,0 @@ nextByLocation: null,

@@ -14,4 +14,15 @@ {

"deleteMessage": "Delete message",
"stepMessage": "Step message"
"stepMessage": "Step message",
"filter": {
"label": "Filter messages",
"all": "all nodes",
"flow": "current flow"
},
"settings": "Debugger options",
"breakpointAction": {
"label": "Breakpoint action",
"pause-all": "pause all nodes",
"pause-bp": "pause at breakpoint"
}
}
}
{
"name": "node-red-debugger",
"version": "1.0.1",
"version": "1.1.0",
"description": "A flow debugger for Node-RED 2.x",

@@ -13,3 +13,3 @@ "repository": {

"copyAssets": "node scripts/copy-static-assets.js",
"dev": "nodemon --exec 'npm run build' -i dist -e 'ts html'",
"dev": "nodemon --exec 'npm run build' -i dist -i resources -e 'ts html css'",
"test": "npm run build"

@@ -20,3 +20,4 @@ },

"files": [
"dist"
"dist",
"resources"
],

@@ -23,0 +24,0 @@ "license": "Apache-2",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet