@bonsae/nrg 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,523 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ import { SchemaOptions, Static, TObject, TOptional, TProperties, TSchema, TString } from '@sinclair/typebox';
4
+ import { EventEmitter } from 'events';
5
+ import { Express as Express$1 } from 'express';
6
+ import { Http2ServerRequest } from 'http2';
7
+
8
+ interface NodeRedRuntimeSettings {
9
+ userDir?: string;
10
+ nodesDir?: string | string[];
11
+ flowFile?: string;
12
+ flowFilePretty?: boolean;
13
+ credentialSecret?: string | false;
14
+ requireHttps?: boolean;
15
+ https?: {
16
+ key: string;
17
+ cert: string;
18
+ } | (() => Promise<{
19
+ key: string;
20
+ cert: string;
21
+ }> | {
22
+ key: string;
23
+ cert: string;
24
+ });
25
+ httpsRefreshInterval?: number;
26
+ httpAdminRoot?: string;
27
+ httpNodeRoot?: string;
28
+ httpNodeCors?: {
29
+ origin: string;
30
+ methods: string;
31
+ };
32
+ httpStatic?: string | {
33
+ path: string;
34
+ root: string;
35
+ }[];
36
+ httpStaticRoot?: string;
37
+ httpAdminMiddleware?: (req: unknown, res: unknown, next: () => void) => void;
38
+ httpNodeMiddleware?: (req: unknown, res: unknown, next: () => void) => void;
39
+ httpServerOptions?: Record<string, unknown>;
40
+ adminAuth?: {
41
+ type?: "credentials" | "strategy";
42
+ users?: {
43
+ username: string;
44
+ password: string;
45
+ permissions?: string | string[];
46
+ }[];
47
+ default?: {
48
+ permissions?: string | string[];
49
+ };
50
+ tokens?: (token: string) => Promise<{
51
+ user: string;
52
+ permissions: string | string[];
53
+ } | null>;
54
+ tokenHeader: "string";
55
+ sessionExpiryTime?: number;
56
+ [key: string]: unknown;
57
+ };
58
+ httpNodeAuth?: {
59
+ user?: string;
60
+ pass?: string;
61
+ };
62
+ httpStaticAuth?: {
63
+ user?: string;
64
+ pass?: string;
65
+ };
66
+ lang?: "en-US" | "de" | "es-ES" | "fr" | "ko" | "pt-BR" | "ru" | "ja" | "zh-CN" | "zh-TW";
67
+ diagnostics?: {
68
+ enabled?: boolean;
69
+ ui?: boolean;
70
+ };
71
+ runtimeState?: {
72
+ enabled?: boolean;
73
+ ui?: boolean;
74
+ };
75
+ disableEditor?: boolean;
76
+ editorTheme?: {
77
+ page?: {
78
+ title?: string;
79
+ favicon?: string;
80
+ css?: string | string[];
81
+ scripts?: string | string[];
82
+ };
83
+ header?: {
84
+ title?: string;
85
+ image?: string;
86
+ url?: string;
87
+ };
88
+ deployButton?: {
89
+ type?: "simple" | "default";
90
+ label?: string;
91
+ icon?: string;
92
+ };
93
+ menu?: {
94
+ "menu-item-import-library"?: boolean;
95
+ "menu-item-export-library"?: boolean;
96
+ "menu-item-keyboard-shortcuts"?: boolean;
97
+ "menu-item-help"?: {
98
+ label?: string;
99
+ url?: string;
100
+ };
101
+ [menuItem: string]: boolean | {
102
+ label?: string;
103
+ url?: string;
104
+ } | undefined;
105
+ };
106
+ userMenu?: boolean;
107
+ login?: {
108
+ image?: string;
109
+ };
110
+ logout?: {
111
+ redirect?: string;
112
+ };
113
+ palette?: {
114
+ catalogues?: string[];
115
+ categories?: string[];
116
+ theme?: {
117
+ category: string;
118
+ type: string;
119
+ color: string;
120
+ }[];
121
+ };
122
+ projects?: {
123
+ enabled?: boolean;
124
+ workflow?: {
125
+ mode: "manual" | "auto";
126
+ };
127
+ };
128
+ codeEditor?: {
129
+ lib?: "monaco" | "ace";
130
+ options?: Record<string, unknown>;
131
+ };
132
+ mermaid?: {
133
+ theme?: string;
134
+ };
135
+ tours?: boolean;
136
+ theme?: string;
137
+ [key: string]: unknown;
138
+ };
139
+ contextStorage?: {
140
+ default?: {
141
+ module?: "memory" | "localfilesystem" | object;
142
+ config?: Record<string, unknown>;
143
+ };
144
+ [store: string]: {
145
+ module?: "memory" | "localfilesystem" | object;
146
+ config?: Record<string, unknown>;
147
+ } | undefined;
148
+ };
149
+ exportGlobalContextKeys?: boolean;
150
+ logging?: {
151
+ console?: {
152
+ level?: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "off";
153
+ metrics?: boolean;
154
+ audit?: boolean;
155
+ };
156
+ };
157
+ fileWorkingDirectory?: string;
158
+ functionExternalModules?: boolean;
159
+ functionGlobalContext?: Record<string, unknown>;
160
+ nodeMessageBufferMaxLength?: number;
161
+ functionTimeout?: number;
162
+ externalModules?: {
163
+ autoInstall?: boolean;
164
+ autoInstallRetry?: number;
165
+ palette?: {
166
+ allowInstall?: boolean;
167
+ allowUpdate?: boolean;
168
+ allowUpload?: boolean;
169
+ allowList?: string[];
170
+ denyList?: string[];
171
+ allowUpdateList?: string[];
172
+ denyUpdateList?: string[];
173
+ };
174
+ modules?: {
175
+ allowInstall?: boolean;
176
+ allowList?: string[];
177
+ denyList?: string[];
178
+ };
179
+ };
180
+ execMaxBufferSize?: number;
181
+ debugMaxLength?: number;
182
+ debugUseColors?: boolean;
183
+ httpRequestTimeout?: number;
184
+ mqttReconnectTime?: number;
185
+ serialReconnectTime?: number;
186
+ socketReconnectTime?: number;
187
+ socketTimeout?: number;
188
+ tcpMsgQueueSize?: number;
189
+ inboundWebSocketTimeout?: number;
190
+ tlsConfigDisableLocalFiles?: boolean;
191
+ webSocketNodeVerifyClient?: (info: {
192
+ origin: string;
193
+ req: Http2ServerRequest;
194
+ secure: boolean;
195
+ }) => boolean;
196
+ apiMaxLength?: string;
197
+ [key: string]: unknown;
198
+ }
199
+ declare const NodeConfigSchema: import("@sinclair/typebox").TObject<{
200
+ id: import("@sinclair/typebox").TString;
201
+ type: import("@sinclair/typebox").TString;
202
+ name: import("@sinclair/typebox").TString;
203
+ z: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
204
+ }>;
205
+ interface NodeRedLog {
206
+ info(msg: any): void;
207
+ warn(msg: any): void;
208
+ error(msg: any, error?: any): void;
209
+ debug(msg: any): void;
210
+ trace(msg: any): void;
211
+ log(msg: {
212
+ level: number;
213
+ msg: string;
214
+ }): void;
215
+ metric(): boolean;
216
+ audit(msg: Record<string, any>, req?: any): void;
217
+ addHandler(handler: (msg: any) => void): void;
218
+ removeHandler(handler: (msg: any) => void): void;
219
+ FATAL: 10;
220
+ ERROR: 20;
221
+ WARN: 30;
222
+ INFO: 40;
223
+ DEBUG: 50;
224
+ TRACE: 60;
225
+ AUDIT: 98;
226
+ METRIC: 99;
227
+ }
228
+ interface NodeRedNode {
229
+ id: string;
230
+ type: string;
231
+ name?: string;
232
+ z?: string;
233
+ x: number;
234
+ y: number;
235
+ g?: string;
236
+ wires: string[][];
237
+ credentials: any;
238
+ _node?: INode;
239
+ send(msg: any): void;
240
+ receive(msg: any): void;
241
+ status(status: string | {
242
+ fill?: string;
243
+ shape?: string;
244
+ text?: string;
245
+ }): void;
246
+ updateWires(wires: string[][]): void;
247
+ on(event: string, callback: (...args: any[]) => void): void;
248
+ log(msg: any): void;
249
+ warn(msg: any): void;
250
+ error(msg: any, errorMsg?: any): void;
251
+ context(): NodeRedNodeContext;
252
+ [key: string]: any;
253
+ }
254
+ interface NodeRedNodeContext extends NodeRedContextStore {
255
+ flow: NodeRedContextStore;
256
+ global: NodeRedContextStore;
257
+ }
258
+ interface NodeRedNodes {
259
+ registerType(type: string, constructor: any, opts?: any): void;
260
+ getNode(id: string): (NodeRedNode & {
261
+ _node?: INode;
262
+ }) | undefined;
263
+ createNode(node: NodeRedNode, config: Record<string, any>): void;
264
+ getCredentials(id: string): Record<string, any> | undefined;
265
+ /** Merge credentials into a node's stored credential set (runtime API). */
266
+ addCredentials(id: string, credentials: Record<string, any>): void;
267
+ eachNode(callback: (node: any) => void): void;
268
+ getType(type: string): any;
269
+ getNodeInfo(type: string): any;
270
+ getNodeList(filter?: any): any[];
271
+ getModuleInfo(module: string): any;
272
+ installModule(module: string, version?: string): Promise<any>;
273
+ uninstallModule(module: string): Promise<any>;
274
+ enableNode(id: string): Promise<any>;
275
+ disableNode(id: string): Promise<any>;
276
+ }
277
+ interface NodeRedUtil {
278
+ evaluateNodeProperty(value: any, type: string, node: any, msg: Record<string, any> | undefined, callback: (err: Error | null, result: any) => void): void;
279
+ generateId(): string;
280
+ cloneMessage<T = any>(msg: T): T;
281
+ ensureString(o: any): string;
282
+ ensureBuffer(o: any): Buffer;
283
+ compareObjects(obj1: any, obj2: any): boolean;
284
+ getMessageProperty(msg: any, expr: string): any;
285
+ setMessageProperty(msg: any, prop: string, value: any, createMissing?: boolean): void;
286
+ getObjectProperty(obj: any, expr: string): any;
287
+ setObjectProperty(obj: any, prop: string, value: any, createMissing?: boolean): void;
288
+ normalisePropertyExpression(str: string, msg?: any, toString?: boolean): string[];
289
+ normaliseNodeTypeName(name: string): string;
290
+ prepareJSONataExpression(value: string, node: any): any;
291
+ evaluateJSONataExpression(expr: any, msg: any, callback: (err: Error | null, result: any) => void): void;
292
+ parseContextStore(key: string): {
293
+ store: string | undefined;
294
+ key: string;
295
+ };
296
+ getSetting(node: any, name: string, flow?: any): any;
297
+ encodeObject(obj: any): any;
298
+ }
299
+ interface NodeRedHooks {
300
+ add(hookId: string, callback: (event: any) => void | Promise<void>): void;
301
+ remove(hookId: string): void;
302
+ trigger(hookId: string, event: any, callback?: (err?: Error) => void): void | Promise<void>;
303
+ has(hookId: string): boolean;
304
+ clear(): void;
305
+ }
306
+ type NodeRedExpressApp = Express;
307
+ interface RED {
308
+ /** Internationalization function */
309
+ _(key: string, substitutions?: Record<string, string>): string;
310
+ /** Logging API */
311
+ log: NodeRedLog;
312
+ /** Node registry and management */
313
+ nodes: NodeRedNodes;
314
+ /** Utility functions */
315
+ util: NodeRedUtil;
316
+ /** Hook system for message lifecycle and module events */
317
+ hooks: NodeRedHooks;
318
+ /** Runtime event emitter */
319
+ events: EventEmitter;
320
+ /** Express app for admin HTTP endpoints */
321
+ httpAdmin: NodeRedExpressApp;
322
+ /** Express app for node HTTP endpoints */
323
+ httpNode: NodeRedExpressApp;
324
+ /** Runtime settings (user-provided settings plus node-registered settings) */
325
+ settings: NodeRedRuntimeSettings & Record<string, any>;
326
+ /** Node-RED version string */
327
+ version(): string;
328
+ }
329
+ interface NodeRedContextStore {
330
+ get(key: string, store: string | undefined, callback: (err: Error | null, value: any) => void): void;
331
+ set(key: string, value: any, store: string | undefined, callback: (err: Error | null) => void): void;
332
+ keys(store: string | undefined, callback: (err: Error | null, keys: string[]) => void): void;
333
+ }
334
+ type Schema<T extends TProperties = TProperties> = TObject<T>;
335
+ interface NodeContextStore {
336
+ get<T = any>(key: string): Promise<T>;
337
+ set<T = any>(key: string, value: T): Promise<void>;
338
+ keys(): Promise<string[]>;
339
+ }
340
+ interface NodeConstructor<T = any, TConfig = any, TCredentials = any> {
341
+ readonly type: string;
342
+ readonly category: string;
343
+ readonly color?: string;
344
+ readonly align?: "left" | "right";
345
+ readonly inputs?: number;
346
+ readonly outputs?: number;
347
+ readonly configSchema?: Schema;
348
+ readonly credentialsSchema?: Schema;
349
+ readonly settingsSchema?: Schema;
350
+ readonly inputSchema?: Schema;
351
+ readonly outputsSchema?: TSchema | TSchema[] | Record<string, TSchema>;
352
+ readonly validateInput?: boolean;
353
+ readonly validateOutput?: boolean;
354
+ readonly name: string;
355
+ registered?(RED: RED): void | Promise<void>;
356
+ register(RED: RED): void | Promise<void>;
357
+ validateSettings(RED: RED): void;
358
+ new (RED: RED, node: NodeRedNode, config: NodeConfig<TConfig>, credentials: NodeCredentials<TCredentials>): T;
359
+ }
360
+ type NodeConfig<TConfig = any> = TConfig & Static<typeof NodeConfigSchema>;
361
+ type NodeCredentials<TCredentials = any> = TCredentials;
362
+ interface INode<TConfig = any, TCredentials = any, TSettings = any> {
363
+ readonly config: NodeConfig<TConfig>;
364
+ readonly id: string;
365
+ readonly name: string | undefined;
366
+ readonly z: string | undefined;
367
+ readonly credentials: NodeCredentials<TCredentials> | undefined;
368
+ readonly settings: TSettings;
369
+ i18n(key: string, substitutions?: Record<string, string>): string;
370
+ setTimeout(fn: () => void, ms: number): NodeJS.Timeout;
371
+ setInterval(fn: () => void, ms: number): NodeJS.Timeout;
372
+ clearTimeout(timer: NodeJS.Timeout): void;
373
+ clearInterval(interval: NodeJS.Timeout): void;
374
+ on(event: string, callback: (...args: any[]) => void): void;
375
+ log(msg: any): void;
376
+ warn(message: string): void;
377
+ error(message: string, msg?: any): void;
378
+ created?(): void | Promise<void>;
379
+ closed?(removed?: boolean): void | Promise<void>;
380
+ }
381
+ type Channel = "sent" | "received";
382
+ declare class Recorder {
383
+ #private;
384
+ recordSent(id: string, port: number, msg: unknown): void;
385
+ recordReceived(id: string | undefined, msg: unknown): void;
386
+ /** Snapshot of all messages on a channel for a node (optionally one port). */
387
+ snapshot(channel: Channel, id: string, port?: number): unknown[];
388
+ /** Resolve the message at `index` on a channel, awaiting it if not yet seen. */
389
+ next(channel: Channel, id: string, port: number | undefined, index: number, timeoutMs: number): Promise<unknown>;
390
+ clear(): void;
391
+ }
392
+ interface NodeContext {
393
+ node: NodeContextStore;
394
+ flow: NodeContextStore;
395
+ global: NodeContextStore;
396
+ }
397
+ export interface AddNodeOptions {
398
+ /** Override the generated node id. */
399
+ id?: string;
400
+ /** Node name (the `name` field). */
401
+ name?: string;
402
+ /** Credentials for the node (stored by the runtime, exposed as `this.credentials`). */
403
+ credentials?: Record<string, unknown>;
404
+ }
405
+ export interface ReadOptions {
406
+ /** Reject if no message arrives within this many ms. @default 5000 */
407
+ timeout?: number;
408
+ }
409
+ /**
410
+ * A handle to one node in a deployed flow. Wraps a generated id; the live
411
+ * instance lives inside the runtime, so harness methods (`receive`/`read`/…)
412
+ * never collide with the node's own methods.
413
+ */
414
+ export declare class NodeRef {
415
+ #private;
416
+ readonly id: string;
417
+ readonly type: string;
418
+ readonly isConfig: boolean;
419
+ readonly name: string;
420
+ readonly config: Record<string, unknown>;
421
+ readonly credentials?: Record<string, unknown>;
422
+ readonly wires: string[][];
423
+ constructor(flow: Flow, type: string, isConfig: boolean, config: Record<string, unknown>, opts: AddNodeOptions);
424
+ /** Wire this node's output `port` to `target`'s input. */
425
+ wire(target: NodeRef, port?: number): this;
426
+ /** Deliver a message to this node's input (Node-RED's upstream path). */
427
+ receive(msg: unknown): Promise<void>;
428
+ /** Snapshot of everything this node has emitted (optionally one port). */
429
+ sent(port?: number): unknown[];
430
+ /** Snapshot of everything delivered to this node's input. */
431
+ received(port?: number): unknown[];
432
+ /**
433
+ * Promise-based access to this node's context stores (`node` / `flow` /
434
+ * `global`) — preset values before `receive`, and assert them afterward.
435
+ */
436
+ get context(): NodeContext;
437
+ /**
438
+ * Consume the next un-read message this node emitted (FIFO cursor), awaiting
439
+ * it if not yet sent. Call repeatedly to walk multiple emissions.
440
+ */
441
+ read(port?: number, opts?: ReadOptions): Promise<unknown>;
442
+ }
443
+ /**
444
+ * Builds a flow from nrg node classes and deploys it into a running runtime.
445
+ * Use `addNode` for every node — config nodes included.
446
+ */
447
+ export declare class Flow {
448
+ #private;
449
+ readonly recorder: Recorder;
450
+ constructor(RED: NodeRedApi, recorder: Recorder);
451
+ /** Add any node — regular or config (detected via `category === "config"`). */
452
+ addNode(Cls: NodeConstructor, config?: Record<string, unknown>, opts?: AddNodeOptions): NodeRef;
453
+ /** Build the flow JSON and deploy it; resolves once the flow has started. */
454
+ deploy(): Promise<void>;
455
+ /** Drop the built nodes and clear captured messages (reset between tests). */
456
+ clear(): Promise<void>;
457
+ runtimeNode(id: string): RuntimeNode | null;
458
+ }
459
+ export interface StartRuntimeOptions {
460
+ /** Node classes (IONode / ConfigNode subclasses) to register in the runtime. */
461
+ nodes: NodeConstructor[];
462
+ /** Extra Node-RED settings merged over the headless defaults. */
463
+ settings?: Record<string, unknown>;
464
+ }
465
+ /**
466
+ * Boot a real, in-process Node-RED runtime with the given node types
467
+ * registered. One runtime per test file (the runtime is a process-wide
468
+ * singleton); each test deploys a flow into it and `flow.clear()`s between.
469
+ */
470
+ export declare function startRuntime(options: StartRuntimeOptions): Promise<Runtime>;
471
+ export declare class Runtime {
472
+ #private;
473
+ constructor(RED: NodeRedApi, server: http.Server, userDir: string, recorder: Recorder);
474
+ /** Start a fresh flow to build, deploy, drive and inspect. */
475
+ flow(): Flow;
476
+ /** Stop Node-RED, close the server and remove the temp user dir. */
477
+ stop(): Promise<void>;
478
+ }
479
+ interface NodeRedApi {
480
+ init(server: http.Server, settings: Record<string, unknown>): void;
481
+ start(): Promise<void>;
482
+ stop(): Promise<void>;
483
+ hooks: {
484
+ add(name: "onReceive", fn: (event: {
485
+ destination?: {
486
+ id?: string;
487
+ };
488
+ msg: unknown;
489
+ }) => void): void;
490
+ };
491
+ nodes: {
492
+ getNode(id: string): RuntimeNode | null;
493
+ };
494
+ events: {
495
+ on(event: string, fn: (...args: unknown[]) => void): void;
496
+ removeListener(event: string, fn: (...args: unknown[]) => void): void;
497
+ };
498
+ runtime: {
499
+ flows: {
500
+ setFlows(opts: {
501
+ flows: {
502
+ flows: unknown[];
503
+ };
504
+ deploymentType?: string;
505
+ }): Promise<{
506
+ rev: string;
507
+ }>;
508
+ };
509
+ };
510
+ }
511
+ interface RuntimeNodeContext extends NodeRedContextStore {
512
+ flow: NodeRedContextStore;
513
+ global: NodeRedContextStore;
514
+ }
515
+ interface RuntimeNode {
516
+ id: string;
517
+ type: string;
518
+ receive(msg: unknown): void;
519
+ send(msg: unknown): void;
520
+ context(): RuntimeNodeContext;
521
+ }
522
+
523
+ export {};
@@ -203,6 +203,11 @@ declare const NodeConfigSchema: import("@sinclair/typebox").TObject<{
203
203
  z: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
204
204
  }>;
205
205
  type Schema<T extends TProperties = TProperties> = TObject<T>;
206
+ interface NodeContextStore {
207
+ get<T = any>(key: string): Promise<T>;
208
+ set<T = any>(key: string, value: T): Promise<void>;
209
+ keys(): Promise<string[]>;
210
+ }
206
211
  interface NodeConstructor<T = any, TConfig = any, TCredentials = any> {
207
212
  readonly type: string;
208
213
  readonly category: string;
@@ -409,6 +414,13 @@ interface TestNodeHelpers<TInput = any, TOutput = any> {
409
414
  logged(level?: "info" | "warn" | "error" | "debug"): string[];
410
415
  warned(): string[];
411
416
  errored(): string[];
417
+ /** Promise-based access to the node's context stores (node / flow / global). */
418
+ context: TestNodeContext;
419
+ }
420
+ interface TestNodeContext {
421
+ node: NodeContextStore;
422
+ flow?: NodeContextStore;
423
+ global: NodeContextStore;
412
424
  }
413
425
  interface CreateNodeResult<T> {
414
426
  node: T & TestNodeHelpers<ExtractInput<T>, ExtractOutput<T>>;
package/types/vite.d.ts CHANGED
@@ -80,15 +80,6 @@ export interface NodeRedLauncherOptions {
80
80
  export interface ServerOptions {
81
81
  /** Options for the Node-RED dev server launcher. */
82
82
  nodeRed?: NodeRedLauncherOptions;
83
- /**
84
- * URL-safe path slug the dev server mounts the Node-RED editor under, so
85
- * several `nrg dev` instances can be told apart by path (e.g. behind a
86
- * shared reverse proxy) — the editor is served at
87
- * `http://host:port/<slug>/`. Must match `/^[a-z0-9]+(?:-[a-z0-9]+)*$/`;
88
- * an invalid value is rejected rather than rewritten.
89
- * @default the slugified project folder name
90
- */
91
- slug?: string;
92
83
  }
93
84
  /**
94
85
  * Options for building the distributable Node-RED package.
@@ -111,7 +102,7 @@ export interface BuildOptions {
111
102
  * `build` for the production bundle.
112
103
  */
113
104
  export interface NrgPluginOptions {
114
- /** Dev server options (Node-RED launcher, editor path slug). */
105
+ /** Dev server options (Node-RED launcher). */
115
106
  server?: ServerOptions;
116
107
  /** Production build options (output dir, server/client bundles, copies). */
117
108
  build?: BuildOptions;
@@ -177,10 +168,6 @@ export interface NodeRedLauncher {
177
168
  cleanup(): void;
178
169
  flushLogs(): void;
179
170
  readonly preferredPort: number;
180
- /** URL-safe path slug the editor is mounted under (empty for root). */
181
- readonly slug: string;
182
- /** Path prefix derived from the slug — `/<slug>/`, or `/` when no slug. */
183
- readonly basePath: string;
184
171
  readonly restartDelay: number;
185
172
  readonly pid: number | null;
186
173
  }