@bonsae/nrg 0.18.5 → 0.19.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 (36) hide show
  1. package/package.json +1 -1
  2. package/server/index.cjs +86 -9
  3. package/server/resources/nrg-client.js +2020 -1987
  4. package/test/client/component/config.js +11 -0
  5. package/test/client/component/index.js +218 -235
  6. package/test/client/component/nrg.css +1 -0
  7. package/test/client/component/setup.js +1549 -140
  8. package/test/client/e2e/index.js +720 -369
  9. package/test/client/unit/index.js +204 -16
  10. package/test/client/unit/setup.js +209 -19
  11. package/test/server/unit/index.js +25 -4
  12. package/tsconfig/core/client.json +1 -1
  13. package/tsconfig/test/client/component.json +1 -1
  14. package/types/client.d.ts +98 -18
  15. package/types/server.d.ts +50 -12
  16. package/types/shims/brands.d.ts +32 -0
  17. package/types/shims/{form → client/form}/components/node-red-editor-input.vue.d.ts +1 -1
  18. package/types/shims/{form → client/form}/components/node-red-json-schema-form.vue.d.ts +21 -2
  19. package/types/shims/{form → client/form}/components/node-red-select-input.vue.d.ts +1 -0
  20. package/types/shims/{form → client/form}/components/node-red-typed-input.vue.d.ts +1 -0
  21. package/types/shims/client/types.d.ts +206 -0
  22. package/types/shims/components.d.ts +8 -8
  23. package/types/shims/constants.d.ts +4 -0
  24. package/types/shims/schema-options.d.ts +23 -10
  25. package/types/shims/typebox.d.ts +2 -2
  26. package/types/test-client-component.d.ts +170 -55
  27. package/types/test-client-e2e.d.ts +50 -0
  28. package/types/test-client-unit.d.ts +86 -22
  29. package/types/test-server-unit.d.ts +3 -1
  30. package/types/vite.d.ts +38 -9
  31. package/vite/index.js +732 -530
  32. /package/types/shims/{form → client/form}/components/node-red-config-input.vue.d.ts +0 -0
  33. /package/types/shims/{form → client/form}/components/node-red-input-label.vue.d.ts +0 -0
  34. /package/types/shims/{form → client/form}/components/node-red-input.vue.d.ts +0 -0
  35. /package/types/shims/{form → client/form}/components/node-red-toggle.vue.d.ts +0 -0
  36. /package/types/shims/{globals.d.ts → client/globals.d.ts} +0 -0
package/types/client.d.ts CHANGED
@@ -1,12 +1,36 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
- import { SchemaOptions, Static, TSchema } from '@sinclair/typebox';
3
+ import { Static, TSchema } from '@sinclair/typebox';
4
+ import { SchemaObject } from 'ajv';
4
5
  import { App, Component } from 'vue';
5
6
 
6
7
  interface NodeRefResolved<T = any> {
7
8
  readonly __nrg_node_ref: true;
8
9
  readonly __instance: T;
9
10
  }
11
+ interface TypedInputResolved {
12
+ resolve(...args: any[]): any;
13
+ value: unknown;
14
+ type: string;
15
+ }
16
+ interface JsonSchemaObjectExtensions {
17
+ format?: "node-id" | "flow-id" | "topic-path" | (string & {});
18
+ /** expose this settings property to the editor via RED.settings */
19
+ exportable?: boolean;
20
+ /** set by SchemaType.NodeRef — the referenced config node type */
21
+ "x-nrg-node-type"?: string;
22
+ /** set by SchemaType.TypedInput — marks a TypedInput value/type pair */
23
+ "x-nrg-typed-input"?: boolean;
24
+ /** set by markNonValidatable — ajv skips this property */
25
+ "x-nrg-skip-validation"?: boolean;
26
+ /** form rendering hints consumed by the auto-generated editor form */
27
+ "x-nrg-form"?: {
28
+ icon?: string;
29
+ typedInputTypes?: string[];
30
+ editorLanguage?: string;
31
+ toggle?: boolean;
32
+ };
33
+ }
10
34
  export interface NodeStateCredentials {
11
35
  [key: string]: any;
12
36
  }
@@ -68,6 +92,18 @@ export interface NodeRedNode {
68
92
  _newState?: NodeRedNode;
69
93
  _app?: App | null;
70
94
  _: (str: string) => string;
95
+ /** dynamic port count (base outputs + enabled built-in ports) */
96
+ outputs?: number;
97
+ /** injected when the node has an inputSchema */
98
+ validateInput?: boolean;
99
+ /** injected when the node has an outputsSchema */
100
+ validateOutput?: boolean;
101
+ /** present when the node's configSchema declares SchemaType.ReturnProperty() */
102
+ returnProperty?: string;
103
+ /** built-in port toggles, present when declared in the configSchema */
104
+ errorPort?: boolean;
105
+ completePort?: boolean;
106
+ statusPort?: boolean;
71
107
  [key: string]: any;
72
108
  }
73
109
  export interface NodeDefinition {
@@ -92,6 +128,56 @@ export interface NodeDefinition {
92
128
  onPaletteRemove?: (this: NodeRedNode) => void;
93
129
  form?: NodeFormDefinition;
94
130
  }
131
+ /** Form rendering hints carried by the `x-nrg-form` schema keyword. */
132
+ export type NrgFormOptions = NonNullable<JsonSchemaObjectExtensions["x-nrg-form"]>;
133
+ /**
134
+ * A serialized property schema inside {@link JsonSchemaObject} `properties`,
135
+ * including NRG's custom keywords (shared vocabulary in core/schema-options)
136
+ * that drive form rendering and NodeRef/TypedInput identification.
137
+ */
138
+ export interface JsonPropertySchema extends JsonSchemaObjectExtensions {
139
+ type?: string | string[];
140
+ properties?: Record<string, JsonPropertySchema>;
141
+ required?: string[];
142
+ enum?: unknown[];
143
+ anyOf?: JsonPropertySchema[];
144
+ const?: unknown;
145
+ items?: JsonPropertySchema;
146
+ title?: string;
147
+ description?: string;
148
+ default?: unknown;
149
+ }
150
+ /**
151
+ * A serialized JSON Schema object as the build pipeline emits it (never a
152
+ * live TypeBox instance). Extends ajv's `SchemaObject` so it flows into
153
+ * validator APIs without casts, while keeping the `type: "object"`
154
+ * discriminant and structured `properties`/`required` that ajv's open
155
+ * `[x: string]: any` shape does not provide.
156
+ */
157
+ export interface JsonSchemaObject extends SchemaObject {
158
+ type: "object";
159
+ properties?: Record<string, JsonPropertySchema>;
160
+ required?: string[];
161
+ }
162
+ /**
163
+ * A node definition as it exists at editor runtime, after the build pipeline
164
+ * merged in the schema-derived artifacts (defaults, credentials, serialized
165
+ * schemas). Authors write {@link NodeDefinition}; the inliner provides the
166
+ * rest.
167
+ */
168
+ export interface RuntimeNodeDefinition extends NodeDefinition {
169
+ defaults?: NodeDefaults;
170
+ credentials?: NodeCredentials;
171
+ configSchema?: JsonSchemaObject;
172
+ credentialsSchema?: JsonSchemaObject;
173
+ inputSchema?: JsonSchemaObject;
174
+ /**
175
+ * Single port, positional ports, or named ports (key = port name).
176
+ * Not constrained to object schemas: with returnProperty the raw sent
177
+ * value is validated, so results may be any schema shape.
178
+ */
179
+ outputsSchema?: JsonPropertySchema | JsonPropertySchema[] | Record<string, JsonPropertySchema>;
180
+ }
95
181
  export interface NodeDefaults {
96
182
  [key: string]: {
97
183
  value: any;
@@ -109,16 +195,6 @@ export interface NodeCredentials {
109
195
  required?: boolean;
110
196
  };
111
197
  }
112
- export interface MergedNodeDefinition extends NodeDefinition {
113
- defaults?: NodeDefaults;
114
- credentials?: NodeCredentials;
115
- configSchema?: Record<string, any>;
116
- credentialsSchema?: {
117
- properties?: Record<string, any>;
118
- };
119
- outputsSchema?: Record<string, any>;
120
- inputSchema?: Record<string, any>;
121
- }
122
198
  export interface NodeFeatures {
123
199
  hasInputSchema: boolean;
124
200
  hasOutputSchema: boolean;
@@ -128,12 +204,16 @@ export interface TypedInputValue {
128
204
  value: string;
129
205
  type: string;
130
206
  }
131
- type _ToClient<T> = T extends NodeRefResolved<any> ? string : T extends {
132
- resolve(...args: any[]): any;
133
- value: unknown;
134
- type: string;
135
- } ? TypedInputValue : T extends (...args: any[]) => any ? T : T extends Array<infer I> ? _ToClient<I>[] : T extends object ? {
136
- [K in keyof T]: _ToClient<T[K]>;
207
+ /**
208
+ * Maps a schema's static type to the raw values the editor form holds.
209
+ * The server counterpart (`ResolvedStatic` in server/schemas/types) maps the
210
+ * same brands — shared via core/brands — to resolved runtime values instead.
211
+ * - `NodeRef<T>` `string` (the referenced node's id)
212
+ * - `TypedInput<T>` → `TypedInputValue` (raw value + type pair)
213
+ * - Functions pass through, arrays and objects map recursively
214
+ */
215
+ export type EditorStatic<T> = T extends NodeRefResolved<any> ? string : T extends TypedInputResolved ? TypedInputValue : T extends (...args: any[]) => any ? T : T extends Array<infer I> ? EditorStatic<I>[] : T extends object ? {
216
+ [K in keyof T]: EditorStatic<T[K]>;
137
217
  } : T;
138
218
  /**
139
219
  * Infers the client-side TypeScript type from a TypeBox schema.
@@ -151,7 +231,7 @@ type _ToClient<T> = T extends NodeRefResolved<any> ? string : T extends {
151
231
  * type Config = Infer<typeof ConfigSchema>;
152
232
  * ```
153
233
  */
154
- export type Infer<T extends TSchema> = _ToClient<Static<T>>;
234
+ export type Infer<T extends TSchema> = EditorStatic<Static<T>>;
155
235
 
156
236
  export {};
157
237
 
package/types/server.d.ts CHANGED
@@ -273,6 +273,8 @@ interface NodeRedNodes {
273
273
  }) | undefined;
274
274
  createNode(node: NodeRedNode, config: Record<string, any>): void;
275
275
  getCredentials(id: string): Record<string, any> | undefined;
276
+ /** Merge credentials into a node's stored credential set (runtime API). */
277
+ addCredentials(id: string, credentials: Record<string, any>): void;
276
278
  eachNode(callback: (node: any) => void): void;
277
279
  getType(type: string): any;
278
280
  getNodeInfo(type: string): any;
@@ -353,10 +355,17 @@ declare class TypedInput<T = unknown> {
353
355
  get value(): unknown;
354
356
  resolve(msg?: Record<string, any>): Promise<T>;
355
357
  }
356
- interface NrgSchemaExtensions {
358
+ interface JsonSchemaObjectExtensions {
357
359
  format?: "node-id" | "flow-id" | "topic-path" | (string & {});
360
+ /** expose this settings property to the editor via RED.settings */
358
361
  exportable?: boolean;
362
+ /** set by SchemaType.NodeRef — the referenced config node type */
359
363
  "x-nrg-node-type"?: string;
364
+ /** set by SchemaType.TypedInput — marks a TypedInput value/type pair */
365
+ "x-nrg-typed-input"?: boolean;
366
+ /** set by markNonValidatable — ajv skips this property */
367
+ "x-nrg-skip-validation"?: boolean;
368
+ /** form rendering hints consumed by the auto-generated editor form */
360
369
  "x-nrg-form"?: {
361
370
  icon?: string;
362
371
  typedInputTypes?: string[];
@@ -444,8 +453,8 @@ export interface TNodeRef<T = any> extends TSchema {
444
453
  format: "node-id";
445
454
  "x-nrg-node-type"?: string;
446
455
  }
447
- type ResolveNodeRefs<T> = T extends NodeRefResolved<infer I> ? I : T extends TypedInput<any> ? T : T extends (...args: any[]) => any ? T : T extends Array<infer Item> ? ResolveNodeRefs<Item>[] : T extends object ? {
448
- [K in keyof T]: ResolveNodeRefs<T[K]>;
456
+ type ResolvedStatic<T> = T extends NodeRefResolved<infer I> ? I : T extends TypedInput<any> ? T : T extends (...args: any[]) => any ? T : T extends Array<infer Item> ? ResolvedStatic<Item>[] : T extends object ? {
457
+ [K in keyof T]: ResolvedStatic<T[K]>;
449
458
  } : T;
450
459
  /**
451
460
  * Infers the TypeScript type from a schema or a record of schemas.
@@ -456,8 +465,8 @@ type ResolveNodeRefs<T> = T extends NodeRefResolved<infer I> ? I : T extends Typ
456
465
  * The record form produces a simple mapped type that resolves eagerly,
457
466
  * giving `sendToPort()` proper autocomplete in class-based nodes.
458
467
  */
459
- export type Infer<T extends TSchema | Record<string, TSchema>> = T extends TSchema ? ResolveNodeRefs<Static<T>> : {
460
- [K in keyof T & string]: T[K] extends TSchema ? ResolveNodeRefs<Static<T[K]>> : never;
468
+ export type Infer<T extends TSchema | Record<string, TSchema>> = T extends TSchema ? ResolvedStatic<Static<T>> : {
469
+ [K in keyof T & string]: T[K] extends TSchema ? ResolvedStatic<Static<T[K]>> : never;
461
470
  };
462
471
  type TypedInputType = (typeof TYPED_INPUT_TYPES)[number];
463
472
  /** Schema type representing a Node-RED TypedInput (value + type pair). */
@@ -466,7 +475,7 @@ export interface TTypedInput<T = unknown> extends TSchema {
466
475
  static: TypedInput<T>;
467
476
  "x-nrg-typed-input": true;
468
477
  }
469
- interface NrgSchemaOptions extends SchemaOptions, NrgSchemaExtensions {
478
+ interface NrgSchemaOptions extends SchemaOptions, JsonSchemaObjectExtensions {
470
479
  }
471
480
  /** An NRG object schema created by {@link defineSchema}. */
472
481
  export type Schema<T extends TProperties = TProperties> = TObject<T>;
@@ -482,13 +491,18 @@ type InferOutputs<T> = T extends readonly TSchema[] ? {
482
491
  } : any;
483
492
  declare function NodeRef<T extends new (...args: any[]) => any>(nodeClass: T, options?: NrgSchemaOptions): TNodeRef<InstanceType<T>>;
484
493
  declare function TypedInput$1<T = unknown>(options?: NrgSchemaOptions): TTypedInput<T>;
494
+ declare function ReturnProperty(options?: NrgSchemaOptions & {
495
+ default?: string;
496
+ }): import("@sinclair/typebox").TString;
485
497
  /**
486
498
  * Extended TypeBox type builder with NRG-specific schema types.
487
- * Includes all standard TypeBox types plus {@link NodeRef} and {@link TypedInput}.
499
+ * Includes all standard TypeBox types plus {@link NodeRef}, {@link TypedInput}
500
+ * and {@link ReturnProperty}.
488
501
  */
489
502
  export declare const SchemaType: import("@sinclair/typebox").JavaScriptTypeBuilder & {
490
503
  NodeRef: typeof NodeRef;
491
504
  TypedInput: typeof TypedInput$1;
505
+ ReturnProperty: typeof ReturnProperty;
492
506
  };
493
507
  /**
494
508
  * Creates a validated object schema from a set of properties. Automatically
@@ -522,7 +536,7 @@ export interface NodeConstructor<T = any, TConfig = any, TCredentials = any> {
522
536
  readonly credentialsSchema?: Schema;
523
537
  readonly settingsSchema?: Schema;
524
538
  readonly inputSchema?: Schema;
525
- readonly outputsSchema?: Schema | Schema[] | Record<string, Schema>;
539
+ readonly outputsSchema?: TSchema | TSchema[] | Record<string, TSchema>;
526
540
  readonly validateInput?: boolean;
527
541
  readonly validateOutput?: boolean;
528
542
  readonly name: string;
@@ -600,10 +614,32 @@ declare abstract class Node$1<TConfig = any, TCredentials = any, TSettings = any
600
614
  get credentials(): NodeCredentials<TCredentials> | undefined;
601
615
  get settings(): TSettings;
602
616
  }
617
+ /**
618
+ * Controls how an outgoing message carries the incoming message's context:
619
+ * - `"nest"` (default): keep all incoming keys and push the full input under
620
+ * `input`, so the prior message — including any value the result overwrites
621
+ * — is always recoverable (`msg.input.output`). The `input` chain
622
+ * accumulates one frame per node, forming a provenance trail visible in the
623
+ * debug panel.
624
+ * - `"carry"`: keep all incoming keys (including any upstream `input`) but do
625
+ * not record this node — context flows through without growing.
626
+ * - `"reset"`: drop all inherited context; the outgoing message is only the
627
+ * result at the return key.
628
+ */
629
+ export type ContextMode = "nest" | "carry" | "reset";
603
630
  /**
604
631
  * Base class for nodes that process messages. Provides input/output handling,
605
632
  * schema validation, status updates, and emit port management.
606
633
  *
634
+ * Every node has a return key (`"output"` by default): the value passed to
635
+ * `send()` is merged into the incoming message at that key and the full prior
636
+ * message is kept under `input` (`{ ...msg, [returnKey]: result, input: msg }`),
637
+ * so upstream properties propagate and the provenance chain is recoverable.
638
+ * Declaring `returnProperty` in the `configSchema` only lets the flow author
639
+ * override the key in the editor — it does not change that a return key always
640
+ * exists. `this.send(x)` always means "x is the result", never "x is the whole
641
+ * message".
642
+ *
607
643
  * @example
608
644
  * ```ts
609
645
  * export default class MyNode extends IONode<Config, any, Input, Output> {
@@ -612,7 +648,8 @@ declare abstract class Node$1<TConfig = any, TCredentials = any, TSettings = any
612
648
  * static readonly color = "#ffffff" as const;
613
649
  *
614
650
  * async input(msg: Input) {
615
- * this.send({ payload: msg.payload.toUpperCase() });
651
+ * // sends { ...msg, output: <result>, input: msg }
652
+ * this.send(msg.output.toUpperCase());
616
653
  * }
617
654
  * }
618
655
  * ```
@@ -622,7 +659,7 @@ export declare abstract class IONode<TConfig = any, TCredentials = any, TInput =
622
659
  static readonly align?: "left" | "right";
623
660
  static readonly color: HexColor;
624
661
  static readonly inputSchema?: Schema;
625
- static readonly outputsSchema?: Schema | Schema[] | Record<string, Schema>;
662
+ static readonly outputsSchema?: TSchema | TSchema[] | Record<string, TSchema>;
626
663
  static readonly validateInput: boolean;
627
664
  static readonly validateOutput: boolean;
628
665
  static get inputs(): 0 | 1;
@@ -632,7 +669,7 @@ export declare abstract class IONode<TConfig = any, TCredentials = any, TInput =
632
669
  constructor(RED: RED, node: NodeRedNode, config: IONodeConfig<TConfig>, credentials: IONodeCredentials<TCredentials>);
633
670
  [WIRE_HANDLERS](nodeRedNode: NodeRedNode, createdPromise: Promise<void>): void;
634
671
  input(msg: TInput): void | Promise<void>;
635
- send(msg: TOutput): void;
672
+ send(msg: TOutput, contextMode?: ContextMode): void;
636
673
  get baseOutputs(): number;
637
674
  get totalOutputs(): number;
638
675
  /**
@@ -645,7 +682,7 @@ export declare abstract class IONode<TConfig = any, TCredentials = any, TInput =
645
682
  * throw an error or call `this.error()` for the error port, and the complete
646
683
  * port is sent automatically on successful input processing.
647
684
  */
648
- sendToPort<P extends (TOutput extends Record<string, Record<string, any>> ? keyof TOutput & string : never) | number>(port: P, msg: P extends keyof TOutput ? TOutput[P] : unknown): void;
685
+ sendToPort<P extends (TOutput extends Record<string, Record<string, any>> ? keyof TOutput & string : never) | number>(port: P, msg: P extends keyof TOutput ? TOutput[P] : unknown, contextMode?: ContextMode): void;
649
686
  status(status: IONodeStatus): void;
650
687
  error(message: string, msg?: any): void;
651
688
  updateWires(wires: string[][]): void;
@@ -660,6 +697,7 @@ type IONodeContextScope = NodeContextScope;
660
697
  type IONodeConfig<TConfig = any> = NodeConfig<TConfig> & Static<typeof IONodeConfigSchema> & {
661
698
  validateInput?: boolean;
662
699
  validateOutput?: boolean;
700
+ returnProperty?: string;
663
701
  };
664
702
  type IONodeCredentials<TCredentials = any> = NodeCredentials<TCredentials>;
665
703
  type IONodeStatus = {
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Type-level contract shared by the server and client planes.
3
+ *
4
+ * `Static<>` of NRG's special schemas (NodeRef, TypedInput) produces these
5
+ * brand shapes. Each plane maps them differently:
6
+ *
7
+ * - server `ResolvedStatic` (server/schemas/types): brand → runtime value
8
+ * (NodeRef → the node instance, TypedInput → the resolving wrapper)
9
+ * - client `EditorStatic` (client/types): brand → editor form value
10
+ * (NodeRef → the referenced node id string, TypedInput → { value, type })
11
+ *
12
+ * Both planes import the brands from here, type-only, so renaming or
13
+ * reshaping a brand is a compile error on both sides instead of silent
14
+ * type drift. Keep this module free of runtime code and imports from
15
+ * either plane.
16
+ */
17
+ /** Brand produced by `Static` of a NodeRef schema. */
18
+ interface NodeRefResolved<T = any> {
19
+ readonly __nrg_node_ref: true;
20
+ readonly __instance: T;
21
+ }
22
+ /**
23
+ * Structural shape of a resolved TypedInput (the server's TypedInput class
24
+ * instance). The client matches this shape to map the field to its raw
25
+ * editor value pair.
26
+ */
27
+ interface TypedInputResolved {
28
+ resolve(...args: any[]): any;
29
+ value: unknown;
30
+ type: string;
31
+ }
32
+ export type { NodeRefResolved, TypedInputResolved };
@@ -29,7 +29,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
29
29
  default: string;
30
30
  };
31
31
  }>, {
32
- editor: import("vue").ShallowRef<any, any>;
32
+ editorInstance: import("vue").ShallowRef<any, any>;
33
33
  expandedEditorTray: import("vue").ShallowRef<any, any>;
34
34
  }, {
35
35
  editorId: string;
@@ -1,3 +1,23 @@
1
+ import type { PropType } from "vue";
2
+ import type { JsonPropertySchema } from "../../types";
3
+ type FieldSchema = JsonPropertySchema;
4
+ interface FormField {
5
+ key: string;
6
+ label: string;
7
+ icon: string;
8
+ inputType: "text" | "number" | "boolean" | "select" | "typed" | "config" | "editor" | "array-text";
9
+ required: boolean;
10
+ htmlType?: "text" | "number" | "password";
11
+ options?: Array<{
12
+ value: string;
13
+ label: string;
14
+ }>;
15
+ multiple?: boolean;
16
+ types?: (NodeRED.DefaultTypedInputType | NodeRED.TypedInputTypeDefinition)[];
17
+ configType?: string;
18
+ language?: string;
19
+ toggle?: boolean;
20
+ }
1
21
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
22
  node: {
3
23
  type: PropType<NodeRED.BaseNode>;
@@ -15,7 +35,6 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
15
35
  configFields(): FormField[];
16
36
  credentialFields(): FormField[];
17
37
  }, {
18
- recalculateOutputs(): void;
19
38
  resolveI18n(prefix: string, key: string): string | undefined;
20
39
  }, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
21
40
  node: {
@@ -657,7 +676,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
657
676
  default: string;
658
677
  };
659
678
  }>, {
660
- editor: import("vue").ShallowRef<any, any>;
679
+ editorInstance: import("vue").ShallowRef<any, any>;
661
680
  expandedEditorTray: import("vue").ShallowRef<any, any>;
662
681
  }, {
663
682
  editorId: string;
@@ -1,3 +1,4 @@
1
+ import { type PropType } from "vue";
1
2
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
3
  modelValue: {
3
4
  type: (StringConstructor | ArrayConstructor)[];
@@ -1,3 +1,4 @@
1
+ import { type PropType } from "vue";
1
2
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
3
  modelValue: {
3
4
  type: PropType<{
@@ -0,0 +1,206 @@
1
+ import type { Component, App } from "vue";
2
+ import type { TSchema, Static } from "@sinclair/typebox";
3
+ import type { SchemaObject } from "ajv";
4
+ import type { NodeRefResolved, TypedInputResolved } from "../brands";
5
+ import type { JsonSchemaObjectExtensions } from "../schema-options";
6
+ export interface NodeStateCredentials {
7
+ [key: string]: any;
8
+ }
9
+ export interface NodeState {
10
+ credentials: NodeStateCredentials;
11
+ [key: string]: any;
12
+ }
13
+ export interface NodeButtonDefinition {
14
+ toggle: string;
15
+ onClick: () => void;
16
+ enabled?: () => boolean;
17
+ visible?: () => boolean;
18
+ }
19
+ export interface NodeRedNodeButtonDefinition {
20
+ toggle: string;
21
+ onclick: () => void;
22
+ enabled?: () => boolean;
23
+ visible?: () => boolean;
24
+ }
25
+ export interface NodeFormDefinition {
26
+ component?: Component;
27
+ }
28
+ export interface NodeRedNode {
29
+ id: string;
30
+ type: string;
31
+ name: string;
32
+ category: string;
33
+ x: string;
34
+ y: string;
35
+ g: string;
36
+ z: string;
37
+ credentials: Record<string, any>;
38
+ _def: {
39
+ defaults: Record<string, {
40
+ value: string;
41
+ type?: string;
42
+ label?: string;
43
+ required?: boolean;
44
+ }>;
45
+ credentials: Record<string, {
46
+ value: string;
47
+ type?: "password" | "text";
48
+ label?: string;
49
+ required?: boolean;
50
+ }>;
51
+ category: string;
52
+ color?: string;
53
+ icon?: string;
54
+ label?: ((this: NodeRedNode) => string) | string;
55
+ inputs?: number;
56
+ outputs?: number;
57
+ paletteLabel?: ((this: NodeRedNode) => string) | string;
58
+ labelStyle?: ((this: NodeRedNode) => string) | string;
59
+ inputLabels?: ((this: NodeRedNode, index: number) => string) | string;
60
+ outputLabels?: ((this: NodeRedNode, index: number) => string) | string;
61
+ align?: "left" | "right";
62
+ button?: NodeRedNodeButtonDefinition;
63
+ };
64
+ _newState?: NodeRedNode;
65
+ _app?: App | null;
66
+ _: (str: string) => string;
67
+ /** dynamic port count (base outputs + enabled built-in ports) */
68
+ outputs?: number;
69
+ /** injected when the node has an inputSchema */
70
+ validateInput?: boolean;
71
+ /** injected when the node has an outputsSchema */
72
+ validateOutput?: boolean;
73
+ /** present when the node's configSchema declares SchemaType.ReturnProperty() */
74
+ returnProperty?: string;
75
+ /** built-in port toggles, present when declared in the configSchema */
76
+ errorPort?: boolean;
77
+ completePort?: boolean;
78
+ statusPort?: boolean;
79
+ [key: string]: any;
80
+ }
81
+ export interface NodeDefinition {
82
+ type: string;
83
+ category?: string;
84
+ color?: string;
85
+ icon?: ((this: NodeRedNode) => string) | string;
86
+ label?: ((this: NodeRedNode) => string) | string;
87
+ inputs?: number;
88
+ outputs?: number;
89
+ paletteLabel?: ((this: NodeRedNode) => string) | string;
90
+ labelStyle?: ((this: NodeRedNode) => string) | string;
91
+ inputLabels?: ((this: NodeRedNode, index: number) => string) | string;
92
+ outputLabels?: ((this: NodeRedNode, index: number) => string) | string;
93
+ align?: "left" | "right";
94
+ button?: NodeButtonDefinition;
95
+ onEditResize?: (this: NodeRedNode, size: {
96
+ width: number;
97
+ height: number;
98
+ }) => void;
99
+ onPaletteAdd?: (this: NodeRedNode) => void;
100
+ onPaletteRemove?: (this: NodeRedNode) => void;
101
+ form?: NodeFormDefinition;
102
+ }
103
+ /** Form rendering hints carried by the `x-nrg-form` schema keyword. */
104
+ export type NrgFormOptions = NonNullable<JsonSchemaObjectExtensions["x-nrg-form"]>;
105
+ /**
106
+ * A serialized property schema inside {@link JsonSchemaObject} `properties`,
107
+ * including NRG's custom keywords (shared vocabulary in core/schema-options)
108
+ * that drive form rendering and NodeRef/TypedInput identification.
109
+ */
110
+ export interface JsonPropertySchema extends JsonSchemaObjectExtensions {
111
+ type?: string | string[];
112
+ properties?: Record<string, JsonPropertySchema>;
113
+ required?: string[];
114
+ enum?: unknown[];
115
+ anyOf?: JsonPropertySchema[];
116
+ const?: unknown;
117
+ items?: JsonPropertySchema;
118
+ title?: string;
119
+ description?: string;
120
+ default?: unknown;
121
+ }
122
+ /**
123
+ * A serialized JSON Schema object as the build pipeline emits it (never a
124
+ * live TypeBox instance). Extends ajv's `SchemaObject` so it flows into
125
+ * validator APIs without casts, while keeping the `type: "object"`
126
+ * discriminant and structured `properties`/`required` that ajv's open
127
+ * `[x: string]: any` shape does not provide.
128
+ */
129
+ export interface JsonSchemaObject extends SchemaObject {
130
+ type: "object";
131
+ properties?: Record<string, JsonPropertySchema>;
132
+ required?: string[];
133
+ }
134
+ /**
135
+ * A node definition as it exists at editor runtime, after the build pipeline
136
+ * merged in the schema-derived artifacts (defaults, credentials, serialized
137
+ * schemas). Authors write {@link NodeDefinition}; the inliner provides the
138
+ * rest.
139
+ */
140
+ export interface RuntimeNodeDefinition extends NodeDefinition {
141
+ defaults?: NodeDefaults;
142
+ credentials?: NodeCredentials;
143
+ configSchema?: JsonSchemaObject;
144
+ credentialsSchema?: JsonSchemaObject;
145
+ inputSchema?: JsonSchemaObject;
146
+ /**
147
+ * Single port, positional ports, or named ports (key = port name).
148
+ * Not constrained to object schemas: with returnProperty the raw sent
149
+ * value is validated, so results may be any schema shape.
150
+ */
151
+ outputsSchema?: JsonPropertySchema | JsonPropertySchema[] | Record<string, JsonPropertySchema>;
152
+ }
153
+ export interface NodeDefaults {
154
+ [key: string]: {
155
+ value: any;
156
+ type?: string;
157
+ label?: string;
158
+ required?: boolean;
159
+ validate?: (this: NodeRedNode, value: any, opt: any) => any;
160
+ };
161
+ }
162
+ export interface NodeCredentials {
163
+ [key: string]: {
164
+ value?: string;
165
+ type?: "password" | "text";
166
+ label?: string;
167
+ required?: boolean;
168
+ };
169
+ }
170
+ export interface NodeFeatures {
171
+ hasInputSchema: boolean;
172
+ hasOutputSchema: boolean;
173
+ }
174
+ /** Client-side representation of a TypedInput field: the raw value string and its type selector. */
175
+ export interface TypedInputValue {
176
+ value: string;
177
+ type: string;
178
+ }
179
+ /**
180
+ * Maps a schema's static type to the raw values the editor form holds.
181
+ * The server counterpart (`ResolvedStatic` in server/schemas/types) maps the
182
+ * same brands — shared via core/brands — to resolved runtime values instead.
183
+ * - `NodeRef<T>` → `string` (the referenced node's id)
184
+ * - `TypedInput<T>` → `TypedInputValue` (raw value + type pair)
185
+ * - Functions pass through, arrays and objects map recursively
186
+ */
187
+ export type EditorStatic<T> = T extends NodeRefResolved<any> ? string : T extends TypedInputResolved ? TypedInputValue : T extends (...args: any[]) => any ? T : T extends Array<infer I> ? EditorStatic<I>[] : T extends object ? {
188
+ [K in keyof T]: EditorStatic<T[K]>;
189
+ } : T;
190
+ /**
191
+ * Infers the client-side TypeScript type from a TypeBox schema.
192
+ *
193
+ * Resolves schema types to their client form representations:
194
+ * - `NodeRef<T>` → `string` (node ID in the editor)
195
+ * - `TypedInput<T>` → `{ value: string; type: string }`
196
+ * - All other types resolve via TypeBox's `Static<T>`
197
+ *
198
+ * @example
199
+ * ```ts
200
+ * import type { Infer } from "@bonsae/nrg/client";
201
+ * import type { ConfigSchema } from "../schemas/my-node";
202
+ *
203
+ * type Config = Infer<typeof ConfigSchema>;
204
+ * ```
205
+ */
206
+ export type Infer<T extends TSchema> = EditorStatic<Static<T>>;
@@ -11,13 +11,13 @@ declare module "vue" {
11
11
  }
12
12
 
13
13
  export interface GlobalComponents {
14
- NodeRedConfigInput: (typeof import("./form/components/node-red-config-input.vue"))["default"];
15
- NodeRedEditorInput: (typeof import("./form/components/node-red-editor-input.vue"))["default"];
16
- NodeRedInputLabel: (typeof import("./form/components/node-red-input-label.vue"))["default"];
17
- NodeRedInput: (typeof import("./form/components/node-red-input.vue"))["default"];
18
- NodeRedJsonSchemaForm: (typeof import("./form/components/node-red-json-schema-form.vue"))["default"];
19
- NodeRedSelectInput: (typeof import("./form/components/node-red-select-input.vue"))["default"];
20
- NodeRedToggle: (typeof import("./form/components/node-red-toggle.vue"))["default"];
21
- NodeRedTypedInput: (typeof import("./form/components/node-red-typed-input.vue"))["default"];
14
+ NodeRedConfigInput: (typeof import("./client/form/components/node-red-config-input.vue"))["default"];
15
+ NodeRedEditorInput: (typeof import("./client/form/components/node-red-editor-input.vue"))["default"];
16
+ NodeRedInputLabel: (typeof import("./client/form/components/node-red-input-label.vue"))["default"];
17
+ NodeRedInput: (typeof import("./client/form/components/node-red-input.vue"))["default"];
18
+ NodeRedJsonSchemaForm: (typeof import("./client/form/components/node-red-json-schema-form.vue"))["default"];
19
+ NodeRedSelectInput: (typeof import("./client/form/components/node-red-select-input.vue"))["default"];
20
+ NodeRedToggle: (typeof import("./client/form/components/node-red-toggle.vue"))["default"];
21
+ NodeRedTypedInput: (typeof import("./client/form/components/node-red-typed-input.vue"))["default"];
22
22
  }
23
23
  }
@@ -0,0 +1,4 @@
1
+ declare const TYPED_INPUT_TYPES: readonly ["msg", "flow", "global", "str", "num", "bool", "json", "bin", "re", "jsonata", "date", "env", "node", "cred"];
2
+ /** Reserved config property names for built-in ports (error, complete, status) */
3
+ declare const BUILTIN_PORT_KEYS: readonly ["errorPort", "completePort", "statusPort"];
4
+ export { BUILTIN_PORT_KEYS, TYPED_INPUT_TYPES };