Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

POSTMAN_FILE="postman.json"

if [ -f "$POSTMAN_FILE" ]; then
# Check if any "src" value is not empty
if grep -Po '"src"\s*:\s*"\K[^"]+' "$POSTMAN_FILE" | grep -qv '^$'; then
echo "$POSTMAN_FILE contains personal src paths" >&2
exit 1
fi
fi

exit 0
105 changes: 87 additions & 18 deletions components/endpoints/class.command.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,56 @@ const { parentPort, isMainThread } = require("worker_threads");
const { commands } = require("../../system/worker/shared.js");
const { randomUUID } = require("crypto");


// check if a passed callback uses old
// command arugments, or the new signature
// see #504 - "change command handler function arguments"
function compatWrapper(fn, { logger }) {
return function (...args) {

// args[0] = cmd
// args[1] = iface
// args[2] = params
// args[3] = timer/cb

// this, provokes "Cannot set headers after they are sent to the client"
// see issue #528
//let { logger } = Command.scope;

if (fn.length === 4) {

// print a deprecation notice (only in dev mode)
// for production this would be to verbose
if (process.env.NODE_ENV === "development") {

let msg = "Command handler signature deprecated!\n";
msg += "`(cmd, iface, params, done) => {}` will be removed in further versions.\n";
msg += "Use `(obj, done) => {}` instead. See: https://github.com/OpenHausIO/backend/issues/504#issuecomment-2922734270";

logger.warn(msg);

}

// old signature/arguments
return fn(...args);

} else if (fn.length === 2) {

// new signature/arguments accepted
return fn({
params: args[2]
}, args[3]);

} else {

return fn(...args);

}

};
}


/**
* @description
* Single command
Expand Down Expand Up @@ -246,7 +296,7 @@ module.exports = class Command {
// when worker = handler like default beaufer
let { events, logger } = Command.scope;

let wrapper = () => {
let wrapper = (abort = null) => {

// feedback
logger.verbose(`Trigger command "${this.name}"`, this);
Expand All @@ -261,15 +311,12 @@ module.exports = class Command {
cb = () => { };
}

let worker = this.#privates.get("handler");
let iface = interfaces.get(this.interface);

// moved up, and used as callback debounce function
// see #528, timeout helper has a internal "called" flag
let timer = _timeout(this.#privates.get("timeout"), (timedout, duration, args) => {
if (timedout) {

logger.warn(`Command timedout for "${this._id}"! Execution was not successful, worker function:`, worker);
logger.warn(`Command timedout for "${this._id}"! Execution was not successful, worker function:`);
cb(null, false);

} else {
Expand All @@ -280,6 +327,10 @@ module.exports = class Command {
}
});

if (abort) {
timer(abort, false);
}

try {
params = params.map((obj) => {

Expand All @@ -303,21 +354,35 @@ module.exports = class Command {

}

// convert to params array with .lean method
params = new Params(...params);
try {

if (!iface) {
let err = new Error(`Interface "${this.interface}" not found, cant write to it.`);
err.code = "NO_INTERFACE";
return timer(err, false);
}
// convert to params array with .lean method
params = new Params(...params);

let handler = this.#privates.get("handler");
let iface = interfaces.get(this.interface);
let worker = compatWrapper(handler, Command.scope);

if (!iface) {
let err = new Error(`Interface "${this.interface}" not found, cant write to it.`);
err.code = "NO_INTERFACE";
return timer(err, false);
}

// emit command event, see #529
events.emit("command", this, params);

// emit command event, see #529
events.emit("command", this, params);
// handle timeout stuff here?
// when so, timeout applys to custom functions too!
worker.call(this, this, iface, params, timer);

// handle timeout stuff here?
// when so, timeout applys to custom functions too!
worker.call(this, this, iface, params, timer);
} catch (err) {

logger.warn(err, "Error catched in worker function");

timer(err, false);

}

};

Expand Down Expand Up @@ -355,8 +420,12 @@ module.exports = class Command {

} else {

let err = new Error("No command handler registered");
err.code = "NO_HANDLER";

// feedback
logger.warn("No command hanlder registered");
logger.warn(err.message);
wrapper(err);

}

Expand Down
Loading