You can add some level of intelligence to VScode. Though I would say that I don't think that the Node-RED typings have been updated for quite a while. Here is a snippet from the uibuilder node package:
"devDependencies": {
"@types/express": "^4.17.13",
"@types/jquery": "^3.5.8",
"@types/node": "^14.18.29",
"@types/node-red": "^1.1.1",
"eslint": "^8.31.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-es": "^4.1.0",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsdoc": "^46.4.2",
"eslint-plugin-n": "^16.0.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-sonarjs": "^0",
"gulp": "^4.0.2",
"gulp-clean-css": "^4.3.0",
"gulp-debug": "^4.0.0",
"gulp-esbuild": "^0.11.1",
"gulp-htmlmin": "^5.0.1",
"gulp-include": "^2.4.1",
"gulp-json-editor": "^2.5.6",
"gulp-once": "^2.1.1",
"gulp-prompt": "^1.2.0",
"gulp-rename": "^2.0.0",
"gulp-replace": "^1.1.3",
"gulp-uglify": "^3.0.2"
},
It is the types that give you some VSC intelligence. The eslint stuff gives you a check of both obvious errors and code formatting.
One of the frustrating things about developing nodes is that the Editor HTML file has to be in the same location as the runtime js file - since they really need different eslint settings. That's one of the reasons I no longer directly develop the Editor HTML file. I use a separate src folder with the 3 separate parts of the html file and use a gulp watch to automatically build the actual html file. A bit overkill for simple nodes but much easier to work on.
In regard to the node-red typings, I actually use my own custom typedefs.js
file where I define all of the main object structures I am using. I use that to define the base node-red node
definition that I can reuse and then I supplement it with each nodes specific definitions.
Here is an extract:
/** 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 {Function} debugMaxLength : [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 {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
*/
/** Node-RED runtimeNodes
* @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} 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 .
* @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 {object} 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
* @property {Function} require : [Function: requireModule],
* @property {Function} comms : { publish: [Function: publish] },
* @property {Function} library : { register: [Function: register] },
* @property {Function} auth : { needsPermission: [Function: needsPermission] },
*
* @property {object} 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 {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]
*/
/** 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} 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 {object=} credentials Optional secured credentials
* @property {object=} name Internal.
* @property {object=} id Internal. uid of node instance.
* @property {object=} type Internal. Type of node instance.
* @property {object=} z Internal. uid of ???
* @property {[Array<string>]=} wires Internal. Array of Array of strings. The wires attached to this node instance (uid's)
*/
/** 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
* @property {object=} wires Internal. The wires attached to this node instance (uid's)
*/
module.exports = {}