@bonsae/nrg 0.7.0 → 0.8.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonsae/nrg",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
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,40 @@ 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
+ // NOTE: NRG nodes are wrapped — surface the NRG instance, fall back to raw NodeRedNode
248
+ node: (raw) => raw?._node ?? raw
249
+ };
250
+ get type() {
251
+ return this.input.type;
252
+ }
253
+ get value() {
254
+ return this.input.value;
255
+ }
256
+ resolve(msg) {
257
+ return new Promise((resolve, reject) => {
258
+ this.RED.util.evaluateNodeProperty(
259
+ this.input.value,
260
+ this.input.type,
261
+ this.node,
262
+ msg,
263
+ (err, raw) => {
264
+ if (err) return reject(err);
265
+ const post = this.resolvers[this.input.type];
266
+ resolve(post ? post(raw) : raw);
267
+ }
268
+ );
269
+ });
270
+ }
271
+ };
272
+
239
273
  // src/core/server/nodes/utils.ts
240
274
  function setupContext(context, store) {
241
275
  return {
@@ -259,14 +293,16 @@ function setupContext(context, store) {
259
293
  )
260
294
  };
261
295
  }
262
- function setupConfigProxy(RED, config, schema) {
296
+ function setupConfigProxy(opts) {
297
+ const { RED, node, config, schema } = opts;
263
298
  const SKIP_PROPS = /* @__PURE__ */ new Set(["id", "_id", "_users"]);
264
299
  const nodeRefProps = /* @__PURE__ */ new Set();
300
+ const typedInputProps = /* @__PURE__ */ new Set();
265
301
  if (schema?.properties) {
266
302
  for (const [key, propSchema] of Object.entries(schema.properties)) {
267
- if (propSchema?.["x-nrg-node-type"]) {
268
- nodeRefProps.add(key);
269
- }
303
+ const s = propSchema;
304
+ if (s?.["x-nrg-node-type"]) nodeRefProps.add(key);
305
+ if (s?.["x-nrg-typed-input"]) typedInputProps.add(key);
270
306
  }
271
307
  }
272
308
  const cache = /* @__PURE__ */ new WeakMap();
@@ -274,12 +310,9 @@ function setupConfigProxy(RED, config, schema) {
274
310
  const cached = cache.get(obj);
275
311
  if (cached) return cached;
276
312
  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
- });
313
+ const mapped = obj.map(
314
+ (item) => item && typeof item === "object" ? createProxy(item) : item
315
+ );
283
316
  cache.set(obj, mapped);
284
317
  return mapped;
285
318
  }
@@ -291,6 +324,14 @@ function setupConfigProxy(RED, config, schema) {
291
324
  if (typeof value === "string" && value.length > 0 && nodeRefProps.has(prop)) {
292
325
  return RED.nodes.getNode(value)?._node ?? value;
293
326
  }
327
+ if (typedInputProps.has(prop) && value && typeof value === "object" && "type" in value && "value" in value) {
328
+ let ref = cache.get(value);
329
+ if (!ref) {
330
+ ref = new TypedInput(RED, node, value);
331
+ cache.set(value, ref);
332
+ }
333
+ return ref;
334
+ }
294
335
  if (value && typeof value === "object") {
295
336
  return createProxy(value);
296
337
  }
@@ -385,11 +426,12 @@ var Node = class {
385
426
  );
386
427
  }
387
428
  }
388
- this.config = setupConfigProxy(
429
+ this.config = setupConfigProxy({
389
430
  RED,
431
+ node,
390
432
  config,
391
- constructor.configSchema
392
- );
433
+ schema: constructor.configSchema
434
+ });
393
435
  if (constructor.credentialsSchema && credentials) {
394
436
  this.log("Validating credentials");
395
437
  const credResult = validator.validate(
@@ -432,28 +474,6 @@ var Node = class {
432
474
  clearInterval(interval);
433
475
  this.intervals.delete(interval);
434
476
  }
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
477
  // NOTE: used by the registered function. Had to be a different one to avoid calling the parent's closed again
458
478
  /** @internal */
459
479
  async _closed(removed) {
@@ -795,16 +815,17 @@ function NodeRef(nodeClass, options) {
795
815
  [import_typebox.Kind]: "NodeRef"
796
816
  };
797
817
  }
798
- function TypedInput(options) {
818
+ function TypedInput2(options) {
799
819
  return {
800
820
  ...TypedInputSchema,
821
+ "x-nrg-typed-input": true,
801
822
  ...options,
802
823
  [import_typebox.Kind]: "TypedInput"
803
824
  };
804
825
  }
805
826
  var SchemaType = Object.assign({}, import_typebox.Type, {
806
827
  NodeRef,
807
- TypedInput
828
+ TypedInput: TypedInput2
808
829
  });
809
830
  function markNonValidatable(schema) {
810
831
  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;