0
# Utilities
1
2
General-purpose utilities provided by Node-RED for message handling, logging, event management, and development tasks. These utilities are available both in embedding applications and within Node-RED's execution environment.
3
4
## Capabilities
5
6
### Logging System
7
8
Comprehensive logging system with multiple levels and configurable handlers.
9
10
```javascript { .api }
11
/**
12
* Logging API
13
*/
14
interface LoggingAPI {
15
init(settings: object): void;
16
addHandler(handler: LogHandler): void;
17
removeHandler(handler: LogHandler): void;
18
log(level: string, msg: any): void;
19
info(msg: any): void;
20
warn(msg: any): void;
21
error(msg: any): void;
22
debug(msg: any): void;
23
trace(msg: any): void;
24
audit(event: AuditEvent, req?: http.IncomingMessage): void;
25
metric(): boolean;
26
}
27
28
/**
29
* Log info message
30
* @param msg - Message to log (string or object)
31
*/
32
RED.log.info(msg: any): void;
33
34
/**
35
* Log warning message
36
* @param msg - Warning message to log
37
*/
38
RED.log.warn(msg: any): void;
39
40
/**
41
* Log error message
42
* @param msg - Error message to log
43
*/
44
RED.log.error(msg: any): void;
45
46
/**
47
* Log debug message
48
* @param msg - Debug message to log
49
*/
50
RED.log.debug(msg: any): void;
51
52
/**
53
* Log audit event
54
* @param event - Audit event object
55
* @param req - Optional HTTP request object
56
*/
57
RED.log.audit(event: AuditEvent, req?: http.IncomingMessage): void;
58
```
59
60
**Usage Examples:**
61
62
```javascript
63
const RED = require("node-red");
64
65
// Basic logging
66
RED.log.info("Application started");
67
RED.log.warn("Configuration file not found, using defaults");
68
RED.log.error("Database connection failed");
69
70
// Logging objects
71
RED.log.debug({ nodeId: "abc123", message: "Processing started" });
72
73
// Audit logging
74
RED.log.audit({
75
event: "flows.deploy",
76
level: 20,
77
user: { username: "admin" },
78
path: "/flows"
79
});
80
```
81
82
### Message Utilities
83
84
Utilities for manipulating Node-RED message objects safely and efficiently.
85
86
```javascript { .api }
87
/**
88
* Message utility functions
89
*/
90
interface MessageUtilities {
91
generateId(): string;
92
ensureString(value: any): string;
93
ensureBuffer(value: any): Buffer;
94
cloneMessage(msg: NodeMessage): NodeMessage;
95
compareObjects(obj1: any, obj2: any): boolean;
96
getMessageProperty(msg: NodeMessage, prop: string): any;
97
setMessageProperty(msg: NodeMessage, prop: string, value: any, createMissing?: boolean): boolean;
98
getObjectProperty(obj: object, expr: string): any;
99
setObjectProperty(obj: object, expr: string, value: any, createMissing?: boolean): boolean;
100
normalisePropertyExpression(str: string, msg?: NodeMessage, toString?: boolean): string[] | string;
101
normaliseNodeTypeName(name: string): string;
102
encodeObject(msg: any, opts?: EncodeOptions): any;
103
getSetting(node: NodeObject, name: string, flow?: FlowObject): string;
104
}
105
106
/**
107
* Generate a pseudo-unique identifier (8 random hex bytes)
108
* @returns Generated 16-character hex identifier string
109
*/
110
RED.util.generateId(): string;
111
112
/**
113
* Safely clone a Node-RED message object
114
* @param msg - Message object to clone
115
* @returns Deep cloned message object
116
*/
117
RED.util.cloneMessage(msg: NodeMessage): NodeMessage;
118
119
/**
120
* Get property from message object using dot notation
121
* @param msg - Message object
122
* @param prop - Property path (e.g., "payload.data.value")
123
* @returns Property value or undefined
124
*/
125
RED.util.getMessageProperty(msg: NodeMessage, prop: string): any;
126
127
/**
128
* Set property on message object using dot notation
129
* @param msg - Message object
130
* @param prop - Property path (e.g., "payload.data.value")
131
* @param value - Value to set
132
* @param createMissing - Whether to create missing intermediate objects
133
* @returns true if property was set successfully
134
*/
135
RED.util.setMessageProperty(msg: NodeMessage, prop: string, value: any, createMissing?: boolean): boolean;
136
137
/**
138
* Get property from any object using dot notation
139
* @param obj - Object to get property from
140
* @param expr - Property expression (e.g., "data.items[0].name")
141
* @returns Property value or undefined
142
*/
143
RED.util.getObjectProperty(obj: object, expr: string): any;
144
145
/**
146
* Set property on any object using dot notation
147
* @param obj - Object to set property on
148
* @param expr - Property expression (e.g., "data.items[0].name")
149
* @param value - Value to set
150
* @param createMissing - Whether to create missing intermediate objects
151
* @returns true if property was set successfully
152
*/
153
RED.util.setObjectProperty(obj: object, expr: string, value: any, createMissing?: boolean): boolean;
154
155
/**
156
* Parse and normalize property expressions
157
* @param str - Property expression string
158
* @param msg - Optional message object for cross-references
159
* @param toString - Whether to return as normalized string
160
* @returns Array of property path segments or normalized string
161
*/
162
RED.util.normalisePropertyExpression(str: string, msg?: NodeMessage, toString?: boolean): string[] | string;
163
164
/**
165
* Normalize node type name to camelCase
166
* @param name - Raw node type name
167
* @returns Normalized camelCase name
168
*/
169
RED.util.normaliseNodeTypeName(name: string): string;
170
171
/**
172
* Encode object for debugging/transmission
173
* @param msg - Object to encode
174
* @param opts - Optional encoding options
175
* @returns Encoded object with type information
176
*/
177
RED.util.encodeObject(msg: any, opts?: EncodeOptions): any;
178
179
/**
180
* Get environment variable or node setting
181
* @param node - Node object for context
182
* @param name - Setting/environment variable name
183
* @param flow - Optional flow object for context
184
* @returns Setting value or empty string if not found
185
*/
186
RED.util.getSetting(node: NodeObject, name: string, flow?: FlowObject): string;
187
```
188
189
**Usage Examples:**
190
191
```javascript
192
const RED = require("node-red");
193
194
// Generate unique IDs
195
const nodeId = RED.util.generateId(); // Returns 16-character hex string
196
const sessionId = RED.util.generateId(); // All IDs are same length
197
198
// Clone messages safely
199
const originalMsg = { payload: { data: [1, 2, 3] }, topic: "test" };
200
const clonedMsg = RED.util.cloneMessage(originalMsg);
201
202
// Get nested properties
203
const value = RED.util.getMessageProperty(originalMsg, "payload.data.0"); // returns 1
204
205
// Set nested properties
206
RED.util.setMessageProperty(clonedMsg, "payload.metadata.timestamp", Date.now(), true);
207
208
// Type conversion
209
const str = RED.util.ensureString(123); // "123"
210
const buf = RED.util.ensureBuffer("hello"); // Buffer.from("hello")
211
212
// Object property manipulation
213
const obj = { data: { items: [{ name: "test" }] } };
214
const name = RED.util.getObjectProperty(obj, "data.items[0].name"); // "test"
215
RED.util.setObjectProperty(obj, "data.items[0].id", 123, true);
216
217
// Property expression parsing
218
const segments = RED.util.normalisePropertyExpression("data.items[0].name"); // ["data", "items", 0, "name"]
219
220
// Node type normalization
221
const normalized = RED.util.normaliseNodeTypeName("My Custom Node"); // "myCustomNode"
222
223
// Environment variables and node settings
224
const nodeId = RED.util.getSetting(node, "NR_NODE_ID"); // Gets the node's ID
225
const customVar = RED.util.getSetting(node, "MY_CUSTOM_VAR"); // Gets environment variable
226
```
227
228
### Property Evaluation
229
230
Advanced property evaluation system for dynamic value resolution.
231
232
```javascript { .api }
233
/**
234
* Evaluate node property based on type
235
* @param value - Property value
236
* @param type - Property type ('str', 'num', 'bool', 'json', 'msg', 'flow', 'global', 'env', etc.)
237
* @param node - Node object for context
238
* @param msg - Message object for context
239
* @returns Evaluated value
240
*/
241
RED.util.evaluateNodeProperty(value: any, type: string, node: NodeObject, msg: NodeMessage): any;
242
243
/**
244
* Parse context store string
245
* @param str - Context store string (e.g., "#:(file)::key")
246
* @returns Parsed context store information
247
*/
248
RED.util.parseContextStore(str: string): ContextStoreInfo;
249
250
/**
251
* Normalize property expression to array
252
* @param str - Property expression string
253
* @returns Array of property path segments
254
*/
255
RED.util.normalisePropertyExpression(str: string): string[];
256
```
257
258
**Usage Examples:**
259
260
```javascript
261
// Evaluate different property types
262
const strValue = RED.util.evaluateNodeProperty("hello", "str", node, msg); // "hello"
263
const msgValue = RED.util.evaluateNodeProperty("payload", "msg", node, msg); // msg.payload
264
const numValue = RED.util.evaluateNodeProperty("42", "num", node, msg); // 42
265
const boolValue = RED.util.evaluateNodeProperty("true", "bool", node, msg); // true
266
267
// Parse context store references
268
const storeInfo = RED.util.parseContextStore("#:(file)::myKey");
269
// Returns: { key: "myKey", store: "file" }
270
```
271
272
### JSONata Integration
273
274
Utilities for working with JSONata expressions in Node-RED.
275
276
```javascript { .api }
277
/**
278
* Prepare JSONata expression with Node-RED functions
279
* @param value - JSONata expression string
280
* @param node - Node object for context
281
* @returns Prepared JSONata expression object
282
*/
283
RED.util.prepareJSONataExpression(value: string, node: NodeObject): JSONataExpression;
284
285
/**
286
* Evaluate prepared JSONata expression
287
* @param expr - Prepared JSONata expression
288
* @param msg - Message object for evaluation context
289
* @param callback - Callback function for async evaluation (required)
290
* @returns void (result returned via callback)
291
*/
292
RED.util.evaluateJSONataExpression(expr: JSONataExpression, msg: NodeMessage, callback: Function): void;
293
```
294
295
### Event System
296
297
Node-RED's event emitter for runtime events and inter-component communication.
298
299
```javascript { .api }
300
/**
301
* Global event emitter
302
*/
303
interface EventsAPI extends EventEmitter {
304
on(event: string, listener: Function): this;
305
emit(event: string, ...args: any[]): boolean;
306
removeListener(event: string, listener: Function): this;
307
removeAllListeners(event?: string): this;
308
}
309
310
/**
311
* Listen for runtime events
312
* @param event - Event name
313
* @param listener - Event handler function
314
*/
315
RED.events.on(event: string, listener: Function): void;
316
317
/**
318
* Emit runtime event
319
* @param event - Event name
320
* @param args - Event arguments
321
*/
322
RED.events.emit(event: string, ...args: any[]): boolean;
323
```
324
325
**Common Events:**
326
327
```javascript
328
// Listen for node events
329
RED.events.on("nodes-started", () => {
330
console.log("All nodes have started");
331
});
332
333
RED.events.on("nodes-stopped", () => {
334
console.log("All nodes have stopped");
335
});
336
337
// Flow deployment events
338
RED.events.on("runtime-event", (event) => {
339
if (event.id === "runtime-deploy") {
340
console.log("Flows deployed");
341
}
342
});
343
```
344
345
### Hook System
346
347
Extensible hook system for intercepting and modifying Node-RED operations.
348
349
```javascript { .api }
350
/**
351
* Hook management API
352
*/
353
interface HooksAPI {
354
add(type: string, handler: Function): void;
355
remove(type: string, handler: Function): void;
356
clear(type: string): void;
357
trigger(type: string, data: any, callback?: Function): any;
358
has(type: string): boolean;
359
}
360
361
/**
362
* Add hook handler
363
* @param type - Hook type
364
* @param handler - Hook handler function
365
*/
366
RED.hooks.add(type: string, handler: Function): void;
367
368
/**
369
* Remove hook handler
370
* @param type - Hook type
371
* @param handler - Hook handler function to remove
372
*/
373
RED.hooks.remove(type: string, handler: Function): void;
374
375
/**
376
* Trigger hook execution
377
* @param type - Hook type
378
* @param data - Data to pass to hooks
379
* @param callback - Optional callback for async hooks
380
*/
381
RED.hooks.trigger(type: string, data: any, callback?: Function): any;
382
```
383
384
**Available Hook Types:**
385
386
- `onSend` - Before message is sent from node
387
- `preRoute` - Before message is routed to next nodes
388
- `preDeliver` - Before message is delivered to node
389
- `postDeliver` - After message is delivered to node
390
- `onReceive` - When node receives message
391
- `postReceive` - After node processes message
392
- `onComplete` - When message processing completes
393
- `preInstall` - Before node module installation
394
- `postInstall` - After node module installation
395
- `preUninstall` - Before node module uninstallation
396
- `postUninstall` - After node module uninstallation
397
398
**Usage Examples:**
399
400
```javascript
401
// Add message logging hook
402
RED.hooks.add("onSend", (sendEvents) => {
403
sendEvents.forEach(event => {
404
console.log(`Node ${event.source.id} sending:`, event.msg.payload);
405
});
406
});
407
408
// Add message transformation hook
409
RED.hooks.add("preDeliver", (event, done) => {
410
// Add timestamp to all messages
411
event.msg.timestamp = Date.now();
412
done();
413
});
414
```
415
416
## Types
417
418
```javascript { .api }
419
interface NodeMessage {
420
_msgid: string;
421
topic?: string;
422
payload: any;
423
[key: string]: any;
424
}
425
426
interface NodeObject {
427
id: string;
428
type: string;
429
name?: string;
430
[key: string]: any;
431
}
432
433
interface AuditEvent {
434
event: string;
435
level: number;
436
user?: UserObject;
437
path?: string;
438
timestamp?: number;
439
[key: string]: any;
440
}
441
442
interface LogHandler {
443
(settings: object): {
444
log: (level: string, msg: any) => void;
445
close?: () => void;
446
};
447
}
448
449
interface ContextStoreInfo {
450
key: string;
451
store?: string;
452
}
453
454
interface JSONataExpression {
455
evaluate(input: any, bindings?: object): any;
456
assign(name: string, value: any): void;
457
}
458
459
interface EncodeOptions {
460
maxLength?: number;
461
}
462
463
interface FlowObject {
464
getSetting(name: string): string;
465
[key: string]: any;
466
}
467
```