@reformer/renderer-json 8.0.0 → 9.0.0-beta.1
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 +87 -0
- package/dist/converter/json-to-render-schema.test.d.ts +1 -0
- package/dist/index-Bu5XPCQ7.js +41 -0
- package/dist/index.js +102 -88
- package/dist/schema/form-schema.schema.json.d.ts +8 -5
- package/dist/schema/index.d.ts +7 -3
- package/dist/validate.js +665 -648
- package/llms.txt +1929 -0
- package/package.json +3 -2
- package/dist/index-BZLcW0SX.js +0 -42
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @reformer/renderer-json
|
|
2
|
+
|
|
3
|
+
Render [`@reformer/core`](https://www.npmjs.com/package/@reformer/core) forms from a **JSON schema**.
|
|
4
|
+
Field bindings, components and data sources are expressed as string operators
|
|
5
|
+
(`$model(...)`, `$component(...)`, `$dataSource(...)`), so an entire form can be described as data and
|
|
6
|
+
rendered through a component registry — no per-field React code.
|
|
7
|
+
|
|
8
|
+
## Documentation
|
|
9
|
+
|
|
10
|
+
Full documentation is available at [https://alexandrbukhtatyy.github.io/ReFormer/](https://alexandrbukhtatyy.github.io/ReFormer/)
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- Describe forms declaratively as JSON (`JsonFormSchema`)
|
|
15
|
+
- String operators bind schema leaves to a reactive `FormModel` and to registered components
|
|
16
|
+
- Component registry (`defineRegistry`) maps operator names to your React components
|
|
17
|
+
- Optional schema validation against a meta-schema (ajv, loaded dynamically — dev only)
|
|
18
|
+
- TypeScript support, tree-shakable exports
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @reformer/renderer-json @reformer/core @reformer/renderer-react
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`@reformer/ui-kit` is an optional peer — use it (or your own components) to populate the registry.
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { useMemo } from 'react';
|
|
32
|
+
import { createModel } from '@reformer/core';
|
|
33
|
+
import { Input, Box, FormField } from '@reformer/ui-kit';
|
|
34
|
+
import {
|
|
35
|
+
JsonFormRenderer,
|
|
36
|
+
JsonRendererProvider,
|
|
37
|
+
defineRegistry,
|
|
38
|
+
FIELD_WRAPPER,
|
|
39
|
+
type JsonFormSchema,
|
|
40
|
+
} from '@reformer/renderer-json';
|
|
41
|
+
|
|
42
|
+
// Bindings are string operators: '$model(...)', '$component(...)', '$dataSource(...)'.
|
|
43
|
+
const schema: JsonFormSchema = {
|
|
44
|
+
version: '1.0',
|
|
45
|
+
root: {
|
|
46
|
+
component: '$component(Box)',
|
|
47
|
+
children: [
|
|
48
|
+
{
|
|
49
|
+
value: '$model(email)',
|
|
50
|
+
component: '$component(Input)',
|
|
51
|
+
componentProps: { label: 'Email' },
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type MyForm = { email: string };
|
|
58
|
+
|
|
59
|
+
export function MyFormPage() {
|
|
60
|
+
// M1: the model is the source of truth; schema leaves bind to its signals.
|
|
61
|
+
const model = useMemo(() => createModel<MyForm>({ email: '' }), []);
|
|
62
|
+
const registry = useMemo(
|
|
63
|
+
() =>
|
|
64
|
+
defineRegistry((reg) => {
|
|
65
|
+
reg.component('Input', Input);
|
|
66
|
+
reg.component('Box', Box);
|
|
67
|
+
reg.component(FIELD_WRAPPER, FormField); // system field wrapper
|
|
68
|
+
}),
|
|
69
|
+
[]
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// The model is provided through the provider (settings.model), not as a renderer prop.
|
|
73
|
+
return (
|
|
74
|
+
<JsonRendererProvider settings={{ registry, model }}>
|
|
75
|
+
<JsonFormRenderer<MyForm> schema={schema} validate={import.meta.env.DEV} />
|
|
76
|
+
</JsonRendererProvider>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`JsonFormRenderer` accepts only `{ schema, renderBehavior?, onSchemaReady?, validate? }`. The
|
|
82
|
+
`FormModel` is supplied via `JsonRendererProvider` settings (`model`); schema leaves are bound to its
|
|
83
|
+
signals by the built-in converter.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const s = /^\$(model|component|dataSource)\((.+)\)$/;
|
|
2
|
+
function n(e) {
|
|
3
|
+
if (typeof e != "string") return null;
|
|
4
|
+
const t = s.exec(e);
|
|
5
|
+
return t ? { op: t[1], arg: t[2] } : null;
|
|
6
|
+
}
|
|
7
|
+
const $ = (e) => n(e)?.op === "model", g = (e) => n(e)?.op === "component", b = (e) => n(e)?.op === "dataSource", p = "http://json-schema.org/draft-07/schema#", c = "https://reformer.dev/schemas/form-schema.schema.json", m = "ReFormer JSON form schema (M1, string-operator DSL)", d = "Base meta-schema: validates node structure + operator string syntax ($model/$component/$dataSource). Component-name enum is tightened per-app via buildFormSchemaMetaSchema; $dataSource names and $model paths are checked outside this schema.", l = "object", f = ["root"], u = !1, h = { $schema: { type: "string" }, version: { type: "string" }, root: { $ref: "#/definitions/node" } }, y = { modelOp: { type: "string", pattern: "^\\$model\\(.+\\)$", description: 'Model binding: "$model(path)" — path resolved at runtime (not validated here).' }, componentOp: { type: "string", pattern: "^\\$component\\(.+\\)$", description: 'Registry component: "$component(Name)". Name is tightened to a registry enum by buildFormSchemaMetaSchema.' }, node: { $comment: "Discriminated by which operator key is present (array→value→component), mirroring the isArrayNode/isFieldNode/isContainerNode runtime guards. Using oneOf here made ajv (allErrors) report failures against all three branches for any single mistake, burying the real cause; if/then/else surfaces only the relevant branch's errors.", if: { type: "object", required: ["array"] }, then: { $ref: "#/definitions/arrayNode" }, else: { if: { type: "object", required: ["value"] }, then: { $ref: "#/definitions/fieldNode" }, else: { $ref: "#/definitions/containerNode" } } }, fieldNode: { type: "object", required: ["value"], additionalProperties: !1, properties: { selector: { type: "string" }, value: { $ref: "#/definitions/modelOp" }, component: { $ref: "#/definitions/componentOp" }, componentProps: { type: "object" }, wrapper: { $ref: "#/definitions/node" } } }, arrayNode: { type: "object", required: ["array", "item"], additionalProperties: !1, properties: { selector: { type: "string" }, array: { $ref: "#/definitions/modelOp" }, item: { type: "object", required: ["$template"], additionalProperties: !1, properties: { $template: { $ref: "#/definitions/node" } } }, initialValue: { type: "object" }, componentProps: { type: "object" } } }, containerNode: { type: "object", required: ["component"], additionalProperties: !1, properties: { selector: { type: "string" }, component: { $ref: "#/definitions/componentOp" }, componentProps: { type: "object" }, children: { type: "array", items: { $ref: "#/definitions/node" } } } } }, i = {
|
|
8
|
+
$schema: p,
|
|
9
|
+
$id: c,
|
|
10
|
+
title: m,
|
|
11
|
+
description: d,
|
|
12
|
+
type: l,
|
|
13
|
+
required: f,
|
|
14
|
+
additionalProperties: u,
|
|
15
|
+
properties: h,
|
|
16
|
+
definitions: y
|
|
17
|
+
}, S = i;
|
|
18
|
+
function N(e) {
|
|
19
|
+
return e.names().filter((t) => e.get(t)?.type === "component");
|
|
20
|
+
}
|
|
21
|
+
function O(e) {
|
|
22
|
+
return e.names().filter((t) => e.get(t)?.type === "dataSource");
|
|
23
|
+
}
|
|
24
|
+
function j(e) {
|
|
25
|
+
const t = JSON.parse(JSON.stringify(i)), o = e?.componentNames;
|
|
26
|
+
if (o && o.length > 0) {
|
|
27
|
+
const r = t.definitions.componentOp;
|
|
28
|
+
delete r.pattern, r.enum = o.map((a) => `$component(${a})`);
|
|
29
|
+
}
|
|
30
|
+
return t;
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
g as a,
|
|
34
|
+
b,
|
|
35
|
+
j as c,
|
|
36
|
+
O as d,
|
|
37
|
+
S as f,
|
|
38
|
+
N as g,
|
|
39
|
+
$ as i,
|
|
40
|
+
n as p
|
|
41
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useContext as
|
|
3
|
-
import { createRenderSchema as
|
|
4
|
-
import { i as
|
|
5
|
-
import { c as rr, f as er, g as tr, d as nr } from "./index-
|
|
6
|
-
class
|
|
1
|
+
import { jsx as m, jsxs as R } from "react/jsx-runtime";
|
|
2
|
+
import { useContext as $, createContext as O, useMemo as w, useState as F, useEffect as j } from "react";
|
|
3
|
+
import { createRenderSchema as k, FormRenderer as v } from "@reformer/renderer-react";
|
|
4
|
+
import { i as p, a as E, p as d, b as A } from "./index-Bu5XPCQ7.js";
|
|
5
|
+
import { c as rr, f as er, g as tr, d as nr } from "./index-Bu5XPCQ7.js";
|
|
6
|
+
class u {
|
|
7
7
|
own = /* @__PURE__ */ new Map();
|
|
8
8
|
parent = null;
|
|
9
9
|
get(e) {
|
|
@@ -25,52 +25,58 @@ class h {
|
|
|
25
25
|
this.own.has(e) && console.warn(`[ComponentRegistry] Overwriting entry: ${e}`), this.own.set(e, t);
|
|
26
26
|
}
|
|
27
27
|
static withParent(e, t) {
|
|
28
|
-
const n = new
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const n = new u(), o = (s) => {
|
|
29
|
+
if (s instanceof u)
|
|
30
|
+
s.own.forEach((i, a) => n.own.set(a, i));
|
|
31
|
+
else
|
|
32
|
+
for (const i of s.names()) {
|
|
33
|
+
const a = s.get(i);
|
|
34
|
+
a && n.own.set(i, a);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
return e instanceof u ? n.parent = e : o(e), o(t), n;
|
|
32
38
|
}
|
|
33
39
|
}
|
|
34
40
|
function K(r) {
|
|
35
|
-
const e = new
|
|
41
|
+
const e = new u();
|
|
36
42
|
return r({
|
|
37
|
-
component(n, o,
|
|
38
|
-
e._set(n, { component: o, type: "component", description:
|
|
43
|
+
component(n, o, s) {
|
|
44
|
+
e._set(n, { component: o, type: "component", description: s });
|
|
39
45
|
},
|
|
40
|
-
dataSource(n, o,
|
|
41
|
-
e._set(n, { component: o, type: "dataSource", description:
|
|
46
|
+
dataSource(n, o, s) {
|
|
47
|
+
e._set(n, { component: o, type: "dataSource", description: s });
|
|
42
48
|
}
|
|
43
49
|
}), e;
|
|
44
50
|
}
|
|
45
|
-
const
|
|
51
|
+
const C = "$fieldWrapper", P = O({});
|
|
46
52
|
function Q({ settings: r, children: e }) {
|
|
47
|
-
const t =
|
|
48
|
-
const
|
|
53
|
+
const t = $(P), n = w(() => t.registry && r.registry ? u.withParent(t.registry, r.registry) : r.registry ?? t.registry, [t.registry, r.registry]), o = w(() => {
|
|
54
|
+
const s = n?.get(C)?.component;
|
|
49
55
|
return {
|
|
50
56
|
...t,
|
|
51
57
|
...r,
|
|
52
58
|
registry: n,
|
|
53
|
-
fieldWrapper: r.fieldWrapper ??
|
|
59
|
+
fieldWrapper: r.fieldWrapper ?? s ?? t.fieldWrapper
|
|
54
60
|
};
|
|
55
61
|
}, [t, r, n]);
|
|
56
|
-
return /* @__PURE__ */
|
|
62
|
+
return /* @__PURE__ */ m(P.Provider, { value: o, children: e });
|
|
57
63
|
}
|
|
58
|
-
function
|
|
59
|
-
return
|
|
64
|
+
function W() {
|
|
65
|
+
return $(P);
|
|
60
66
|
}
|
|
61
|
-
function
|
|
67
|
+
function J(r) {
|
|
62
68
|
const e = r;
|
|
63
|
-
return
|
|
69
|
+
return p(e.array) && typeof e.item == "object" && e.item !== null && "$template" in e.item;
|
|
64
70
|
}
|
|
65
|
-
function
|
|
66
|
-
return
|
|
71
|
+
function M(r) {
|
|
72
|
+
return p(r.value);
|
|
67
73
|
}
|
|
68
|
-
function
|
|
69
|
-
return
|
|
74
|
+
function D(r) {
|
|
75
|
+
return E(r.component) && !M(r) && !J(r);
|
|
70
76
|
}
|
|
71
|
-
function
|
|
77
|
+
function y(r, e) {
|
|
72
78
|
if (!r) return;
|
|
73
|
-
const t =
|
|
79
|
+
const t = d(r)?.arg;
|
|
74
80
|
if (!t) throw new Error(`Invalid $component operator: "${r}"`);
|
|
75
81
|
const n = e.get(t);
|
|
76
82
|
if (!n)
|
|
@@ -87,28 +93,30 @@ function L(r, e) {
|
|
|
87
93
|
throw new Error(
|
|
88
94
|
`Data source "${r}" not found in registry. Available: ${e.names().join(", ")}`
|
|
89
95
|
);
|
|
96
|
+
if (t.type !== "dataSource")
|
|
97
|
+
throw new Error(`Entry "${r}" is a '${t.type}' and cannot be used as $dataSource(...)`);
|
|
90
98
|
return t.component;
|
|
91
99
|
}
|
|
92
|
-
function
|
|
100
|
+
function V(r, e) {
|
|
93
101
|
return e.split(".").reduce((t, n) => t == null ? t : t[n], r);
|
|
94
102
|
}
|
|
95
|
-
function
|
|
103
|
+
function q(r) {
|
|
96
104
|
if (r === null || typeof r != "object") return !1;
|
|
97
105
|
const e = r;
|
|
98
|
-
return
|
|
106
|
+
return p(e.value) || p(e.array) || E(e.component);
|
|
99
107
|
}
|
|
100
|
-
function
|
|
108
|
+
function T(r) {
|
|
101
109
|
return r == null ? r : JSON.parse(JSON.stringify(r));
|
|
102
110
|
}
|
|
103
111
|
function b(r, e, t) {
|
|
104
|
-
if (A(r)) return L(
|
|
105
|
-
if (
|
|
106
|
-
if (
|
|
107
|
-
if (
|
|
112
|
+
if (A(r)) return L(d(r).arg, t);
|
|
113
|
+
if (E(r)) return y(r, t);
|
|
114
|
+
if (p(r)) return e.signalAt(d(r).arg);
|
|
115
|
+
if (q(r)) return h(r, e, t);
|
|
108
116
|
if (Array.isArray(r)) return r.map((n) => b(n, e, t));
|
|
109
117
|
if (r !== null && typeof r == "object") {
|
|
110
118
|
const n = r, o = {};
|
|
111
|
-
for (const
|
|
119
|
+
for (const s of Object.keys(n)) o[s] = b(n[s], e, t);
|
|
112
120
|
return o;
|
|
113
121
|
}
|
|
114
122
|
return r;
|
|
@@ -119,43 +127,45 @@ function S(r, e, t) {
|
|
|
119
127
|
for (const o of Object.keys(r)) n[o] = b(r[o], e, t);
|
|
120
128
|
return n;
|
|
121
129
|
}
|
|
122
|
-
function
|
|
123
|
-
if (
|
|
124
|
-
const n =
|
|
130
|
+
function h(r, e, t) {
|
|
131
|
+
if (J(r)) {
|
|
132
|
+
const n = V(e, d(r.array).arg), o = r.item.$template, s = r.initialValue;
|
|
125
133
|
return {
|
|
126
134
|
...r.selector ? { selector: r.selector } : {},
|
|
127
135
|
array: n,
|
|
128
|
-
initialValue: () =>
|
|
129
|
-
item: (
|
|
136
|
+
initialValue: () => s ? T(s) : {},
|
|
137
|
+
item: (i) => h(o, i, t),
|
|
130
138
|
componentProps: S(r.componentProps, e, t)
|
|
131
139
|
};
|
|
132
140
|
}
|
|
133
|
-
if (
|
|
134
|
-
const n =
|
|
135
|
-
|
|
141
|
+
if (M(r)) {
|
|
142
|
+
const n = d(r.value).arg, o = e.signalAt(n);
|
|
143
|
+
!o && typeof console < "u" && console.warn(`[JsonRenderer/M1] No model signal for "${n}".`);
|
|
144
|
+
const s = S(r.componentProps, e, t), i = r.wrapper ? y(r.wrapper.component, t) : void 0;
|
|
145
|
+
return {
|
|
136
146
|
...r.selector ? { selector: r.selector } : {},
|
|
137
147
|
value: o,
|
|
138
|
-
component:
|
|
139
|
-
componentProps:
|
|
148
|
+
component: y(r.component, t),
|
|
149
|
+
componentProps: i ? { ...s ?? {}, fieldWrapper: i } : s
|
|
140
150
|
};
|
|
141
151
|
}
|
|
142
|
-
if (
|
|
152
|
+
if (D(r))
|
|
143
153
|
return {
|
|
144
154
|
...r.selector ? { selector: r.selector } : {},
|
|
145
|
-
component:
|
|
155
|
+
component: y(r.component, t),
|
|
146
156
|
componentProps: S(r.componentProps, e, t),
|
|
147
|
-
children: r.children?.map((n) =>
|
|
157
|
+
children: r.children?.map((n) => h(n, e, t))
|
|
148
158
|
};
|
|
149
159
|
throw new Error(`Invalid JSON node (M1): ${JSON.stringify(r)}`);
|
|
150
160
|
}
|
|
151
161
|
function U(r, e, t) {
|
|
152
|
-
return
|
|
162
|
+
return h(r.root, t, e);
|
|
153
163
|
}
|
|
154
|
-
function
|
|
155
|
-
return () =>
|
|
164
|
+
function z(r, e, t) {
|
|
165
|
+
return () => h(r.root, t, e);
|
|
156
166
|
}
|
|
157
|
-
function
|
|
158
|
-
return /* @__PURE__ */
|
|
167
|
+
function I({ errors: r }) {
|
|
168
|
+
return /* @__PURE__ */ R(
|
|
159
169
|
"div",
|
|
160
170
|
{
|
|
161
171
|
role: "alert",
|
|
@@ -169,12 +179,12 @@ function q({ errors: r }) {
|
|
|
169
179
|
font: "14px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace"
|
|
170
180
|
},
|
|
171
181
|
children: [
|
|
172
|
-
/* @__PURE__ */
|
|
182
|
+
/* @__PURE__ */ R("strong", { style: { display: "block", marginBottom: 8, fontSize: 15 }, children: [
|
|
173
183
|
"Невалидная JSON-схема формы (",
|
|
174
184
|
r.length,
|
|
175
185
|
")"
|
|
176
186
|
] }),
|
|
177
|
-
/* @__PURE__ */
|
|
187
|
+
/* @__PURE__ */ m("ul", { style: { margin: 0, paddingLeft: 20 }, children: r.map((e, t) => /* @__PURE__ */ m("li", { style: { marginBottom: 4 }, children: e }, t)) })
|
|
178
188
|
]
|
|
179
189
|
}
|
|
180
190
|
);
|
|
@@ -185,56 +195,60 @@ function X({
|
|
|
185
195
|
onSchemaReady: t,
|
|
186
196
|
validate: n = !1
|
|
187
197
|
}) {
|
|
188
|
-
const { registry: o, model:
|
|
198
|
+
const { registry: o, model: s, ...i } = W(), [a, g] = F(
|
|
189
199
|
n ? void 0 : null
|
|
190
200
|
);
|
|
191
|
-
|
|
201
|
+
j(() => {
|
|
192
202
|
if (!n) {
|
|
193
|
-
|
|
203
|
+
g(null);
|
|
194
204
|
return;
|
|
195
205
|
}
|
|
196
|
-
let
|
|
197
|
-
return
|
|
198
|
-
if (
|
|
199
|
-
const { valid:
|
|
200
|
-
|
|
201
|
-
}).catch((
|
|
202
|
-
|
|
206
|
+
let f = !1;
|
|
207
|
+
return g(void 0), import("./validate.js").then(({ validateFormSchema: c }) => {
|
|
208
|
+
if (f) return;
|
|
209
|
+
const { valid: N, errors: x } = c(r, { registry: o });
|
|
210
|
+
g(N ? null : x);
|
|
211
|
+
}).catch((c) => {
|
|
212
|
+
f || g([`Schema validator failed to load: ${String(c)}`]);
|
|
203
213
|
}), () => {
|
|
204
|
-
|
|
214
|
+
f = !0;
|
|
205
215
|
};
|
|
206
216
|
}, [n, r, o]);
|
|
207
|
-
const
|
|
208
|
-
if (!
|
|
217
|
+
const l = w(() => {
|
|
218
|
+
if (!s)
|
|
209
219
|
throw new Error(
|
|
210
220
|
"JsonFormRenderer: settings.model is required (M1). Pass the FormModel via JsonRendererProvider."
|
|
211
221
|
);
|
|
212
222
|
if (a !== null) return null;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
223
|
+
if (!o)
|
|
224
|
+
throw new Error(
|
|
225
|
+
"JsonFormRenderer: settings.registry is required. Pass a ComponentRegistry via JsonRendererProvider."
|
|
226
|
+
);
|
|
227
|
+
const f = z(r, o, s), c = k(f);
|
|
228
|
+
return e && e(c), c;
|
|
229
|
+
}, [r, o, e, s, a]);
|
|
230
|
+
return w(() => {
|
|
231
|
+
l && t && t(l);
|
|
232
|
+
}, [l]), a && a.length > 0 ? /* @__PURE__ */ m(I, { errors: a }) : l ? /* @__PURE__ */ m(v, { render: l, settings: i }) : null;
|
|
219
233
|
}
|
|
220
234
|
export {
|
|
221
|
-
|
|
235
|
+
C as FIELD_WRAPPER,
|
|
222
236
|
X as JsonFormRenderer,
|
|
223
237
|
Q as JsonRendererProvider,
|
|
224
|
-
|
|
238
|
+
I as SchemaErrorPanel,
|
|
225
239
|
rr as buildFormSchemaMetaSchema,
|
|
226
240
|
U as convertJsonToM1Tree,
|
|
227
|
-
|
|
241
|
+
z as createRenderSchemaFromJsonM1,
|
|
228
242
|
K as defineRegistry,
|
|
229
243
|
er as formSchemaMetaSchema,
|
|
230
244
|
tr as getComponentNames,
|
|
231
245
|
nr as getDataSourceNames,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
246
|
+
J as isArrayNode,
|
|
247
|
+
E as isComponentOp,
|
|
248
|
+
D as isContainerNode,
|
|
235
249
|
A as isDataSourceOp,
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
250
|
+
M as isFieldNode,
|
|
251
|
+
p as isModelOp,
|
|
252
|
+
d as parseOperator,
|
|
253
|
+
W as useJsonRendererSettings
|
|
240
254
|
};
|
|
@@ -23,11 +23,14 @@ declare const _default: {
|
|
|
23
23
|
"description": "Registry component: \"$component(Name)\". Name is tightened to a registry enum by buildFormSchemaMetaSchema."
|
|
24
24
|
},
|
|
25
25
|
"node": {
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
"$comment": "Discriminated by which operator key is present (array→value→component), mirroring the isArrayNode/isFieldNode/isContainerNode runtime guards. Using oneOf here made ajv (allErrors) report failures against all three branches for any single mistake, burying the real cause; if/then/else surfaces only the relevant branch's errors.",
|
|
27
|
+
"if": { "type": "object", "required": ["array"] },
|
|
28
|
+
"then": { "$ref": "#/definitions/arrayNode" },
|
|
29
|
+
"else": {
|
|
30
|
+
"if": { "type": "object", "required": ["value"] },
|
|
31
|
+
"then": { "$ref": "#/definitions/fieldNode" },
|
|
32
|
+
"else": { "$ref": "#/definitions/containerNode" }
|
|
33
|
+
}
|
|
31
34
|
},
|
|
32
35
|
"fieldNode": {
|
|
33
36
|
"type": "object",
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -38,9 +38,13 @@ export declare function getComponentNames(registry: ComponentRegistry): string[]
|
|
|
38
38
|
*/
|
|
39
39
|
export declare function getDataSourceNames(registry: ComponentRegistry): string[];
|
|
40
40
|
/**
|
|
41
|
-
* Конкретная мета-схема: базовая + (если заданы `componentNames`) сужение
|
|
42
|
-
*
|
|
43
|
-
* (вложены в произвольный componentProps) — их проверяет рекурсивный обход
|
|
41
|
+
* Конкретная мета-схема: базовая + (если заданы `componentNames`) сужение `$component(...)` до
|
|
42
|
+
* enum допустимых значений (`["$component(Input)", "$component(Select)", …]`). `$dataSource`-имена
|
|
43
|
+
* JSON Schema'й не покрыть (вложены в произвольный componentProps) — их проверяет рекурсивный обход
|
|
44
|
+
* в `validateFormSchema`.
|
|
45
|
+
*
|
|
46
|
+
* enum, а не regex-`pattern`: ajv перечисляет допустимые имена в тексте ошибки, IDE даёт
|
|
47
|
+
* автодополнение по значениям, а имена не нужно экранировать под regex (напр. `$fieldWrapper`).
|
|
44
48
|
*
|
|
45
49
|
* @example
|
|
46
50
|
* ```ts
|