🤖 Merge PR #46284 [node-red] New definitions (rewrites defs for 1 module, adds defs for 5 dep modules) by @alexk111

* New definitions for node-red

* [@node-red/util] Add jsonata dep

* [node-red] Add v0

* [node-red] Merge namespaces

* Fix compilation error caused by a space from prettier
This commit is contained in:
Alex Kaul 2020-08-12 10:57:22 +07:00 committed by GitHub
parent 55e2c9837e
commit 3181e16275
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 5140 additions and 246 deletions

View File

@ -1,221 +1,232 @@
// Type definitions for node-red 0.20
// Project: http://nodered.org
// Type definitions for node-red 1.1
// Project: https://github.com/node-red/node-red/tree/master/packages/node_modules/node-red, https://nodered.org/
// Definitions by: Anders E. Andersen <https://github.com/andersea>
// Thomas B. Mørch <https://github.com/tbowmo>
// Bernardo Belchior <https://github.com/bernardobelchior>
// Alex Kaul <https://github.com/alexk111>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 3.4
// Minimum TypeScript Version: 3.1
/// <reference types="node" />
// tslint:disable:no-empty-interface
import { Express } from 'express';
import { EventEmitter } from 'events';
import { Server as HttpServer } from 'http';
/**
* Node-RED node creation api.
*/
export interface Red {
/** Node lifecycle management api. Used by all nodes. */
nodes: Nodes;
log: any;
settings: any;
events: any;
util: any;
httpAdmin: any;
auth: any;
comms: any;
library: any;
httpNode: any;
server: any;
/** Returns the version of the running Node-RED environment. */
version(): string;
}
/**
* Node base type.
*
* See the Nodes interfaces registerType() method for information about
* declaring node constructors in typescript.
*
* The id, type and name properties are available after the
* call to RED.nodes.createNode().
*/
export interface Node extends EventEmitter, NodeProperties {
updateWires(wires: any): void;
context(): any;
close(removed: any): void;
/**
* Send one or more messages to multiple downstream nodes.
* It is possible to send multiple messages to any
* one node by sending an array to the node instead
* of a single message.
* @param msg - array of messages and/or message bundle arrays.
*/
send(msg: any[]): void;
/**
* Send a message to the downstream node. If msg is null or
* undefined, no message is sent.
* @param msg - optional message to send.
*/
send(msg?: any): void;
/**
* Send a message to this node.
* @param msg - optional message to send.
*/
receive(msg: any): void;
/**
* Log an log-level event. Used for mundane events
* that are part of the normal functioning of the
* node.
* @param msg - message to log.
*/
log(msg: any): void;
/**
* Log a warn-level event. For important events
* that the user should be made aware of.
* @param msg - message to log.
*/
warn(msg: any): void;
/**
* Log an error-level event. To trigger catch nodes on
* the workflow call the function with msg set to the
* original message.
* @param logMessage - description of the error.
* @param msg - optional payload that caused the error.
*/
error(logMessage: any, msg?: any): void;
/**
* Log a debug-level event. Use this is for logging
* internal detail not needed for normal operation.
* @param msg - message to log.
*/
debug(msg: any): void;
/**
* Log a trace-level event. Even more internal details than
* debug-level.
* @param msg - message to log.
*/
trace(msg: any): void;
metric(eventname?: any, msg?: any, metricValue?: any): void;
/**
* Set or clear node status.
*
* For more info see: https://nodered.org/docs/creating-nodes/status
* @param status - the status to set or an empty object to clear the
* node status.
*/
status(status: NodeStatus | ClearNodeStatus): void;
}
/**
* Contains the user selected property values
* for the node.
*
* This object is also known as the node's definition
* object.
*/
export interface NodeProperties {
/** This node's unique identifier. */
id: NodeId;
/** The type name for this node. */
type: NodeType;
/**
* The UI visible name for this node. Many nodes
* allow the user to pick the name and provide
* a fallback name, if they leave it blank.
*/
name: string;
}
/** Unique node identifier. */
export type NodeId = string;
/** Node type name. */
export type NodeType = string;
/** Node status icon color choices. */
export type StatusFill = "red" | "green" | "yellow" | "blue" | "grey";
/** Node status icon shape choices. */
export type StatusShape = "ring" | "dot";
/**
* Object used to set the nodes status flag.
*/
export interface NodeStatus {
/** Selects the icon color. */
fill: StatusFill;
/** Selects either ring or dot shape. */
shape: StatusShape;
/** Status label. */
text: string;
}
/** Fancy definition that matches an empty object. */
export interface ClearNodeStatus {
fill?: undefined;
shape?: undefined;
text?: undefined;
}
export interface Nodes {
/**
* Node constructor functions must call this to
* finish setting up the node. Among other things
* it adds the node credentials, which are stored
* outside the flow.
*
* @param node - the node object under construction.
* @param props - the node's properties object, aka.
* the node instance definition.
*/
createNode(node: Node, props: NodeProperties): void;
/**
* Get a node by NodeID.
*
* If your node uses a configuration
* node, this call is used to get access to the running
* instance.
* @param id - the id of the node.
* @return - the node matching the given id, or null if it does not exist.
*/
getNode(id: NodeId): Node | null;
/**
* Cycle through all node definition objects.
*
* To get the actual node, use getNode() with the id
* from the definition object.
*/
eachNode(callback: (node: NodeProperties) => any): void;
/**
* Adds a set of credentials for the given node id.
* @param id the node id for the credentials
* @param creds an object of credential key/value pairs
*/
addCredentials(id: NodeId, creds: object): void;
/**
* Gets the credentials for the given node id.
* @param id the node id for the credentials
* @return the credentials
*/
getCredentials(id: NodeId): object;
/**
* Deletes the credentials for the given node id.
* @param id the node id for the credentials
*/
deleteCredentials(id: NodeId): void;
/**
* Registers a node constructor.
*
* Node constructors should be declared as functions with an explicit this
* argument of a type descending from the Node interface. You can extend
* the NodeProperties interface also, to add your node's properties.
*
* Example, using in-line declaration:
*
* RED.nodes.registerType('my-node', function(this: MyNode, props: MyProperties)
* => { RED.nodes.createNode(this, props); ... }, { ... });
* @param type - the string type name
* @param constructor - the constructor function for this node type
* @param opts - optional additional options for the node
*/
// tslint:disable-next-line no-unnecessary-generics
registerType<T extends NodeProperties>(type: string, constructor: (props: T) => any, opts?: any): void;
import * as editorAPI from '@node-red/editor-api';
import * as editorClient from '@node-red/editor-client';
import * as registry from '@node-red/registry';
import * as runtime from '@node-red/runtime';
import * as util from '@node-red/util';
declare const nodeRed: nodeRed.NodeRedApp;
export = nodeRed;
declare namespace nodeRed {
interface NodeRedApp {
/**
* Initialise the Node-RED application.
* @param httpServer - the HTTP server object to use
* @param userSettings - an object containing the runtime settings
*/
init: (httpServer: HttpServer, userSettings: runtime.LocalSettings) => void;
/**
* Start the Node-RED application.
*/
start: () => Promise<void>;
/**
* Stop the Node-RED application.
*/
stop: () => Promise<void>;
/**
* Logging utilities
*/
log: util.Log;
/**
* General utilities
*/
util: util.Util;
/**
* This provides access to the internal nodes module of the
* runtime. The details of this API remain undocumented as they should not
* be used directly.
*
* Most administrative actions should be performed use the runtime api
* under @node-red/runtime.
*/
readonly nodes: runtime.InternalNodesModule;
/**
* Runtime events emitter
*/
events: EventEmitter;
/**
* This provides access to the internal settings module of the
* runtime.
*/
readonly settings: runtime.PersistentSettings;
/**
* Get the version of the runtime
*/
readonly version: string;
/**
* The express application for the Editor Admin API
*/
readonly httpAdmin: Express;
/**
* The express application for HTTP Nodes
*/
readonly httpNode: Express;
/**
* The HTTP Server used by the runtime
*/
readonly server: HttpServer;
/**
* The runtime api
*/
runtime: runtime.RuntimeModule;
/**
* The editor authentication api.
*/
auth: editorAPI.Auth;
}
/*******************************************************************
* Type shortcuts for writing the runtime side of nodes (.js file)
*******************************************************************/
/**
* Type def for the functions that should be exported
* by the node .js files.
*/
interface NodeInitializer<TSets extends NodeAPISettingsWithData = NodeAPISettingsWithData>
extends registry.NodeInitializer<TSets> {}
interface NodeConstructor<TNode extends Node<TCreds>, TNodeDef extends NodeDef, TCreds>
extends registry.NodeConstructor<TNode, TNodeDef, TCreds> {}
interface NodeAPISettingsWithData extends registry.NodeAPISettingsWithData {}
interface NodeSetting<T> extends registry.NodeSetting<T> {}
type NodeSettings<TSets> = registry.NodeSettings<TSets>;
interface NodeCredential extends registry.NodeCredential {}
type NodeCredentials<TCreds> = registry.NodeCredentials<TCreds>;
interface NodeMessage extends registry.NodeMessage {}
interface NodeMessageParts extends registry.NodeMessageParts {}
interface NodeMessageInFlow extends registry.NodeMessageInFlow {}
interface NodeAPI<TSets extends NodeAPISettingsWithData = NodeAPISettingsWithData>
extends registry.NodeAPI<TSets> {}
interface Node<TCreds extends {} = {}> extends registry.Node<TCreds> {}
type NodeStatusFill = registry.NodeStatusFill;
type NodeStatusShape = registry.NodeStatusShape;
interface NodeStatus extends registry.NodeStatus {}
interface NodeDef extends registry.NodeDef {}
interface NodeContextData extends registry.NodeContextData {}
interface NodeContext extends registry.NodeContext {}
/********************************************************************
* Type shortcuts for writing the editor side of nodes (.html file)
********************************************************************/
/**
* Property definition
* Read more: https://nodered.org/docs/creating-nodes/properties#property-definitions
*/
interface EditorNodePropertyDef<TVal, TInstProps extends EditorNodeProperties = EditorNodeProperties>
extends editorClient.NodePropertyDef<TVal, TInstProps> {}
/**
* Properties definitions (`defaults` object)
* Read more: https://nodered.org/docs/creating-nodes/properties
*/
type EditorNodePropertiesDef<
TProps extends EditorNodeProperties,
TInstProps extends TProps = TProps
> = editorClient.NodePropertiesDef<TProps, TInstProps>;
/**
* Node properties
* Read more: https://nodered.org/docs/creating-nodes/properties
*/
interface EditorNodeProperties extends editorClient.NodeProperties {}
type EditorNodeInstance<TProps extends EditorNodeProperties = EditorNodeProperties> = editorClient.NodeInstance<
TProps
>;
type EditorNodeCredentials<T> = editorClient.NodeCredentials<T>;
interface EditorNodeCredential extends editorClient.NodeCredential {}
/**
* Node Definition
* Read more: https://nodered.org/docs/creating-nodes/node-html#node-definition
*/
interface EditorNodeDef<
TProps extends EditorNodeProperties = EditorNodeProperties,
TCreds = undefined,
TInstProps extends TProps = TProps
> extends editorClient.NodeDef<TProps, TCreds, TInstProps> {}
/**
* Type def for the global `RED` in the node .html files.
* Should be used to access `RED.nodes.registerType` function
* registering a node with the editor.
*
* Example:
* ```
* declare const RED: EditorRED;
*
* RED.nodes.registerType<
* MyNodeProps
* >("my-node", {
* ...
* })
* ```
*
*/
interface EditorRED extends editorClient.RED {}
/**
* WIDGETS
*/
interface EditorWidgetEditableListOptions<T> extends editorClient.WidgetEditableListOptions<T> {}
interface EditorWidgetEditableList extends editorClient.WidgetEditableList {}
interface EditorWidgetTypedInputOptions extends editorClient.WidgetTypedInputOptions {}
type EditorWidgetTypedInputType = editorClient.WidgetTypedInputType;
interface EditorWidgetTypedInputTypeDefinition extends editorClient.WidgetTypedInputTypeDefinition {}
interface EditorWidgetTypedInput extends editorClient.WidgetTypedInput {}
}

View File

@ -1,36 +1,76 @@
import * as nodered from 'node-red';
import RED = require('node-red');
import { createServer } from 'http';
import { LocalSettings } from '@node-red/runtime';
interface MyFantasticNode extends nodered.Node {
myStrProp: string;
myNmbProp: number;
someResource: any;
async function REDTests() {
const server = createServer();
const settings: LocalSettings = {
uiHost: '127.0.0.1',
uiPort: 1880,
};
RED.init(server, settings);
await RED.start();
await RED.stop();
// RED.log is covered in @node-red/util
// just check the link
// $ExpectType Log
RED.log;
// RED.util is covered in @node-red/util
// just check the link
// $ExpectType Util
RED.util;
// $ExpectType EventEmitter
RED.events;
// RED.runtime is covered in @node-red/runtime
// just check the link
// $ExpectType RuntimeModule
RED.runtime;
// RED.runtime is covered in @node-red/editor-api
// just check the link
// $ExpectType Auth
RED.auth;
}
interface MyFantasticProps extends nodered.NodeProperties {
config: nodered.NodeId;
}
// check the shortcuts
export = (RED: nodered.Red) => {
RED.nodes.registerType('my-fantastic-node', function(this: MyFantasticNode, props: MyFantasticProps) {
RED.nodes.createNode(this, props);
const config = RED.nodes.getNode(props.config);
RED.nodes.eachNode(node => {
RED.nodes.getNode(node.id);
});
this.log('Something fantastic happened.');
this.warn('Something exceptional happened.');
this.error('Something disastrous happened when I tried to process this.', { payload: 'Cookies' });
this.debug('A behind the scenes look.');
this.trace('A look behind the scenes, under the floor.');
this.status({ fill: 'red', shape: 'dot', text: 'status' });
this.status({});
this.send({ payload: 'Milk' });
this.send([[
{ payload: 'FirstMessageFirstNode' },
{ payload: 'SecondMessageFirstNode' },
], { payload: "MessageSecondNode" }]);
this.on('close', () => {
this.someResource.close();
});
});
};
type CheckTypeShortcutsForJs =
| RED.NodeInitializer
| RED.NodeConstructor<RED.Node<RED.NodeCredentials<{}>>, RED.NodeDef, RED.NodeCredentials<{}>>
| RED.NodeAPISettingsWithData
| RED.NodeSetting<string>
| RED.NodeSettings<{}>
| RED.NodeCredential
| RED.NodeCredentials<{}>
| RED.NodeMessage
| RED.NodeMessageParts
| RED.NodeMessageInFlow
| RED.NodeAPI
| RED.Node
| RED.NodeStatusFill
| RED.NodeStatusShape
| RED.NodeStatus
| RED.NodeDef
| RED.NodeContextData
| RED.NodeContext;
type CheckTypeShortcutsForHtml =
| RED.EditorNodePropertyDef<string, RED.EditorNodeProperties>
| RED.EditorNodePropertiesDef<RED.EditorNodeProperties, RED.EditorNodeProperties>
| RED.EditorNodeProperties
| RED.EditorNodeInstance
| RED.EditorNodeCredentials<{}>
| RED.EditorNodeCredential
| RED.EditorNodeDef
| RED.EditorRED
| RED.EditorWidgetEditableListOptions<string>
| RED.EditorWidgetEditableList
| RED.EditorWidgetTypedInputOptions
| RED.EditorWidgetTypedInputType
| RED.EditorWidgetTypedInputTypeDefinition
| RED.EditorWidgetTypedInput;

View File

@ -6,15 +6,32 @@
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
"forceConsistentCasingInFileNames": true,
"paths": {
"@node-red/editor-api": [
"node-red__editor-api"
],
"@node-red/editor-client": [
"node-red__editor-client"
],
"@node-red/registry": [
"node-red__registry"
],
"@node-red/runtime": [
"node-red__runtime"
],
"@node-red/util": [
"node-red__util"
]
}
},
"files": [
"index.d.ts",

221
types/node-red/v0/index.d.ts vendored Normal file
View File

@ -0,0 +1,221 @@
// Type definitions for node-red 0.20
// Project: http://nodered.org
// Definitions by: Anders E. Andersen <https://github.com/andersea>
// Thomas B. Mørch <https://github.com/tbowmo>
// Bernardo Belchior <https://github.com/bernardobelchior>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 3.4
/// <reference types="node" />
import { EventEmitter } from 'events';
/**
* Node-RED node creation api.
*/
export interface Red {
/** Node lifecycle management api. Used by all nodes. */
nodes: Nodes;
log: any;
settings: any;
events: any;
util: any;
httpAdmin: any;
auth: any;
comms: any;
library: any;
httpNode: any;
server: any;
/** Returns the version of the running Node-RED environment. */
version(): string;
}
/**
* Node base type.
*
* See the Nodes interfaces registerType() method for information about
* declaring node constructors in typescript.
*
* The id, type and name properties are available after the
* call to RED.nodes.createNode().
*/
export interface Node extends EventEmitter, NodeProperties {
updateWires(wires: any): void;
context(): any;
close(removed: any): void;
/**
* Send one or more messages to multiple downstream nodes.
* It is possible to send multiple messages to any
* one node by sending an array to the node instead
* of a single message.
* @param msg - array of messages and/or message bundle arrays.
*/
send(msg: any[]): void;
/**
* Send a message to the downstream node. If msg is null or
* undefined, no message is sent.
* @param msg - optional message to send.
*/
send(msg?: any): void;
/**
* Send a message to this node.
* @param msg - optional message to send.
*/
receive(msg: any): void;
/**
* Log an log-level event. Used for mundane events
* that are part of the normal functioning of the
* node.
* @param msg - message to log.
*/
log(msg: any): void;
/**
* Log a warn-level event. For important events
* that the user should be made aware of.
* @param msg - message to log.
*/
warn(msg: any): void;
/**
* Log an error-level event. To trigger catch nodes on
* the workflow call the function with msg set to the
* original message.
* @param logMessage - description of the error.
* @param msg - optional payload that caused the error.
*/
error(logMessage: any, msg?: any): void;
/**
* Log a debug-level event. Use this is for logging
* internal detail not needed for normal operation.
* @param msg - message to log.
*/
debug(msg: any): void;
/**
* Log a trace-level event. Even more internal details than
* debug-level.
* @param msg - message to log.
*/
trace(msg: any): void;
metric(eventname?: any, msg?: any, metricValue?: any): void;
/**
* Set or clear node status.
*
* For more info see: https://nodered.org/docs/creating-nodes/status
* @param status - the status to set or an empty object to clear the
* node status.
*/
status(status: NodeStatus | ClearNodeStatus): void;
}
/**
* Contains the user selected property values
* for the node.
*
* This object is also known as the node's definition
* object.
*/
export interface NodeProperties {
/** This node's unique identifier. */
id: NodeId;
/** The type name for this node. */
type: NodeType;
/**
* The UI visible name for this node. Many nodes
* allow the user to pick the name and provide
* a fallback name, if they leave it blank.
*/
name: string;
}
/** Unique node identifier. */
export type NodeId = string;
/** Node type name. */
export type NodeType = string;
/** Node status icon color choices. */
export type StatusFill = 'red' | 'green' | 'yellow' | 'blue' | 'grey';
/** Node status icon shape choices. */
export type StatusShape = 'ring' | 'dot';
/**
* Object used to set the nodes status flag.
*/
export interface NodeStatus {
/** Selects the icon color. */
fill: StatusFill;
/** Selects either ring or dot shape. */
shape: StatusShape;
/** Status label. */
text: string;
}
/** Fancy definition that matches an empty object. */
export interface ClearNodeStatus {
fill?: undefined;
shape?: undefined;
text?: undefined;
}
export interface Nodes {
/**
* Node constructor functions must call this to
* finish setting up the node. Among other things
* it adds the node credentials, which are stored
* outside the flow.
*
* @param node - the node object under construction.
* @param props - the node's properties object, aka.
* the node instance definition.
*/
createNode(node: Node, props: NodeProperties): void;
/**
* Get a node by NodeID.
*
* If your node uses a configuration
* node, this call is used to get access to the running
* instance.
* @param id - the id of the node.
* @return - the node matching the given id, or null if it does not exist.
*/
getNode(id: NodeId): Node | null;
/**
* Cycle through all node definition objects.
*
* To get the actual node, use getNode() with the id
* from the definition object.
*/
eachNode(callback: (node: NodeProperties) => any): void;
/**
* Adds a set of credentials for the given node id.
* @param id the node id for the credentials
* @param creds an object of credential key/value pairs
*/
addCredentials(id: NodeId, creds: object): void;
/**
* Gets the credentials for the given node id.
* @param id the node id for the credentials
* @return the credentials
*/
getCredentials(id: NodeId): object;
/**
* Deletes the credentials for the given node id.
* @param id the node id for the credentials
*/
deleteCredentials(id: NodeId): void;
/**
* Registers a node constructor.
*
* Node constructors should be declared as functions with an explicit this
* argument of a type descending from the Node interface. You can extend
* the NodeProperties interface also, to add your node's properties.
*
* Example, using in-line declaration:
*
* RED.nodes.registerType('my-node', function(this: MyNode, props: MyProperties)
* => { RED.nodes.createNode(this, props); ... }, { ... });
* @param type - the string type name
* @param constructor - the constructor function for this node type
* @param opts - optional additional options for the node
*/
// tslint:disable-next-line no-unnecessary-generics
registerType<T extends NodeProperties>(type: string, constructor: (props: T) => any, opts?: any): void;
}

View File

@ -0,0 +1,38 @@
// tslint:disable:space-before-function-paren
import * as nodered from 'node-red';
interface MyFantasticNode extends nodered.Node {
myStrProp: string;
myNmbProp: number;
someResource: any;
}
interface MyFantasticProps extends nodered.NodeProperties {
config: nodered.NodeId;
}
export = (RED: nodered.Red) => {
RED.nodes.registerType('my-fantastic-node', function (this: MyFantasticNode, props: MyFantasticProps) {
RED.nodes.createNode(this, props);
const config = RED.nodes.getNode(props.config);
RED.nodes.eachNode(node => {
RED.nodes.getNode(node.id);
});
this.log('Something fantastic happened.');
this.warn('Something exceptional happened.');
this.error('Something disastrous happened when I tried to process this.', { payload: 'Cookies' });
this.debug('A behind the scenes look.');
this.trace('A look behind the scenes, under the floor.');
this.status({ fill: 'red', shape: 'dot', text: 'status' });
this.status({});
this.send({ payload: 'Milk' });
this.send([
[{ payload: 'FirstMessageFirstNode' }, { payload: 'SecondMessageFirstNode' }],
{ payload: 'MessageSecondNode' },
]);
this.on('close', () => {
this.someResource.close();
});
});
};

View File

@ -0,0 +1,28 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../../",
"typeRoots": [
"../../"
],
"types": [],
"paths": {
"node-red": [
"node-red/v0"
]
},
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"node-red-tests.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

52
types/node-red__editor-api/index.d.ts vendored Normal file
View File

@ -0,0 +1,52 @@
// Type definitions for @node-red/editor-api 1.1
// Project: https://github.com/node-red/node-red/tree/master/packages/node_modules/%40node-red/editor-api, https://nodered.org/
// Definitions by: Alex Kaul <https://github.com/alexk111>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// Minimum TypeScript Version: 3.1
import { Request, Response, NextFunction, Express } from 'express';
import { Server as HttpsServer } from 'https';
import * as runtime from '@node-red/runtime';
declare const editorAPI: editorAPI.EditorAPIModule;
export = editorAPI;
declare namespace editorAPI {
interface Auth {
needsPermission: (permission: string) => (req: Request, res: Response, next: NextFunction) => void;
}
interface EditorAPIModule {
/**
* Initialise the module.
* @param settings The runtime settings
* @param _server An instance of HTTP Server
* @param storage An instance of Node-RED Storage
* @param runtimeAPI An instance of Node-RED Runtime
*/
init: (
settings: runtime.LocalSettings,
_server: HttpsServer,
storage: runtime.StorageModule,
runtimeAPI: runtime.RuntimeModule,
) => void;
/**
* Start the module.
*/
start: () => Promise<void>;
/**
* Stop the module.
*/
stop: () => Promise<void>;
auth: Auth;
/**
* The Express app used to serve the Node-RED Editor
*/
readonly httpAdmin: Express;
}
}

View File

@ -0,0 +1,6 @@
import editorAPI = require('@node-red/editor-api');
async function tests() {
await editorAPI.start();
await editorAPI.stop();
}

View File

@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"@node-red/editor-api": [
"node-red__editor-api"
],
"@node-red/editor-client": [
"node-red__editor-client"
],
"@node-red/registry": [
"node-red__registry"
],
"@node-red/runtime": [
"node-red__runtime"
],
"@node-red/util": [
"node-red__util"
]
}
},
"files": [
"index.d.ts",
"node-red__editor-api-tests.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

1635
types/node-red__editor-client/index.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,370 @@
// tslint:disable:space-before-function-paren
import editorClient = require('@node-red/editor-client');
function redTests(RED: editorClient.RED) {
interface MyNodeProperties extends editorClient.NodeProperties {
key: string;
}
interface MyNodeCredentials {
username: string;
password: string;
}
interface MyNodeInstanceProperties extends MyNodeProperties {
instanceProp: string;
}
function nodeInstanceTests(nodeInstance: editorClient.NodeInstance<MyNodeInstanceProperties>) {
// $ExpectType string
nodeInstance.instanceProp;
// $ExpectError
nodeInstance.wrongKey;
// $ExpectType string
nodeInstance._('myNode.label');
// $ExpectType string
nodeInstance._('myNode.status', { num: 10 });
}
const myNodeDef: editorClient.NodeDef<MyNodeProperties, MyNodeCredentials, MyNodeInstanceProperties> = {
category: 'category',
defaults: {
key: {
value: '',
required: true,
type: 'my-config-node',
validate(val) {
// $ExpectType string
val;
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
return true;
},
},
// $ExpectError
instanceProp: {
value: '',
},
},
credentials: {
username: {
type: 'text',
},
password: {
type: 'password',
},
},
align: 'right',
button: {
onclick() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
},
enabled() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
return true;
},
visible() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
return true;
},
},
color: '#3377CC',
icon: 'icon.svg',
inputLabels: true
? 'label'
: function () {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
return 'label';
},
inputs: 0,
label: true
? 'label'
: function () {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
return 'label';
},
labelStyle: true
? 'italic'
: function () {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
return 'italic';
},
oneditcancel() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
},
oneditdelete() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
},
oneditprepare() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
},
oneditresize(size) {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
// $ExpectType number
size.height;
// $ExpectType number
size.width;
},
oneditsave() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
},
onpaletteadd() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
},
onpaletteremove() {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
},
outputLabels: true
? true
? 'label'
: ['label1', 'label2']
: function (idx) {
// $ExpectType number
idx;
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
return 'label';
},
outputs: 2,
paletteLabel: true
? 'label'
: function () {
// $ExpectType string
this.key;
// $ExpectType string
this.instanceProp;
// $ExpectError
this.wrongKey;
return 'label';
},
};
RED.nodes.registerType('my-node', myNodeDef);
RED.nodes.registerType<MyNodeProperties, MyNodeCredentials>('my-node', {
category: 'category',
defaults: {
// $ExpectError
wrongKey: {
value: '',
},
},
credentials: {
// $ExpectError
wrongKey: {
type: 'text',
},
},
});
}
function widgetEditableListTests() {
interface MyItemData {
key: string;
}
type MyEditableListOptions = editorClient.WidgetEditableListOptions<MyItemData>;
const myListOptions: MyEditableListOptions = {
addButtons: false,
addItem: (elem, i, data) => {
// $ExpectType JQuery<HTMLElement>
elem;
// $ExpectType number
i;
// $ExpectType string
data.key;
// $ExpectError
data.wrongKey;
},
connectWith: '.cssSelector',
filter: data => {
// $ExpectType string
data.key;
// $ExpectError
data.wrongKey;
return true;
},
header: $('<div/>'),
height: true ? 200 : 'auto',
removable: true,
removeItem: data => {
data.key;
// $ExpectError
data.wrongKey;
},
resize: () => {},
resizeItem: (row, idx) => {
// $ExpectType JQuery<HTMLElement>
row;
// $ExpectType number
idx;
},
scrollOnAdd: true,
sort: (data1, data2) => {
// $ExpectType string
data1.key;
// $ExpectError
data1.wrongKey;
// $ExpectType string
data2.key;
// $ExpectError
data2.wrongKey;
return 1;
},
sortItems: items => {
// $ExpectType JQuery<HTMLElement>
items[0];
},
sortable: true ? true : '.cssSelector',
};
}
function widgetTypedInputTests() {
const goodType: editorClient.WidgetTypedInputType = 'msg';
// $ExpectError
const wrongType: editorClient.WidgetTypedInputType = 'wrongType';
const goodTypeDef: editorClient.WidgetTypedInputTypeDefinition = {
value: 'mytype',
hasValue: false,
icon: 'icon',
label: 'label',
options: ['opt1', 'opt2'],
};
const wrongTypeDef: editorClient.WidgetTypedInputTypeDefinition = {
// $ExpectError
wrongKey: 'value',
};
$('#inputId').typedInput({
types: [goodType, wrongType, goodTypeDef, wrongTypeDef],
});
$('#inputId').typedInput({
types: ['msg', 'flow', 'global', 'str', 'num', 'bool', 'json', 'bin', 're', 'date', 'jsonata', 'env'],
});
$('#inputId').typedInput({
types: [
{
value: 'mytype',
validate: (_v: string) => true,
},
],
});
$('#inputId').typedInput({
types: [
{
value: 'mytype',
validate: /\d/,
},
],
});
$('#inputId').typedInput('hide');
$('#inputId').typedInput('show');
const type = $('#inputId').typedInput('type');
$('#inputId').typedInput('type', type);
// $ExpectError
$('#inputId').typedInput('types', [{ wrongKey: 'value' }]);
$('#inputId').typedInput('types', [
'msg',
'flow',
'global',
'str',
'num',
'bool',
'json',
'bin',
're',
'date',
'jsonata',
'env',
{
value: 'mytype',
hasValue: false,
icon: 'icon',
label: 'label',
options: ['opt1', 'opt2'],
},
]);
// $ExpectType boolean
$('#inputId').typedInput('validate');
// $ExpectType string
const val = $('#inputId').typedInput('value');
$('#inputId').typedInput('value', val);
$('#inputId').typedInput('width', 200);
}

View File

@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"@node-red/editor-api": [
"node-red__editor-api"
],
"@node-red/editor-client": [
"node-red__editor-client"
],
"@node-red/registry": [
"node-red__registry"
],
"@node-red/runtime": [
"node-red__runtime"
],
"@node-red/util": [
"node-red__util"
]
}
},
"files": [
"index.d.ts",
"node-red__editor-client-tests.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

381
types/node-red__registry/index.d.ts vendored Normal file
View File

@ -0,0 +1,381 @@
// Type definitions for @node-red/registry 1.1
// Project: https://github.com/node-red/node-red/tree/master/packages/node_modules/%40node-red/registry, https://nodered.org/
// Definitions by: Alex Kaul <https://github.com/alexk111>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// Minimum TypeScript Version: 3.1
import { EventEmitter } from 'events';
import { Request, Response, NextFunction, Express } from 'express';
import { Server as HttpsServer } from 'https';
import { LocalSettings } from '@node-red/runtime';
import * as util from '@node-red/util';
/**
* Omit Helper
* Typescript 3.5 includes this.
* TODO: Remove after March 2021, after
* the end of support for TS 3.4
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
declare const registry: registry.RegistryModule;
export = registry;
declare namespace registry {
interface RegistryModule {} // tslint:disable-line:no-empty-interface
interface NodeConstructor<TNode extends Node<TCred>, TNodeDef extends NodeDef, TCred> {
(this: TNode, nodeDef: TNodeDef): void;
}
interface NodeSetting<T> {
value: T;
exportable?: boolean;
}
type NodeSettings<TSets> = {
[K in keyof TSets]: NodeSetting<TSets[K]>;
};
interface NodeCredential {
type: 'text' | 'password';
}
type NodeCredentials<TCreds> = {
[K in keyof TCreds]: NodeCredential;
};
interface NodeAPINodes {
/**
* Registers a node constructor
* @param type - the string type name
* @param constructor - the constructor function for this node type
* @param opts - optional additional options for the node
*/
registerType<TNode extends Node<TCreds>, TNodeDef extends NodeDef, TSets, TCreds>(
type: string,
constructor: NodeConstructor<TNode, TNodeDef, TCreds>, // tslint:disable-line:no-unnecessary-generics
opts?: {
credentials?: NodeCredentials<TCreds>;
settings?: NodeSettings<TSets>; // tslint:disable-line:no-unnecessary-generics
},
): void;
/**
* Called from a Node's constructor function, invokes the super-class
* constructor and attaches any credentials to the node.
* @param node the node object being created
* @param def the instance definition for the node
*/
createNode(node: Node, def: NodeDef): void;
getNode(id: string): Node;
eachNode(cb: (node: NodeDef) => void): void;
/**
* Adds a set of credentials for the given node id.
* @param id the node id for the credentials
* @param creds an object of credential key/value pairs
* @returns a promise for backwards compatibility TODO: can this be removed?
*/
addCredentials(id: string, creds: object): Promise<void>;
/**
* Gets the credentials for the given node id.
* @param id the node id for the credentials
* @returns the credentials
*/
getCredentials(id: string): object;
/**
* Deletes the credentials for the given node id.
* @param id the node id for the credentials
*/
deleteCredentials(id: string): void;
}
interface NodeAPIComms {
publish(topic: string, data: any, retain: boolean): void;
}
interface NodeAPILibrary {
register(type: string): void;
}
type NodeApiLog = Omit<util.Log, 'init'>;
interface NodeAPISettings {
get(prop: string): any;
set(prop: string, value: any): Promise<void>;
delete(prop: string): Promise<void>;
available(): boolean;
registerNodeSettings(type: string, opts: object): void;
exportNodeSettings(safeSettings: object): object;
enableNodeSettings(types: string[]): void;
disableNodeSettings(types: string[]): void;
getUserSettings(username: string): void;
setUserSettings(username: string, settings: object): Promise<void>;
}
interface NodeAPISettingsWithData extends NodeAPISettings, LocalSettings {}
interface NodeAPIAuth {
/**
* Returns an Express middleware function that ensures the user making a request has the necessary permission.
*/
needsPermission(permission: string): (req: Request, res: Response, next: NextFunction) => void;
}
/**
* Runtime API provided to nodes by Node Registry
*/
interface NodeAPI<TSets extends NodeAPISettingsWithData = NodeAPISettingsWithData> {
nodes: NodeAPINodes;
log: NodeApiLog;
settings: TSets;
events: EventEmitter;
util: util.Util;
version(): Promise<string>;
require(id: string): any;
comms: NodeAPIComms;
library: NodeAPILibrary;
auth: NodeAPIAuth;
readonly httpNode: Express;
readonly httpAdmin: Express;
readonly server: HttpsServer;
_: util.I18nTFunction;
}
/**
* Function called by Node Registry to init node.
*/
interface NodeInitializer<TSets extends NodeAPISettingsWithData = NodeAPISettingsWithData> {
(RED: NodeAPI<TSets>): void | Promise<void>;
}
interface NodeMessage {
payload?: unknown;
_msgid?: string;
}
interface NodeMessageParts {
/** a unique identifier for the sequence */
id: string;
/** the message's position within the sequence */
index: number;
/** if known, the total number of messages in the sequence */
count?: number;
}
interface NodeMessageInFlow extends NodeMessage {
_msgid: string;
/**
* If there is a message sequence, then each message in a sequence has the ```parts``` property.
* More info: https://nodered.org/docs/user-guide/messages#understanding-msgparts
*/
parts?: NodeMessageParts;
}
interface Node<TCreds extends {} = {}> extends EventEmitter {
id: string;
type: string;
z: string;
name?: string;
credentials: TCreds;
/**
* Update the wiring configuration for this node.
* @param wires -the new wiring configuration
*/
updateWires(wires: Array<[]>): void;
/**
* Get the context object for this node.
* @returnsthe context object
*/
context(): NodeContext;
/**
* Called when the node is being stopped
* @param removed Whether the node has been removed, or just being stopped
* @returns Promises which resolves when the node has closed
*/
close(removed: boolean): Promise<void>;
/**
* Send a message to the nodes wired.
* @param msg A message or array of messages to send
*/
send(msg?: NodeMessage | NodeMessage[]): void;
/**
* Receive a message.
*
* This will emit the `input` event with the provided message.
* As of 1.0, this will return *before* any 'input' callback handler is invoked.
*/
receive(msg?: NodeMessage): void;
/**
* Log an INFO level message
*/
log(msg: any): void;
/**
* Log a WARN level message
*/
warn(msg: any): void;
/**
* Log an ERROR level message
*/
error(logMessage: any, msg?: NodeMessage): void;
/**
* Log an DEBUG level message
*/
debug(msg: any): void;
/**
* Log an TRACE level message
*/
trace(msg: any): void;
/**
* Log a metric event.
* If called with no args, returns whether metric collection is enabled
*/
metric(): boolean;
metric(eventname: string, msg: NodeMessage, metricValue: number): void;
/**
* Set the node's status object
*
* status: { fill:"red|green", shape:"dot|ring", text:"blah" }
* or
* status: "simple text status"
*/
status(status: string | NodeStatus): void;
/**
* Nodes register a listener on the input event to receive messages from the
* up-stream nodes in a flow.
* More info: https://nodered.org/docs/creating-nodes/node-js#receiving-messages
*/
on(
event: 'input',
listener: (
msg: NodeMessageInFlow,
send: (msg: NodeMessage | Array<NodeMessage | null>) => void,
done: (err?: Error) => void,
) => void,
): this;
/**
* Whenever a new flow is deployed, the existing nodes are deleted. If any of them
* need to tidy up state when this happens, such as disconnecting from a remote
* system, they should register a listener on the close event.
* More info: https://nodered.org/docs/creating-nodes/node-js#closing-the-node
*/
on(event: 'close', listener: () => void): this;
/**
* If the node needs to do any asynchronous work to complete the tidy up, the
* registered listener should accept an argument which is a function to be called
* when all the work is complete.
* More info: https://nodered.org/docs/creating-nodes/node-js#closing-the-node
*/
on(event: 'close', listener: (done: () => void) => void): this; // tslint:disable-line:unified-signatures
/**
* If the registered listener accepts two arguments, the first will be a boolean
* flag that indicates whether the node is being closed because it has been removed
* entirely, or that it is just being restarted.
* More info: https://nodered.org/docs/creating-nodes/node-js#closing-the-node
*/
on(event: 'close', listener: (removed: boolean, done: () => void) => void): this; // tslint:disable-line:unified-signatures
}
type NodeStatusFill = 'red' | 'green' | 'yellow' | 'blue' | 'grey';
type NodeStatusShape = 'ring' | 'dot';
interface NodeStatus {
fill?: NodeStatusFill;
shape?: NodeStatusShape;
text?: string;
}
/**
* Node Instance Definition Object
*/
interface NodeDef {
id: string;
type: string;
name: string;
z: string;
}
interface NodeContextData {
/**
* Get a value from context
* @param key
* @param storeName - store name when multiple context stores are used
*/
get(key: string, storeName?: string): unknown;
/**
* Get a value from context asynchronously
*/
get(key: string, cb: (err: Error, value: unknown) => void): void;
/**
* Get multiple values from context
* @param keys
* @param storeName - store name when multiple context stores are used
*/
get(keys: string[], storeName?: string): unknown[];
/**
* Get multiple values from context asynchronously
*/
get(keys: string[], cb: (err: Error, value: unknown[]) => void): void;
/**
* Get a value from context asynchronously, when multiple context stores are used
*/
get(key: string, storeName: string | undefined, cb: (err: Error, value: unknown) => void): void;
/**
* Get multiple values from context asynchronously, when multiple context stores are used
*/
get(keys: string[], storeName: string | undefined, cb: (err: Error, value: unknown[]) => void): void;
/**
* Set a value in context
* @param key
* @param value
* @param cb - callback for async calls
*/
set(key: string, value: unknown, cb?: (err: Error) => void): void;
/**
* Set multiple values in context
* @param keys
* @param values
* @param cb - callback for async calls
*/
set(keys: string[], values: unknown[], cb?: (err: Error) => void): void;
/**
* Set a value in context, when multiple context stores are used
* @param key
* @param value
* @param storeName
* @param cb - callback for async calls
*/
set(key: string, value: unknown, storeName: string | undefined, cb?: (err: Error) => void): void;
/**
* Set multiple values in context, when multiple context stores are used
* @param keys
* @param values
* @param storeName
* @param cb - callback for async calls
*/
set(keys: string[], values: unknown[], storeName: string | undefined, cb?: (err: Error) => void): void;
/**
* Returns a list of all node-scoped context property keys
* @param storeName - store name when multiple context stores are used
*/
keys(storeName?: string): string[];
/**
* Returns a list of all node-scoped context property keys asynchronously
*/
keys(cb: (err: Error, value: unknown[]) => void): void;
/**
* Returns a list of all node-scoped context property keys asynchronously, when multiple context stores are used
*/
keys(storeName: string | undefined, cb: (err: Error, value: unknown[]) => void): void;
}
interface NodeContext extends NodeContextData {
global: NodeContextData;
flow: NodeContextData;
}
}

View File

@ -0,0 +1,112 @@
import registry = require('@node-red/registry');
function registryTests() {
interface ExtendedNodeRedSettings extends registry.NodeAPISettingsWithData {
myKey: string;
}
interface MyNodeProperties {
defKey: string;
}
interface MyNodeCredentials {
username: string;
password: string;
}
interface MyNode extends registry.Node<MyNodeCredentials> {
instanceKey: string;
}
interface MyNodeDef extends registry.NodeDef, MyNodeProperties {}
function nodeAPITests(RED: registry.NodeAPI<ExtendedNodeRedSettings>) {
// $ExpectType string
RED.settings.myKey;
// $ExpectType boolean | undefined
RED.settings.verbose;
// $ExpectError
RED.settings.wrongKey;
// tslint:disable-next-line:space-before-function-paren
const nodeConstructor: registry.NodeConstructor<MyNode, MyNodeDef, MyNodeCredentials> = function (nodeDef) {
RED.nodes.createNode(this, nodeDef);
// $ExpectType string
nodeDef.defKey;
// $ExpectError
nodeDef.wrongKey;
// $ExpectType string
this.credentials.password;
// $ExpectType string
this.credentials.username;
// $ExpectError
this.credentials.wrongKey;
this.instanceKey = 'value';
// $ExpectError
this.instanceKey = 123;
// $ExpectError
this.wrongKey;
const status: registry.NodeStatus = {
text: 'status',
fill: 'blue',
shape: 'dot',
};
// $ExpectError
status.fill = 'invalid-fill';
// $ExpectError
status.shape = 'invalid-shape';
this.status(status);
this.status({});
this.context().set('key', 'value');
this.context().set('key', 123);
this.context().set('key', undefined);
this.context().get('key');
this.on('input', (msg, send, done) => {
// $ExpectType string
msg._msgid;
// $ExpectType boolean
this.metric();
this.metric('eventname', msg, 10);
this.log('log info');
this.warn('log warn');
this.error('log error');
this.trace('log trace');
this.debug('log debug');
send(msg);
done();
done(new Error('error'));
});
this.on('close', () => {});
this.receive({});
// $ExpectType Node<{}>
RED.nodes.getNode('node-id');
// RED.util covered in @node-red/util
// just check the link
// $ExpectType Util
RED.util;
// $ExpectType Express
RED.httpNode;
// $ExpectType Express
RED.httpAdmin;
// $ExpectType Server
RED.server;
// $ExpectType string
RED._('myNode.label');
// $ExpectType string
RED._('myNode.status', { num: 10 });
};
RED.nodes.registerType('my-node', nodeConstructor);
}
}

View File

@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"@node-red/editor-api": [
"node-red__editor-api"
],
"@node-red/editor-client": [
"node-red__editor-client"
],
"@node-red/registry": [
"node-red__registry"
],
"@node-red/runtime": [
"node-red__runtime"
],
"@node-red/util": [
"node-red__util"
]
}
},
"files": [
"index.d.ts",
"node-red__registry-tests.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

1292
types/node-red__runtime/index.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
import runtime = require('@node-red/runtime');
async function runtimeTests() {
await runtime.start();
await runtime.stop();
// $ExpectType boolean
await runtime.isStarted();
// $ExpectType string
await runtime.version();
}

View File

@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"@node-red/editor-api": [
"node-red__editor-api"
],
"@node-red/editor-client": [
"node-red__editor-client"
],
"@node-red/registry": [
"node-red__registry"
],
"@node-red/runtime": [
"node-red__runtime"
],
"@node-red/util": [
"node-red__util"
]
}
},
"files": [
"index.d.ts",
"node-red__runtime-tests.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

337
types/node-red__util/index.d.ts vendored Normal file
View File

@ -0,0 +1,337 @@
// Type definitions for @node-red/util 1.1
// Project: https://github.com/node-red/node-red/tree/master/packages/node_modules/%40node-red/util, https://nodered.org/
// Definitions by: Alex Kaul <https://github.com/alexk111>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// Minimum TypeScript Version: 3.1
import { EventEmitter } from 'events';
import { Expression as JsonataExpression } from 'jsonata';
import * as registry from '@node-red/registry';
import * as runtime from '@node-red/runtime';
declare const util: util.UtilModule;
export = util;
declare namespace util {
interface LogMessageObject {
level: number;
msg?: LogMessage;
type?: string;
id?: string;
name?: string;
}
type LogMessage = any;
interface Log {
/** Fatal level */
readonly FATAL: number;
/** Error level */
readonly ERROR: number;
/** Warn level */
readonly WARN: number;
/** Info level */
readonly INFO: number;
/** Debug level */
readonly DEBUG: number;
/** Trace level */
readonly TRACE: number;
/** Audit level */
readonly AUDIT: number;
/** Metric level */
readonly METRIC: number;
/**
* Perform a message catalog lookup.
*/
_: I18nTFunction;
/**
* Add a log handler
* @param - event emitter with `(msg: LogMessageObject) => void` listener on `log` events
*/
addHandler(handler: EventEmitter): void;
/**
* Remove a log handler
*/
removeHandler(handler: EventEmitter): void;
/**
* Log a message object
*/
log(msg: LogMessageObject): void;
/**
* Log a message at INFO level
*/
info(msg: LogMessage): void;
/**
* Log a message at WARN level
*/
warn(msg: LogMessage): void;
/**
* Log a message at ERROR level
*/
error(msg: LogMessage): void;
/**
* Log a message at TRACE level
*/
trace(msg: LogMessage): void;
/**
* Log a message at DEBUG level
*/
debug(msg: LogMessage): void;
/**
* Check if metrics are enabled
*/
metric(): boolean;
/**
* Log an audit event.
*/
audit(msg: LogMessageObject, req?: object): void;
}
interface MessageCatalog {
namespace: string;
dir: string;
file: string;
}
// tslint:disable-next-line:interface-name
interface I18nTFunction {
(id: string, tplStrs?: Record<string, string | number>): string;
}
// tslint:disable-next-line:interface-name
interface I18n {
/**
* Perform a message catalog lookup.
*/
_: I18nTFunction;
/**
* Register multiple message catalogs with i18n.
*/
registerMessageCatalogs(catalogs: MessageCatalog[]): Promise<object[]>;
/**
* Register a message catalog with i18n.
*/
registerMessageCatalog(namespace: string, dir: string, file: string): Promise<void>;
/**
* Gets a message catalog.
*/
catalog(namespace: string, lang: string): MessageCatalog;
/**
* Gets a list of languages a given catalog is available in.
*/
availableLanguages(namespace: string): string[];
}
interface Util {
/**
* Generates a psuedo-unique-random id.
* @returns a random-ish id
*/
generateId(): string;
/**
* Converts the provided argument to a String, using type-dependent
* methods.
*
* @param o - the property to convert to a String
* @returns the stringified version
*/
ensureString(o: unknown): string;
/**
* Converts the provided argument to a Buffer, using type-dependent
* methods.
*
* @param o - the property to convert to a Buffer
* @returns the Buffer version
*/
ensureBuffer(o: unknown): Buffer;
/**
* Safely clones a message object. This handles msg.req/msg.res objects that must
* not be cloned.
*
* @param msg - the message object to clone
* @returns the cloned message
*/
cloneMessage<T extends registry.NodeMessage>(msg: T): T;
/**
* Compares two objects, handling various JavaScript types.
*
* @param obj1
* @param obj2
* @returns whether the two objects are the same
*/
compareObjects(obj1: object, obj2: object): boolean;
/**
* Parses a property expression, such as `msg.foo.bar[3]` to validate it
* and convert it to a canonical version expressed as an Array of property
* names.
*
* For example, `a["b"].c` returns `['a','b','c']`
*
* @param str - the property expression
* @returns the normalised expression
*/
normalisePropertyExpression(str: string): Array<string | number>;
/**
* Gets a property of a message object.
*
* Unlike `getObjectProperty`, this function will strip `msg.` from the
* front of the property expression if present.
*
* @param msg - the message object
* @param expr - the property expression
* @returns the message property, or undefined if it does not exist
*/
getMessageProperty(msg: object, expr: string): any;
/**
* Gets a property of an object.
*
* @param msg - the object
* @param expr - the property expression
* @returns the object property, or undefined if it does not exist
*/
getObjectProperty(msg: object, expr: string): any;
/**
* Sets a property of a message object.
*
* Unlike `setObjectProperty`, this function will strip `msg.` from the
* front of the property expression if present.
*
* @param msg - the message object
* @param prop - the property expression
* @param value - the value to set
* @param createMissing - whether to create missing parent properties
*/
setMessageProperty(msg: object, prop: string, value: any, createMissing?: boolean): boolean;
/**
* Sets a property of an object.
*
* @param msg - the object
* @param prop - the property expression
* @param value - the value to set
* @param createMissing - whether to create missing parent properties
*/
setObjectProperty(msg: object, prop: string, value: any, createMissing?: boolean): boolean;
/**
* Get value of environment variable.
* @param node - accessing node
* @param name - name of variable
* @returns value of env var
*/
getSetting(node: registry.Node, name: string): string;
/**
* Checks if a String contains any Environment Variable specifiers and returns
* it with their values substituted in place.
*
* For example, if the env var `WHO` is set to `Joe`, the string `Hello ${WHO}!`
* will return `Hello Joe!`.
* @param value - the string to parse
* @param node - the node evaluating the property
* @returns The parsed string
*/
evaluateEnvProperty(value: string, node: registry.Node): string;
/**
* Parses a context property string, as generated by the TypedInput, to extract
* the store name if present.
*
* For example, `#:(file)::foo` results in ` { store: "file", key: "foo" }`.
*
* @param key - the context property string to parse
* @returns The parsed property
*/
parseContextStore(key: string): { store?: string; key: string };
/**
* Evaluates a property value according to its type.
*
* @param value - the raw value
* @param type - the type of the value
* @param node - the node evaluating the property
* @param msg - the message object to evaluate against
* @param callback - (optional) called when the property is evaluated
* @returns The evaluted property, if no `callback` is provided
*/
evaluateNodeProperty(value: string, type: string, node: registry.Node, msg: object): any;
evaluateNodeProperty(
value: string,
type: string,
node: registry.Node,
msg: object,
callback: (err: Error | null, result: any) => void,
): void;
/**
* Prepares a JSONata expression for evaluation.
* This attaches Node-RED specific functions to the expression.
*
* @param value - the JSONata expression
* @param node - the node evaluating the property
* @returns The JSONata expression that can be evaluated
*/
prepareJSONataExpression(value: string, node: registry.Node): JsonataExpression;
/**
* Evaluates a JSONata expression.
* The expression must have been prepared with `prepareJSONataExpression`
* before passing to this function.
*
* @param expr - the prepared JSONata expression
* @param msg - the message object to evaluate against
* @param callback - (optional) called when the expression is evaluated
* @returns If no callback was provided, the result of the expression
*/
evaluateJSONataExpression(expr: JsonataExpression, msg: object): any;
evaluateJSONataExpression(
expr: JsonataExpression,
msg: object,
callback: (err: Error | null, resp: any) => void,
): void;
/**
* Normalise a node type name to camel case.
*
* For example: `a-random node type` will normalise to `aRandomNodeType`
*
* @param name - the node type
* @returns The normalised name
*/
normaliseNodeTypeName(name: string): string;
/**
* Encode an object to JSON without losing information about non-JSON types
* such as Buffer and Function.
*
* *This function is closely tied to its reverse within the editor*
*
* @param msg
* @param opts
* @returns the encoded object
*/
encodeObject(msg: { msg: any }, opts?: { maxLength?: number }): { format: string; msg: string };
}
interface UtilModule {
/**
* Initialise the module with the runtime settings
* @param settings
*/
init(settings: runtime.LocalSettings): void;
/**
* Logging utilities
*/
log: Log;
/**
* Internationalization utilities
*/
i18n: I18n;
/**
* General utilities
*/
util: Util;
}
}

View File

@ -0,0 +1,130 @@
import utilModule = require('@node-red/util');
import { EventEmitter } from 'events';
import { NodeMessage, Node } from '@node-red/registry';
function i18nTests() {
const i18n = utilModule.i18n;
// $ExpectType string
i18n._('my.key1');
// $ExpectType string
i18n._('my.key2', { dataKey: 'dataVal' });
// $ExpectType string[]
i18n.availableLanguages('editor');
}
function logTests() {
const log = utilModule.log;
// $ExpectType string
log._('my.key1');
// $ExpectType string
log._('my.key2', { dataKey: 'dataVal' });
const logHandler = new EventEmitter();
log.addHandler(logHandler);
log.removeHandler(logHandler);
// $ExpectType boolean
log.metric();
// $ExpectError
log.log({});
log.log({ level: log.INFO, msg: 'log' });
log.info('log info');
log.warn('log warn');
log.error('log error');
log.trace('log trace');
log.debug('log debug');
log.audit({ level: log.INFO, msg: 'audit' });
}
function utilTests(someNode: Node) {
const util = utilModule.util;
// $ExpectType string
util.generateId();
// $ExpectType string
util.ensureString(123);
// $ExpectType string
util.ensureString({});
// $ExpectType string
util.ensureString('abc');
// $ExpectType Buffer
util.ensureBuffer(123);
// $ExpectType Buffer
util.ensureBuffer({});
// $ExpectType Buffer
util.ensureBuffer('abc');
interface SomeNodeMsg extends NodeMessage {
key: string;
}
const msg: SomeNodeMsg = {
key: 'value',
};
const msgClone = util.cloneMessage(msg);
// $ExpectType string
const msgKey = msgClone.key;
// $ExpectError
const msgWrongKey = msgClone.wrongKey;
// $ExpectType boolean
util.compareObjects({}, {});
// $ExpectType (string | number)[]
util.normalisePropertyExpression('a["b"].c');
// $ExpectType any
util.getMessageProperty({}, 'key');
// $ExpectType any
util.getObjectProperty({}, 'key');
// $ExpectType boolean
util.setMessageProperty({}, 'key', { dataKey: 'dataVal' });
// $ExpectType boolean
util.setMessageProperty({}, 'key', { dataKey: 'dataVal' }, true);
// $ExpectType boolean
util.setObjectProperty({}, 'key', { dataKey: 'dataVal' });
// $ExpectType boolean
util.setObjectProperty({}, 'key', { dataKey: 'dataVal' }, true);
// $ExpectType string
util.getSetting(someNode, 'name');
// $ExpectType string
util.evaluateEnvProperty('name', someNode);
// $ExpectType any
util.evaluateNodeProperty('value', 'type', someNode, {});
// $ExpectType void
util.evaluateNodeProperty('value', 'type', someNode, {}, (err: Error | null, res: any): void => {});
const parsedStore = util.parseContextStore('#:(file)::foo');
// $ExpectType string | undefined
parsedStore.store;
// $ExpectType string
parsedStore.key;
// $ExpectType Expression
const jsonataExpr = util.prepareJSONataExpression('expr', someNode);
// $ExpectType any
util.evaluateJSONataExpression(jsonataExpr, {});
// $ExpectType void
util.evaluateJSONataExpression(jsonataExpr, {}, (err: Error | null, res: any): void => {});
// $ExpectType string
util.normaliseNodeTypeName('a-random node type');
const encoded = util.encodeObject({ msg: 123 });
// $ExpectType string
encoded.format;
// $ExpectType string
encoded.msg;
}

View File

@ -0,0 +1,6 @@
{
"private": true,
"dependencies": {
"jsonata": "1.8.3"
}
}

View File

@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"@node-red/editor-api": [
"node-red__editor-api"
],
"@node-red/editor-client": [
"node-red__editor-client"
],
"@node-red/registry": [
"node-red__registry"
],
"@node-red/runtime": [
"node-red__runtime"
],
"@node-red/util": [
"node-red__util"
]
}
},
"files": [
"index.d.ts",
"node-red__util-tests.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }