@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 +54 -34
- package/package.json +33 -3
- package/test/client/component/config.js +37 -0
- package/test/client/component/index.js +25 -10
- package/test/client/unit/config.js +26 -0
- package/test/client/unit/index.js +18 -7
- package/test/server/unit/config.js +15 -0
- package/types/test-client-component.d.ts +94 -9
- package/types/test-client-unit.d.ts +89 -5
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/
|
|
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`, `
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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-
|
|
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
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const
|
|
234
|
-
|
|
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("
|
|
240
|
-
const {
|
|
241
|
-
render(
|
|
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.
|
|
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
|
-
"
|
|
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/
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
-
|
|
210
|
+
useFormNode
|
|
200
211
|
};
|
|
@@ -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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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 {};
|