@reformer/renderer-json 5.0.2 → 6.1.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/dist/components/json-form-renderer.d.ts +13 -4
- package/dist/components/schema-error-panel.d.ts +8 -0
- package/dist/context/json-renderer-context.d.ts +6 -0
- package/dist/converter/json-to-render-schema.d.ts +11 -27
- package/dist/index-CI7YxPq2.js +45 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.js +195 -164
- package/dist/operators.d.ts +46 -0
- package/dist/schema/form-schema.schema.json.d.ts +81 -0
- package/dist/schema/index.d.ts +20 -0
- package/dist/types/json-schema.d.ts +59 -108
- package/dist/validate.d.ts +23 -0
- package/dist/validate.js +4467 -0
- package/dist/validate.test.d.ts +1 -0
- package/package.json +8 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://reformer.dev/schemas/form-schema.schema.json",
|
|
4
|
+
"title": "ReFormer JSON form schema (M1, string-operator DSL)",
|
|
5
|
+
"description": "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.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["root"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": { "type": "string" },
|
|
11
|
+
"version": { "type": "string" },
|
|
12
|
+
"root": { "$ref": "#/definitions/node" }
|
|
13
|
+
},
|
|
14
|
+
"definitions": {
|
|
15
|
+
"modelOp": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"pattern": "^\\$model\\(.+\\)$",
|
|
18
|
+
"description": "Model binding: \"$model(path)\" — path resolved at runtime (not validated here)."
|
|
19
|
+
},
|
|
20
|
+
"componentOp": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"pattern": "^\\$component\\(.+\\)$",
|
|
23
|
+
"description": "Registry component: \"$component(Name)\". Name is tightened to a registry enum by buildFormSchemaMetaSchema."
|
|
24
|
+
},
|
|
25
|
+
"node": {
|
|
26
|
+
"oneOf": [
|
|
27
|
+
{ "$ref": "#/definitions/fieldNode" },
|
|
28
|
+
{ "$ref": "#/definitions/arrayNode" },
|
|
29
|
+
{ "$ref": "#/definitions/containerNode" }
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"fieldNode": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"required": ["value"],
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"properties": {
|
|
37
|
+
"selector": { "type": "string" },
|
|
38
|
+
"value": { "$ref": "#/definitions/modelOp" },
|
|
39
|
+
"component": { "$ref": "#/definitions/componentOp" },
|
|
40
|
+
"componentProps": { "type": "object" },
|
|
41
|
+
"wrapper": { "$ref": "#/definitions/node" }
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"arrayNode": {
|
|
45
|
+
"type": "object",
|
|
46
|
+
"required": ["array", "item"],
|
|
47
|
+
"additionalProperties": false,
|
|
48
|
+
"properties": {
|
|
49
|
+
"selector": { "type": "string" },
|
|
50
|
+
"array": { "$ref": "#/definitions/modelOp" },
|
|
51
|
+
"item": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"required": ["$template"],
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"properties": {
|
|
56
|
+
"$template": { "$ref": "#/definitions/node" }
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"initialValue": { "type": "object" },
|
|
60
|
+
"componentProps": { "type": "object" }
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"containerNode": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"required": ["component"],
|
|
66
|
+
"additionalProperties": false,
|
|
67
|
+
"properties": {
|
|
68
|
+
"selector": { "type": "string" },
|
|
69
|
+
"component": { "$ref": "#/definitions/componentOp" },
|
|
70
|
+
"componentProps": { "type": "object" },
|
|
71
|
+
"children": {
|
|
72
|
+
"type": "array",
|
|
73
|
+
"items": { "$ref": "#/definitions/node" }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
;
|
|
80
|
+
|
|
81
|
+
export default _default;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ComponentRegistry } from '../registry/types';
|
|
2
|
+
/** Базовая мета-схема form-DSL (draft-07): структура + синтаксис операторов, имена не ограничены. */
|
|
3
|
+
export declare const formSchemaMetaSchema: Record<string, unknown>;
|
|
4
|
+
/** Имена компонентов реестра (`reg.field`/`reg.container`). */
|
|
5
|
+
export declare function getComponentNames(registry: ComponentRegistry): string[];
|
|
6
|
+
/** Имена registry-source (`reg.source`): options/itemLabel/константы/loading-компоненты. */
|
|
7
|
+
export declare function getSourceNames(registry: ComponentRegistry): string[];
|
|
8
|
+
/**
|
|
9
|
+
* Конкретная мета-схема: базовая + (если заданы `componentNames`) сужение паттерна `$component(...)`
|
|
10
|
+
* до enum имён (`^\$component\((Input|Select|…)\)$`). `$dataSource`-имена JSON Schema'й не покрыть
|
|
11
|
+
* (вложены в произвольный componentProps) — их проверяет рекурсивный обход в `validateFormSchema`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const schema = buildFormSchemaMetaSchema({ componentNames: getComponentNames(registry) });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildFormSchemaMetaSchema(opts?: {
|
|
19
|
+
componentNames?: string[];
|
|
20
|
+
}): Record<string, unknown>;
|
|
@@ -1,125 +1,76 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Унифицированный узел JSON-схемы
|
|
8
|
-
*
|
|
9
|
-
* Может представлять:
|
|
10
|
-
* - Поле формы (если указан `model`)
|
|
11
|
-
* - Контейнер/компонент (если указан только `component`)
|
|
12
|
-
* - Поле с кастомным компонентом (если указаны оба)
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```json
|
|
16
|
-
* // Поле формы с дефолтным компонентом
|
|
17
|
-
* { "model": "email" }
|
|
18
|
-
*
|
|
19
|
-
* // Поле с кастомным компонентом
|
|
20
|
-
* { "model": "password", "component": "InputPassword" }
|
|
21
|
-
*
|
|
22
|
-
* // Контейнер
|
|
23
|
-
* { "component": "Box", "children": [...] }
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export interface JsonNode {
|
|
27
|
-
/**
|
|
28
|
-
* Идентификатор узла для renderBehavior (hideWhen, patchProps).
|
|
29
|
-
* Необязателен — нужен только если к узлу привязано поведение.
|
|
30
|
-
*/
|
|
1
|
+
import { ModelOp, ComponentOp } from '../operators';
|
|
2
|
+
/** Лист формы: значение из модели (`$model`) + опциональный компонент (`$component`, дефолт — Input). */
|
|
3
|
+
export interface JsonFieldNode {
|
|
4
|
+
/** Id для render-behavior (hideWhen/patchProps). Опционален. */
|
|
31
5
|
selector?: string;
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*/
|
|
38
|
-
component?: string;
|
|
39
|
-
/**
|
|
40
|
-
* Путь к полю формы (модели): "email", "personalData.firstName", "addresses[0].city"
|
|
41
|
-
*
|
|
42
|
-
* Если указан — узел представляет поле формы.
|
|
43
|
-
*/
|
|
44
|
-
model?: string;
|
|
45
|
-
/**
|
|
46
|
-
* Props для компонента (className, title и т.д.)
|
|
47
|
-
*/
|
|
6
|
+
/** Привязка к сигналу модели: `'$model(personalData.lastName)'`. */
|
|
7
|
+
value: ModelOp;
|
|
8
|
+
/** Компонент поля из реестра: `'$component(Select)'`. Опционален. */
|
|
9
|
+
component?: ComponentOp;
|
|
10
|
+
/** Props компонента; значения могут содержать строки-операторы (`'$dataSource(NAME)'`) или вложенные узлы. */
|
|
48
11
|
componentProps?: Record<string, unknown>;
|
|
12
|
+
/** Обёртка поля (например, FormField). */
|
|
13
|
+
wrapper?: JsonNode;
|
|
14
|
+
}
|
|
15
|
+
/** Массив форм: данные из модели (`$model`) + шаблон элемента (`$template`). */
|
|
16
|
+
export interface JsonArrayNode {
|
|
17
|
+
/** Id для render-behavior. */
|
|
18
|
+
selector?: string;
|
|
19
|
+
/** Привязка к массиву модели: `'$model(coBorrowers)'`. */
|
|
20
|
+
array: ModelOp;
|
|
21
|
+
/** Шаблон под-схемы элемента. */
|
|
22
|
+
item: {
|
|
23
|
+
$template: JsonNode;
|
|
24
|
+
};
|
|
49
25
|
/**
|
|
50
|
-
*
|
|
26
|
+
* «Пустой» элемент для кнопки «Добавить» (литерал-объект по форме элемента).
|
|
27
|
+
* Нужен, т.к. листья шаблона несут `value: '$model(...)'`, а не литерал-дефолт.
|
|
51
28
|
*/
|
|
29
|
+
initialValue?: Record<string, unknown>;
|
|
30
|
+
/** Оформление секции массива (title/addButtonLabel/itemLabel/emptyMessage/…). */
|
|
31
|
+
componentProps?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
/** Контейнер (Box/Section/Wizard/Step/…) с дочерними узлами. */
|
|
34
|
+
export interface JsonContainerNode {
|
|
35
|
+
/** Id для render-behavior. */
|
|
36
|
+
selector?: string;
|
|
37
|
+
/** Компонент-контейнер из реестра: `'$component(Section)'`. */
|
|
38
|
+
component: ComponentOp;
|
|
39
|
+
/** Props компонента; значения могут содержать строки-операторы или вложенные узлы. */
|
|
40
|
+
componentProps?: Record<string, unknown>;
|
|
41
|
+
/** Дочерние узлы. */
|
|
52
42
|
children?: JsonNode[];
|
|
53
|
-
/**
|
|
54
|
-
* Обёртка для узла (например, fieldWrapper)
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```json
|
|
58
|
-
* {
|
|
59
|
-
* "model": "email",
|
|
60
|
-
* "wrapper": {
|
|
61
|
-
* "component": "FormField",
|
|
62
|
-
* "componentProps": { "className": "col-span-2" }
|
|
63
|
-
* }
|
|
64
|
-
* }
|
|
65
|
-
* ```
|
|
66
|
-
*/
|
|
67
|
-
wrapper?: JsonNode;
|
|
68
43
|
}
|
|
44
|
+
/** Узел JSON-схемы (M1). */
|
|
45
|
+
export type JsonNode = JsonFieldNode | JsonArrayNode | JsonContainerNode;
|
|
69
46
|
/**
|
|
70
|
-
* Корневая JSON-схема
|
|
47
|
+
* Корневая JSON-схема формы.
|
|
71
48
|
*
|
|
72
49
|
* @example
|
|
73
|
-
* ```
|
|
74
|
-
* {
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* { "model": "password", "component": "InputPassword" }
|
|
82
|
-
* ]
|
|
83
|
-
* }
|
|
84
|
-
* }
|
|
50
|
+
* ```ts
|
|
51
|
+
* const schema: JsonFormSchema = {
|
|
52
|
+
* version: '1.0',
|
|
53
|
+
* root: {
|
|
54
|
+
* component: '$component(Box)',
|
|
55
|
+
* children: [{ value: '$model(email)', component: '$component(Input)' }],
|
|
56
|
+
* },
|
|
57
|
+
* };
|
|
85
58
|
* ```
|
|
86
59
|
*/
|
|
87
60
|
export interface JsonFormSchema {
|
|
88
61
|
/**
|
|
89
|
-
*
|
|
62
|
+
* Путь к мета-схеме для IDE (VSCode подсветит структуру/синтаксис/имена `$component`).
|
|
63
|
+
* Игнорируется конвертером. Сгенерировать конкретную мета-схему: `gen-form-json-schema.ts`.
|
|
90
64
|
*/
|
|
65
|
+
$schema?: string;
|
|
66
|
+
/** Версия схемы (для миграций). */
|
|
91
67
|
version?: string;
|
|
92
|
-
/**
|
|
93
|
-
* Корневой узел схемы
|
|
94
|
-
*/
|
|
68
|
+
/** Корневой узел. */
|
|
95
69
|
root: JsonNode;
|
|
96
70
|
}
|
|
97
|
-
/**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
* @example
|
|
104
|
-
* ```typescript
|
|
105
|
-
* if (isFieldNode(node)) {
|
|
106
|
-
* // node.model гарантированно строка
|
|
107
|
-
* readField(node.model);
|
|
108
|
-
* }
|
|
109
|
-
* ```
|
|
110
|
-
*/
|
|
111
|
-
export declare function isFieldNode(node: JsonNode): boolean;
|
|
112
|
-
/**
|
|
113
|
-
* Type guard: проверяет, является ли узел контейнером (только `component`, без `model`).
|
|
114
|
-
*
|
|
115
|
-
* @param node - Узел JSON-схемы.
|
|
116
|
-
* @returns `true`, если у узла есть `component`, но нет `model`.
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* ```typescript
|
|
120
|
-
* if (isContainerNode(node)) {
|
|
121
|
-
* node.children?.forEach(walk);
|
|
122
|
-
* }
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
export declare function isContainerNode(node: JsonNode): boolean;
|
|
71
|
+
/** Type-guard: узел — массив (`array: '$model(...)'` + `item.$template`). Проверять ПЕРВЫМ. */
|
|
72
|
+
export declare function isArrayNode(node: JsonNode): node is JsonArrayNode;
|
|
73
|
+
/** Type-guard: узел — лист (`value: '$model(...)'`). */
|
|
74
|
+
export declare function isFieldNode(node: JsonNode): node is JsonFieldNode;
|
|
75
|
+
/** Type-guard: узел — контейнер (`component: '$component(...)'`, без `value`/`array`). */
|
|
76
|
+
export declare function isContainerNode(node: JsonNode): node is JsonContainerNode;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComponentRegistry } from './registry/types';
|
|
2
|
+
/** Результат валидации схемы. */
|
|
3
|
+
export interface FormSchemaValidationResult {
|
|
4
|
+
valid: boolean;
|
|
5
|
+
/** Человекочитаемые ошибки (путь + сообщение). Пусто, если валидно. */
|
|
6
|
+
errors: string[];
|
|
7
|
+
}
|
|
8
|
+
/** Опции: реестр (имена извлекаются автоматически) либо явные списки имён. */
|
|
9
|
+
export interface ValidateFormSchemaOptions {
|
|
10
|
+
registry?: ComponentRegistry;
|
|
11
|
+
componentNames?: string[];
|
|
12
|
+
sourceNames?: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Валидирует form-DSL JSON-схему. Если передан `registry`, имена компонентов/source берутся из него.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const { valid, errors } = validateFormSchema(jsonSchema, { registry });
|
|
20
|
+
* if (!valid) console.error(errors);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateFormSchema(schema: unknown, opts?: ValidateFormSchemaOptions): FormSchemaValidationResult;
|