node-red-contrib-uibuilder
Version:
Easily create data-driven web UI's for Node-RED. Single- & Multi-page. Multiple UI's. Work with existing web development workflows or mix and match with no-code/low-code features.
999 lines (959 loc) • 48.3 kB
JavaScript
/* eslint-disable jsdoc/valid-types */
/* eslint-disable jsdoc/no-undefined-types */
// @ts-nocheck
/* eslint-disable no-irregular-whitespace */
/** Define typedefs for linting and JSDoc/ts checks - does not actually contain live code
*
* Copyright (c) 2017-2025 Julian Knight (Totally Information)
* https://it.knightnet.org.uk, https://github.com/TotallyInformation/node-red-contrib-uibuilder
*
* 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.
*/
'use strict'
/** editorRED
* typedef {object} editorRED The Node-RED core object available to a custom node's .html file
*
*/
/** Node-RED runtimeSettings - See settings.js for static settings.
* @typedef {object} runtimeSettings Static and Dynamic settings for Node-RED runtime
*
* @property {string} uiPort The port used by Node-RED (default=1880)
* @property {string} uiHost The host IP used by Node-RED (default=0.0.0.0)
* @property {string} userDir The userDir folder
* @property {string} httpNodeRoot Optional base URL. All user url's will be under this. Default empty string.
* @property {object} FunctionGlobalContext Add values, Functions, packages to the Global context variable store.
* @property {Function} mqttReconnectTime : [Getter/Setter],
* @property {Function} serialReconnectTime : [Getter/Setter],
* @property {number} debugMaxLength : [Getter/Setter],
* @property {number} debugStatusLength : [Getter/Setter],
* @property {Function} debugUseColors : [Getter/Setter],
* @property {string} flowFile : [Getter/Setter],
* @property {Function} flowFilePretty : [Getter/Setter],
* @property {string} credentialSecret : [Getter/Setter],
* @property {string} httpAdminRoot : [Getter/Setter],
* @property {string} httpStatic : [Getter/Setter],
* @property {Function} adminAuth : [Getter/Setter],
* @property {Function} httpNodeMiddleware : [Getter/Setter],
* @property {Function} httpAdminMiddleware : [Getter/Setter],
* @property {Function} httpServerOptions : [Getter/Setter],
* @property {Function} webSocketNodeVerifyClient : [Getter/Setter],
* @property {Function} exportGlobalContextKeys : [Getter/Setter],
* @property {Function} contextStorage : [Getter/Setter],
* @property {Function} editorTheme : [Getter/Setter],
* @property {string} settingsFile : [Getter/Setter],
* @property {string} httpRoot : [Getter/Setter],
* @property {Function} disableEditor : [Getter/Setter],
* @property {Function} httpAdminAuth : [Getter/Setter],
* @property {Function} httpNodeAuth : [Getter/Setter],
* @property {object|Function} [https] If present, https will be used for ExpressJS servers.
*
* @property {object} [uibuilder] Optional uibuilder specific Node-RED settings
* @property {number} [uibuilder.port] Port number if uib is using its own ExpressJS instance
* @property {string} [uibuilder.uibRoot] Folder name that will hold all uib runtime and instance folders
* @property {('http'|'https')} [uibuilder.customType] Connection type - only if using custom ExpressJS instance
* @property {object|Function} [uibuilder.https] Override https server settings (key/cert) - if not specified, uses main NR https prop
* @property {object} [uibuilder.serverOptions] Optional ExpressJS server options for uib custom server
* @property {object} [uibuilder.socketOptions] Override Socket.IO options if desired. See https://socket.io/docs/v4/server-options/
* @property {boolean} [uibuilder.instanceApiAllowed] Allow instance-level custom API's to be loaded. Could be a security issue so it is controlled in settings.js
* @property {Function} [uibuilder.hooks] Provide hook functions
*
* @property {string} coreNodesDir Folder containing Node-RED core nodes
* @property {string} version Node-RED version
*
* @property {object} logging Controls the type and amount of logging output
* @property {object} logging.console Controls output levels and types to the console log
* @property {string} logging.console.level What level of output? (fatal, error, warn, info, debug, trace)
* @property {boolean} logging.console.metrics Should metrics also be shown?
* @property {boolean} logging.console.audit Should audit also be shown?
*
* @property {Function} get Get dynamic settings. NB: entries in settings.js are read-only and shouldn't be read using RED.settings.get, that is only for settings that can change in-flight.
* @property {Function} set Set dynamic settings
* @property {Function} delete .
* @property {Function} available .
*
* @property {Function} registerNodeSettings : [Function: registerNodeSettings],
* @property {Function} exportNodeSettings : [Function: exportNodeSettings],
* @property {Function} enableNodeSettings : [Function: enableNodeSettings],
* @property {Function} disableNodeSettings : [Function: disableNodeSettings],
*
* @property {Function} getUserSettings : [Function: getUserSettings],
* @property {Function} setUserSettings : [Function: setUserSettings],
*/
/** Node-RED runtimeLogging
* @typedef {object} runtimeLogging Logging. Levels that are output to the Node-RED log are controlled by the logging.console.level setting in settings.js
* @property {Function} fatal Lvel 0. Lowest level, things that have broken Node-RED only.
* @property {Function} error Level 1. Copy is sent to Editor debug panel as well as error log.
* @property {Function} warn Level 2.
* @property {Function} info Level 3.
* @property {Function} debug Level 4.
* @property {Function} trace Level 5. Very verbose output. Should tell the operator everything that is going on.
* @property {Function} metric Log metrics (timings)
* @property {Function} audit Audit log
* @property {Function} addHandler Adds a log handler
* @property {Function} removeHandler Removes a log handler
* @property {10} FATAL : 10,
* @property {20} ERROR : 20,
* @property {30} WARN : 30,
* @property {40} INFO : 40,
* @property {50} DEBUG : 50,
* @property {60} TRACE : 60,
* @property {98} AUDIT : 98,
* @property {99} METRIC: 99,
*/
/** Node-RED runtimeNodes: RED.nodes
* obsidian://open?vault=Obsidian%20Vault&file=Programming%2FNode-RED%2FRuntime%20API's%2FRED.nodes
* @typedef {object} runtimeNodes Gives access to other active nodes in the flows.
* @property {Function} registerType Register a new type of node to Node-RED.
* @property {Function} registerSubflow .
* @property {Function} createNode Create a node instance (called from within registerType Function).
* @property {Function} getNode Get a reference to another node instance in the current flows. Can then access its properties.
* @property {Function} eachNode Walk through each node
* @property {Function} addCredentials .
* @property {Function} getCredentials .
* @property {Function} deleteCredentials .
*/
/** runtimeRED
* @typedef {object} runtimeRED The core Node-RED runtime object
* @property {expressApp} httpAdmin Reference to the ExpressJS app for Node-RED Admin including the Editor
* @property {expressApp} httpNode Reference to the ExpressJS app for Node-RED user-facing nodes including http-in/-out and Dashboard
* @property {Server} server Node.js http(s) Server object
* @property {runtimeLogging} log Logging.
* @property {runtimeNodes} nodes Gives access to other active nodes in the flows.
* @property {runtimeSettings} settings Static and Dynamic settings for Node-RED runtime
*
* @property {Function} version Get the Node-RED version [Function: getVersion],
* @property {Function} require : [Function: requireModule],
* @property {Function} import : [Function: importModule],
* @property {Function} _ Locale translation function. Use with `RED._('key')`
*
* @property {object} auth :
* @property {Function} auth.needsPermission : [Function: needsPermission]
*
* @property {object} library :
* @property {Function} library.register : [Function: register],
*
* @property {object} comms Communicate with admin pages
* @property {Function} comms.publish : [Function: publish],
*
* @property {EventEmitter} events Event handler object
* @property {Function} events.on Event Listener Function. Types: 'nodes-started', 'nodes-stopped'
* @property {Function} events.once .
* @property {Function} events.addListener .
* @property {((name:string, opts:object)=>void)} events.emit Emit a new event
*
* @property {object} hooks .
* @property {Function} hooks.has .
* @property {Function} hooks.clear .
* @property {Function} hooks.add .
* @property {Function} hooks.remove .
* @property {Function} hooks.trigger .
*
* @property {object} util .
* @property {Function} util.encodeObject : [Function: encodeobject],
* @property {Function} util.ensureString : [Function: ensurestring],
* @property {Function} util.ensureBuffer : [Function: ensureBuffer],
* @property {Function} util.cloneMessage : [Function: cloneMessage],
* @property {Function} util.compareObjects : [Function: compareobjects],
* @property {Function} util.generateId : [Function: generateId],
* @property {Function} util.getMessageProperty : [Function: getMessageProperty],
* @property {Function} util.setMessageProperty : [Function: setMessageProperty],
* @property {Function} util.getObjectProperty : [Function: getobjectProperty],
* @property {Function} util.setObjectProperty : [Function: setobjectProperty],
* @property {Function} util.evaluateNodeProperty : [Function: evaluateNodeProperty],
* @property {Function} util.normalisePropertyExpression : [Function: normalisePropertyExpression],
* @property {Function} util.normaliseNodeTypeName : [Function: normaliseNodeTypeName],
* @property {Function} util.prepareJSONataExpression : [Function: prepareJSONataExpression],
* @property {Function} util.evaluateJSONataExpression : [Function: evaluateJSONataExpression],
* @property {Function} util.parseContextStore : [Function: parseContextStore]
* @property {Function} util.getSetting ??
*
* @property {object} util.uib : Added by uibuilder.js - utility functions made available to function nodes
* @property {Function} util.uib.deepObjFind : Recursive object deep find - https://totallyinformation.github.io/node-red-contrib-uibuilder/#/client-docs/config-driven-ui?id=manipulating-msg_ui
* @property {Function} util.uib.listAllApps : Return a list of all uibuilder instances
* @property {Function} util.uib.dp : Return a formatted number using a specified locale and number of decimal places
* @property {Function} util.uib.send : Send a message to a client via a uibuilder instance
* @property {Function} util.uib.truthy : Returns true/false or a default value for truthy/falsy and other values
*
* @property {object} plugins Node-RED plugins
* @property {Function} plugins.registerPlugin : [Function: registerPlugin],
* @property {Function} plugins.get: [Function: get],
* @property {Function} plugins.getByType: [Function: getByType]
*/
/** runtimeNode
* @typedef {object} runtimeNode Local copy of the node instance config + other info
* @property {Function} send Send a Node-RED msg to an output port
* @property {Function} receive Sends the node an input message (e.g. a msg to itself)
* @property {Function} done Dummy done Function for pre-Node-RED 1.0 servers
* @property {Function} context get/set context data. Also .flow and .global contexts
* @property {Function} on Event listeners for the node instance ('input', 'close')
* @property {Function} removeListener Event handling
* @property {Function} log General log output, Does not show in the Editor's debug panel
* @property {Function} warn Warning log output, also logs to the Editor's debug panel
* @property {Function} error Error log output, also logs to the Editor's debug panel
* @property {Function} trace Trace level log output
* @property {Function} debug Debug level log output
* @property {Function} status Show a status message under the node in the Editor
* @property {Function} _ Locale translation function. Use with `node._('key')`
*
* @property {object=} credentials Optional secured credentials
* @property {string=} name name of the node
* @property {string=} id id of the node
* @property {string=} type Internal. Type of node instance.
* @property {string=} z Internal. uid of ???
* @property {string=} g Internal. uid of ???
* @property {[Array<string>]=} wires Internal. Array of Array of strings. The wires attached to this node instance (uid's)
*
* @property {number=} _wireCount Count of connected wires
* @property {string=} _wire ID of connected wire
* @property {[Array<Function>]=} _closeCallbacks ??
* @property {[Array<Function>]=} _inputCallback Input callback fn
* @property {[Array<Function>]=} _inputCallbacks ??
* @property {number=} _expectedDoneCount ??
* @property {Flow=} _flow Full definition of this node's containing flow
* @property {*=} _alias ??
*/
/** runtimeNodeConfig
* @typedef {object} runtimeNodeConfig Configuration of node instance. Will also have Editor panel's defined variables as properties.
* @property {object=} id Internal. uid of node instance.
* @property {object=} type Internal. Type of node instance.
* @property {object=} x Internal
* @property {object=} y Internal
* @property {object=} z Internal. ID of the flow the node belongs to.
* @property {object=} wires Internal. The wires attached to this node instance (uid's)
*/
/** uibuilderEditorVars
* @typedef {object} uibuilderEditorVars The node instance variables accessible from the Editor config panel
*
* @property {string} name Descriptive name, only used by Editor
* @property {string} topic msg.topic overrides incoming msg.topic
* @property {string} url The url path (and folder path) to be used by this instance
* @property {boolean} okToGo Is the url valid for this node or not? Not passed into the node, only used to stop processing.
* @property {string} oldUrl The PREVIOUS url path (and folder path) after a url rename
* @property {boolean} fwdInMessages Forward input msgs to output #1?
* @property {boolean} allowScripts Allow scripts to be sent to front-end via msg? WARNING: can be a security issue.
* @property {boolean} allowStyles Allow CSS to be sent to the front-end via msg? WARNING: can be a security issue.
* @property {boolean} copyIndex DEPRECATED Copy index.(html|js|css) files from templates if they don't exist?
* @property {string} templateFolder Folder name for the source of the chosen template
* @property {string} extTemplate Degit url reference for an external template (e.g. from GitHub)
* @property {boolean} showfolder Provide a folder index web page?
* @property {boolean} reload If true, notify all clients to reload on a change to any source file
* @property {string} sourceFolder (src or dist) the instance FE code folder to be served by ExpressJS
* @property {string} deployedVersion The version of uibuilder when this node was last deployed
* @property {boolean} showMsgUib Whether to include msg._uib (clientId/real IP/page name) in std output msgs
*
* @property {string} customFolder Name of the fs path used to hold custom files & folders for THIS INSTANCE
* @property {number} ioClientsCount How many Socket clients connected to this instance?
* @property {number} rcvMsgCount How many msg's received since last reset or redeploy?
* @property {object} ioChannels The channel names for Socket.IO
* @property {string} ioChannels.control SIO Control channel name 'uiBuilderControl'
* @property {string} ioChannels.client SIO Client channel name 'uiBuilderClient'
* @property {string} ioChannels.server SIO Server channel name 'uiBuilder'
* @property {string} ioNamespace Make sure each node instance uses a separate Socket.IO namespace
* @property {string} title Short descriptive title for the instance
* @property {string} descr Longer description for the instance
* @property {string} editurl Shortcut URL that will open a code editor at the node instance folder
*/
/** uibNode
* @typedef {object} uibNode Local copy of the node instance config + other info
* @property {string} id Unique identifier for this instance
* @property {string} type What type of node is this an instance of? (uibuilder)
*
* @property {string} name Descriptive name, only used by Editor
* @property {string} topic msg.topic overrides incoming msg.topic
* @property {string} url The url path (and folder path) to be used by this instance
* @property {string} oldUrl The PREVIOUS url path (and folder path) after a url rename
* @property {boolean} fwdInMessages Forward input msgs to output #1?
* @property {boolean} allowScripts Allow scripts to be sent to front-end via msg? WARNING: can be a security issue.
* @property {boolean} allowStyles Allow CSS to be sent to the front-end via msg? WARNING: can be a security issue.
* @property {boolean} copyIndex DEPRECATED Copy index.(html|js|css) files from templates if they don't exist?
* @property {string} templateFolder Folder name for the source of the chosen template
* @property {string} extTemplate Degit url reference for an external template (e.g. from GitHub)
* @property {boolean} showfolder Provide a folder index web page?
* @property {boolean} reload If true, notify all clients to reload on a change to any source file
* @property {string} sourceFolder (src or dist) the instance FE code folder to be served by ExpressJS
* @property {string} deployedVersion The version of uibuilder when this node was last deployed
* @property {boolean} showMsgUib Whether to include msg._uib (clientId/real IP/page name) in std output msgs
*
* @property {string} instanceFolder Name of the fs path used to hold custom files & folders for THIS INSTANCE
* @property {number} ioClientsCount How many Socket clients connected to this instance?
* @property {number} rcvMsgCount How many msg's received since last reset or redeploy?
* @property {object} ioChannels The channel names for Socket.IO
* @property {string} ioChannels.control SIO Control channel name 'uiBuilderControl'
* @property {string} ioChannels.client SIO Client channel name 'uiBuilderClient'
* @property {string} ioChannels.server SIO Server channel name 'uiBuilder'
* @property {string} ioNamespace Make sure each node instance uses a separate Socket.IO namespace
*
* @property {Function} send Send a Node-RED msg to an output port
* @property {Function=} done Dummy done Function for pre-Node-RED 1.0 servers
* @property {Function=} on Event handler
* @property {Function=} removeListener Event handling
* @property {Function=} context Function that accesses the nodes context vars or the flow/global vars
* @property {Function=} emit Function that emits an event
* @property {Function=} receive Function that ???
* @property {object=} credentials Optional secured credentials
* @property {object=} z Internal
* @property {object=} wires Internal. The wires attached to this node instance (uid's)
*
* @property {boolean} commonStaticLoaded Whether the common static folder has been added
* @property {boolean} initCopyDone Has the initial template copy been done?
*
* @property {Function} warn Output warn level info to node-red console and to editor debug
*
* @property {object} statusDisplay Settings for the uibuilder node status
* @property {string} statusDisplay.text Text to display
* @property {string} statusDisplay.fill Fill colour: black, blue, red, yellow, ...
* @property {string} statusDisplay.shape dot or ring
*
* @property {string} title Short descriptive title for the instance
* @property {string} descr Longer description for the instance
* @property {string} editurl Shortcut URL that will open a code editor at the node instance folder
*
* @property {Function} sendToFe Ref to sockets.sendToFe
* @property {Function} sender Ref to uib-sender event sending function
*/
/** uibConfig - THe module-level `uib` configuration variable
* @typedef {object} uibConfig Local copy of the node master config + other module-level info
* @property {object} me Contents of uibuilder's `package.json` file
* @property {string} moduleName Module name must match this nodes html file.
*
* Default 'uibuilder'
* @property {string} nodeRoot URL path prefix set in `settings.js` - prefixes all URL's -
* equiv of httpNodeRoot from settings.js.
*
* Default `empty string`.
* @property {object} deployments Track across redeployments
* @property {object} instances When nodeInstance is run, add the node.id as a key with the value being the
* url then add processing to ensure that the URL's are unique.
*
* Schema: `{<node.id>: <url>}`
* @property {object} apps Instance details
* Schema: `{url: {node.id, node.url, node.title, node.desc}}
* @property {string} masterTemplateFolder Location of master template folders (containing default front-end code).
*
* Default `../template`
* @property {string} masterStaticFeFolder Location of master FE folder (containing built core front-end code).
*
* Default `../front-end`
* @property {string|null} rootFolder Folder on the server FS to hold common & custom files & folders for all instances of uibuilder.
*
* Cannot be set until we have the RED object and know if projects are being used.
*
* **Can be changed by `settings.js`**
*
* Default `<userDir>/<uib.moduleName>` or `<userDir>/projects/<currProject>/<uib.moduleName>`
* @property {string|null} configFolder Location for uib config folder - set once rootFolder is finalised
* @property {string} configFolderName Name of the config folder. Default `.config`
* @property {string|null} commonFolder Location for uib common folder - set once rootFolder is finalised
* @property {string} commonFolderName URI name of the common folder for shared resources. Default `common`
* @property {string} sioUseMwName Name of the optional Socket.IO per-msg input `use` middleware. Default 'sioUse.js' in the uibRoot/.config folder
* @property {string} sioMsgOutMwName Name of the optional Socket.IO per-msg output middleware. Default 'sioMsgOut.js' in the uibRoot/.config folder
* @property {object} ioChannels The channel names for Socket.IO.
* @property {string} ioChannels.control Channel for control messages. Default `uiBuilderControl`
* @property {string} ioChannels.client Channel for messages to front-end clients. Default `uiBuilderClient`
* @property {string} ioChannels.server Channel for messages from clients to server. Default `uiBuilder`
* @property {Array<number|string>} nodeVersion What version of Node.JS are we running under? Impacts some file processing.
* @property {object} staticOpts Options for serveStatic. See https://expressjs.com/en/resources/middleware/serve-static.html
* @property {{url:string,value:boolean}|{}} deleteOnDelete Set of instances that have requested their local instance folders be
* deleted on deploy - see html file oneditdelete, updated by admin api.
* Actually set in admin-api-v3.js/put and consumed in uiblib.js/instanceClose
* @property {object} customServer Set in libs/web.js:_webSetup()
* Parameters for custom webserver if required. Port is undefined if using Node-RED's webserver.
* @property {undefined|number} customServer.port TCP/IP port number.
*
* If defined, uibuilder will use its own ExpressJS server/app.
*
* If undefined, uibuilder will use the Node-RED user-facing ExpressJS server
* @property {('http'|'https'|'http2')} customServer.type Node.js server type. One of ['http', 'https', 'http2']
* @property {undefined|string} customServer.host uibuilder Host. sub(domain) name or IP Address
* @property {undefined|string} customServer.hostName The host name of the Node-RED server
* @property {boolean} customServer.isCustom Is uibuilder using a custom ExpressJS server?
* @property {object} customServer.serverOptions Optional ExpressJS server options
*
* @property {undefined|object} degitEmitter Event emitter for degit, populated on 1st use. See POST admin API
* @property {runtimeRED|null} RED Keep a reference to RED for convenience. Set at the start of Uib
* @property {string=} version The deployed version of uibuilder (from `package.json`)
* @property {string=} httpRoot Copy of RED.settings.httpRoot for ease of use
* @property {string=} reDeployNeeded If the last deployed version is this version or earlier and the current version is greater than this, tell the Editor that a redeploy is needed
* @property {boolean} instanceApiAllowed Are instance-level API's allowed to be loaded? Could be a security issue so controlled from settings.js uibuilder.instanceApiAllowed. Default=false
*/
/** senderNode1
* @typedef {{
* name: string;
* topic: string;
* passthrough: boolean;
* return: boolean;
* url: string;
* uibId: string;
* }} senderNode1
*/
/** cacheNode1
* @typedef {object} cacheNode1 Local copy of the node instance config + other info
* @property {string} name only used for labelling the node in the flow
* @property {boolean} cacheall Flag indicating each individual msg is cached
* @property {string|undefined} cacheKey msg property to use to group cached msgs
* @property {boolean} newcache Only replay cache if client is actually new, not a reconnection
* @property {number} num number of cached msgs to retain
* @property {string} storeName Which store to use for the context variable
* @property {'context'|'flow'|'node'} storeContext Which store to use for the context variable
* @property {object} cache A reference to the actual cache for this node instance
* @property {string} varName The variable name in use in the store
* @property {Function} getC A reference to the context get function for this node instance
* @property {Function} setC A reference to the context set function for this node instance
*/
/** uibListNode
* @typedef {{
* name: string;
* url: string;
* elementid: string;
* elementtype: string;
* parent: string;
* passthrough: boolean;
* cacheOn: boolean;
* storeName: string;
* storeContext: 'context'|'flow'|'node';
* varName: string;
* newcache: boolean;
* cache: object;
* getC: Function;
* setC: Function;
* _ui: any;
* }} uibListNode
*/
/** uibElNode (Element Node)
* @typedef {{
* name: string;
* topic: string;
* elementtype: string;
* parent: string;
* parentSource: string;
* parentSourceType: string;
* elementid: string;
* elementId: string;
* elementIdSource: string;
* elementIdSourceType: string;
* heading: string;
* headingSource: string;
* headingSourceType: string;
* headingLevel: string;
* data: any;
* dataSource: string|number;
* dataSourceType: string;
* position: string|number;
* positionSource: string|number;
* positionSourceType: string;
* confData: object;
* passthrough: boolean;
* _ui: any;
* tag: string;
* }} uibElNode
*/
/** uibTagNode (Tag Node)
* @typedef {{
* name: string;
* topic: string;
* tag: string;
* tagSource: string;
* tagSourceType: string;
* elementId: string;
* elementIdSource: string;
* elementIdSourceType: string;
* parent: string;
* parentSource: string;
* parentSourceType: string;
* position: string|number;
* positionSource: string|number;
* positionSourceType: string;
*
* slotContent: string;
* slotSourceProp: string;
* slotContentSource: string;
* slotContentSourceType: string;
* slotSourcePropType: string;
* attribs: object;
* attribsSource: string;
* attribsSourceType: string;
* slotPropMarkdown: boolean;
* _ui: any;
* }} uibTagNode
*/
/** uibHtmlNode (HTML Node)
* @typedef {{
* name: string;
* topic: string;
* useTemplate: boolean;
* _ui: any;
* }} uibHtmlNode
*/
/** uibSaveNode (Save Node)
* @typedef {{
* url: string;
* folder: string;
* fname: string;
* createFolder: boolean;
* reload: boolean;
* usePageName: boolean;
* encoding: string;
* mode: number;
* uibId: string;
* instanceRoot: string;
* name: string;
* topic: string;
* counters: object;
* statusDisplay: object;
* }} uibSaveNode
*/
/** uibFileListNode (File List Node)
* @typedef {{
* name: string;
* topic: string;
* url: string;
* uibId: string;
* folder: string;
* filter: Array<string>;
* exclude: string;
* urlOut: boolean;
* live: boolean;
* fullPrefix: boolean;
* statusDisplay: object;
* }} uibFileListNode
*/
/** uibUpdNode (Update Node)
* @typedef {{
* name: string;
* topic: string;
* mode: 'update'|'delete'|'remove'|'msg.mode';
* modeSource: string;
* modeSourceType: string;
* cssSelector: string;
* cssSelectorSource: string;
* cssSelectorType: string;
* cssSelectorSourceType: string;
* slotContent: string;
* slotSourceProp: string;
* slotContentSource: string;
* slotContentSourceType: string;
* slotSourcePropType: string;
* attribs: object;
* attribsSource: string;
* attribsSourceType: string;
* slotPropMarkdown: boolean;
* _ui: any;
* }} uibUpdNode
*/
/** LibLowCodeNode (nodes/libs/low-code.js)
* @typedef {{
* _ui: any;
* elementId: string;
* parent: string;
* tag: string;
* position: string|number;
* slotPropMarkdown: boolean;
* slotContent: string;
* attribs: object;
* }} LibLowCodeNode
*/
/** MsgAuth
* @typedef {object} MsgAuth The standard auth object used by uibuilder security. See docs for details.
* Note that any other data may be passed from your front-end code in the _auth.info object.
* _auth.info.error, _auth.info.validJwt, _auth.info.message, _auth.info.warning
* @property {object} MsgAuth .
* @property {string|null} MsgAuth.id Required. A unique user identifier.
* @property {string} [MsgAuth.password] Required for login only.
* @property {string} [MsgAuth.jwt] Required if logged in. Needed for ongoing session validation and management.
* @property {number} [MsgAuth.sessionExpiry] Required if logged in. Milliseconds since 1970. Needed for ongoing session validation and management.
* @property {boolean} [MsgAuth.userValidated] Required after user validation. Whether the input ID (and optional additional data from the _auth object) validated correctly or not.
* @property {object=} [MsgAuth.info] Optional metadata about the user.
*/
/** userValidation
* @typedef {object} userValidation Optional return object that is able to pass on additional use metadata back to the client.
* @property {object} userValidation Optional return object that is able to pass on additional use metadata back to the client.
* @property {boolean} userValidation.userValidated Required. Whether the input ID (and optional additional data from the _auth object) validated correctly or not.
* @property {userMetadata} [userValidation.authData] Optional return metadata about the user. Will be added to the output msg's _auth object
*/
/** userMetadata
* @typedef {object} userMetadata Optional. Metadata about the user. Will be added to the output msg's _auth object.
* This is just an example of what you might want to return, you can send anything you like.
* @property {object} userMetadata Optional. Metadata about the user. Will be added to the output msg's _auth object.
* @property {string} [userMetadata.name] Users full name or screen name.
* @property {string} [userMetadata.message] A message that the front-end code could use to display to the user when they log in.
* @property {string} [userMetadata.level] Users authorisation level (admin, gold, silver, reader, editor, author, ...).
* @property {string} [userMetadata.location] Users location.
* @property {Date} [userMetadata.passwordExpiry] Date/time the users password expires.
* @property {Date} [userMetadata.subsExpiry] Date/time the users subscription expires.
*/
/** uibPackageJsonPackage
* @typedef {{
* estimatedEntryPoint?: string;
* homepage?: string;
* installedFrom?: string;
* installedVersion?: string;
* installFolder?: string;
* latestVersion?: string;
* missing?: boolean;
* outdated?: object;
* packageUrl?: string;
* problems?: Array<string>;
* scope?: string;
* spec?: string;
* url?: string;
* }} uibPackageJsonPackage
*/
/** uibPackageJson
* The package.json file in the uibRoot folder. Contains uibuilder extensions
* @typedef {{
* name?: string;
* version?: string;
* description?: string;
* scripts?: {} | {
* [key: string]: string;
* };
* dependencies?: {} | {
* [key: string]: string;
* };
* homepage?: string;
* bugs?: string;
* author?: string;
* license?: string;
* repository?: object;
* uibuilder?: {
* packages?: {} | {
* [key: string]: uibPackageJsonPackage;
* };
* };
* }} uibPackageJson
*/
/** routeDefinition
* @typedef {object} routeDefinition Single route configuration
* @property {string} id REQUIRED. Route ID
* @property {string} src REQUIRED for external, optional for internal (default=route id). CSS Selector for template tag routes, url for external routes
* @property {"url"|undefined} [type] OPTIONAL, default=internal route. "url" for external routes
* @property {string} [title] OPTIONAL, default=route id. Text to use as a short title for the route
* @property {string} [description] OPTIONAL, default=route id. Text to use as a long description for the route
* @property {"html"|"md"|"markdown"} [format] OPTIONAL, default=html. Route content format, HTML or Markdown (md). Markdown requires the Markdown-IT library to have been loaded.
*/
/** UibRouterConfig
* @typedef {object} UibRouterConfig Configuration for the UiBRouter class instances
* @property {routeDefinition[]} routes REQUIRED. Array of route definitions
* @property {Array<string|object>} [mdPlugins] OPTIONAL. Array of Markdown-IT plugins
* @property {string} [defaultRoute] OPTIONAL, default=1st route. If set to a route id, that route will be automatically shown on load
* @property {string} [routeContainer] OPTIONAL, default='#uibroutecontainer'. CSS Selector for an HTML Element containing routes
* @property {boolean} [hide] OPTIONAL, default=false. If TRUE, routes will be hidden/shown on change instead of removed/added
* @property {boolean} [templateLoadAll] OPTIONAL, default=false. If TRUE, all external route templates will be loaded when the router is instanciated. Default is to lazy-load external templates
* @property {boolean} [templateUnload] OPTIONAL, default=true. If TRUE, route templates will be unloaded from DOM after access.
* @property {otherLoadDefinition[]} [otherLoad] OPTIONAL, default=none. If present, router start will pre-load other external templates direct to the DOM. Use for menu's, etc.
*/
/** otherLoadDefinition
* @typedef {object} otherLoadDefinition Single external load configuration
* @property {string} id REQUIRED. Unique (to page) ID. Will be applied to loaded content.
* @property {string} src REQUIRED. url of external template to load
* @property {string} container REQUIRED. CSS Selector defining the parent element that this will become the child of. If it doesn't exist on page, content will not be loaded.
*/
/** routeMenu
* @typedef {object} routeMenu
* @property {string} id REQUIRED. Unique (to page) ID. Used as the menu container
* @property {"horizontal"|"vertical"} menuType OPTIONAL. Type of menu to create. Default is "horizontal".
* @property {string} src REQUIRED. url of external template to load
* @property {string} container REQUIRED. CSS Selector defining the parent element that this will become the child of. If it doesn't exist on page, content will not be loaded.
* @property {string} [title] OPTIONAL. Text to use as a short title for the route
*/
/** Node-RED WidgetTypedInputType
* @typedef { Array<"bin"|"bool"|"date"|"env"|"flow"|"global"|"json"|"jsonata"|"msg"|"num"|"re"|"str"> } WidgetTypedInputType
*/
/** Props define attributes on a virtual node.
* @typedef {{string, any} | {}} Props
* @property {object} Props .
* @property {Children} Props.children .
*/
/** The vnode children of a virtual node.
* @typedef {VNode[]} Children
*/
/** Define a custom type for virtual nodes:
* @typedef {string | number | Function} Type
*/
/** Define a custom type for virtual nodes:
* @typedef {{string, any}} VNode
* @property {{string, any}} VNode .
* @property {Type} VNode.type .
* @property {Props} VNode.props .
* @property {Children} VNode.children .
* @property {string} [VNode.key] .
*/
// ==== vvv These need some work vvv ==== //
/** ExpressJS App
* @typedef {object} expressApp ExpessJS `app` object
* @property {object} _events : [object: null prototype] { mount: [Function: onmount] },
* @property {number} _eventsCount : 1,
* @property {number} _maxListeners : undefined,
* @property {Function} setMaxListeners : [Function: setMaxListeners],
* @property {Function} getMaxListeners : [Function: getMaxListeners],
* @property {Function} emit : [Function: emit],
* @property {Function} addListener : [Function: addListener],
* @property {Function} on : [Function: addListener],
* @property {Function} prependListener : [Function: prependListener],
* @property {Function} once : [Function: once],
* @property {Function} prependOnceListener : [Function: prependOnceListener],
* @property {Function} removeListener : [Function: removeListener],
* @property {Function} off : [Function: removeListener],
* @property {Function} removeAllListeners : [Function: removeAllListeners],
* @property {Function} listeners : [Function: listeners],
* @property {Function} rawListeners : [Function: rawListeners],
* @property {Function} listenerCount : [Function: listenerCount],
* @property {Function} eventNames : [Function: eventNames],
* @property {Function} init : [Function: init],
* @property {Function} defaultConfiguration : [Function: defaultConfiguration],
* @property {Function} lazyrouter : [Function: lazyrouter],
* @property {Function} handle : [Function: handle],
* @property {Function} use : [Function: use],
* @property {Function} route : [Function: route],
* @property {Function} engine : [Function: engine],
* @property {Function} param : [Function: param],
* @property {Function} set : [Function: set],
* @property {Function} path : [Function: path],
* @property {Function} enabled : [Function: enabled],
* @property {Function} disabled : [Function: disabled],
* @property {Function} enable : [Function: enable],
* @property {Function} disable : [Function: disable],
* @property {Function} acl : [Function (anonymous)],
* @property {Function} bind : [Function (anonymous)],
* @property {Function} checkout : [Function (anonymous)],
* @property {Function} connect : [Function (anonymous)],
* @property {Function} copy : [Function (anonymous)],
* @property {Function} delete : [Function (anonymous)],
* @property {Function} get : [Function (anonymous)],
* @property {Function} head : [Function (anonymous)],
* @property {Function} link : [Function (anonymous)],
* @property {Function} lock : [Function (anonymous)],
* @property {Function} "m-search" : [Function (anonymous)],
* @property {Function} merge : [Function (anonymous)],
* @property {Function} mkactivity : [Function (anonymous)],
* @property {Function} mkcalendar : [Function (anonymous)],
* @property {Function} mkcol : [Function (anonymous)],
* @property {Function} move : [Function (anonymous)],
* @property {Function} notify : [Function (anonymous)],
* @property {Function} options : [Function (anonymous)],
* @property {Function} patch : [Function (anonymous)],
* @property {Function} post : [Function (anonymous)],
* @property {Function} pri : [Function (anonymous)],
* @property {Function} propfind : [Function (anonymous)],
* @property {Function} proppatch : [Function (anonymous)],
* @property {Function} purge : [Function (anonymous)],
* @property {Function} put : [Function (anonymous)],
* @property {Function} rebind : [Function (anonymous)],
* @property {Function} report : [Function (anonymous)],
* @property {Function} search : [Function (anonymous)],
* @property {Function} source : [Function (anonymous)],
* @property {Function} subscribe : [Function (anonymous)],
* @property {Function} trace : [Function (anonymous)],
* @property {Function} unbind : [Function (anonymous)],
* @property {Function} unlink : [Function (anonymous)],
* @property {Function} unlock : [Function (anonymous)],
* @property {Function} unsubscribe : [Function (anonymous)],
* @property {Function} all : [Function: all],
* @property {Function} del : [Function (anonymous)],
* @property {Function} render : [Function: render],
* @property {Function} listen : [Function: listen],
* @property {Function} request : IncomingMessage { app: [Circular *1] },
* @property {Function} response : ServerResponse { app: [Circular *1] },
*
* @property {object} cache : {},
* @property {object} engines : {},
*
* @property {{
* 'x-powered-by': boolean,
* etag: string,
* "etag fn": Function,
* env: string,
* 'query parser' : string,
* 'query parser fn' : Function,
* 'subdomain offset': number,
* view: Function,
* views: string,
* 'jsonp callback name' : string
* }} settings ExpressJS App Settings
*
* property {boolean} settings.'x-powered-by' : true,
* property {string} settings.etag : 'weak',
* property {Function} settings."etag fn" : [Function: generateETag],
* property {string} settings.env : 'development',
* property {string} settings.'query parser' : 'extended',
* property {Function} settings.'query parser fn' : [Function: parseExtendedQuerystring],
* property {number} settings.'subdomain offset' : 2,
* property {Function} settings.view : [Function: View],
* property {string} settings.views : 'C:\\src\\nr2\\views',
* property {string} settings.'jsonp callback name' : 'callback'
*
* @property {object} locals : [object: null prototype] { settings: [object] },
* @property {string} mountpath : '/nr/',
*
* @property {Function} parent : [Function: app] {
* @property {Function} parent._events : [object: null prototype],
* @property {Function} parent._eventsCount : 1,
* @property {Function} parent._maxListeners : undefined,
* @property {Function} parent.setMaxListeners : [Function: setMaxListeners],
* @property {Function} parent.getMaxListeners : [Function: getMaxListeners],
* @property {Function} parent.emit : [Function: emit],
* @property {Function} parent.addListener : [Function: addListener],
* @property {Function} parent.on : [Function: addListener],
* @property {Function} parent.prependListener : [Function: prependListener],
* @property {Function} parent.once : [Function: once],
* @property {Function} parent.prependOnceListener : [Function: prependOnceListener],
* @property {Function} parent.removeListener : [Function: removeListener],
* @property {Function} parent.off : [Function: removeListener],
* @property {Function} parent.removeAllListeners : [Function: removeAllListeners],
* @property {Function} parent.listeners : [Function: listeners],
* @property {Function} parent.rawListeners : [Function: rawListeners],
* @property {Function} parent.listenerCount : [Function: listenerCount],
* @property {Function} parent.eventNames : [Function: eventNames],
* @property {Function} parent.init : [Function: init],
* @property {Function} parent.defaultConfiguration : [Function: defaultConfiguration],
* @property {Function} parent.lazyrouter : [Function: lazyrouter],
* @property {Function} parent.handle : [Function: handle],
* @property {Function} parent.use : [Function: use],
* @property {Function} parent.route : [Function: route],
* @property {Function} parent.engine : [Function: engine],
* @property {Function} parent.param : [Function: param],
* @property {Function} parent.set : [Function: set],
* @property {Function} parent.path : [Function: path],
* @property {Function} parent.enabled : [Function: enabled],
* @property {Function} parent.disabled : [Function: disabled],
* @property {Function} parent.enable : [Function: enable],
* @property {Function} parent.disable : [Function: disable],
* @property {Function} parent.acl : [Function (anonymous)],
* @property {Function} parent.bind : [Function (anonymous)],
* @property {Function} parent.checkout : [Function (anonymous)],
* @property {Function} parent.connect : [Function (anonymous)],
* @property {Function} parent.copy : [Function (anonymous)],
* @property {Function} parent.delete : [Function (anonymous)],
* @property {Function} parent.get : [Function (anonymous)],
* @property {Function} parent.head : [Function (anonymous)],
* @property {Function} parent.link : [Function (anonymous)],
* @property {Function} parent.lock : [Function (anonymous)],
* @property {Function} parent.'m-search' : [Function (anonymous)],
* @property {Function} parent.merge : [Function (anonymous)],
* @property {Function} parent.mkactivity : [Function (anonymous)],
*
* @property {Function} _router : [Function]
*/
module.exports = {}
/* RED
{
"loader": {},
"events": {},
"i18n": {},
"settings": {
"apiRootUrl": "",
"httpNodeRoot": "/nr/",
"version": "1.2.7",
"user": {
"anonymous": true,
"permissions": "*"
},
"context": {
"default": "default",
"stores": [
"default",
"file"
]
},
"flowFilePretty": true,
"flowEncryptionType": "user",
"tlsConfigDisableLocalFiles": false,
"uibuilderNodeEnv": "development", // === CUSTOM ===
"uibuilderTemplates": {}, // === CUSTOM ===
"uibuilderPort": 3000, // === CUSTOM ===
"editorTheme": {},
"get": Function,
init: Function,
load: Function,
loadUserSettings: Function,
remove: Function,
set: Function,
theme: Function,
"user": {},
"comms": {},
"text": {},
"state": {},
"nodes": {},
"history": {},
"validators": {},
"utils": {},
"menu": {},
"panels": {},
"popover": {},
"tabs": {},
"stack": {},
"colorPicker": {},
"actions": {},
"deploy": {},
"diff": {},
"keyboard": {},
"workspaces": {},
"statusBar": {},
"view": {
"navigator": {},
"tools": {}
},
"sidebar": {},
"palette": {},
"editor": {},
"eventLog": {},
"tray": {},
"clipboard": {},
"library": {},
"notifications": {},
"search": {},
"actionList": {},
"typeSearch": {},
"subflow": {},
"group": {},
"userSettings": {},
"projects": {},
"touch": {},
"debug": {}
}
*/
/* this
{
name: ""
topic: ""
//... other vars ...//
credentials: { has_jwtSecret: false, _: { … } }
changed: false
dirty: false
icon: undefined
id: "b18a50dd.f7e5c"
info: undefined
infoEditor: w { $toDestroy: Array(46), container: div.red - ui - editor - text - container.ace_editor.ace_hidpi.red - ui - editor - text - container - toolbar.ace - tomo…, renderer: y, id: "editor2", commands: o, … }
inputLabels: ""
inputs: 1
outputLabels: ['','']
outputs: 2
resize: false
selected: true
status: { text: "Node Initialised", fill: "blue", shape: "dot" }
type: "uibuilder"
valid: true
validationErrors: []
g: "c49c82f3.7e716"
h: 30
l: true
w: 120
x: 530
y: 120
z: "18cb249f.38bafb"
_: ƒ()
__outputs: 2
_config: { name: """", topic: """", url: ""vue - file"", fwdInMessages: "false", allowScripts: "false", … }
_def: { category: "uibuilder", color: "#E6E0F8", defaults: { … }, credentials: { … }, inputs: 1, … }
}
*/