@bonsae/nrg 0.7.0 → 0.8.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonsae/nrg",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "NRG framework — build Node-RED nodes with Vue 3, TypeScript, and JSON Schema",
5
5
  "author": "Allan Oricil <allanoricil@duck.com>",
6
6
  "license": "MIT",
package/server/index.cjs CHANGED
@@ -236,6 +236,48 @@ var NrgError = class _NrgError extends Error {
236
236
  }
237
237
  };
238
238
 
239
+ // src/core/server/typed-input.ts
240
+ var TypedInput = class {
241
+ constructor(RED, node, input) {
242
+ this.RED = RED;
243
+ this.node = node;
244
+ this.input = input;
245
+ }
246
+ resolvers = {
247
+ // evaluateNodeProperty returns the node ID string for "node" type —
248
+ // resolve it to the actual node instance via RED.nodes.getNode,
249
+ // then surface the NRG wrapper if available.
250
+ node: (raw) => {
251
+ if (typeof raw === "string") {
252
+ const node = this.RED.nodes.getNode(raw);
253
+ return node?._node ?? node ?? raw;
254
+ }
255
+ return raw?._node ?? raw;
256
+ }
257
+ };
258
+ get type() {
259
+ return this.input.type;
260
+ }
261
+ get value() {
262
+ return this.input.value;
263
+ }
264
+ resolve(msg) {
265
+ return new Promise((resolve, reject) => {
266
+ this.RED.util.evaluateNodeProperty(
267
+ this.input.value,
268
+ this.input.type,
269
+ this.node,
270
+ msg,
271
+ (err, raw) => {
272
+ if (err) return reject(err);
273
+ const post = this.resolvers[this.input.type];
274
+ resolve(post ? post(raw) : raw);
275
+ }
276
+ );
277
+ });
278
+ }
279
+ };
280
+
239
281
  // src/core/server/nodes/utils.ts
240
282
  function setupContext(context, store) {
241
283
  return {
@@ -259,14 +301,16 @@ function setupContext(context, store) {
259
301
  )
260
302
  };
261
303
  }
262
- function setupConfigProxy(RED, config, schema) {
304
+ function setupConfigProxy(opts) {
305
+ const { RED, node, config, schema } = opts;
263
306
  const SKIP_PROPS = /* @__PURE__ */ new Set(["id", "_id", "_users"]);
264
307
  const nodeRefProps = /* @__PURE__ */ new Set();
308
+ const typedInputProps = /* @__PURE__ */ new Set();
265
309
  if (schema?.properties) {
266
310
  for (const [key, propSchema] of Object.entries(schema.properties)) {
267
- if (propSchema?.["x-nrg-node-type"]) {
268
- nodeRefProps.add(key);
269
- }
311
+ const s = propSchema;
312
+ if (s?.["x-nrg-node-type"]) nodeRefProps.add(key);
313
+ if (s?.["x-nrg-typed-input"]) typedInputProps.add(key);
270
314
  }
271
315
  }
272
316
  const cache = /* @__PURE__ */ new WeakMap();
@@ -274,12 +318,9 @@ function setupConfigProxy(RED, config, schema) {
274
318
  const cached = cache.get(obj);
275
319
  if (cached) return cached;
276
320
  if (Array.isArray(obj)) {
277
- const mapped = obj.map((item) => {
278
- if (item && typeof item === "object") {
279
- return createProxy(item);
280
- }
281
- return item;
282
- });
321
+ const mapped = obj.map(
322
+ (item) => item && typeof item === "object" ? createProxy(item) : item
323
+ );
283
324
  cache.set(obj, mapped);
284
325
  return mapped;
285
326
  }
@@ -291,6 +332,14 @@ function setupConfigProxy(RED, config, schema) {
291
332
  if (typeof value === "string" && value.length > 0 && nodeRefProps.has(prop)) {
292
333
  return RED.nodes.getNode(value)?._node ?? value;
293
334
  }
335
+ if (typedInputProps.has(prop) && value && typeof value === "object" && "type" in value && "value" in value) {
336
+ let ref = cache.get(value);
337
+ if (!ref) {
338
+ ref = new TypedInput(RED, node, value);
339
+ cache.set(value, ref);
340
+ }
341
+ return ref;
342
+ }
294
343
  if (value && typeof value === "object") {
295
344
  return createProxy(value);
296
345
  }
@@ -385,11 +434,12 @@ var Node = class {
385
434
  );
386
435
  }
387
436
  }
388
- this.config = setupConfigProxy(
437
+ this.config = setupConfigProxy({
389
438
  RED,
439
+ node,
390
440
  config,
391
- constructor.configSchema
392
- );
441
+ schema: constructor.configSchema
442
+ });
393
443
  if (constructor.credentialsSchema && credentials) {
394
444
  this.log("Validating credentials");
395
445
  const credResult = validator.validate(
@@ -432,28 +482,6 @@ var Node = class {
432
482
  clearInterval(interval);
433
483
  this.intervals.delete(interval);
434
484
  }
435
- // NOTE: typing msg isnt necessary in this case
436
- resolveTypedInput(typedInput, msg) {
437
- return new Promise((resolve, reject) => {
438
- this.RED.util.evaluateNodeProperty(
439
- typedInput.value,
440
- typedInput.type,
441
- this.node,
442
- msg,
443
- (error, result) => {
444
- if (error) {
445
- reject(error);
446
- return;
447
- }
448
- if (typedInput.type === "node" && result) {
449
- resolve(result._node ?? result);
450
- return;
451
- }
452
- resolve(result);
453
- }
454
- );
455
- });
456
- }
457
485
  // NOTE: used by the registered function. Had to be a different one to avoid calling the parent's closed again
458
486
  /** @internal */
459
487
  async _closed(removed) {
@@ -795,16 +823,17 @@ function NodeRef(nodeClass, options) {
795
823
  [import_typebox.Kind]: "NodeRef"
796
824
  };
797
825
  }
798
- function TypedInput(options) {
826
+ function TypedInput2(options) {
799
827
  return {
800
828
  ...TypedInputSchema,
829
+ "x-nrg-typed-input": true,
801
830
  ...options,
802
831
  [import_typebox.Kind]: "TypedInput"
803
832
  };
804
833
  }
805
834
  var SchemaType = Object.assign({}, import_typebox.Type, {
806
835
  NodeRef,
807
- TypedInput
836
+ TypedInput: TypedInput2
808
837
  });
809
838
  function markNonValidatable(schema) {
810
839
  const type = schema.type;
package/types/server.d.ts CHANGED
@@ -1716,33 +1716,6 @@ declare const TYPED_INPUT_TYPES: readonly [
1716
1716
  "node",
1717
1717
  "cred"
1718
1718
  ];
1719
- export interface TNodeRef<T = any> extends TSchema {
1720
- [Kind]: "NodeRef";
1721
- static: T;
1722
- type: "string";
1723
- "x-nrg-node-type"?: string;
1724
- }
1725
- export type ResolveNodeRefs<T> = T extends TNodeRef<infer N> ? N : T extends (...args: any[]) => any ? T : T extends Array<infer Item> ? ResolveNodeRefs<Item>[] : T extends object ? {
1726
- [K in keyof T]: ResolveNodeRefs<T[K]>;
1727
- } : T;
1728
- export type Infer<T extends TSchema> = ResolveNodeRefs<Static<T>>;
1729
- export type TypedInputType = (typeof TYPED_INPUT_TYPES)[number];
1730
- export interface TTypedInput extends TSchema {
1731
- [Kind]: "TypedInput";
1732
- static: {
1733
- value: string | number | boolean | null;
1734
- type: TypedInputType;
1735
- };
1736
- }
1737
- export interface NrgFormOptions {
1738
- icon?: string;
1739
- typedInputTypes?: string[];
1740
- editorLanguage?: string;
1741
- toggle?: boolean;
1742
- }
1743
- export interface Schema<T extends TProperties = TProperties> extends TObject<T> {
1744
- $id: string;
1745
- }
1746
1719
  export interface NodeRedRuntimeSettings {
1747
1720
  userDir?: string;
1748
1721
  nodesDir?: string | string[];
@@ -2072,6 +2045,48 @@ export interface NodeRedContextStore {
2072
2045
  set(key: string, value: any, store: string | undefined, callback: (err: Error | null) => void): void;
2073
2046
  keys(store: string | undefined, callback: (err: Error | null, keys: string[]) => void): void;
2074
2047
  }
2048
+ declare class TypedInput<T = unknown> {
2049
+ private readonly RED;
2050
+ private readonly node;
2051
+ private readonly input;
2052
+ private readonly resolvers;
2053
+ constructor(RED: RED, node: NodeRedNode, input: {
2054
+ value: unknown;
2055
+ type: TypedInputType;
2056
+ });
2057
+ get type(): TypedInputType;
2058
+ get value(): unknown;
2059
+ resolve(msg?: Record<string, any>): Promise<T>;
2060
+ }
2061
+ export interface TNodeRef<T = any> extends TSchema {
2062
+ [Kind]: "NodeRef";
2063
+ static: T;
2064
+ type: "string";
2065
+ "x-nrg-node-type"?: string;
2066
+ }
2067
+ export type ResolveNodeRefs<T> = T extends TypedInput<any> ? T : T extends (...args: any[]) => any ? T : T extends Array<infer Item> ? ResolveNodeRefs<Item>[] : T extends object ? {
2068
+ [K in keyof T]: ResolveNodeRefs<T[K]>;
2069
+ } : T;
2070
+ export type Infer<T extends TSchema> = ResolveNodeRefs<Static<T>>;
2071
+ export type TypedInputType = (typeof TYPED_INPUT_TYPES)[number];
2072
+ export interface TTypedInput<T = unknown> extends TSchema {
2073
+ [Kind]: "TypedInput";
2074
+ static: TypedInput<T>;
2075
+ }
2076
+ export interface NrgFormOptions {
2077
+ icon?: string;
2078
+ typedInputTypes?: string[];
2079
+ editorLanguage?: string;
2080
+ toggle?: boolean;
2081
+ }
2082
+ export interface NrgSchemaOptions extends SchemaOptions {
2083
+ exportable?: boolean;
2084
+ "x-nrg-node-type"?: string;
2085
+ "x-nrg-form"?: NrgFormOptions;
2086
+ }
2087
+ export interface Schema<T extends TProperties = TProperties> extends TObject<T> {
2088
+ $id: string;
2089
+ }
2075
2090
  declare const NodeConfigSchema: TObject<{
2076
2091
  id: TString;
2077
2092
  type: TString;
@@ -2095,11 +2110,11 @@ declare const IONodeConfigSchema: TObject<{
2095
2110
  name: TString;
2096
2111
  z: TOptional<TString>;
2097
2112
  }>;
2098
- declare function NodeRef<T extends new (...args: any[]) => any>(nodeClass: T, options?: SchemaOptions): TNodeRef<InstanceType<T>>;
2099
- declare function TypedInput(options?: SchemaOptions): TTypedInput;
2113
+ declare function NodeRef<T extends new (...args: any[]) => any>(nodeClass: T, options?: NrgSchemaOptions): TNodeRef<InstanceType<T>>;
2114
+ declare function TypedInput$1<T = unknown>(options?: NrgSchemaOptions): TTypedInput<T>;
2100
2115
  export declare const SchemaType: JavaScriptTypeBuilder & {
2101
2116
  NodeRef: typeof NodeRef;
2102
- TypedInput: typeof TypedInput;
2117
+ TypedInput: typeof TypedInput$1;
2103
2118
  };
2104
2119
  export declare function defineSchema<T extends TProperties>(properties: T, options: ObjectOptions & {
2105
2120
  $id: string;
@@ -2112,7 +2127,6 @@ export interface NodeContextStore {
2112
2127
  }
2113
2128
  export type NodeConfig<TConfig = any> = TConfig & Static<typeof NodeConfigSchema>;
2114
2129
  export type NodeCredentials<TCredentials = any> = TCredentials;
2115
- type TypedInput$1 = Static<TTypedInput>;
2116
2130
  export type IONodeContextScope = NodeContextScope;
2117
2131
  export type IONodeConfig<TConfig = any> = NodeConfig<TConfig> & Static<typeof IONodeConfigSchema> & {
2118
2132
  validateInput?: boolean;
@@ -2257,7 +2271,6 @@ declare abstract class Node$1<TConfig = any, TCredentials = any, TSettings = any
2257
2271
  clearInterval(interval: NodeJS.Timeout): void;
2258
2272
  created?(): void | Promise<void>;
2259
2273
  closed?(removed?: boolean): void | Promise<void>;
2260
- resolveTypedInput<T = any>(typedInput: TypedInput$1, msg?: Record<string, any>): Promise<T>;
2261
2274
  on(event: string, callback: (...args: any[]) => void): void;
2262
2275
  log(msg: any): void;
2263
2276
  warn(message: string): void;