Skip to content

Commit

Permalink
Merge pull request #384 from mStirner/dev
Browse files Browse the repository at this point in the history
Improvements
  • Loading branch information
mStirner committed Dec 29, 2023
2 parents 37fb4c2 + 6c2e54c commit 97c7a42
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 31 deletions.
55 changes: 32 additions & 23 deletions components/endpoints/class.command.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const mongodb = require("mongodb");
const _timeout = require("../../helper/timeout.js");
const { interfaces } = require("../../system/shared.js");

const Param = require("./class.param.js");

/**
* @description
Expand Down Expand Up @@ -84,6 +85,13 @@ module.exports = class Command {
this.payload = obj.payload.read(0);
}

// fix #383
obj.params?.forEach((param, i, arr) => {
if (!(param instanceof Param)) {
arr[i] = new Param(param);
}
});

// command duration timeout
this.#privates.set("timeout", Number(process.env.COMMAND_RESPONSE_TIMEOUT));

Expand Down Expand Up @@ -190,12 +198,35 @@ module.exports = class Command {
let worker = this.#privates.get("handler");
let iface = interfaces.get(this.interface);

//console.log("params array:", this.params, params)

let valid = params.every(({ key, value }) => {

let param = this.params.find((param) => {
return param.key === key;
});

// auto convert "123" to 123
if (param.type === "number") {
value = Number(value);
}

return typeof (value) === param.type;

});

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

if (!valid) {
let err = new Error(`Invalid params type`);
err.code = "INVALID_PARAMETER_TYPE";
return cb(err);
}

let timer = _timeout(this.#privates.get("timeout"), (timedout, duration, args) => {
if (timedout) {

Expand Down Expand Up @@ -237,29 +268,7 @@ module.exports = class Command {
//payload: Joi.string().allow(null).default(null),
payload: Joi.alternatives().try(Joi.string(), Joi.binary()).allow(null).default(null),
description: Joi.string().allow(null).default(null),
params: Joi.array().items(Joi.object({
type: Joi.string().valid("number", "string", "boolean").required(),
key: Joi.string().required()
}).when(".type", {
switch: [{
is: "number",
then: Joi.object({
value: Joi.number().default(null).allow(null),
min: Joi.number().default(0),
max: Joi.number().default(100)
})
}, {
is: "string",
then: Joi.object({
value: Joi.string().default(null).allow(null)
})
}, {
is: "boolean",
then: Joi.object({
value: Joi.boolean().default(null).allow(null)
})
}]
}))
params: Joi.array().items(Param.schema())
});
}

Expand Down
70 changes: 70 additions & 0 deletions components/endpoints/class.param.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const Joi = require("joi");

module.exports = class Param {

constructor(obj) {

Object.assign(this, obj);

Object.defineProperty(this, "value", {
get() {
return obj.value;
},
set(val) {

if (val === null) {
obj.value = null;
return;
}

if (typeof (val) !== obj.type) {
throw new Error(`Parameter "${obj.key}" invalid type ${typeof (val)}. Expected ${obj.type}`);
}

if (obj.type === "number" && !(val >= obj.min && obj.max >= val)) {
throw new Error(`Invalid value: ${val}. Expected value >= ${obj.min} or ${obj.max} >= value`);
}

obj.value = val;

},
enumerable: true,
configurable: true
});

}

static schema() {
return Joi.object({
type: Joi.string().valid("number", "string", "boolean").required(),
key: Joi.string().required()
}).when(".type", {
switch: [{
is: "number",
then: Joi.object({
value: Joi.number().default(null).allow(null),
min: Joi.number().default(0),
max: Joi.number().default(100),
//default: Joi.number().allow(null).default(null)
})
}, {
is: "string",
then: Joi.object({
value: Joi.string().default(null).allow(null),
//default: Joi.string().allow(null).default(null)
})
}, {
is: "boolean",
then: Joi.object({
value: Joi.boolean().default(null).allow(null),
//default: Joi.boolean().allow(null).default(null)
})
}]
});
}

static validate(data) {
return Param.schema().validate(data);
}

};
2 changes: 1 addition & 1 deletion routes/router.api.endpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module.exports = (app, router) => {
error: err.message
});
} else {
res.status(500).end({
res.status(500).json({
error: err.message
});
}
Expand Down
21 changes: 14 additions & 7 deletions system/component/class.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,10 @@ module.exports = class COMPONENT extends COMMON {
if (key === "labels" && Array.isArray(filter[key]) && Array.isArray(target[key])) {

found = filter[key].every((label) => {
return target[key].includes(label);
// fix #381
// target[key] is a instance if class.labels.js and not of plain string.
// convert it to a array wiht plain strings, so that .includes works.
return target[key]?.toString().includes(label);
});

return;
Expand Down Expand Up @@ -786,7 +789,7 @@ module.exports = class COMPONENT extends COMMON {

/**
* @function _labels
* Checks if filter array contains matching labels
* Checks if filter array contains matching labels on items.labels array
*
* @param {Array} arr Array with item labels to check with filter
* @param {Array} filter Filter array
Expand All @@ -795,7 +798,13 @@ module.exports = class COMPONENT extends COMMON {
*/
_labels(arr, filter) {
return filter.every((filter) => {
if (arr.includes(filter)) {
if (arr.map((label) => {

// convert back to string array
// so the .include can do its job
return label.toString();

}).includes(filter)) {

return true;

Expand All @@ -805,14 +814,12 @@ module.exports = class COMPONENT extends COMMON {

return arr.some((label) => {

let [k, v] = label.split("=");

if (value === "*") {
return key === k;
return key === label.key;
}

if (key === "*") {
return value === v;
return value === label.value;
}

return false;
Expand Down

0 comments on commit 97c7a42

Please sign in to comment.