standaardisation updates

This commit is contained in:
znetsixe
2025-06-25 10:55:50 +02:00
parent dbc36c2f57
commit 3198690a81
126 changed files with 5028 additions and 608 deletions

106
src/helper/endpointUtils.js Normal file
View File

@@ -0,0 +1,106 @@
const MenuUtils = require('./menuUtils');
/**
* Server-side helper for exposing MenuUtils to the browser via HTTP endpoints.
*/
class EndpointUtils {
/**
* @param {Object} options
* @param {Function} options.MenuUtilsClass the MenuUtils constructor/function
*/
constructor({ MenuUtilsClass = MenuUtils } = {}) {
this.MenuUtils = MenuUtilsClass;
}
/**
* Registers an HTTP GET endpoint that serves the client-side MenuUtils code
* @param {object} RED the Node-RED API object
* @param {string} nodeName the name of the node (used in the URL)
* @param {object} customHelpers additional helper functions to inject
*/
createMenuUtilsEndpoint(RED, nodeName, customHelpers = {}) {
RED.httpAdmin.get(`/${nodeName}/resources/menuUtils.js`, (req, res) => {
console.log(`Serving menuUtils.js for ${nodeName} node`);
res.set('Content-Type', 'application/javascript');
const browserCode = this.generateMenuUtilsCode(nodeName, customHelpers);
res.send(browserCode);
});
}
/**
* Generates the browser-side JavaScript that redefines MenuUtils and helper fns
* @param {string} nodeName
* @param {object} customHelpers map of name: functionString pairs
* @returns {string} a JS snippet to run in the browser
*/
generateMenuUtilsCode(nodeName, customHelpers = {}) {
// Default helper implementations to expose alongside MenuUtils
const defaultHelpers = {
validateRequired: `function(value) {
return value != null && value.toString().trim() !== '';
}`,
formatDisplayValue: `function(value, unit) {
return \`${'${'}value} ${'${'}unit || ''}\`.trim();
}`,
validateScaling: `function(min, max) {
return !isNaN(min) && !isNaN(max) && Number(min) < Number(max);
}`,
validateUnit: `function(unit) {
return typeof unit === 'string' && unit.trim() !== '';
}`,
};
// Merge any custom overrides
const allHelpers = { ...defaultHelpers, ...customHelpers };
// Build the helpers code block
const helpersCode = Object.entries(allHelpers)
.map(([name, fnBody]) => ` ${name}: ${fnBody}`)
.join(',\n');
// Introspect MenuUtils prototype to extract method definitions
const proto = this.MenuUtils.prototype;
const browserMethods = Object.getOwnPropertyNames(proto)
.filter(key => key !== 'constructor')
.map(methodName => {
const fn = proto[methodName];
const src = fn.toString();
const isAsync = fn.constructor.name === 'AsyncFunction';
// extract signature and body
const signature = src.slice(src.indexOf('('));
const prefix = isAsync ? 'async ' : '';
return ` ${prefix}${methodName}${signature}`;
})
.join('\n\n');
// Return a complete JS snippet for the browser
return `
// Auto-generated MenuUtils for node: ${nodeName}
window.EVOLV = window.EVOLV || {};
window.EVOLV.nodes = window.EVOLV.nodes || {};
window.EVOLV.nodes.${nodeName} = window.EVOLV.nodes.${nodeName} || {};
class MenuUtils {
constructor(opts) {
// Allow same options API as server-side
this.useCloud = opts.useCloud || false;
this.projectSettings = opts.projectSettings || {};
// any other client-side initialization...
}
${browserMethods}
}
window.EVOLV.nodes.${nodeName}.utils = {
menuUtils: new MenuUtils({}),
helpers: {
${helpersCode}
}
};
console.log('Loaded EVOLV.nodes.${nodeName}.utils.menuUtils');
`;
}
}
module.exports = EndpointUtils;

View File

@@ -1,4 +1,5 @@
class MenuUtils {
initBasicToggles(elements) {
// Toggle visibility for log level