@bonsae/nrg 0.21.2 → 0.22.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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -3
  3. package/package.json +14 -9
  4. package/schemas/labels.schema.json +15 -5
  5. package/server/index.cjs +2 -1358
  6. package/test/client/component/index.js +41 -224
  7. package/test/client/component/setup.js +201 -1475
  8. package/test/client/e2e/config.js +12 -0
  9. package/test/client/e2e/index.js +419 -199
  10. package/test/client/unit/index.js +19 -32
  11. package/test/client/unit/setup.js +28 -21
  12. package/test/server/integration/index.js +2 -26
  13. package/test/server/unit/index.js +2 -184
  14. package/types/client.d.ts +1 -266
  15. package/types/server.d.ts +1 -900
  16. package/types/test-client-component.d.ts +7 -143
  17. package/types/test-client-e2e.d.ts +0 -6
  18. package/types/test-client-unit.d.ts +11 -105
  19. package/types/test-server-integration.d.ts +73 -49
  20. package/types/test-server-unit.d.ts +26 -2
  21. package/types/vite.d.ts +2 -0
  22. package/vite/index.js +378 -150
  23. package/server/resources/nrg-client.js +0 -7493
  24. package/test/client/component/nrg.css +0 -1
  25. package/types/shims/brands.d.ts +0 -32
  26. package/types/shims/client/form/components/node-red-config-input.vue.d.ts +0 -125
  27. package/types/shims/client/form/components/node-red-editor-input.vue.d.ts +0 -124
  28. package/types/shims/client/form/components/node-red-input-label.vue.d.ts +0 -34
  29. package/types/shims/client/form/components/node-red-input.vue.d.ts +0 -123
  30. package/types/shims/client/form/components/node-red-json-schema-form.vue.d.ts +0 -772
  31. package/types/shims/client/form/components/node-red-select-input.vue.d.ts +0 -132
  32. package/types/shims/client/form/components/node-red-toggle.vue.d.ts +0 -36
  33. package/types/shims/client/form/components/node-red-typed-input.vue.d.ts +0 -151
  34. package/types/shims/client/globals.d.ts +0 -320
  35. package/types/shims/client/types.d.ts +0 -227
  36. package/types/shims/components.d.ts +0 -23
  37. package/types/shims/constants.d.ts +0 -4
  38. package/types/shims/schema-options.d.ts +0 -24
  39. package/types/shims/shims-vue.d.ts +0 -5
  40. package/types/shims/typebox.d.ts +0 -10
package/server/index.cjs CHANGED
@@ -1,1358 +1,2 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/core/server/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- CompletePortSchema: () => CompletePortSchema,
34
- ConfigNode: () => ConfigNode,
35
- ErrorPortSchema: () => ErrorPortSchema,
36
- IONode: () => IONode,
37
- Node: () => Node,
38
- NodeSourceSchema: () => NodeSourceSchema,
39
- NrgError: () => NrgError,
40
- SchemaType: () => SchemaType,
41
- StatusPortSchema: () => StatusPortSchema,
42
- defineConfigNode: () => defineConfigNode,
43
- defineIONode: () => defineIONode,
44
- defineModule: () => defineModule,
45
- defineSchema: () => defineSchema,
46
- registerType: () => registerType,
47
- registerTypes: () => registerTypes
48
- });
49
- module.exports = __toCommonJS(index_exports);
50
-
51
- // src/core/server/nodes/utils.ts
52
- var import_typebox = require("@sinclair/typebox");
53
-
54
- // src/core/errors.ts
55
- var NrgError = class _NrgError extends Error {
56
- constructor(message) {
57
- super(message);
58
- this.name = "NrgError";
59
- Object.setPrototypeOf(this, _NrgError.prototype);
60
- }
61
- };
62
-
63
- // src/core/server/typed-input.ts
64
- var TypedInput = class {
65
- constructor(RED, node, input) {
66
- this.RED = RED;
67
- this.node = node;
68
- this.input = input;
69
- }
70
- resolvers = {
71
- // evaluateNodeProperty returns the node ID string for "node" type —
72
- // resolve it to the actual node instance via RED.nodes.getNode,
73
- // then surface the NRG wrapper if available.
74
- node: (raw) => {
75
- if (typeof raw === "string") {
76
- const node = this.RED.nodes.getNode(raw);
77
- return node?._node ?? node ?? raw;
78
- }
79
- return raw?._node ?? raw;
80
- }
81
- };
82
- get type() {
83
- return this.input.type;
84
- }
85
- get value() {
86
- return this.input.value;
87
- }
88
- resolve(msg) {
89
- return new Promise((resolve, reject) => {
90
- this.RED.util.evaluateNodeProperty(
91
- this.input.value,
92
- this.input.type,
93
- this.node,
94
- msg,
95
- (err, raw) => {
96
- if (err) return reject(err);
97
- const post = this.resolvers[this.input.type];
98
- resolve(post ? post(raw) : raw);
99
- }
100
- );
101
- });
102
- }
103
- };
104
-
105
- // src/core/server/nodes/utils.ts
106
- function isSchemaLike(obj) {
107
- return obj != null && typeof obj === "object" && import_typebox.Kind in obj;
108
- }
109
- function setupContext(context, store) {
110
- return {
111
- get: (key) => new Promise(
112
- (resolve, reject) => context.get(
113
- key,
114
- store,
115
- (error, value) => error ? reject(error) : resolve(value)
116
- )
117
- ),
118
- set: (key, value) => new Promise(
119
- (resolve, reject) => context.set(
120
- key,
121
- value,
122
- store,
123
- (error) => error ? reject(error) : resolve()
124
- )
125
- ),
126
- keys: () => new Promise(
127
- (resolve, reject) => context.keys(store, (error, k) => error ? reject(error) : resolve(k))
128
- )
129
- };
130
- }
131
- function setupConfigProxy(opts) {
132
- const { RED, node, config, schema } = opts;
133
- const SKIP_PROPS = /* @__PURE__ */ new Set(["id", "_id", "_users"]);
134
- const nodeRefProps = /* @__PURE__ */ new Set();
135
- const typedInputProps = /* @__PURE__ */ new Set();
136
- if (schema?.properties) {
137
- for (const [key, propSchema] of Object.entries(schema.properties)) {
138
- const s = propSchema;
139
- if (s?.["x-nrg-node-type"]) nodeRefProps.add(key);
140
- if (s?.["x-nrg-typed-input"]) typedInputProps.add(key);
141
- }
142
- }
143
- const cache = /* @__PURE__ */ new WeakMap();
144
- const createProxy = (obj) => {
145
- const cached = cache.get(obj);
146
- if (cached) return cached;
147
- if (Array.isArray(obj)) {
148
- const mapped = obj.map(
149
- (item) => item && typeof item === "object" ? createProxy(item) : item
150
- );
151
- cache.set(obj, mapped);
152
- return mapped;
153
- }
154
- const proxy = new Proxy(obj, {
155
- get(target, prop) {
156
- if (typeof prop === "symbol") return target[prop];
157
- if (SKIP_PROPS.has(prop)) return target[prop];
158
- const value = target[prop];
159
- if (typeof value === "string" && value.length > 0 && nodeRefProps.has(prop)) {
160
- return RED.nodes.getNode(value)?._node ?? value;
161
- }
162
- if (typedInputProps.has(prop) && value && typeof value === "object" && "type" in value && "value" in value) {
163
- let ref = cache.get(value);
164
- if (!ref) {
165
- ref = new TypedInput(RED, node, value);
166
- cache.set(value, ref);
167
- }
168
- return ref;
169
- }
170
- if (value && typeof value === "object") {
171
- return createProxy(value);
172
- }
173
- return value;
174
- },
175
- set(_target, prop) {
176
- throw new NrgError(
177
- `Cannot set property '${String(prop)}' on read-only node config`
178
- );
179
- }
180
- });
181
- cache.set(obj, proxy);
182
- return proxy;
183
- };
184
- return createProxy(config);
185
- }
186
-
187
- // src/core/server/utils.ts
188
- function getCredentialsFromSchema(schema) {
189
- const result = {};
190
- for (const [key, value] of Object.entries(schema.properties)) {
191
- const property = value;
192
- result[key] = {
193
- // NOTE: required is always false because it is controlled by the JSON Schema and AJV validation instead of using node-red client core
194
- required: false,
195
- type: property.format === "password" ? "password" : "text",
196
- value: property.default ?? void 0
197
- };
198
- }
199
- return result;
200
- }
201
-
202
- // src/core/server/nodes/symbols.ts
203
- var WIRE_HANDLERS = Symbol.for("nrg.wireHandlers");
204
-
205
- // src/core/server/nodes/node.ts
206
- var cachedSettingsMap = /* @__PURE__ */ new WeakMap();
207
- var Node = class _Node {
208
- static type;
209
- static category;
210
- static configSchema;
211
- static credentialsSchema;
212
- static settingsSchema;
213
- static validateSettings(RED) {
214
- if (!this.settingsSchema) return;
215
- RED.log.info("Validating settings");
216
- const prefix = this.type.replace(/-./g, (x) => x[1].toUpperCase());
217
- const properties = this.settingsSchema.properties;
218
- const settings = {};
219
- for (const key of Object.keys(properties)) {
220
- const settingKey = prefix + key.charAt(0).toUpperCase() + key.slice(1);
221
- const value = RED.settings[settingKey];
222
- if (value !== void 0) {
223
- settings[key] = value;
224
- }
225
- }
226
- for (const [key, prop] of Object.entries(properties)) {
227
- if (settings[key] === void 0) {
228
- const defaultValue = prop.default ?? prop._default;
229
- if (defaultValue !== void 0) {
230
- settings[key] = defaultValue;
231
- }
232
- }
233
- }
234
- RED.validator.validate(settings, this.settingsSchema, {
235
- cacheKey: this.settingsSchema.$id || `${this.type}:settings`,
236
- throwOnError: true
237
- });
238
- cachedSettingsMap.set(this, settings);
239
- RED.log.info("Settings are valid");
240
- }
241
- static #buildSettings(NC) {
242
- if (!NC.settingsSchema) return;
243
- const settings = {};
244
- const prefix = NC.type.replace(/-./g, (x) => x[1].toUpperCase());
245
- for (const [key, prop] of Object.entries(NC.settingsSchema.properties)) {
246
- const settingKey = prefix + key.charAt(0).toUpperCase() + key.slice(1);
247
- settings[settingKey] = {
248
- value: prop.default,
249
- exportable: prop.exportable ?? false
250
- };
251
- }
252
- return settings;
253
- }
254
- /**
255
- * Registers this node class with Node-RED. Handles instance creation,
256
- * event handler wiring, settings validation, and the user's registered() hook.
257
- */
258
- static async register(RED) {
259
- const NodeClass = this;
260
- if (NodeClass.color && !/^#[0-9A-Fa-f]{6}$/.test(NodeClass.color)) {
261
- throw new NrgError(
262
- `Invalid color for ${NodeClass.type}: ${NodeClass.color} color must be in hex format`
263
- );
264
- }
265
- RED.nodes.registerType(
266
- NodeClass.type,
267
- function(config) {
268
- RED.nodes.createNode(this, config);
269
- const node = new NodeClass(RED, this, config, this.credentials);
270
- Object.defineProperty(this, "_node", {
271
- value: node,
272
- writable: false,
273
- configurable: false,
274
- enumerable: false
275
- });
276
- const createdPromise = Promise.resolve(node.created?.()).catch(
277
- (error) => {
278
- const message = error instanceof Error ? error.message : String(error);
279
- this.error("Error during created hook: " + message);
280
- throw error;
281
- }
282
- );
283
- createdPromise.catch(() => {
284
- });
285
- node[WIRE_HANDLERS](this, createdPromise);
286
- },
287
- {
288
- credentials: NodeClass.credentialsSchema ? getCredentialsFromSchema(NodeClass.credentialsSchema) : {},
289
- settings: _Node.#buildSettings(this)
290
- }
291
- );
292
- NodeClass.validateSettings(RED);
293
- try {
294
- await Promise.resolve(NodeClass.registered?.(RED));
295
- } catch (error) {
296
- const message = error instanceof Error ? error.message : String(error);
297
- RED.log.error(
298
- `Error during registered hook for ${NodeClass.type}: ${message}`
299
- );
300
- }
301
- }
302
- RED;
303
- node;
304
- context;
305
- config;
306
- timers = /* @__PURE__ */ new Set();
307
- intervals = /* @__PURE__ */ new Set();
308
- constructor(RED, node, config, credentials) {
309
- this.RED = RED;
310
- this.node = node;
311
- const constructor = this.constructor;
312
- if (constructor.configSchema) {
313
- this.log("Validating configs");
314
- const configResult = this.RED.validator.validate(
315
- config,
316
- constructor.configSchema,
317
- {
318
- cacheKey: constructor.configSchema.$id || `${constructor.type}:configs-schema`,
319
- throwOnError: false
320
- }
321
- );
322
- if (!configResult.valid && configResult.errors?.length) {
323
- this.warn(
324
- `Config validation errors: ${configResult.errors.map((e) => `${e.instancePath} ${e.message}`).join("; ")}`
325
- );
326
- }
327
- }
328
- this.config = setupConfigProxy({
329
- RED,
330
- node,
331
- config,
332
- schema: constructor.configSchema
333
- });
334
- if (constructor.credentialsSchema && credentials) {
335
- this.log("Validating credentials");
336
- const credResult = this.RED.validator.validate(
337
- credentials,
338
- constructor.credentialsSchema,
339
- {
340
- cacheKey: constructor.credentialsSchema.$id || `${constructor.type}:credentials-schema`,
341
- throwOnError: false
342
- }
343
- );
344
- if (!credResult.valid && credResult.errors?.length) {
345
- this.warn(
346
- `Credentials validation errors: ${credResult.errors.map((e) => `${e.instancePath} ${e.message}`).join("; ")}`
347
- );
348
- }
349
- }
350
- }
351
- [WIRE_HANDLERS](nodeRedNode, createdPromise) {
352
- nodeRedNode.on(
353
- "close",
354
- async (removed, done) => {
355
- try {
356
- this.log("Calling closed");
357
- await this.#closed(removed);
358
- this.log("Node was closed");
359
- done();
360
- } catch (error) {
361
- if (error instanceof Error) {
362
- this.error("Error while closing node: " + error.message);
363
- done(error);
364
- } else {
365
- this.error("Unknown error occurred while closing node");
366
- done(new Error("Unknown error occurred while closing node"));
367
- }
368
- }
369
- }
370
- );
371
- }
372
- async #closed(removed) {
373
- try {
374
- await Promise.resolve(this.closed?.(removed));
375
- } finally {
376
- this.log("clearing timers and intervals");
377
- this.timers.forEach((t) => clearTimeout(t));
378
- this.intervals.forEach((i) => clearInterval(i));
379
- this.timers.clear();
380
- this.intervals.clear();
381
- this.log("timers and intervals cleared");
382
- }
383
- }
384
- i18n(key, substitutions) {
385
- const nodeType = this.constructor.type;
386
- return this.RED._(`${nodeType}.${key}`, substitutions);
387
- }
388
- setTimeout(fn, ms) {
389
- const timer = setTimeout(() => {
390
- this.timers.delete(timer);
391
- fn();
392
- }, ms);
393
- this.timers.add(timer);
394
- return timer;
395
- }
396
- setInterval(fn, ms) {
397
- const interval = setInterval(fn, ms);
398
- this.intervals.add(interval);
399
- return interval;
400
- }
401
- clearTimeout(timer) {
402
- clearTimeout(timer);
403
- this.timers.delete(timer);
404
- }
405
- clearInterval(interval) {
406
- clearInterval(interval);
407
- this.intervals.delete(interval);
408
- }
409
- on(event, callback) {
410
- this.node.on(event, callback);
411
- }
412
- log(msg) {
413
- this.node.log(msg);
414
- }
415
- warn(message) {
416
- this.node.warn(message);
417
- }
418
- error(message, msg) {
419
- this.node.error(message, msg);
420
- }
421
- get id() {
422
- return this.node.id;
423
- }
424
- get name() {
425
- return this.node.name;
426
- }
427
- get z() {
428
- return this.node.z;
429
- }
430
- get credentials() {
431
- return this.node.credentials;
432
- }
433
- get settings() {
434
- const constructor = this.constructor;
435
- return cachedSettingsMap.get(constructor) ?? {};
436
- }
437
- };
438
-
439
- // src/core/server/nodes/io-node.ts
440
- var RETURN_PROPERTY_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
441
- var INPUT_KEY = "input";
442
- var IONode = class extends Node {
443
- static align;
444
- static color;
445
- static inputSchema;
446
- // outputsSchema accepts any schema shape: the raw sent value (per port) is
447
- // validated, and results are frequently non-objects.
448
- static outputsSchema;
449
- static validateInput = false;
450
- static validateOutput = false;
451
- static get inputs() {
452
- return this.inputSchema ? 1 : 0;
453
- }
454
- static get outputs() {
455
- const s = this.outputsSchema;
456
- if (!s) return 0;
457
- if (Array.isArray(s)) return s.length;
458
- if (isSchemaLike(s)) return 1;
459
- const keys = Object.keys(s);
460
- for (const key of keys) {
461
- if (/^\d+$/.test(key)) {
462
- throw new NrgError(
463
- `outputsSchema record key "${key}" in ${this.type} looks numeric. Use descriptive string names (e.g. "success", "failure") to avoid JavaScript object key ordering issues.`
464
- );
465
- }
466
- if (key === "error" || key === "complete" || key === "status") {
467
- throw new NrgError(
468
- `outputsSchema record key "${key}" in ${this.type} is reserved for built-in ports. Use a different name (e.g. "failed" instead of "error").`
469
- );
470
- }
471
- }
472
- return keys.length;
473
- }
474
- /**
475
- * The names of the base output ports when `outputsSchema` is a record of
476
- * named ports (`{ success, failure }`), in declaration order — otherwise
477
- * `undefined` (a single schema or a positional array). Resolved here, where
478
- * TypeBox's `Kind` symbol is intact, so the editor reads the names directly
479
- * instead of guessing them from a serialized (symbol-stripped) schema.
480
- */
481
- static get outputPortNames() {
482
- const s = this.outputsSchema;
483
- if (!s || Array.isArray(s) || isSchemaLike(s)) return void 0;
484
- return Object.keys(s);
485
- }
486
- #send;
487
- /**
488
- * Most recent input message — the spread base for output wrapping. Not
489
- * cleared after input() so late async sends merge with the last received
490
- * message.
491
- */
492
- #currentInputMsg;
493
- context;
494
- constructor(RED, node, config, credentials) {
495
- super(RED, node, config, credentials);
496
- const context = node.context();
497
- const fn = (scope, store) => {
498
- const target = scope === "global" ? context.global : scope === "flow" ? context.flow : context;
499
- return setupContext(target, store);
500
- };
501
- fn.node = setupContext(context);
502
- fn.flow = setupContext(context.flow);
503
- fn.global = setupContext(context.global);
504
- this.context = fn;
505
- const outputReturnProperties = this.config.outputReturnProperties;
506
- if (outputReturnProperties) {
507
- for (const [port, key] of Object.entries(outputReturnProperties)) {
508
- if (typeof key === "string" && key.trim() && !RETURN_PROPERTY_PATTERN.test(key.trim())) {
509
- throw new NrgError(
510
- `Invalid return property "${key}" for output port ${port} in ${this.constructor.type} \u2014 it must be a valid JavaScript identifier (letters, digits, _, $; not starting with a digit)`
511
- );
512
- }
513
- }
514
- }
515
- }
516
- [WIRE_HANDLERS](nodeRedNode, createdPromise) {
517
- super[WIRE_HANDLERS](nodeRedNode, createdPromise);
518
- const NC = this.constructor;
519
- nodeRedNode.on(
520
- "input",
521
- async (msg, send, done) => {
522
- try {
523
- await createdPromise;
524
- } catch {
525
- done(new Error("Node failed to initialize"));
526
- return;
527
- }
528
- try {
529
- nodeRedNode.log("Calling input");
530
- this.#currentInputMsg = msg;
531
- await Promise.resolve(this.#input(msg, send));
532
- this.#sendToPort("complete", {
533
- ...msg,
534
- complete: {
535
- source: this.#nodeSource()
536
- },
537
- [INPUT_KEY]: msg
538
- });
539
- done();
540
- nodeRedNode.log("Input processed");
541
- } catch (error) {
542
- const errorMsg = error instanceof Error ? error.message : "Unknown error during input handling";
543
- this.#sendToPort("error", {
544
- ...msg,
545
- error: {
546
- message: errorMsg,
547
- source: this.#nodeSource()
548
- },
549
- [INPUT_KEY]: msg
550
- });
551
- if (error instanceof Error) {
552
- nodeRedNode.error(
553
- "Error while processing input: " + error.message,
554
- msg
555
- );
556
- done(error);
557
- } else {
558
- nodeRedNode.error(
559
- "Unknown error occurred during input handling",
560
- msg
561
- );
562
- done(new Error(errorMsg));
563
- }
564
- }
565
- }
566
- );
567
- }
568
- input(msg) {
569
- }
570
- async #input(msg, send) {
571
- const NodeClass = this.constructor;
572
- const shouldValidateInput = this.config.validateInput ?? NodeClass.validateInput;
573
- if (shouldValidateInput && NodeClass.inputSchema) {
574
- this.log("Validating input");
575
- this.RED.validator.validate(msg, NodeClass.inputSchema, {
576
- cacheKey: NodeClass.inputSchema.$id || `${NodeClass.type}:input-schema`,
577
- throwOnError: true
578
- });
579
- this.log("Input is valid");
580
- }
581
- this.#send = send;
582
- try {
583
- await Promise.resolve(this.input(msg));
584
- } finally {
585
- this.#send = void 0;
586
- }
587
- }
588
- send(msg) {
589
- const sendsValue = this.baseOutputs <= 1;
590
- if (Array.isArray(msg) && !sendsValue) {
591
- const slots = msg.slice(0, this.baseOutputs);
592
- const out = slots.map((m, port) => {
593
- if (m == null) return m;
594
- this.#validatePort(m, port);
595
- return this.#wrapOutgoing(m, this.#resolveContextMode(port), port);
596
- });
597
- this.#deliver(out);
598
- return;
599
- }
600
- if (msg == null) {
601
- this.#deliver(msg);
602
- return;
603
- }
604
- this.#validatePort(msg, 0);
605
- this.#deliver(this.#wrapOutgoing(msg, this.#resolveContextMode(0), 0));
606
- }
607
- #deliver(out) {
608
- if (this.#send) {
609
- this.#send(out);
610
- } else {
611
- this.node.send(out);
612
- }
613
- }
614
- /**
615
- * Per-port output validation. A port validates when its flow-author flag
616
- * (`config.validateOutputs[port]`) — or the node's static `validateOutput`
617
- * fallback — is on and a schema exists for that port.
618
- */
619
- #validatePort(value, port) {
620
- const NodeClass = this.constructor;
621
- const configured = this.config.validateOutputs?.[port];
622
- if (!(configured ?? NodeClass.validateOutput)) return;
623
- const schema = this.#outputSchemaForPort(port);
624
- if (!schema) return;
625
- this.log("Validating output");
626
- this.RED.validator.validate(value, schema, {
627
- cacheKey: schema.$id || `${NodeClass.type}:output-schema:${port}`,
628
- throwOnError: true
629
- });
630
- this.log("Output is valid");
631
- }
632
- /** Resolves the output schema for a base-output port: array → `[port]`,
633
- * record → the port-th value, single schema → itself. */
634
- #outputSchemaForPort(port) {
635
- const raw = this.constructor.outputsSchema;
636
- if (!raw) return void 0;
637
- if (Array.isArray(raw)) return raw[port];
638
- if (isSchemaLike(raw)) return raw;
639
- return Object.values(raw)[port];
640
- }
641
- /**
642
- * The return key for an output port — `"output"` unless a custom one is set
643
- * via `outputReturnProperties[port]` (author default and/or flow-author
644
- * override, only possible when the node declares `outputReturnProperties`).
645
- * `this.send(x)` always means "x is the value at this port's return key",
646
- * never "x is the whole outgoing message".
647
- */
648
- #returnPropertyKey(port) {
649
- const configured = this.config.outputReturnProperties?.[port];
650
- if (typeof configured === "string" && configured.trim()) {
651
- return configured.trim();
652
- }
653
- return "output";
654
- }
655
- /**
656
- * Resolves the context mode for a base-output port from the flow author's
657
- * per-port config (`config.outputContextModes[port]`, written by the editor
658
- * when the node declares `outputContextModes`), falling back to `"carry"`.
659
- */
660
- #resolveContextMode(port) {
661
- return this.config.outputContextModes?.[port] ?? "carry";
662
- }
663
- /**
664
- * Merges a sent value into the incoming message at the returnProperty key so
665
- * upstream message properties propagate. A fresh base is built per call so
666
- * multi-port sends never share an object.
667
- */
668
- #wrapOutgoing(value, mode, port) {
669
- const key = this.#returnPropertyKey(port);
670
- const input = this.#currentInputMsg ?? {};
671
- if (mode === "reset") {
672
- return { [key]: value };
673
- }
674
- if (mode === "trace") {
675
- return { ...input, [key]: value, [INPUT_KEY]: input };
676
- }
677
- return { ...input, [key]: value };
678
- }
679
- // --- Built-in port management ---
680
- get baseOutputs() {
681
- return this.constructor.outputs ?? 0;
682
- }
683
- get totalOutputs() {
684
- const config = this.config;
685
- let count = this.baseOutputs;
686
- if (config.errorPort) count++;
687
- if (config.completePort) count++;
688
- if (config.statusPort) count++;
689
- return count;
690
- }
691
- /**
692
- * Send a message to a specific output port by index or name.
693
- * Custom named ports are resolved from `outputsSchema` when it is a record.
694
- * Numeric indices refer to the base output ports (0-based).
695
- *
696
- * Built-in ports (`"error"`, `"complete"`, `"status"`) are managed by the
697
- * framework and cannot be sent to directly. Use `this.status()` for status,
698
- * throw an error or call `this.error()` for the error port, and the complete
699
- * port is sent automatically on successful input processing.
700
- */
701
- sendToPort(port, msg) {
702
- if (port === "error" || port === "complete" || port === "status") {
703
- throw new NrgError(
704
- `sendToPort("${port}") is not allowed. Built-in ports are managed by the framework.`
705
- );
706
- }
707
- const portIndex = typeof port === "number" ? port : this.#getNamedPortIndex(port);
708
- const mode = this.#resolveContextMode(portIndex ?? 0);
709
- this.#sendToPort(
710
- port,
711
- msg == null ? msg : this.#wrapOutgoing(msg, mode, portIndex ?? 0)
712
- );
713
- }
714
- #sendToPort(port, msg) {
715
- let portIndex;
716
- if (typeof port === "number") {
717
- portIndex = port;
718
- } else if (port === "error" || port === "complete" || port === "status") {
719
- portIndex = this.#getBuiltinPortIndex(port);
720
- if (portIndex === null) return;
721
- } else {
722
- portIndex = this.#getNamedPortIndex(port);
723
- if (portIndex === null) return;
724
- }
725
- const out = new Array(this.totalOutputs);
726
- out[portIndex] = msg;
727
- this.node.send(out);
728
- }
729
- #getNamedPortIndex(name) {
730
- const schema = this.constructor.outputsSchema;
731
- if (!schema || Array.isArray(schema) || isSchemaLike(schema)) return null;
732
- const idx = Object.keys(schema).indexOf(name);
733
- return idx === -1 ? null : idx;
734
- }
735
- #getBuiltinPortIndex(name) {
736
- const config = this.config;
737
- if (name === "error") {
738
- return config.errorPort ? this.baseOutputs : null;
739
- }
740
- let idx = this.baseOutputs;
741
- if (config.errorPort) idx++;
742
- if (name === "complete") {
743
- return config.completePort ? idx : null;
744
- }
745
- if (config.completePort) idx++;
746
- return config.statusPort ? idx : null;
747
- }
748
- #nodeSource() {
749
- return {
750
- id: this.id,
751
- type: this.constructor.type,
752
- name: this.name
753
- };
754
- }
755
- status(status) {
756
- this.node.status(status);
757
- this.#sendToPort("status", {
758
- status,
759
- source: this.#nodeSource()
760
- });
761
- }
762
- error(message, msg) {
763
- super.error(message, msg);
764
- if (msg) {
765
- this.#sendToPort("error", {
766
- ...msg,
767
- error: {
768
- message,
769
- source: this.#nodeSource()
770
- },
771
- [INPUT_KEY]: msg
772
- });
773
- }
774
- }
775
- updateWires(wires) {
776
- this.node.updateWires(wires);
777
- }
778
- receive(msg) {
779
- this.node.receive(msg);
780
- }
781
- get x() {
782
- return this.node.x;
783
- }
784
- get y() {
785
- return this.node.y;
786
- }
787
- get g() {
788
- return this.node.g;
789
- }
790
- get wires() {
791
- return this.node.wires;
792
- }
793
- get credentials() {
794
- return this.node.credentials;
795
- }
796
- };
797
-
798
- // src/core/server/nodes/config-node.ts
799
- var ConfigNode = class extends Node {
800
- static category = "config";
801
- context;
802
- constructor(RED, node, config, credentials) {
803
- super(RED, node, config, credentials);
804
- const context = node.context();
805
- const fn = (scope, store) => {
806
- const target = scope === "global" ? context.global : context;
807
- return setupContext(target, store);
808
- };
809
- fn.node = setupContext(context);
810
- fn.global = setupContext(context.global);
811
- this.context = fn;
812
- }
813
- get userIds() {
814
- return this.config._users;
815
- }
816
- get users() {
817
- return this.userIds.map((id) => this.RED.nodes.getNode(id)?._node).filter((node) => node != null);
818
- }
819
- getUser(index) {
820
- const id = this.userIds[index];
821
- if (!id) return void 0;
822
- return this.RED.nodes.getNode(id)?._node;
823
- }
824
- get credentials() {
825
- return this.node.credentials;
826
- }
827
- };
828
-
829
- // src/core/server/nodes/factories.ts
830
- function defineIONode(def) {
831
- const NodeClass = class extends IONode {
832
- static type = def.type;
833
- static category = def.category ?? "function";
834
- static color = def.color ?? "#a6bbcf";
835
- static align = def.align;
836
- static configSchema = def.configSchema;
837
- static credentialsSchema = def.credentialsSchema;
838
- static settingsSchema = def.settingsSchema;
839
- static inputSchema = def.inputSchema;
840
- static outputsSchema = def.outputsSchema;
841
- static validateInput = def.validateInput ?? false;
842
- static validateOutput = def.validateOutput ?? false;
843
- static registered(RED) {
844
- return def.registered?.(RED);
845
- }
846
- async input(msg) {
847
- if (def.input) return def.input.call(this, msg);
848
- }
849
- async created() {
850
- if (def.created) return def.created.call(this);
851
- }
852
- async closed(removed) {
853
- if (def.closed) return def.closed.call(this, removed);
854
- }
855
- };
856
- Object.defineProperty(NodeClass, "name", {
857
- value: def.type.replace(
858
- /(^|-)(\w)/g,
859
- (_, __, c) => c.toUpperCase()
860
- ),
861
- configurable: true
862
- });
863
- return NodeClass;
864
- }
865
- function defineConfigNode(def) {
866
- const NodeClass = class extends ConfigNode {
867
- static type = def.type;
868
- static configSchema = def.configSchema;
869
- static credentialsSchema = def.credentialsSchema;
870
- static settingsSchema = def.settingsSchema;
871
- static registered(RED) {
872
- return def.registered?.(RED);
873
- }
874
- async created() {
875
- if (def.created) return def.created.call(this);
876
- }
877
- async closed(removed) {
878
- if (def.closed) return def.closed.call(this, removed);
879
- }
880
- };
881
- Object.defineProperty(NodeClass, "name", {
882
- value: def.type.replace(
883
- /(^|-)(\w)/g,
884
- (_, __, c) => c.toUpperCase()
885
- ),
886
- configurable: true
887
- });
888
- return NodeClass;
889
- }
890
-
891
- // src/core/validator.ts
892
- var import_ajv = __toESM(require("ajv"), 1);
893
- var import_ajv_formats = __toESM(require("ajv-formats"), 1);
894
- var import_ajv_errors = __toESM(require("ajv-errors"), 1);
895
- var Validator = class {
896
- ajv;
897
- constructor(options) {
898
- const { customKeywords, customFormats, ...ajvOptions } = options || {};
899
- this.ajv = new import_ajv.default({
900
- allErrors: true,
901
- code: {
902
- source: false
903
- },
904
- coerceTypes: true,
905
- removeAdditional: false,
906
- strict: false,
907
- strictSchema: false,
908
- useDefaults: true,
909
- validateFormats: true,
910
- // NOTE: typebox handles validation via typescript
911
- // NOTE: if true, types that are not serializable JSON, like Function, would not work
912
- validateSchema: false,
913
- verbose: true,
914
- ...ajvOptions
915
- });
916
- (0, import_ajv_formats.default)(this.ajv);
917
- (0, import_ajv_errors.default)(this.ajv);
918
- this.addCustomKeywords(customKeywords || []);
919
- this.addCustomFormats(customFormats || {});
920
- }
921
- /**
922
- * Add custom keywords to the validator
923
- */
924
- addCustomKeywords(keywords) {
925
- if (!keywords) return;
926
- keywords.forEach((keyword) => {
927
- this.ajv.addKeyword(keyword);
928
- });
929
- }
930
- /**
931
- * Add custom formats to the validator
932
- */
933
- addCustomFormats(formats) {
934
- if (!formats) return;
935
- Object.entries(formats).forEach(([name, validator]) => {
936
- if (validator instanceof RegExp) {
937
- this.ajv.addFormat(name, validator);
938
- } else {
939
- this.ajv.addFormat(name, { validate: validator });
940
- }
941
- });
942
- }
943
- /**
944
- * Create a validator function with caching
945
- * @param schema - JSON Schema to validate against
946
- * @param cacheKey - Optional cache key for reusing validators
947
- */
948
- createValidator(schema, cacheKey) {
949
- if (cacheKey && !schema.$id) {
950
- schema.$id = cacheKey;
951
- }
952
- if (schema.$id) {
953
- const cached = this.ajv.getSchema(schema.$id);
954
- if (cached) return cached;
955
- }
956
- const validator = this.ajv.compile(schema);
957
- return validator;
958
- }
959
- /**
960
- * Validate data against a schema and return a structured result
961
- */
962
- validate(data, schema, options) {
963
- const validator = this.createValidator(schema, options?.cacheKey);
964
- const valid = validator(data);
965
- if (!valid) {
966
- const errorMessage = this.formatErrors(validator.errors);
967
- if (options?.throwOnError) {
968
- throw new ValidationError(errorMessage, validator.errors || []);
969
- }
970
- return {
971
- valid: false,
972
- errors: validator.errors || void 0,
973
- errorMessage
974
- };
975
- }
976
- return {
977
- valid: true,
978
- data
979
- };
980
- }
981
- /**
982
- * Format errors into a human-readable string
983
- */
984
- formatErrors(errors, options) {
985
- if (!errors || errors.length === 0) {
986
- return "No errors";
987
- }
988
- return this.ajv.errorsText(errors, {
989
- separator: "; ",
990
- dataVar: "data",
991
- ...options
992
- });
993
- }
994
- /**
995
- * Get detailed error information
996
- */
997
- getDetailedErrors(errors) {
998
- if (!errors || errors.length === 0) return [];
999
- return errors.map((error) => ({
1000
- field: error.instancePath || "/",
1001
- message: error.message || "Validation failed",
1002
- keyword: error.keyword,
1003
- params: error.params,
1004
- schemaPath: error.schemaPath
1005
- }));
1006
- }
1007
- /**
1008
- * Add a schema to the validator for reference
1009
- */
1010
- addSchema(schema, key) {
1011
- this.ajv.addSchema(schema, key);
1012
- return this;
1013
- }
1014
- /**
1015
- * Remove a schema from the validator
1016
- */
1017
- removeSchema(key) {
1018
- this.ajv.removeSchema(key);
1019
- return this;
1020
- }
1021
- };
1022
- var ValidationError = class _ValidationError extends Error {
1023
- constructor(message, errors) {
1024
- super(message);
1025
- this.errors = errors;
1026
- this.name = "ValidationError";
1027
- Object.setPrototypeOf(this, _ValidationError.prototype);
1028
- }
1029
- };
1030
-
1031
- // src/core/server/validation.ts
1032
- function initValidator(RED) {
1033
- if (RED.validator) return;
1034
- const nrg = {
1035
- validator: new Validator({
1036
- customKeywords: [
1037
- {
1038
- keyword: "x-nrg-skip-validation",
1039
- schemaType: "boolean",
1040
- valid: true
1041
- },
1042
- {
1043
- keyword: "x-nrg-node-type",
1044
- type: "string",
1045
- validate: (schemaValue, dataValue) => {
1046
- if (!dataValue) return true;
1047
- const node = RED.nodes.getNode(dataValue);
1048
- return node?.type === schemaValue;
1049
- }
1050
- }
1051
- ],
1052
- customFormats: {
1053
- "node-id": /^[a-zA-Z0-9-_]+$/,
1054
- "flow-id": /^[a-f0-9]{16}$/,
1055
- "topic-path": (data) => /^[a-zA-Z0-9/_-]+$/.test(data)
1056
- }
1057
- })
1058
- };
1059
- Object.defineProperty(RED, "_nrg", {
1060
- value: nrg,
1061
- writable: false,
1062
- enumerable: false,
1063
- configurable: false
1064
- });
1065
- Object.defineProperty(RED, "validator", {
1066
- get: () => nrg.validator,
1067
- enumerable: false,
1068
- configurable: false
1069
- });
1070
- }
1071
-
1072
- // src/core/server/api/assets.ts
1073
- var import_path = __toESM(require("path"), 1);
1074
- var import_fs = __toESM(require("fs"), 1);
1075
- var import_module = require("module");
1076
- function serveFile(filePath) {
1077
- return (_req, res, next) => {
1078
- if (!import_fs.default.existsSync(filePath)) return next();
1079
- res.setHeader("Content-Type", "application/javascript");
1080
- import_fs.default.createReadStream(filePath).pipe(res);
1081
- };
1082
- }
1083
- function initAssetsRoutes(router) {
1084
- const resourcesDir = import_path.default.resolve(__dirname, "./resources");
1085
- if (!import_fs.default.existsSync(resourcesDir)) return;
1086
- const _require = (0, import_module.createRequire)(import_path.default.join(__dirname, "package.json"));
1087
- const vueFile = process.env.NODE_ENV !== "production" ? _require.resolve("vue/dist/vue.esm-browser.js") : _require.resolve("vue/dist/vue.esm-browser.prod.js");
1088
- router.get(
1089
- "/nrg/assets/nrg-client.js",
1090
- serveFile(import_path.default.join(resourcesDir, "nrg-client.js"))
1091
- );
1092
- router.get("/nrg/assets/vue.esm-browser.prod.js", serveFile(vueFile));
1093
- router.get("/nrg/assets/vue.esm-browser.js", serveFile(vueFile));
1094
- }
1095
-
1096
- // src/core/server/api/routes.ts
1097
- var _initialized = false;
1098
- function initRoutes(RED) {
1099
- if (_initialized) return;
1100
- _initialized = true;
1101
- initAssetsRoutes(RED.httpAdmin);
1102
- }
1103
-
1104
- // src/core/server/registration.ts
1105
- async function registerType(RED, NodeClass) {
1106
- RED.log.debug(`Registering Type: ${NodeClass.type}`);
1107
- if (!(NodeClass.prototype instanceof Node)) {
1108
- throw new NrgError(
1109
- `${NodeClass.name} must extend IONode or ConfigNode classes`
1110
- );
1111
- }
1112
- if (!NodeClass.type) {
1113
- throw new NrgError("type must be provided when registering the node");
1114
- }
1115
- await NodeClass.register(RED);
1116
- RED.log.debug(`Type registered: ${NodeClass.type}`);
1117
- }
1118
- function registerTypes(nodes) {
1119
- const fn = Object.assign(
1120
- async function(RED) {
1121
- initValidator(RED);
1122
- initRoutes(RED);
1123
- try {
1124
- RED.log.info("Registering node types in series");
1125
- for (const NodeClass of nodes) {
1126
- await registerType(RED, NodeClass);
1127
- }
1128
- RED.log.info("All node types registered in series");
1129
- } catch (error) {
1130
- RED.log.error("Error registering node types:", error);
1131
- throw error;
1132
- }
1133
- },
1134
- { nodes }
1135
- );
1136
- return fn;
1137
- }
1138
-
1139
- // src/core/constants.ts
1140
- var TYPED_INPUT_TYPES = [
1141
- "msg",
1142
- "flow",
1143
- "global",
1144
- "str",
1145
- "num",
1146
- "bool",
1147
- "json",
1148
- "bin",
1149
- "re",
1150
- "jsonata",
1151
- "date",
1152
- "env",
1153
- "node",
1154
- "cred"
1155
- ];
1156
-
1157
- // src/core/server/schemas/type.ts
1158
- var import_typebox2 = require("@sinclair/typebox");
1159
- var import_rules = require("ajv/dist/compile/rules");
1160
- function NodeRef(nodeClass, options) {
1161
- return {
1162
- ...import_typebox2.Type.String({
1163
- description: options?.description || `Reference to ${nodeClass.type}`,
1164
- format: "node-id"
1165
- }),
1166
- "x-nrg-node-type": nodeClass.type,
1167
- ...options,
1168
- [import_typebox2.Kind]: "NodeRef"
1169
- };
1170
- }
1171
- function TypedInput2(options) {
1172
- return {
1173
- ...TypedInputSchema,
1174
- "x-nrg-typed-input": true,
1175
- ...options,
1176
- [import_typebox2.Kind]: "TypedInput"
1177
- };
1178
- }
1179
- function OutputReturnProperties(options) {
1180
- return import_typebox2.Type.Record(
1181
- import_typebox2.Type.Number(),
1182
- import_typebox2.Type.String({ pattern: "^[A-Za-z_$][A-Za-z0-9_$]*$" }),
1183
- {
1184
- description: "Per-port return property, keyed by output port index. A missing entry falls back to `output`.",
1185
- default: {},
1186
- ...options
1187
- }
1188
- );
1189
- }
1190
- function OutputContextModes(options) {
1191
- return import_typebox2.Type.Record(
1192
- import_typebox2.Type.Number(),
1193
- import_typebox2.Type.Union([
1194
- import_typebox2.Type.Literal("carry"),
1195
- import_typebox2.Type.Literal("trace"),
1196
- import_typebox2.Type.Literal("reset")
1197
- ]),
1198
- {
1199
- description: "Per-port context mode, keyed by output port index. A missing entry falls back to `carry`.",
1200
- default: {},
1201
- ...options
1202
- }
1203
- );
1204
- }
1205
- var SchemaType = Object.assign({}, import_typebox2.Type, {
1206
- NodeRef,
1207
- TypedInput: TypedInput2,
1208
- OutputReturnProperties,
1209
- OutputContextModes
1210
- });
1211
- function markNonValidatable(schema) {
1212
- const type = schema.type;
1213
- const hasInvalidType = type !== void 0 && (Array.isArray(type) ? !type.every(import_rules.isJSONType) : !(0, import_rules.isJSONType)(type));
1214
- if (hasInvalidType) {
1215
- schema["x-nrg-skip-validation"] = true;
1216
- if (schema.default !== void 0) {
1217
- schema._default = schema.default;
1218
- delete schema.default;
1219
- }
1220
- delete schema.type;
1221
- }
1222
- if (schema.properties) {
1223
- for (const prop of Object.values(schema.properties)) {
1224
- markNonValidatable(prop);
1225
- }
1226
- }
1227
- if (schema.items) {
1228
- markNonValidatable(schema.items);
1229
- }
1230
- if (schema.anyOf) {
1231
- schema.anyOf.forEach((s) => markNonValidatable(s));
1232
- }
1233
- if (schema.allOf) {
1234
- schema.allOf.forEach((s) => markNonValidatable(s));
1235
- }
1236
- if (schema.oneOf) {
1237
- schema.oneOf.forEach((s) => markNonValidatable(s));
1238
- }
1239
- return schema;
1240
- }
1241
- function defineSchema(properties, options) {
1242
- const schema = SchemaType.Object(properties, options);
1243
- return markNonValidatable(schema);
1244
- }
1245
-
1246
- // src/core/server/schemas/base.ts
1247
- var NodeConfigSchema = SchemaType.Object({
1248
- id: SchemaType.String(),
1249
- type: SchemaType.String(),
1250
- name: SchemaType.String(),
1251
- z: SchemaType.Optional(SchemaType.String())
1252
- });
1253
- var ConfigNodeConfigSchema = SchemaType.Object({
1254
- ...NodeConfigSchema.properties,
1255
- _users: SchemaType.Array(SchemaType.String())
1256
- });
1257
- var IONodeConfigSchema = SchemaType.Object({
1258
- ...NodeConfigSchema.properties,
1259
- wires: SchemaType.Array(
1260
- SchemaType.Array(SchemaType.String(), { default: [] }),
1261
- {
1262
- default: [[]]
1263
- }
1264
- ),
1265
- x: SchemaType.Number(),
1266
- y: SchemaType.Number(),
1267
- g: SchemaType.Optional(SchemaType.String())
1268
- });
1269
- var TypedInputSchema = SchemaType.Object(
1270
- {
1271
- value: SchemaType.Union(
1272
- [
1273
- SchemaType.String(),
1274
- SchemaType.Number(),
1275
- SchemaType.Boolean(),
1276
- SchemaType.Null()
1277
- ],
1278
- {
1279
- description: "The actual value entered or selected.",
1280
- default: ""
1281
- }
1282
- ),
1283
- type: SchemaType.Union(
1284
- TYPED_INPUT_TYPES.map((type) => SchemaType.Literal(type)),
1285
- {
1286
- description: "The type of the value (string, number, message property, etc.)",
1287
- default: "str"
1288
- }
1289
- )
1290
- },
1291
- {
1292
- description: "Represents a Node-RED TypedInput value and its type.",
1293
- default: {
1294
- type: "str",
1295
- value: ""
1296
- }
1297
- }
1298
- );
1299
- var NodeSourceSchema = SchemaType.Object({
1300
- id: SchemaType.String(),
1301
- type: SchemaType.String(),
1302
- name: SchemaType.String()
1303
- });
1304
- var ErrorPortSchema = SchemaType.Object({
1305
- error: SchemaType.Object({
1306
- message: SchemaType.String(),
1307
- source: NodeSourceSchema
1308
- })
1309
- });
1310
- var CompletePortSchema = SchemaType.Object({
1311
- complete: SchemaType.Object({
1312
- source: NodeSourceSchema
1313
- })
1314
- });
1315
- var StatusPortSchema = SchemaType.Object({
1316
- status: SchemaType.Union([
1317
- SchemaType.Object({
1318
- fill: SchemaType.Optional(
1319
- SchemaType.Union([
1320
- SchemaType.Literal("red"),
1321
- SchemaType.Literal("green")
1322
- ])
1323
- ),
1324
- shape: SchemaType.Optional(
1325
- SchemaType.Union([
1326
- SchemaType.Literal("dot"),
1327
- SchemaType.Literal("string")
1328
- ])
1329
- ),
1330
- text: SchemaType.Optional(SchemaType.String())
1331
- }),
1332
- SchemaType.String()
1333
- ]),
1334
- source: NodeSourceSchema
1335
- });
1336
-
1337
- // src/core/server/index.ts
1338
- function defineModule(definition) {
1339
- return definition;
1340
- }
1341
- // Annotate the CommonJS export names for ESM import in node:
1342
- 0 && (module.exports = {
1343
- CompletePortSchema,
1344
- ConfigNode,
1345
- ErrorPortSchema,
1346
- IONode,
1347
- Node,
1348
- NodeSourceSchema,
1349
- NrgError,
1350
- SchemaType,
1351
- StatusPortSchema,
1352
- defineConfigNode,
1353
- defineIONode,
1354
- defineModule,
1355
- defineSchema,
1356
- registerType,
1357
- registerTypes
1358
- });
1
+ 'use strict';
2
+ module.exports = require("@bonsae/nrg-runtime/server");