@bonsae/nrg 0.26.3 → 0.28.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/eslint/index.js +48 -0
- package/package.json +2 -1
- package/server/index.cjs +198 -151
- package/server/resources/nrg-client.js +9 -9
- package/test/client/component/index.js +107 -99
- package/test/client/component/nrg.css +1 -1
- package/test/client/component/setup.js +103 -75
- package/test/client/e2e/index.js +27 -24
- package/test/server/integration/config.js +0 -6
- package/test/server/integration/index.js +9 -13
- package/test/server/unit/config.js +0 -6
- package/test/server/unit/index.js +1 -9
- package/types/client.d.ts +15 -7
- package/types/server.d.ts +81 -72
- package/types/shims/core/client/form/components/node-red-json-schema-form.vue.d.ts +11 -1
- package/types/shims/core/client/form/components/node-red-toggle.vue.d.ts +15 -0
- package/types/shims/core/client/types.d.ts +8 -3
- package/types/shims/core/schema-options.d.ts +1 -1
- package/types/shims/core/types.d.ts +32 -8
- package/types/shims/schema-options.d.ts +1 -1
- package/types/test-client-component.d.ts +9 -6
- package/types/test-client-e2e.d.ts +2 -15
- package/types/test-client-unit.d.ts +8 -5
- package/types/test-server-integration.d.ts +1 -1
- package/types/vite.d.ts +8 -17
- package/vite/index.js +47 -54
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
var
|
|
2
|
-
var $ = (
|
|
3
|
-
var v = (
|
|
4
|
-
import { inject as
|
|
5
|
-
import { inject as l, reactive as _, watch as
|
|
6
|
-
import
|
|
1
|
+
var w = Object.defineProperty;
|
|
2
|
+
var $ = (r, e, t) => e in r ? w(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
3
|
+
var v = (r, e, t) => $(r, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import { inject as b, vi as y } from "vitest";
|
|
5
|
+
import { inject as l, reactive as _, watch as F } from "vue";
|
|
6
|
+
import P from "jsonpointer";
|
|
7
7
|
import k from "ajv";
|
|
8
8
|
import O from "ajv-formats";
|
|
9
|
-
import
|
|
10
|
-
class
|
|
9
|
+
import N from "ajv-errors";
|
|
10
|
+
class S {
|
|
11
11
|
constructor(e) {
|
|
12
12
|
v(this, "ajv");
|
|
13
|
-
const { customKeywords:
|
|
13
|
+
const { customKeywords: t, customFormats: o, ...n } = e || {};
|
|
14
14
|
this.ajv = new k({
|
|
15
15
|
allErrors: !0,
|
|
16
16
|
code: {
|
|
@@ -26,23 +26,23 @@ class N {
|
|
|
26
26
|
// NOTE: if true, types that are not serializable JSON, like Function, would not work
|
|
27
27
|
validateSchema: !1,
|
|
28
28
|
verbose: !0,
|
|
29
|
-
...
|
|
30
|
-
}), O(this.ajv),
|
|
29
|
+
...n
|
|
30
|
+
}), O(this.ajv), N(this.ajv), this.addCustomKeywords(t || []), this.addCustomFormats(o || {});
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Add custom keywords to the validator
|
|
34
34
|
*/
|
|
35
35
|
addCustomKeywords(e) {
|
|
36
|
-
e && e.forEach((
|
|
37
|
-
this.ajv.addKeyword(
|
|
36
|
+
e && e.forEach((t) => {
|
|
37
|
+
this.ajv.addKeyword(t);
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Add custom formats to the validator
|
|
42
42
|
*/
|
|
43
43
|
addCustomFormats(e) {
|
|
44
|
-
e && Object.entries(e).forEach(([
|
|
45
|
-
o instanceof RegExp ? this.ajv.addFormat(
|
|
44
|
+
e && Object.entries(e).forEach(([t, o]) => {
|
|
45
|
+
o instanceof RegExp ? this.ajv.addFormat(t, o) : this.ajv.addFormat(t, { validate: o });
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
@@ -50,25 +50,25 @@ class N {
|
|
|
50
50
|
* @param schema - JSON Schema to validate against
|
|
51
51
|
* @param cacheKey - Optional cache key for reusing validators
|
|
52
52
|
*/
|
|
53
|
-
createValidator(e,
|
|
54
|
-
if (
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
53
|
+
createValidator(e, t) {
|
|
54
|
+
if (t && !e.$id && (e.$id = t), e.$id) {
|
|
55
|
+
const n = this.ajv.getSchema(e.$id);
|
|
56
|
+
if (n) return n;
|
|
57
57
|
}
|
|
58
58
|
return this.ajv.compile(e);
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Validate data against a schema and return a structured result
|
|
62
62
|
*/
|
|
63
|
-
validate(e,
|
|
64
|
-
const
|
|
65
|
-
if (!
|
|
66
|
-
const i = this.formatErrors(
|
|
63
|
+
validate(e, t, o) {
|
|
64
|
+
const n = this.createValidator(t, o == null ? void 0 : o.cacheKey);
|
|
65
|
+
if (!n(e)) {
|
|
66
|
+
const i = this.formatErrors(n.errors);
|
|
67
67
|
if (o != null && o.throwOnError)
|
|
68
|
-
throw new
|
|
68
|
+
throw new p(i, n.errors || []);
|
|
69
69
|
return {
|
|
70
70
|
valid: !1,
|
|
71
|
-
errors:
|
|
71
|
+
errors: n.errors || void 0,
|
|
72
72
|
errorMessage: i
|
|
73
73
|
};
|
|
74
74
|
}
|
|
@@ -80,30 +80,30 @@ class N {
|
|
|
80
80
|
/**
|
|
81
81
|
* Format errors into a human-readable string
|
|
82
82
|
*/
|
|
83
|
-
formatErrors(e,
|
|
83
|
+
formatErrors(e, t) {
|
|
84
84
|
return !e || e.length === 0 ? "No errors" : this.ajv.errorsText(e, {
|
|
85
85
|
separator: "; ",
|
|
86
86
|
dataVar: "data",
|
|
87
|
-
...
|
|
87
|
+
...t
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
91
|
* Get detailed error information
|
|
92
92
|
*/
|
|
93
93
|
getDetailedErrors(e) {
|
|
94
|
-
return !e || e.length === 0 ? [] : e.map((
|
|
95
|
-
field:
|
|
96
|
-
message:
|
|
97
|
-
keyword:
|
|
98
|
-
params:
|
|
99
|
-
schemaPath:
|
|
94
|
+
return !e || e.length === 0 ? [] : e.map((t) => ({
|
|
95
|
+
field: t.instancePath || "/",
|
|
96
|
+
message: t.message || "Validation failed",
|
|
97
|
+
keyword: t.keyword,
|
|
98
|
+
params: t.params,
|
|
99
|
+
schemaPath: t.schemaPath
|
|
100
100
|
}));
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* Add a schema to the validator for reference
|
|
104
104
|
*/
|
|
105
|
-
addSchema(e,
|
|
106
|
-
return this.ajv.addSchema(e,
|
|
105
|
+
addSchema(e, t) {
|
|
106
|
+
return this.ajv.addSchema(e, t), this;
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
109
|
* Remove a schema from the validator
|
|
@@ -112,12 +112,12 @@ class N {
|
|
|
112
112
|
return this.ajv.removeSchema(e), this;
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
class
|
|
116
|
-
constructor(e,
|
|
117
|
-
super(e), this.errors =
|
|
115
|
+
class p extends Error {
|
|
116
|
+
constructor(e, t) {
|
|
117
|
+
super(e), this.errors = t, this.name = "ValidationError", Object.setPrototypeOf(this, p.prototype);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
-
const V = new
|
|
120
|
+
const V = new S({
|
|
121
121
|
customKeywords: [
|
|
122
122
|
{
|
|
123
123
|
keyword: "x-nrg-skip-validation",
|
|
@@ -127,118 +127,126 @@ const V = new N({
|
|
|
127
127
|
{
|
|
128
128
|
keyword: "x-nrg-node-type",
|
|
129
129
|
type: "string",
|
|
130
|
-
validate: (
|
|
130
|
+
validate: (r, e) => {
|
|
131
131
|
if (!e) return !0;
|
|
132
|
-
const
|
|
133
|
-
return !!
|
|
132
|
+
const t = RED.nodes.node(e);
|
|
133
|
+
return !!t && t.type === r;
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
],
|
|
137
137
|
customFormats: {
|
|
138
|
-
"node-id": /^[a-zA-Z0-9-_]
|
|
139
|
-
"flow-id": /^[a-f0-9]{16}$/,
|
|
140
|
-
"topic-path": (t) => /^[a-zA-Z0-9/_-]+$/.test(t)
|
|
138
|
+
"node-id": /^[a-zA-Z0-9-_]+$/
|
|
141
139
|
}
|
|
142
140
|
});
|
|
143
|
-
function x(
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
function x(r, e) {
|
|
142
|
+
const t = e == null ? void 0 : e.properties;
|
|
143
|
+
if (!t) return r;
|
|
144
|
+
const o = {
|
|
145
|
+
type: "object",
|
|
146
|
+
properties: t,
|
|
147
|
+
// Propagate `required` so required credentials are actually enforced
|
|
148
|
+
// (previously they never were, even alongside a config schema).
|
|
149
|
+
...e != null && e.required ? { required: e.required } : {}
|
|
150
|
+
};
|
|
151
|
+
return r ? {
|
|
152
|
+
...r,
|
|
146
153
|
properties: {
|
|
147
|
-
...
|
|
148
|
-
credentials:
|
|
149
|
-
type: "object",
|
|
150
|
-
properties: e.properties
|
|
151
|
-
}
|
|
154
|
+
...r.properties,
|
|
155
|
+
credentials: o
|
|
152
156
|
}
|
|
153
|
-
} :
|
|
157
|
+
} : {
|
|
158
|
+
type: "object",
|
|
159
|
+
properties: { credentials: o },
|
|
160
|
+
additionalProperties: !0
|
|
161
|
+
};
|
|
154
162
|
}
|
|
155
|
-
function K(
|
|
156
|
-
const
|
|
157
|
-
cacheKey: `node-schema-${
|
|
163
|
+
function K(r, e) {
|
|
164
|
+
const t = V.validate(r, e, {
|
|
165
|
+
cacheKey: `node-schema-${r.type}`
|
|
158
166
|
});
|
|
159
|
-
return
|
|
167
|
+
return t.valid ? [] : t.errors ?? [];
|
|
160
168
|
}
|
|
161
|
-
function g(
|
|
162
|
-
return K(
|
|
163
|
-
var
|
|
164
|
-
return ((
|
|
169
|
+
function g(r, e) {
|
|
170
|
+
return K(r, e).filter((t) => {
|
|
171
|
+
var n;
|
|
172
|
+
return ((n = t.parentSchema) == null ? void 0 : n.format) !== "password" ? !0 : P.get(r, t.instancePath) !== "__PWD__";
|
|
165
173
|
}).reduce(
|
|
166
|
-
(
|
|
174
|
+
(t, o) => {
|
|
167
175
|
var i;
|
|
168
|
-
let
|
|
169
|
-
o.keyword === "required" && ((i = o.params) != null && i.missingProperty) && (
|
|
170
|
-
const
|
|
171
|
-
return
|
|
176
|
+
let n = o.instancePath;
|
|
177
|
+
o.keyword === "required" && ((i = o.params) != null && i.missingProperty) && (n = `${n}/${o.params.missingProperty}`);
|
|
178
|
+
const a = `node${n.replaceAll("/", ".")}`;
|
|
179
|
+
return t[a] = o.message ?? "Invalid", t;
|
|
172
180
|
},
|
|
173
181
|
{}
|
|
174
182
|
);
|
|
175
183
|
}
|
|
176
184
|
function B() {
|
|
177
|
-
const
|
|
178
|
-
if (!
|
|
185
|
+
const r = l("__nrg_form_node"), e = l("__nrg_form_schema"), t = l("__nrg_form_errors");
|
|
186
|
+
if (!r)
|
|
179
187
|
throw new Error(
|
|
180
188
|
"useFormNode() must be called inside a form component mounted by NRG."
|
|
181
189
|
);
|
|
182
190
|
return {
|
|
183
|
-
node:
|
|
191
|
+
node: r,
|
|
184
192
|
schema: e,
|
|
185
|
-
errors:
|
|
193
|
+
errors: t
|
|
186
194
|
};
|
|
187
195
|
}
|
|
188
|
-
let
|
|
189
|
-
function H(
|
|
190
|
-
var
|
|
191
|
-
const e = "type" in
|
|
192
|
-
id: `test-${
|
|
196
|
+
let j = 0;
|
|
197
|
+
function H(r = {}) {
|
|
198
|
+
var h;
|
|
199
|
+
const e = "type" in r || "configs" in r || "configSchema" in r || "credentialsSchema" in r || "nodes" in r ? r : { configs: r }, t = e.type ? (h = C()) == null ? void 0 : h[e.type] : void 0, o = e.configSchema ?? (t == null ? void 0 : t.configSchema), n = e.credentialsSchema ?? (t == null ? void 0 : t.credentialsSchema), a = _({
|
|
200
|
+
id: `test-${j}`,
|
|
193
201
|
// Unique type per node: validateForm caches compiled schemas by
|
|
194
202
|
// `node-schema-${subject.type}`, so a shared type would silently reuse
|
|
195
203
|
// the first schema for every later createNode call in the same file.
|
|
196
|
-
type: `test-node-${
|
|
204
|
+
type: `test-node-${j++}`,
|
|
197
205
|
changed: !1,
|
|
198
206
|
_def: { outputs: 1 },
|
|
199
207
|
_: (c) => c,
|
|
200
208
|
...e.configs,
|
|
201
209
|
credentials: { ...e.credentials }
|
|
202
|
-
}), i = x(o,
|
|
210
|
+
}), i = x(o, n);
|
|
203
211
|
let d;
|
|
204
212
|
if (i) {
|
|
205
|
-
const { $id: c, ...
|
|
206
|
-
d =
|
|
213
|
+
const { $id: c, ...f } = i;
|
|
214
|
+
d = f;
|
|
207
215
|
}
|
|
208
|
-
const
|
|
209
|
-
|
|
216
|
+
const m = q();
|
|
217
|
+
T(m), m.nodes.clear();
|
|
210
218
|
for (const c of e.nodes ?? [])
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
d ? g(
|
|
219
|
+
m.nodes.add(c);
|
|
220
|
+
const u = _(
|
|
221
|
+
d ? g(a, d) : {}
|
|
214
222
|
);
|
|
215
|
-
return d &&
|
|
216
|
-
|
|
223
|
+
return d && F(
|
|
224
|
+
a,
|
|
217
225
|
() => {
|
|
218
|
-
const c = g(
|
|
219
|
-
Object.keys(
|
|
226
|
+
const c = g(a, d);
|
|
227
|
+
Object.keys(u).forEach((f) => delete u[f]), Object.assign(u, c);
|
|
220
228
|
},
|
|
221
229
|
{ deep: !0 }
|
|
222
|
-
), { node:
|
|
223
|
-
__nrg_form_node:
|
|
230
|
+
), { node: a, errors: u, RED: m, provide: {
|
|
231
|
+
__nrg_form_node: a,
|
|
224
232
|
__nrg_form_schema: d ?? {},
|
|
225
|
-
__nrg_form_errors:
|
|
233
|
+
__nrg_form_errors: u
|
|
226
234
|
} };
|
|
227
235
|
}
|
|
228
|
-
function
|
|
236
|
+
function C() {
|
|
229
237
|
try {
|
|
230
|
-
return
|
|
238
|
+
return b("__nrg_schemas");
|
|
231
239
|
} catch {
|
|
232
240
|
return;
|
|
233
241
|
}
|
|
234
242
|
}
|
|
235
|
-
function s(
|
|
236
|
-
y.isMockFunction(
|
|
243
|
+
function s(r, e) {
|
|
244
|
+
y.isMockFunction(r[e]) || y.spyOn(r, e);
|
|
237
245
|
}
|
|
238
|
-
function
|
|
239
|
-
s(
|
|
246
|
+
function T(r) {
|
|
247
|
+
s(r, "_"), s(r, "notify"), s(r.editor, "createEditor"), s(r.editor, "prepareConfigNodeSelect"), s(r.editor, "validateNode"), s(r.tray, "show"), s(r.tray, "close"), s(r.popover, "tooltip"), s(r.popover, "create"), s(r.nodes, "registerType"), s(r.nodes, "node"), s(r.nodes, "add"), s(r.nodes, "remove"), s(r.nodes, "getType"), s(r.nodes, "dirty"), s(r.events, "on"), s(r.events, "off"), s(r.events, "emit"), s(r.comms, "subscribe"), s(r.comms, "unsubscribe");
|
|
240
248
|
}
|
|
241
|
-
function
|
|
249
|
+
function q() {
|
|
242
250
|
return window.RED;
|
|
243
251
|
}
|
|
244
252
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.nrg-label[data-v-864b02f2]{display:inline-block;width:100%;margin-bottom:4px;cursor:default}.nrg-label i[data-v-864b02f2]{margin-right:5px}.nrg-required[data-v-864b02f2]{color:var(--red-ui-text-color-error);margin-left:2px}.editor-wrapper[data-v-ea93e881]{position:relative}.expand-button[data-v-ea93e881]{position:absolute;top:-23px;right:0;z-index:10;transition:color .3s ease;cursor:pointer}.nrg-toggle-wrapper[data-v-
|
|
1
|
+
.nrg-label[data-v-864b02f2]{display:inline-block;width:100%;margin-bottom:4px;cursor:default}.nrg-label i[data-v-864b02f2]{margin-right:5px}.nrg-required[data-v-864b02f2]{color:var(--red-ui-text-color-error);margin-left:2px}.editor-wrapper[data-v-ea93e881]{position:relative}.expand-button[data-v-ea93e881]{position:absolute;top:-23px;right:0;z-index:10;transition:color .3s ease;cursor:pointer}.nrg-toggle-wrapper[data-v-4657f355]{display:inline-flex;align-items:center}.nrg-toggle[data-v-4657f355]{position:relative;display:inline-flex!important;flex-direction:column;align-items:flex-start;cursor:pointer;gap:4px;-webkit-user-select:none;user-select:none}.nrg-toggle__input[data-v-4657f355]{position:absolute;opacity:0;width:0;height:0}.nrg-toggle__slider[data-v-4657f355]{position:relative;display:inline-block;width:36px;min-width:36px;height:20px;background-color:var(--red-ui-secondary-border-color, #ccc);border-radius:10px;transition:background-color .2s ease}.nrg-toggle__slider[data-v-4657f355]:after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;background-color:#fff;border-radius:50%;transition:transform .2s ease}.nrg-toggle--checked .nrg-toggle__slider[data-v-4657f355]{background-color:var(--red-ui-text-color-link, #0070d2)}.nrg-toggle--checked .nrg-toggle__slider[data-v-4657f355]:after{transform:translate(16px)}.nrg-toggle__label[data-v-4657f355]{cursor:default;white-space:nowrap}.nrg-toggle__label i[data-v-4657f355]{margin-right:2px}
|