@bonsae/nrg 0.18.0 → 0.18.2

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/README.md CHANGED
@@ -22,9 +22,12 @@ Build Node-RED nodes with Vue 3, TypeScript, JSON Schema validations, Vite and V
22
22
  | `@bonsae/nrg/client` | Client-side registration (`registerTypes`, `defineNode`, `useFormNode`, `Infer`) |
23
23
  | `@bonsae/nrg/vite` | Vite plugin for building and developing Node-RED packages |
24
24
  | `@bonsae/nrg/test/server/unit` | Server unit test helpers (`createNode`, `createRED`, `MockRED`) |
25
- | `@bonsae/nrg/test/client/unit` | Client unit test config and mocks (`defaultConfig`, `createRED`, `createJQuery`) |
25
+ | `@bonsae/nrg/test/server/unit/config` | Server unit test default vitest config (`defaultConfig`) |
26
+ | `@bonsae/nrg/test/client/unit` | Client unit test mocks (`createRED`, `createJQuery`, `useFormNode`) |
27
+ | `@bonsae/nrg/test/client/unit/config` | Client unit test default vitest config (`defaultConfig`) |
26
28
  | `@bonsae/nrg/test/client/unit/setup` | Setup file that installs `RED` and `$` mocks on `window` |
27
- | `@bonsae/nrg/test/client/component` | Client component test helpers (`createNode`, `defaultConfig`, `createRED`, `createJQuery`) |
29
+ | `@bonsae/nrg/test/client/component` | Client component test helpers (`createNode`, `createRED`, `createJQuery`, `useFormNode`) |
30
+ | `@bonsae/nrg/test/client/component/config` | Client component test default vitest config (`defaultConfig`) |
28
31
  | `@bonsae/nrg/test/client/component/setup` | Setup file that installs `RED` and `$` mocks on `window` with Vue i18n |
29
32
  | `@bonsae/nrg/test/client/e2e` | Browser E2E test helpers (`NodeRedEditor`, `NodeRedField`, `setup`, `teardown`) |
30
33
  | `@bonsae/nrg/tsconfig/base.json` | Base TypeScript configuration |
@@ -142,7 +145,21 @@ See the [consumer template](https://github.com/AllanOricil/node-red-vue-template
142
145
 
143
146
  ## Testing
144
147
 
145
- NRG provides four test libraries:
148
+ NRG provides four test libraries and bundles most test infrastructure as direct dependencies. Install `vitest` plus any optional peer dependencies you need:
149
+
150
+ ```bash
151
+ pnpm add -D vitest
152
+ ```
153
+
154
+ Optional peer dependencies:
155
+
156
+ | Package | When to install |
157
+ | --- | --- |
158
+ | `@vitest/browser-playwright` | Component tests (Playwright browser provider for Vitest) |
159
+ | `playwright` | Component tests or E2E tests (direct `import` in test files) |
160
+ | `vitest-browser-vue` | Component tests (`render` helper for Vue components) |
161
+ | `@vitest/coverage-v8` | Coverage with `--coverage` (V8 provider) |
162
+ | `@vitest/coverage-istanbul` | Coverage with `--coverage` (Istanbul provider) |
146
163
 
147
164
  - `@bonsae/nrg/test/server/unit` — server-side unit tests
148
165
  - `@bonsae/nrg/test/client/unit` — client-side unit tests (TypeScript logic)
@@ -174,15 +191,15 @@ describe("my-node", () => {
174
191
  Test client-side TypeScript logic (validation, utilities) with mocked `RED` and `$` globals:
175
192
 
176
193
  ```typescript
177
- // vitest.config.ts
178
- import { defineConfig } from "vitest/config";
179
- import { defaultConfig } from "@bonsae/nrg/test/client/unit";
194
+ // vitest.client.unit.config.ts
195
+ import { defineConfig, mergeConfig } from "vitest/config";
196
+ import { defaultConfig } from "@bonsae/nrg/test/client/unit/config";
180
197
 
181
- export default defineConfig({
198
+ export default mergeConfig(defaultConfig, defineConfig({
182
199
  test: {
183
- ...defaultConfig,
200
+ include: ["tests/client/unit/**/*.test.ts"],
184
201
  },
185
- });
202
+ }));
186
203
  ```
187
204
 
188
205
  ```typescript
@@ -199,46 +216,49 @@ describe("myUtil", () => {
199
216
 
200
217
  ### Client Component Tests
201
218
 
202
- Test your Vue editor components with mocked Node-RED globals:
219
+ Test your Vue editor components with mocked Node-RED globals. Components that use `useFormNode()` receive their node data via Vue's `provide`/`inject` — use `createNode().provide` to supply it in tests:
203
220
 
204
221
  ```typescript
205
- // vitest.config.ts
206
- import { defineConfig } from "vitest/config";
207
- import { playwright } from "@vitest/browser-playwright";
208
- import vue from "@vitejs/plugin-vue";
209
- import { defaultConfig } from "@bonsae/nrg/test/client/component";
222
+ // vitest.client.component.config.ts
223
+ import { defineConfig, mergeConfig } from "vitest/config";
224
+ import { defaultConfig } from "@bonsae/nrg/test/client/component/config";
210
225
 
211
- export default defineConfig({
212
- plugins: [vue()],
226
+ export default mergeConfig(defaultConfig, defineConfig({
213
227
  test: {
214
- ...defaultConfig,
215
- browser: {
216
- ...defaultConfig.browser,
217
- provider: playwright(),
218
- },
228
+ include: ["tests/client/component/**/*.test.ts"],
219
229
  },
220
- });
230
+ }));
221
231
  ```
222
232
 
223
233
  ```typescript
224
- // tests/client/component/my-component.test.ts
234
+ // tests/client/component/my-form.test.ts
225
235
  import { describe, test, expect, vi } from "vitest";
226
236
  import { render } from "vitest-browser-vue";
227
237
  import { createNode } from "@bonsae/nrg/test/client/component";
228
- import MyComponent from "../src/client/components/my-component.vue";
238
+ import MyForm from "../src/client/components/my-form.vue";
239
+
240
+ describe("MyForm", () => {
241
+ test("renders fields from injected node", async () => {
242
+ const { provide } = createNode({ name: "test", url: "https://example.com" });
243
+ const screen = render(MyForm, {
244
+ global: { provide },
245
+ });
246
+ await expect.element(screen.getByDisplayValue("test")).toBeInTheDocument();
247
+ });
229
248
 
230
- describe("MyComponent", () => {
231
- test("renders with node props", async () => {
232
- const { node } = createNode({ name: "test" });
233
- const screen = render(MyComponent, {
234
- props: { node },
249
+ test("accesses node id for API calls", async () => {
250
+ const fetchSpy = vi.fn().mockResolvedValue({ ok: true, json: () => ({}) });
251
+ vi.stubGlobal("fetch", fetchSpy);
252
+ const { node, provide } = createNode({ name: "test" });
253
+ render(MyForm, { global: { provide } });
254
+ await vi.waitFor(() => {
255
+ expect(fetchSpy).toHaveBeenCalledWith(`my-api/${node.id}`);
235
256
  });
236
- await expect.element(screen.getByText("test")).toBeInTheDocument();
237
257
  });
238
258
 
239
- test("calls RED.editor API", async () => {
240
- const { node, RED } = createNode();
241
- render(MyComponent, { props: { node, value: "" } });
259
+ test("asserts RED.editor API calls", async () => {
260
+ const { RED, provide } = createNode();
261
+ render(MyForm, { global: { provide } });
242
262
  expect(RED.editor.createEditor).toHaveBeenCalled();
243
263
  });
244
264
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonsae/nrg",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
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",
@@ -51,15 +51,18 @@
51
51
  "types": "./types/test-server-unit.d.ts",
52
52
  "default": "./test/server/unit/index.js"
53
53
  },
54
+ "./test/server/unit/config": "./test/server/unit/config.js",
54
55
  "./test/client/component": {
55
56
  "types": "./types/test-client-component.d.ts",
56
57
  "default": "./test/client/component/index.js"
57
58
  },
59
+ "./test/client/component/config": "./test/client/component/config.js",
58
60
  "./test/client/component/setup": "./test/client/component/setup.js",
59
61
  "./test/client/unit": {
60
62
  "types": "./types/test-client-unit.d.ts",
61
63
  "default": "./test/client/unit/index.js"
62
64
  },
65
+ "./test/client/unit/config": "./test/client/unit/config.js",
63
66
  "./test/client/unit/setup": "./test/client/unit/setup.js",
64
67
  "./test/client/e2e": {
65
68
  "types": "./types/test-client-e2e.d.ts",
@@ -75,7 +78,30 @@
75
78
  },
76
79
  "peerDependencies": {
77
80
  "vite": "^6.0.0",
78
- "vue": "^3.5.14"
81
+ "vitest": "^4.0.0",
82
+ "vue": "^3.5.14",
83
+ "@vitest/coverage-istanbul": "^4.0.0",
84
+ "@vitest/coverage-v8": "^4.0.0",
85
+ "@vitest/browser-playwright": "^4.0.0",
86
+ "playwright": "^1.50.0",
87
+ "vitest-browser-vue": "^2.0.0"
88
+ },
89
+ "peerDependenciesMeta": {
90
+ "@vitest/coverage-istanbul": {
91
+ "optional": true
92
+ },
93
+ "@vitest/coverage-v8": {
94
+ "optional": true
95
+ },
96
+ "@vitest/browser-playwright": {
97
+ "optional": true
98
+ },
99
+ "playwright": {
100
+ "optional": true
101
+ },
102
+ "vitest-browser-vue": {
103
+ "optional": true
104
+ }
79
105
  },
80
106
  "dependencies": {
81
107
  "@clack/prompts": "^1.0.1",
@@ -95,6 +121,10 @@
95
121
  "typescript": "^5.8.3",
96
122
  "vite-plugin-dts": "^4.5.4",
97
123
  "vite-plugin-static-copy": "^3.1.0",
98
- "vue": "^3.5.14"
124
+ "vue": "^3.5.14",
125
+ "@vitest/browser-playwright": "^4.1.5",
126
+ "happy-dom": "^20.10.2",
127
+ "playwright": "^1.60.0",
128
+ "vitest-browser-vue": "^2.1.0"
99
129
  }
100
130
  }
@@ -0,0 +1,37 @@
1
+ // src/test/client/component/config.ts
2
+ import path from "path";
3
+ import vue from "@vitejs/plugin-vue";
4
+ import { playwright } from "@vitest/browser-playwright";
5
+ var defaultConfig = {
6
+ plugins: [vue()],
7
+ esbuild: {
8
+ tsconfigRaw: "{}"
9
+ },
10
+ resolve: {
11
+ alias: {
12
+ "@": path.resolve(process.cwd(), "src"),
13
+ "@bonsae/nrg/client": "@bonsae/nrg/test/client/component"
14
+ }
15
+ },
16
+ server: {
17
+ fs: {
18
+ allow: [".."]
19
+ }
20
+ },
21
+ test: {
22
+ testTimeout: 3e4,
23
+ setupFiles: ["@bonsae/nrg/test/client/component/setup"],
24
+ browser: {
25
+ enabled: true,
26
+ instances: [
27
+ { browser: "chromium" },
28
+ { browser: "firefox" },
29
+ { browser: "webkit" }
30
+ ],
31
+ provider: playwright()
32
+ }
33
+ }
34
+ };
35
+ export {
36
+ defaultConfig
37
+ };
@@ -190,15 +190,25 @@ function createJQuery() {
190
190
  };
191
191
  }
192
192
 
193
- // src/test/client/component/index.ts
194
- var defaultConfig = {
195
- testTimeout: 3e4,
196
- setupFiles: ["@bonsae/nrg/test/client/component/setup"],
197
- browser: {
198
- enabled: true,
199
- instances: [{ browser: "chromium" }]
193
+ // src/core/client/use-form-node.ts
194
+ import { inject } from "vue";
195
+ function useFormNode() {
196
+ const node = inject("__nrg_form_node");
197
+ const schema = inject("__nrg_form_schema");
198
+ const errors = inject("__nrg_form_errors");
199
+ if (!node) {
200
+ throw new Error(
201
+ "useFormNode() must be called inside a form component mounted by NRG."
202
+ );
200
203
  }
201
- };
204
+ return {
205
+ node,
206
+ schema,
207
+ errors
208
+ };
209
+ }
210
+
211
+ // src/test/client/component/index.ts
202
212
  function createNode(overrides = {}) {
203
213
  const node = {
204
214
  id: `test-${Math.random().toString(36).slice(2, 10)}`,
@@ -210,7 +220,12 @@ function createNode(overrides = {}) {
210
220
  };
211
221
  const RED = getMockRED();
212
222
  spyOnRED(RED);
213
- return { node, RED };
223
+ const provide = {
224
+ __nrg_form_node: node,
225
+ __nrg_form_schema: {},
226
+ __nrg_form_errors: {}
227
+ };
228
+ return { node, RED, provide };
214
229
  }
215
230
  function spyIfNeeded(obj, method) {
216
231
  if (!vi.isMockFunction(obj[method])) {
@@ -240,5 +255,5 @@ export {
240
255
  createJQuery,
241
256
  createNode,
242
257
  createRED,
243
- defaultConfig
258
+ useFormNode
244
259
  };
@@ -0,0 +1,26 @@
1
+ // src/test/client/unit/config.ts
2
+ import path from "path";
3
+ var defaultConfig = {
4
+ esbuild: {
5
+ tsconfigRaw: "{}"
6
+ },
7
+ resolve: {
8
+ alias: {
9
+ "@": path.resolve(process.cwd(), "src"),
10
+ "@bonsae/nrg/client": "@bonsae/nrg/test/client/unit"
11
+ }
12
+ },
13
+ server: {
14
+ fs: {
15
+ allow: [".."]
16
+ }
17
+ },
18
+ test: {
19
+ testTimeout: 3e4,
20
+ environment: "happy-dom",
21
+ setupFiles: ["@bonsae/nrg/test/client/unit/setup"]
22
+ }
23
+ };
24
+ export {
25
+ defaultConfig
26
+ };
@@ -187,14 +187,25 @@ function createJQuery() {
187
187
  };
188
188
  }
189
189
 
190
- // src/test/client/unit/index.ts
191
- var defaultConfig = {
192
- testTimeout: 3e4,
193
- environment: "happy-dom",
194
- setupFiles: ["@bonsae/nrg/test/client/unit/setup"]
195
- };
190
+ // src/core/client/use-form-node.ts
191
+ import { inject } from "vue";
192
+ function useFormNode() {
193
+ const node = inject("__nrg_form_node");
194
+ const schema = inject("__nrg_form_schema");
195
+ const errors = inject("__nrg_form_errors");
196
+ if (!node) {
197
+ throw new Error(
198
+ "useFormNode() must be called inside a form component mounted by NRG."
199
+ );
200
+ }
201
+ return {
202
+ node,
203
+ schema,
204
+ errors
205
+ };
206
+ }
196
207
  export {
197
208
  createJQuery,
198
209
  createRED,
199
- defaultConfig
210
+ useFormNode
200
211
  };
@@ -0,0 +1,15 @@
1
+ // src/test/server/unit/config.ts
2
+ import path from "path";
3
+ var defaultConfig = {
4
+ resolve: {
5
+ alias: {
6
+ "@": path.resolve(process.cwd(), "src")
7
+ }
8
+ },
9
+ test: {
10
+ testTimeout: 3e4
11
+ }
12
+ };
13
+ export {
14
+ defaultConfig
15
+ };
@@ -1,5 +1,8 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
+ import { SchemaOptions, Static, TSchema } from '@sinclair/typebox';
4
+ import { App } from 'vue';
5
+
3
6
  export interface MockEditor {
4
7
  getValue(): string;
5
8
  setValue(val: string): void;
@@ -43,16 +46,92 @@ export interface MockRED {
43
46
  }
44
47
  export declare function createRED(): MockRED;
45
48
  export declare function createJQuery(): (selector: any, attrs?: Record<string, any>) => any;
46
- export declare const defaultConfig: {
47
- testTimeout: number;
48
- setupFiles: string[];
49
- browser: {
50
- enabled: boolean;
51
- instances: {
52
- browser: string;
53
- }[];
49
+ interface NodeRefResolved<T = any> {
50
+ readonly __nrg_node_ref: true;
51
+ readonly __instance: T;
52
+ }
53
+ interface NodeRedNodeButtonDefinition {
54
+ toggle: string;
55
+ onclick: () => void;
56
+ enabled?: () => boolean;
57
+ visible?: () => boolean;
58
+ }
59
+ interface NodeRedNode {
60
+ id: string;
61
+ type: string;
62
+ name: string;
63
+ category: string;
64
+ x: string;
65
+ y: string;
66
+ g: string;
67
+ z: string;
68
+ credentials: Record<string, any>;
69
+ _def: {
70
+ defaults: Record<string, {
71
+ value: string;
72
+ type?: string;
73
+ label?: string;
74
+ required?: boolean;
75
+ }>;
76
+ credentials: Record<string, {
77
+ value: string;
78
+ type?: "password" | "text";
79
+ label?: string;
80
+ required?: boolean;
81
+ }>;
82
+ category: string;
83
+ color?: string;
84
+ icon?: string;
85
+ label?: ((this: NodeRedNode) => string) | string;
86
+ inputs?: number;
87
+ outputs?: number;
88
+ paletteLabel?: ((this: NodeRedNode) => string) | string;
89
+ labelStyle?: ((this: NodeRedNode) => string) | string;
90
+ inputLabels?: ((this: NodeRedNode, index: number) => string) | string;
91
+ outputLabels?: ((this: NodeRedNode, index: number) => string) | string;
92
+ align?: "left" | "right";
93
+ button?: NodeRedNodeButtonDefinition;
54
94
  };
55
- };
95
+ _newState?: NodeRedNode;
96
+ _app?: App | null;
97
+ _: (str: string) => string;
98
+ [key: string]: any;
99
+ }
100
+ interface TypedInputValue {
101
+ value: string;
102
+ type: string;
103
+ }
104
+ type _ToClient<T> = T extends NodeRefResolved<any> ? string : T extends {
105
+ resolve(...args: any[]): any;
106
+ value: unknown;
107
+ type: string;
108
+ } ? TypedInputValue : T extends (...args: any[]) => any ? T : T extends Array<infer I> ? _ToClient<I>[] : T extends object ? {
109
+ [K in keyof T]: _ToClient<T[K]>;
110
+ } : T;
111
+ interface FormNode<TConfig extends TSchema = TSchema, TCredentials extends TSchema = TSchema> {
112
+ node: NodeRedNode & _ToClient<Static<TConfig>> & {
113
+ credentials: _ToClient<Static<TCredentials>> & Record<string, any>;
114
+ };
115
+ schema: Record<string, any>;
116
+ errors: Record<string, string>;
117
+ }
118
+ /**
119
+ * Composable that provides typed access to the form node, schema, and errors.
120
+ * Replaces `defineProps` in custom form components — no props declaration needed.
121
+ *
122
+ * @example
123
+ * ```vue
124
+ * <script setup lang="ts">
125
+ * import { useFormNode } from "@bonsae/nrg/client";
126
+ * import type { ConfigsSchema, CredentialsSchema } from "../../server/schemas/my-node";
127
+ *
128
+ * const { node, errors } = useFormNode<typeof ConfigsSchema, typeof CredentialsSchema>();
129
+ * node.name // string — typed from ConfigsSchema
130
+ * node.credentials.apiKey // string — typed from CredentialsSchema
131
+ * </script>
132
+ * ```
133
+ */
134
+ export declare function useFormNode<TConfig extends TSchema = TSchema, TCredentials extends TSchema = TSchema>(): FormNode<TConfig, TCredentials>;
56
135
  export interface TestNode {
57
136
  id: string;
58
137
  type: string;
@@ -61,9 +140,15 @@ export interface TestNode {
61
140
  _: (key: string) => string;
62
141
  [key: string]: any;
63
142
  }
143
+ interface FormProvide {
144
+ __nrg_form_node: TestNode;
145
+ __nrg_form_schema: Record<string, any>;
146
+ __nrg_form_errors: Record<string, string>;
147
+ }
64
148
  interface CreateNodeResult {
65
149
  node: TestNode;
66
150
  RED: MockRED;
151
+ provide: FormProvide;
67
152
  }
68
153
  export declare function createNode(overrides?: Record<string, any>): CreateNodeResult;
69
154
 
@@ -1,5 +1,8 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
+ import { SchemaOptions, Static, TSchema } from '@sinclair/typebox';
4
+ import { App } from 'vue';
5
+
3
6
  export interface MockEditor {
4
7
  getValue(): string;
5
8
  setValue(val: string): void;
@@ -43,10 +46,91 @@ export interface MockRED {
43
46
  }
44
47
  export declare function createRED(): MockRED;
45
48
  export declare function createJQuery(): (selector: any, attrs?: Record<string, any>) => any;
46
- export declare const defaultConfig: {
47
- testTimeout: number;
48
- environment: "happy-dom";
49
- setupFiles: string[];
50
- };
49
+ interface NodeRefResolved<T = any> {
50
+ readonly __nrg_node_ref: true;
51
+ readonly __instance: T;
52
+ }
53
+ interface NodeRedNodeButtonDefinition {
54
+ toggle: string;
55
+ onclick: () => void;
56
+ enabled?: () => boolean;
57
+ visible?: () => boolean;
58
+ }
59
+ interface NodeRedNode {
60
+ id: string;
61
+ type: string;
62
+ name: string;
63
+ category: string;
64
+ x: string;
65
+ y: string;
66
+ g: string;
67
+ z: string;
68
+ credentials: Record<string, any>;
69
+ _def: {
70
+ defaults: Record<string, {
71
+ value: string;
72
+ type?: string;
73
+ label?: string;
74
+ required?: boolean;
75
+ }>;
76
+ credentials: Record<string, {
77
+ value: string;
78
+ type?: "password" | "text";
79
+ label?: string;
80
+ required?: boolean;
81
+ }>;
82
+ category: string;
83
+ color?: string;
84
+ icon?: string;
85
+ label?: ((this: NodeRedNode) => string) | string;
86
+ inputs?: number;
87
+ outputs?: number;
88
+ paletteLabel?: ((this: NodeRedNode) => string) | string;
89
+ labelStyle?: ((this: NodeRedNode) => string) | string;
90
+ inputLabels?: ((this: NodeRedNode, index: number) => string) | string;
91
+ outputLabels?: ((this: NodeRedNode, index: number) => string) | string;
92
+ align?: "left" | "right";
93
+ button?: NodeRedNodeButtonDefinition;
94
+ };
95
+ _newState?: NodeRedNode;
96
+ _app?: App | null;
97
+ _: (str: string) => string;
98
+ [key: string]: any;
99
+ }
100
+ interface TypedInputValue {
101
+ value: string;
102
+ type: string;
103
+ }
104
+ type _ToClient<T> = T extends NodeRefResolved<any> ? string : T extends {
105
+ resolve(...args: any[]): any;
106
+ value: unknown;
107
+ type: string;
108
+ } ? TypedInputValue : T extends (...args: any[]) => any ? T : T extends Array<infer I> ? _ToClient<I>[] : T extends object ? {
109
+ [K in keyof T]: _ToClient<T[K]>;
110
+ } : T;
111
+ interface FormNode<TConfig extends TSchema = TSchema, TCredentials extends TSchema = TSchema> {
112
+ node: NodeRedNode & _ToClient<Static<TConfig>> & {
113
+ credentials: _ToClient<Static<TCredentials>> & Record<string, any>;
114
+ };
115
+ schema: Record<string, any>;
116
+ errors: Record<string, string>;
117
+ }
118
+ /**
119
+ * Composable that provides typed access to the form node, schema, and errors.
120
+ * Replaces `defineProps` in custom form components — no props declaration needed.
121
+ *
122
+ * @example
123
+ * ```vue
124
+ * <script setup lang="ts">
125
+ * import { useFormNode } from "@bonsae/nrg/client";
126
+ * import type { ConfigsSchema, CredentialsSchema } from "../../server/schemas/my-node";
127
+ *
128
+ * const { node, errors } = useFormNode<typeof ConfigsSchema, typeof CredentialsSchema>();
129
+ * node.name // string — typed from ConfigsSchema
130
+ * node.credentials.apiKey // string — typed from CredentialsSchema
131
+ * </script>
132
+ * ```
133
+ */
134
+ export declare function useFormNode<TConfig extends TSchema = TSchema, TCredentials extends TSchema = TSchema>(): FormNode<TConfig, TCredentials>;
51
135
 
52
136
  export {};