@verbb/plugin-kit-vue 2.0.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/CHANGELOG.md +14 -0
- package/LICENSE.md +21 -0
- package/README.md +132 -0
- package/dist/app/PluginKitProvider.d.ts +92 -0
- package/dist/app/PluginKitProvider.d.ts.map +1 -0
- package/dist/app/PluginKitProvider.js +75 -0
- package/dist/app/PluginKitProvider.js.map +1 -0
- package/dist/app/configure.d.ts +29 -0
- package/dist/app/configure.d.ts.map +1 -0
- package/dist/app/configure.js +35 -0
- package/dist/app/configure.js.map +1 -0
- package/dist/app/index.d.ts +5 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +5 -0
- package/dist/app/mountShadowApp.d.ts +6 -0
- package/dist/app/mountShadowApp.d.ts.map +1 -0
- package/dist/app/mountShadowApp.js +2 -0
- package/dist/components/Button.d.ts +208 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Button.js +71 -0
- package/dist/components/Button.js.map +1 -0
- package/dist/components/ButtonGroup.d.ts +22 -0
- package/dist/components/ButtonGroup.d.ts.map +1 -0
- package/dist/components/ButtonGroup.js +19 -0
- package/dist/components/ButtonGroup.js.map +1 -0
- package/dist/components/Calendar.d.ts +9 -0
- package/dist/components/Calendar.d.ts.map +1 -0
- package/dist/components/Calendar.js +13 -0
- package/dist/components/Calendar.js.map +1 -0
- package/dist/components/Checkbox.d.ts +177 -0
- package/dist/components/Checkbox.d.ts.map +1 -0
- package/dist/components/Checkbox.js +69 -0
- package/dist/components/Checkbox.js.map +1 -0
- package/dist/components/CheckboxInput.d.ts +210 -0
- package/dist/components/CheckboxInput.d.ts.map +1 -0
- package/dist/components/CheckboxInput.js +109 -0
- package/dist/components/CheckboxInput.js.map +1 -0
- package/dist/components/CheckboxSelect.d.ts +9 -0
- package/dist/components/CheckboxSelect.d.ts.map +1 -0
- package/dist/components/CheckboxSelect.js +13 -0
- package/dist/components/CheckboxSelect.js.map +1 -0
- package/dist/components/CodeEditor.d.ts +9 -0
- package/dist/components/CodeEditor.d.ts.map +1 -0
- package/dist/components/CodeEditor.js +13 -0
- package/dist/components/CodeEditor.js.map +1 -0
- package/dist/components/ColorInput.d.ts +9 -0
- package/dist/components/ColorInput.d.ts.map +1 -0
- package/dist/components/ColorInput.js +13 -0
- package/dist/components/ColorInput.js.map +1 -0
- package/dist/components/Combobox.d.ts +9 -0
- package/dist/components/Combobox.d.ts.map +1 -0
- package/dist/components/Combobox.js +13 -0
- package/dist/components/Combobox.js.map +1 -0
- package/dist/components/ComboboxInput.d.ts +410 -0
- package/dist/components/ComboboxInput.d.ts.map +1 -0
- package/dist/components/ComboboxInput.js +174 -0
- package/dist/components/ComboboxInput.js.map +1 -0
- package/dist/components/CopyButton.d.ts +9 -0
- package/dist/components/CopyButton.d.ts.map +1 -0
- package/dist/components/CopyButton.js +13 -0
- package/dist/components/CopyButton.js.map +1 -0
- package/dist/components/DatePicker.d.ts +9 -0
- package/dist/components/DatePicker.d.ts.map +1 -0
- package/dist/components/DatePicker.js +13 -0
- package/dist/components/DatePicker.js.map +1 -0
- package/dist/components/Dialog.d.ts +9 -0
- package/dist/components/Dialog.d.ts.map +1 -0
- package/dist/components/Dialog.js +13 -0
- package/dist/components/Dialog.js.map +1 -0
- package/dist/components/DropdownMenu.d.ts +29 -0
- package/dist/components/DropdownMenu.d.ts.map +1 -0
- package/dist/components/DropdownMenu.js +22 -0
- package/dist/components/DropdownMenu.js.map +1 -0
- package/dist/components/EditableTable.d.ts +9 -0
- package/dist/components/EditableTable.d.ts.map +1 -0
- package/dist/components/EditableTable.js +13 -0
- package/dist/components/EditableTable.js.map +1 -0
- package/dist/components/Field.d.ts +9 -0
- package/dist/components/Field.d.ts.map +1 -0
- package/dist/components/Field.js +13 -0
- package/dist/components/Field.js.map +1 -0
- package/dist/components/Icon.d.ts +9 -0
- package/dist/components/Icon.d.ts.map +1 -0
- package/dist/components/Icon.js +13 -0
- package/dist/components/Icon.js.map +1 -0
- package/dist/components/Input.d.ts +9 -0
- package/dist/components/Input.d.ts.map +1 -0
- package/dist/components/Input.js +13 -0
- package/dist/components/Input.js.map +1 -0
- package/dist/components/InputGroup.d.ts +43 -0
- package/dist/components/InputGroup.d.ts.map +1 -0
- package/dist/components/InputGroup.js +28 -0
- package/dist/components/InputGroup.js.map +1 -0
- package/dist/components/Lightswitch.d.ts +197 -0
- package/dist/components/Lightswitch.d.ts.map +1 -0
- package/dist/components/Lightswitch.js +74 -0
- package/dist/components/Lightswitch.js.map +1 -0
- package/dist/components/Popover.d.ts +9 -0
- package/dist/components/Popover.d.ts.map +1 -0
- package/dist/components/Popover.js +13 -0
- package/dist/components/Popover.js.map +1 -0
- package/dist/components/Popup.d.ts +9 -0
- package/dist/components/Popup.d.ts.map +1 -0
- package/dist/components/Popup.js +13 -0
- package/dist/components/Popup.js.map +1 -0
- package/dist/components/RadioGroup.d.ts +15 -0
- package/dist/components/RadioGroup.d.ts.map +1 -0
- package/dist/components/RadioGroup.js +16 -0
- package/dist/components/RadioGroup.js.map +1 -0
- package/dist/components/RadioGroupInput.d.ts +202 -0
- package/dist/components/RadioGroupInput.d.ts.map +1 -0
- package/dist/components/RadioGroupInput.js +84 -0
- package/dist/components/RadioGroupInput.js.map +1 -0
- package/dist/components/ScrollArea.d.ts +9 -0
- package/dist/components/ScrollArea.d.ts.map +1 -0
- package/dist/components/ScrollArea.js +13 -0
- package/dist/components/ScrollArea.js.map +1 -0
- package/dist/components/Select.d.ts +22 -0
- package/dist/components/Select.d.ts.map +1 -0
- package/dist/components/Select.js +19 -0
- package/dist/components/Select.js.map +1 -0
- package/dist/components/SelectInput.d.ts +311 -0
- package/dist/components/SelectInput.d.ts.map +1 -0
- package/dist/components/SelectInput.js +127 -0
- package/dist/components/SelectInput.js.map +1 -0
- package/dist/components/Separator.d.ts +9 -0
- package/dist/components/Separator.d.ts.map +1 -0
- package/dist/components/Separator.js +13 -0
- package/dist/components/Separator.js.map +1 -0
- package/dist/components/Spinner.d.ts +94 -0
- package/dist/components/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner.js +40 -0
- package/dist/components/Spinner.js.map +1 -0
- package/dist/components/Status.d.ts +9 -0
- package/dist/components/Status.d.ts.map +1 -0
- package/dist/components/Status.js +13 -0
- package/dist/components/Status.js.map +1 -0
- package/dist/components/Tabs.d.ts +29 -0
- package/dist/components/Tabs.d.ts.map +1 -0
- package/dist/components/Tabs.js +22 -0
- package/dist/components/Tabs.js.map +1 -0
- package/dist/components/Textarea.d.ts +9 -0
- package/dist/components/Textarea.d.ts.map +1 -0
- package/dist/components/Textarea.js +13 -0
- package/dist/components/Textarea.js.map +1 -0
- package/dist/components/TimePicker.d.ts +9 -0
- package/dist/components/TimePicker.d.ts.map +1 -0
- package/dist/components/TimePicker.js +13 -0
- package/dist/components/TimePicker.js.map +1 -0
- package/dist/components/Tiptap.d.ts +22 -0
- package/dist/components/Tiptap.d.ts.map +1 -0
- package/dist/components/Tiptap.js +21 -0
- package/dist/components/Tiptap.js.map +1 -0
- package/dist/components/Toggle.d.ts +9 -0
- package/dist/components/Toggle.d.ts.map +1 -0
- package/dist/components/Toggle.js +13 -0
- package/dist/components/Toggle.js.map +1 -0
- package/dist/components/ToggleGroup.d.ts +9 -0
- package/dist/components/ToggleGroup.d.ts.map +1 -0
- package/dist/components/ToggleGroup.js +13 -0
- package/dist/components/ToggleGroup.js.map +1 -0
- package/dist/components/Tooltip.d.ts +9 -0
- package/dist/components/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip.js +13 -0
- package/dist/components/Tooltip.js.map +1 -0
- package/dist/components/index.d.ts +38 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +38 -0
- package/dist/createPkComponent.d.ts +17 -0
- package/dist/createPkComponent.d.ts.map +1 -0
- package/dist/createPkComponent.js +33 -0
- package/dist/createPkComponent.js.map +1 -0
- package/dist/fault/AppFaultBoundary.d.ts +17 -0
- package/dist/fault/AppFaultBoundary.d.ts.map +1 -0
- package/dist/fault/AppFaultBoundary.js +31 -0
- package/dist/fault/AppFaultBoundary.js.map +1 -0
- package/dist/fault/AppFaultProvider.d.ts +116 -0
- package/dist/fault/AppFaultProvider.d.ts.map +1 -0
- package/dist/fault/AppFaultProvider.js +214 -0
- package/dist/fault/AppFaultProvider.js.map +1 -0
- package/dist/fault/FaultFallback.d.ts +88 -0
- package/dist/fault/FaultFallback.d.ts.map +1 -0
- package/dist/fault/FaultFallback.js +91 -0
- package/dist/fault/FaultFallback.js.map +1 -0
- package/dist/fault/buildSupportBundle.d.ts +3 -0
- package/dist/fault/buildSupportBundle.d.ts.map +1 -0
- package/dist/fault/buildSupportBundle.js +22 -0
- package/dist/fault/buildSupportBundle.js.map +1 -0
- package/dist/fault/index.d.ts +8 -0
- package/dist/fault/index.d.ts.map +1 -0
- package/dist/fault/index.js +7 -0
- package/dist/fault/isIgnorableGlobalError.d.ts +3 -0
- package/dist/fault/isIgnorableGlobalError.d.ts.map +1 -0
- package/dist/fault/isIgnorableGlobalError.js +14 -0
- package/dist/fault/isIgnorableGlobalError.js.map +1 -0
- package/dist/fault/types.d.ts +18 -0
- package/dist/fault/types.d.ts.map +1 -0
- package/dist/fault/useUiWatchdog.d.ts +14 -0
- package/dist/fault/useUiWatchdog.d.ts.map +1 -0
- package/dist/fault/useUiWatchdog.js +37 -0
- package/dist/fault/useUiWatchdog.js.map +1 -0
- package/dist/forms/Field.d.ts +123 -0
- package/dist/forms/Field.d.ts.map +1 -0
- package/dist/forms/Field.js +77 -0
- package/dist/forms/Field.js.map +1 -0
- package/dist/forms/SchemaFormEngine.d.ts +50 -0
- package/dist/forms/SchemaFormEngine.d.ts.map +1 -0
- package/dist/forms/SchemaFormEngine.js +372 -0
- package/dist/forms/SchemaFormEngine.js.map +1 -0
- package/dist/forms/SchemaFormFieldNode.d.ts +41 -0
- package/dist/forms/SchemaFormFieldNode.d.ts.map +1 -0
- package/dist/forms/SchemaFormFieldNode.js +73 -0
- package/dist/forms/SchemaFormFieldNode.js.map +1 -0
- package/dist/forms/assertSchemaRegistry.d.ts +17 -0
- package/dist/forms/assertSchemaRegistry.d.ts.map +1 -0
- package/dist/forms/assertSchemaRegistry.js +68 -0
- package/dist/forms/assertSchemaRegistry.js.map +1 -0
- package/dist/forms/builtin-field-loaders.d.ts +11 -0
- package/dist/forms/builtin-field-loaders.d.ts.map +1 -0
- package/dist/forms/builtin-field-loaders.js +31 -0
- package/dist/forms/builtin-field-loaders.js.map +1 -0
- package/dist/forms/components/FieldWrap.d.ts +124 -0
- package/dist/forms/components/FieldWrap.d.ts.map +1 -0
- package/dist/forms/components/FieldWrap.js +99 -0
- package/dist/forms/components/FieldWrap.js.map +1 -0
- package/dist/forms/components/ModalTabs.d.ts +147 -0
- package/dist/forms/components/ModalTabs.d.ts.map +1 -0
- package/dist/forms/components/ModalTabs.js +135 -0
- package/dist/forms/components/ModalTabs.js.map +1 -0
- package/dist/forms/components/index.d.ts +3 -0
- package/dist/forms/components/index.d.ts.map +1 -0
- package/dist/forms/components/schemaErrors.d.ts +4 -0
- package/dist/forms/components/schemaErrors.d.ts.map +1 -0
- package/dist/forms/components/schemaErrors.js +34 -0
- package/dist/forms/components/schemaErrors.js.map +1 -0
- package/dist/forms/datetime.d.ts +11 -0
- package/dist/forms/datetime.d.ts.map +1 -0
- package/dist/forms/datetime.js +35 -0
- package/dist/forms/datetime.js.map +1 -0
- package/dist/forms/engine/context.d.ts +44 -0
- package/dist/forms/engine/context.d.ts.map +1 -0
- package/dist/forms/engine/context.js +15 -0
- package/dist/forms/engine/context.js.map +1 -0
- package/dist/forms/fields/CheckboxSelectField.d.ts +29 -0
- package/dist/forms/fields/CheckboxSelectField.d.ts.map +1 -0
- package/dist/forms/fields/CheckboxSelectField.js +44 -0
- package/dist/forms/fields/CheckboxSelectField.js.map +1 -0
- package/dist/forms/fields/CodeEditorField.d.ts +29 -0
- package/dist/forms/fields/CodeEditorField.d.ts.map +1 -0
- package/dist/forms/fields/CodeEditorField.js +46 -0
- package/dist/forms/fields/CodeEditorField.js.map +1 -0
- package/dist/forms/fields/ColorField.d.ts +29 -0
- package/dist/forms/fields/ColorField.d.ts.map +1 -0
- package/dist/forms/fields/ColorField.js +42 -0
- package/dist/forms/fields/ColorField.js.map +1 -0
- package/dist/forms/fields/ComboboxField.d.ts +29 -0
- package/dist/forms/fields/ComboboxField.d.ts.map +1 -0
- package/dist/forms/fields/ComboboxField.js +47 -0
- package/dist/forms/fields/ComboboxField.js.map +1 -0
- package/dist/forms/fields/DateTimeField.d.ts +29 -0
- package/dist/forms/fields/DateTimeField.d.ts.map +1 -0
- package/dist/forms/fields/DateTimeField.js +54 -0
- package/dist/forms/fields/DateTimeField.js.map +1 -0
- package/dist/forms/fields/GroupField.d.ts +27 -0
- package/dist/forms/fields/GroupField.d.ts.map +1 -0
- package/dist/forms/fields/GroupField.js +55 -0
- package/dist/forms/fields/GroupField.js.map +1 -0
- package/dist/forms/fields/LightswitchField.d.ts +29 -0
- package/dist/forms/fields/LightswitchField.d.ts.map +1 -0
- package/dist/forms/fields/LightswitchField.js +39 -0
- package/dist/forms/fields/LightswitchField.js.map +1 -0
- package/dist/forms/fields/NumberField.d.ts +29 -0
- package/dist/forms/fields/NumberField.d.ts.map +1 -0
- package/dist/forms/fields/NumberField.js +44 -0
- package/dist/forms/fields/NumberField.js.map +1 -0
- package/dist/forms/fields/RadioGroupField.d.ts +29 -0
- package/dist/forms/fields/RadioGroupField.d.ts.map +1 -0
- package/dist/forms/fields/RadioGroupField.js +55 -0
- package/dist/forms/fields/RadioGroupField.js.map +1 -0
- package/dist/forms/fields/SelectField.d.ts +29 -0
- package/dist/forms/fields/SelectField.d.ts.map +1 -0
- package/dist/forms/fields/SelectField.js +58 -0
- package/dist/forms/fields/SelectField.js.map +1 -0
- package/dist/forms/fields/TextField.d.ts +29 -0
- package/dist/forms/fields/TextField.d.ts.map +1 -0
- package/dist/forms/fields/TextField.js +43 -0
- package/dist/forms/fields/TextField.js.map +1 -0
- package/dist/forms/fields/TextareaField.d.ts +29 -0
- package/dist/forms/fields/TextareaField.d.ts.map +1 -0
- package/dist/forms/fields/TextareaField.js +44 -0
- package/dist/forms/fields/TextareaField.js.map +1 -0
- package/dist/forms/fields/options.d.ts +13 -0
- package/dist/forms/fields/options.d.ts.map +1 -0
- package/dist/forms/fields/options.js +29 -0
- package/dist/forms/fields/options.js.map +1 -0
- package/dist/forms/index.d.ts +13 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/index.js +12 -0
- package/dist/forms/registry.d.ts +10 -0
- package/dist/forms/registry.d.ts.map +1 -0
- package/dist/forms/registry.js +45 -0
- package/dist/forms/registry.js.map +1 -0
- package/dist/forms/useEngineField.d.ts +11 -0
- package/dist/forms/useEngineField.d.ts.map +1 -0
- package/dist/forms/useEngineField.js +34 -0
- package/dist/forms/useEngineField.js.map +1 -0
- package/dist/forms/utils.d.ts +6 -0
- package/dist/forms/utils.d.ts.map +1 -0
- package/dist/forms/utils.js +20 -0
- package/dist/forms/utils.js.map +1 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/useTranslation.d.ts +4 -0
- package/dist/hooks/useTranslation.d.ts.map +1 -0
- package/dist/hooks/useTranslation.js +10 -0
- package/dist/hooks/useTranslation.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/utils/cn.d.ts +4 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/cn.js +11 -0
- package/dist/utils/cn.js.map +1 -0
- package/dist/utils/craftHostBridge.d.ts +17 -0
- package/dist/utils/craftHostBridge.d.ts.map +1 -0
- package/dist/utils/craftHostBridge.js +29 -0
- package/dist/utils/craftHostBridge.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/pk-change.d.ts +5 -0
- package/dist/utils/pk-change.d.ts.map +1 -0
- package/dist/utils/pk-change.js +13 -0
- package/dist/utils/pk-change.js.map +1 -0
- package/package.json +109 -0
- package/style.css +4 -0
- package/tailwind-preflight-scope.css +28 -0
- package/tailwind-theme.css +245 -0
- package/vite-dev.mjs +60 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { Separator } from "../components/Separator.js";
|
|
2
|
+
import { SchemaEngineContextKey } from "./engine/context.js";
|
|
3
|
+
import { getFormComponentRegistry } from "./registry.js";
|
|
4
|
+
import { SchemaFormFieldNode } from "./SchemaFormFieldNode.js";
|
|
5
|
+
import { isRecord, normalizeAttrs, readEventValue } from "./utils.js";
|
|
6
|
+
import { defineComponent, h, inject, onBeforeUnmount, onMounted, provide, ref, shallowRef } from "vue";
|
|
7
|
+
import { FormStateStore, buildGroupedMessage, createValidationEngine, evaluateCondition, normalizeSchema } from "@verbb/plugin-kit-forms";
|
|
8
|
+
//#region src/forms/SchemaFormEngine.ts
|
|
9
|
+
var normalizeServerErrors = (rawErrors) => {
|
|
10
|
+
const normalized = {};
|
|
11
|
+
if (!rawErrors) return normalized;
|
|
12
|
+
const appendMessages = (path, messages) => {
|
|
13
|
+
if (!path) return;
|
|
14
|
+
const nextMessages = messages.filter((message) => message !== void 0 && message !== null && message !== "").map((message) => String(message));
|
|
15
|
+
if (!nextMessages.length) return;
|
|
16
|
+
if (!normalized[path]) normalized[path] = [];
|
|
17
|
+
normalized[path].push(...nextMessages);
|
|
18
|
+
};
|
|
19
|
+
const collectErrors = (node, path) => {
|
|
20
|
+
if (Array.isArray(node)) {
|
|
21
|
+
if (node.length === 0) return;
|
|
22
|
+
if (node.every((entry) => typeof entry === "string")) {
|
|
23
|
+
appendMessages(path, node);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!path) {
|
|
27
|
+
node.forEach((entry) => collectErrors(entry, path));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
node.forEach((entry, index) => {
|
|
31
|
+
collectErrors(entry, `${path}.${index}`);
|
|
32
|
+
});
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!isRecord(node)) return;
|
|
36
|
+
Object.entries(node).forEach(([key, value]) => {
|
|
37
|
+
collectErrors(value, path ? `${path}.${key}` : key);
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
if (Array.isArray(rawErrors)) {
|
|
41
|
+
collectErrors(rawErrors, "");
|
|
42
|
+
return normalized;
|
|
43
|
+
}
|
|
44
|
+
if (isRecord(rawErrors) && "errors" in rawErrors) {
|
|
45
|
+
collectErrors(rawErrors.errors, "");
|
|
46
|
+
return normalized;
|
|
47
|
+
}
|
|
48
|
+
collectErrors(rawErrors, "");
|
|
49
|
+
return normalized;
|
|
50
|
+
};
|
|
51
|
+
var createEngineFieldComponent = (formRef) => defineComponent({
|
|
52
|
+
name: "SchemaEngineField",
|
|
53
|
+
props: { name: {
|
|
54
|
+
type: String,
|
|
55
|
+
required: true
|
|
56
|
+
} },
|
|
57
|
+
setup(props, { slots }) {
|
|
58
|
+
const version = ref(0);
|
|
59
|
+
let unsubscribe;
|
|
60
|
+
onMounted(() => {
|
|
61
|
+
unsubscribe = formRef.value?.store.subscribe(() => {
|
|
62
|
+
version.value += 1;
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
onBeforeUnmount(() => {
|
|
66
|
+
unsubscribe?.();
|
|
67
|
+
});
|
|
68
|
+
return () => {
|
|
69
|
+
const form = formRef.value;
|
|
70
|
+
if (!form) return null;
|
|
71
|
+
version.value;
|
|
72
|
+
const fieldApi = {
|
|
73
|
+
state: { value: form.getFieldValue(props.name) },
|
|
74
|
+
handleChange: (valueOrEvent) => {
|
|
75
|
+
form.setFieldValue(props.name, readEventValue(valueOrEvent));
|
|
76
|
+
},
|
|
77
|
+
handleBlur: () => {
|
|
78
|
+
form.store.setTouched(props.name, true);
|
|
79
|
+
},
|
|
80
|
+
errors: form.getErrorMapFields()[props.name] || []
|
|
81
|
+
};
|
|
82
|
+
return slots.default?.(fieldApi);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
var buildConditionData = (form, field, values) => {
|
|
87
|
+
const scopePath = typeof field._scopePath === "string" ? field._scopePath : "";
|
|
88
|
+
const scopedValues = scopePath ? form.getFieldValue(scopePath) : null;
|
|
89
|
+
const scopedObject = isRecord(scopedValues) ? scopedValues : {};
|
|
90
|
+
const conditionContext = form.getConditionContext?.(values, field);
|
|
91
|
+
const normalizedConditionContext = isRecord(conditionContext) ? conditionContext : {};
|
|
92
|
+
const fieldData = isRecord(field._data) ? field._data : {};
|
|
93
|
+
return {
|
|
94
|
+
...values,
|
|
95
|
+
...scopedObject,
|
|
96
|
+
...fieldData,
|
|
97
|
+
...normalizedConditionContext
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
var renderSchemaItem = (schemaItem, index, form) => {
|
|
101
|
+
return h(SchemaItem, {
|
|
102
|
+
key: typeof schemaItem._id === "string" ? schemaItem._id : `schema-item-${index}`,
|
|
103
|
+
field: schemaItem,
|
|
104
|
+
form
|
|
105
|
+
}, { default: () => h(SchemaRenderer, { schema: schemaItem }) });
|
|
106
|
+
};
|
|
107
|
+
var renderFormField = (schema, form) => {
|
|
108
|
+
const { $field, ...props } = schema.$field ? {
|
|
109
|
+
$field: schema.$field,
|
|
110
|
+
...schema
|
|
111
|
+
} : {
|
|
112
|
+
$field: schema.type,
|
|
113
|
+
...schema
|
|
114
|
+
};
|
|
115
|
+
return h(SchemaFormFieldNode, {
|
|
116
|
+
fieldType: String($field ?? ""),
|
|
117
|
+
schema,
|
|
118
|
+
field: { ...props },
|
|
119
|
+
form
|
|
120
|
+
}, { default: () => props.children ? h(SchemaRenderer, { schema: props.children }) : null });
|
|
121
|
+
};
|
|
122
|
+
var renderHtmlElement = (schema) => {
|
|
123
|
+
const { $el, children, attrs = {} } = schema;
|
|
124
|
+
const normalizedAttrs = normalizeAttrs(isRecord(attrs) ? attrs : {});
|
|
125
|
+
if (typeof $el !== "string" || !$el) return null;
|
|
126
|
+
if ($el === "hr") return h(Separator, normalizedAttrs);
|
|
127
|
+
return h($el, normalizedAttrs, children ? () => h(SchemaRenderer, { schema: children }) : void 0);
|
|
128
|
+
};
|
|
129
|
+
var renderFormComponent = (schema) => {
|
|
130
|
+
const { $cmp, props = {}, children, ...rest } = schema;
|
|
131
|
+
const Component = getFormComponentRegistry()[$cmp];
|
|
132
|
+
if (!Component) {
|
|
133
|
+
console.warn(`Unknown form component: ${$cmp}`);
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const componentProps = {
|
|
137
|
+
...isRecord(props) ? props : {},
|
|
138
|
+
...rest
|
|
139
|
+
};
|
|
140
|
+
if (Boolean(Component.usesSchemaNode)) componentProps.schemaNode = schema;
|
|
141
|
+
else if ("schemaNode" in componentProps) delete componentProps.schemaNode;
|
|
142
|
+
return h(Component, componentProps, { default: () => children ? h(SchemaRenderer, { schema: children }) : null });
|
|
143
|
+
};
|
|
144
|
+
var SchemaItem = defineComponent({
|
|
145
|
+
name: "SchemaItem",
|
|
146
|
+
props: {
|
|
147
|
+
field: {
|
|
148
|
+
type: Object,
|
|
149
|
+
required: true
|
|
150
|
+
},
|
|
151
|
+
form: {
|
|
152
|
+
type: Object,
|
|
153
|
+
required: true
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
setup(props, { slots }) {
|
|
157
|
+
const shouldShow = ref(true);
|
|
158
|
+
const resolveVisibility = (values) => {
|
|
159
|
+
if (!props.field.if) return true;
|
|
160
|
+
return Boolean(evaluateCondition(props.field.if, buildConditionData(props.form, props.field, values)));
|
|
161
|
+
};
|
|
162
|
+
const update = () => {
|
|
163
|
+
shouldShow.value = resolveVisibility(props.form.store.state.values);
|
|
164
|
+
};
|
|
165
|
+
update();
|
|
166
|
+
onBeforeUnmount(props.form.store.subscribe(update));
|
|
167
|
+
return () => {
|
|
168
|
+
if (!shouldShow.value) return props.field.hideOnIf ? h("div", { style: { display: "none" } }, slots.default?.()) : null;
|
|
169
|
+
return slots.default?.();
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
var SchemaRenderer = defineComponent({
|
|
174
|
+
name: "SchemaRenderer",
|
|
175
|
+
props: { schema: {
|
|
176
|
+
type: null,
|
|
177
|
+
required: true
|
|
178
|
+
} },
|
|
179
|
+
setup(props) {
|
|
180
|
+
const form = provideAwareForm();
|
|
181
|
+
return () => {
|
|
182
|
+
const schema = props.schema;
|
|
183
|
+
if (typeof schema === "string") return schema;
|
|
184
|
+
if (Array.isArray(schema)) return schema.map((schemaItem, index) => {
|
|
185
|
+
if (typeof schemaItem === "string") return schemaItem;
|
|
186
|
+
if (!isRecord(schemaItem)) return null;
|
|
187
|
+
return renderSchemaItem(schemaItem, index, form);
|
|
188
|
+
});
|
|
189
|
+
if (schema.$field || schema.$cmp === "Field") return renderFormField(schema, form);
|
|
190
|
+
if (schema.$el) return renderHtmlElement(schema);
|
|
191
|
+
if (schema.$cmp) return renderFormComponent(schema);
|
|
192
|
+
console.warn("Unknown schema item:", schema);
|
|
193
|
+
return null;
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
var provideAwareForm = () => {
|
|
198
|
+
const form = inject(SchemaEngineContextKey, null);
|
|
199
|
+
if (!form) throw new Error("SchemaRenderer must be used within SchemaFormEngine.");
|
|
200
|
+
return form;
|
|
201
|
+
};
|
|
202
|
+
var useSchemaFormEngine = ({ schemaIndex = null, defaultValues = {}, errors, onChange, getConditionContext, parentForm, parentPath }) => {
|
|
203
|
+
if (!schemaIndex) throw new Error("SchemaFormEngine requires a compiled schemaIndex.");
|
|
204
|
+
const index = {
|
|
205
|
+
...schemaIndex,
|
|
206
|
+
schema: normalizeSchema(schemaIndex.schema)
|
|
207
|
+
};
|
|
208
|
+
const store = new FormStateStore(defaultValues);
|
|
209
|
+
const validationEngine = createValidationEngine(index, { conditionDataResolver: getConditionContext });
|
|
210
|
+
const labelMap = /* @__PURE__ */ new Map();
|
|
211
|
+
const nestedForms = /* @__PURE__ */ new Map();
|
|
212
|
+
const formRef = shallowRef(null);
|
|
213
|
+
const Field = createEngineFieldComponent(formRef);
|
|
214
|
+
index.fieldEntries.forEach((entry) => {
|
|
215
|
+
if (entry.path) {
|
|
216
|
+
const label = String(entry.field?.label || entry.field?.name || entry.path);
|
|
217
|
+
labelMap.set(entry.path, label);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
let onSubmitHandler = null;
|
|
221
|
+
let onErrorHandler = null;
|
|
222
|
+
let onSuccessHandler = null;
|
|
223
|
+
let onChangeHandler = onChange ? (value) => {
|
|
224
|
+
if (formRef.value) onChange(value, formRef.value);
|
|
225
|
+
} : null;
|
|
226
|
+
const validateNestedForms = () => {
|
|
227
|
+
const nestedErrors = {};
|
|
228
|
+
nestedForms.forEach((api, path) => {
|
|
229
|
+
const result = api.validate();
|
|
230
|
+
if (result?.fields) Object.entries(result.fields).forEach(([fieldPath, messages]) => {
|
|
231
|
+
const mergedPath = fieldPath ? `${path}.${fieldPath}` : path;
|
|
232
|
+
nestedErrors[mergedPath] = messages;
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
return nestedErrors;
|
|
236
|
+
};
|
|
237
|
+
const getGroupedErrorsForPath = (path) => {
|
|
238
|
+
if (!path) return [];
|
|
239
|
+
const currentErrors = store.state.errors || {};
|
|
240
|
+
const rootErrors = currentErrors[path] || [];
|
|
241
|
+
const childKeys = Object.keys(currentErrors).filter((key) => key.startsWith(`${path}.`));
|
|
242
|
+
if (!childKeys.length) return rootErrors;
|
|
243
|
+
const parentLabel = labelMap.get(path);
|
|
244
|
+
const groupedMessages = [];
|
|
245
|
+
childKeys.forEach((key) => {
|
|
246
|
+
const wildcardPath = key.replace(/\.\d+(?=\.|$)/g, ".*");
|
|
247
|
+
const childLabel = labelMap.get(wildcardPath) || key.split(".").slice(-1)[0];
|
|
248
|
+
(currentErrors[key] || []).forEach((message) => {
|
|
249
|
+
if (parentLabel) {
|
|
250
|
+
groupedMessages.push(buildGroupedMessage(String(message), parentLabel, childLabel));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
groupedMessages.push(String(message));
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
return Array.from(new Set([...rootErrors, ...groupedMessages]));
|
|
257
|
+
};
|
|
258
|
+
const handleSubmit = async () => {
|
|
259
|
+
const errorsMap = validationEngine.validate(store.state.values)?.fields || {};
|
|
260
|
+
const nestedErrors = validateNestedForms();
|
|
261
|
+
const mergedErrors = {
|
|
262
|
+
...errorsMap,
|
|
263
|
+
...nestedErrors
|
|
264
|
+
};
|
|
265
|
+
if (Object.keys(mergedErrors).length > 0) {
|
|
266
|
+
store.setErrors(mergedErrors);
|
|
267
|
+
onErrorHandler?.(mergedErrors);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
store.clearErrors();
|
|
271
|
+
await onSubmitHandler?.(store.state.values);
|
|
272
|
+
if (parentForm && parentPath) parentForm.setFieldValue(parentPath, store.state.values);
|
|
273
|
+
onSuccessHandler?.(store.state.values);
|
|
274
|
+
};
|
|
275
|
+
const form = {
|
|
276
|
+
schema: index.schema,
|
|
277
|
+
store,
|
|
278
|
+
index,
|
|
279
|
+
Field,
|
|
280
|
+
getFieldValue: (path) => store.getValue(path),
|
|
281
|
+
setFieldValue: (path, value) => store.setValue(path, value),
|
|
282
|
+
getErrorMapFields: () => store.state.errors || {},
|
|
283
|
+
SchemaRenderer,
|
|
284
|
+
handleSubmit,
|
|
285
|
+
onChange: (handler) => {
|
|
286
|
+
onChangeHandler = handler;
|
|
287
|
+
},
|
|
288
|
+
onSubmit: (handler) => {
|
|
289
|
+
onSubmitHandler = handler;
|
|
290
|
+
},
|
|
291
|
+
onError: (handler) => {
|
|
292
|
+
onErrorHandler = handler;
|
|
293
|
+
},
|
|
294
|
+
onSuccess: (handler) => {
|
|
295
|
+
onSuccessHandler = handler;
|
|
296
|
+
},
|
|
297
|
+
registerNestedForm: (path, api) => {
|
|
298
|
+
nestedForms.set(path, api);
|
|
299
|
+
},
|
|
300
|
+
unregisterNestedForm: (path) => {
|
|
301
|
+
nestedForms.delete(path);
|
|
302
|
+
},
|
|
303
|
+
getGroupedErrorsForPath,
|
|
304
|
+
getConditionContext: (values, field) => getConditionContext?.(values, field) || {}
|
|
305
|
+
};
|
|
306
|
+
formRef.value = form;
|
|
307
|
+
onBeforeUnmount(store.subscribe(() => {
|
|
308
|
+
onChangeHandler?.(store.state.values);
|
|
309
|
+
}));
|
|
310
|
+
const normalized = normalizeServerErrors(errors);
|
|
311
|
+
if (Object.keys(normalized).length) store.setErrors(normalized);
|
|
312
|
+
if (parentForm && parentPath) {
|
|
313
|
+
const nestedApi = {
|
|
314
|
+
path: parentPath,
|
|
315
|
+
validate: () => {
|
|
316
|
+
const result = validationEngine.validate(store.state.values);
|
|
317
|
+
const fieldErrors = result?.fields || {};
|
|
318
|
+
if (Object.keys(fieldErrors).length) store.setErrors(fieldErrors);
|
|
319
|
+
else store.clearErrors();
|
|
320
|
+
return result;
|
|
321
|
+
},
|
|
322
|
+
getValues: () => store.state.values
|
|
323
|
+
};
|
|
324
|
+
parentForm.registerNestedForm(parentPath, nestedApi);
|
|
325
|
+
onBeforeUnmount(() => {
|
|
326
|
+
parentForm.unregisterNestedForm(parentPath);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
return form;
|
|
330
|
+
};
|
|
331
|
+
var SchemaFormEngine = defineComponent({
|
|
332
|
+
name: "SchemaFormEngine",
|
|
333
|
+
props: {
|
|
334
|
+
form: {
|
|
335
|
+
type: Object,
|
|
336
|
+
required: true
|
|
337
|
+
},
|
|
338
|
+
class: {
|
|
339
|
+
type: null,
|
|
340
|
+
default: void 0
|
|
341
|
+
},
|
|
342
|
+
withoutForm: {
|
|
343
|
+
type: Boolean,
|
|
344
|
+
default: false
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
setup(props, { expose }) {
|
|
348
|
+
expose(props.form);
|
|
349
|
+
provide(SchemaEngineContextKey, props.form);
|
|
350
|
+
return () => {
|
|
351
|
+
const content = h(SchemaRenderer, { schema: props.form.schema });
|
|
352
|
+
if (props.withoutForm) return h("div", { class: props.class }, content);
|
|
353
|
+
return h("form", {
|
|
354
|
+
class: props.class,
|
|
355
|
+
onSubmit: (event) => {
|
|
356
|
+
event.preventDefault();
|
|
357
|
+
event.stopPropagation();
|
|
358
|
+
props.form.handleSubmit();
|
|
359
|
+
}
|
|
360
|
+
}, [content, h("button", {
|
|
361
|
+
type: "submit",
|
|
362
|
+
tabindex: -1,
|
|
363
|
+
"aria-hidden": "true",
|
|
364
|
+
class: "sr-only"
|
|
365
|
+
})]);
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
//#endregion
|
|
370
|
+
export { SchemaFormEngine, useSchemaFormEngine };
|
|
371
|
+
|
|
372
|
+
//# sourceMappingURL=SchemaFormEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaFormEngine.js","names":[],"sources":["../../src/forms/SchemaFormEngine.ts"],"sourcesContent":["import {\n defineComponent,\n h,\n inject,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n shallowRef,\n type PropType,\n type VNodeChild,\n} from 'vue';\nimport {\n FormStateStore,\n buildGroupedMessage,\n createValidationEngine,\n evaluateCondition,\n normalizeSchema,\n} from '@verbb/plugin-kit-forms';\nimport type { SchemaIndex, SchemaNode, SchemaRenderable } from '@verbb/plugin-kit-forms';\n\nimport { Separator } from '../components/Separator.js';\nimport { getFormComponentRegistry } from './registry.js';\nimport { SchemaFormFieldNode } from './SchemaFormFieldNode.js';\nimport type {\n FormValues,\n NestedFormApi,\n SchemaFieldApi,\n SchemaFormEngineApi,\n} from './engine/context.js';\nimport { SchemaEngineContextKey } from './engine/context.js';\nimport { isRecord, normalizeAttrs, readEventValue } from './utils.js';\n\ntype SchemaFormEngineErrors = Record<string, unknown> | { errors?: unknown } | unknown[];\n\ntype SchemaFormEngineOptions = {\n schemaIndex: SchemaIndex | null;\n defaultValues?: FormValues;\n errors?: SchemaFormEngineErrors;\n onChange?: (values: Record<string, unknown>, form: SchemaFormEngineApi) => void;\n getConditionContext?: (values: FormValues, field?: SchemaNode) => Record<string, unknown>;\n parentForm?: SchemaFormEngineApi | null;\n parentPath?: string;\n};\n\nconst normalizeServerErrors = (rawErrors: SchemaFormEngineErrors | undefined): Record<string, string[]> => {\n const normalized: Record<string, string[]> = {};\n\n if (!rawErrors) {\n return normalized;\n }\n\n const appendMessages = (path: string, messages: unknown[]) => {\n if (!path) {\n return;\n }\n\n const nextMessages = messages\n .filter((message) => message !== undefined && message !== null && message !== '')\n .map((message) => String(message));\n\n if (!nextMessages.length) {\n return;\n }\n\n if (!normalized[path]) {\n normalized[path] = [];\n }\n\n normalized[path].push(...nextMessages);\n };\n\n const collectErrors = (node: unknown, path: string) => {\n if (Array.isArray(node)) {\n if (node.length === 0) {\n return;\n }\n\n const isMessageArray = node.every((entry) => typeof entry === 'string');\n if (isMessageArray) {\n appendMessages(path, node);\n return;\n }\n\n if (!path) {\n node.forEach((entry) => collectErrors(entry, path));\n return;\n }\n\n node.forEach((entry, index) => {\n collectErrors(entry, `${path}.${index}`);\n });\n return;\n }\n\n if (!isRecord(node)) {\n return;\n }\n\n Object.entries(node).forEach(([key, value]) => {\n const nextPath = path ? `${path}.${key}` : key;\n collectErrors(value, nextPath);\n });\n };\n\n if (Array.isArray(rawErrors)) {\n collectErrors(rawErrors, '');\n return normalized;\n }\n\n if (isRecord(rawErrors) && 'errors' in rawErrors) {\n collectErrors(rawErrors.errors, '');\n return normalized;\n }\n\n collectErrors(rawErrors, '');\n return normalized;\n};\n\nconst createEngineFieldComponent = (formRef: { value: SchemaFormEngineApi | null }) => defineComponent({\n name: 'SchemaEngineField',\n props: {\n name: { type: String, required: true },\n },\n setup(props, { slots }) {\n const version = ref(0);\n let unsubscribe: (() => void) | undefined;\n\n onMounted(() => {\n unsubscribe = formRef.value?.store.subscribe(() => {\n version.value += 1;\n });\n });\n onBeforeUnmount(() => {\n unsubscribe?.();\n });\n\n return () => {\n const form = formRef.value;\n if (!form) {\n return null;\n }\n\n version.value;\n const fieldApi: SchemaFieldApi = {\n state: { value: form.getFieldValue(props.name) },\n handleChange: (valueOrEvent: unknown) => {\n form.setFieldValue(props.name, readEventValue(valueOrEvent));\n },\n handleBlur: () => {\n form.store.setTouched(props.name, true);\n },\n errors: form.getErrorMapFields()[props.name] || [],\n };\n\n return slots.default?.(fieldApi);\n };\n },\n});\n\nconst buildConditionData = (\n form: SchemaFormEngineApi,\n field: SchemaNode,\n values: FormValues,\n): Record<string, unknown> => {\n const scopePath = typeof field._scopePath === 'string' ? field._scopePath : '';\n const scopedValues = scopePath ? form.getFieldValue(scopePath) : null;\n const scopedObject = isRecord(scopedValues) ? scopedValues : {};\n const conditionContext = form.getConditionContext?.(values, field);\n const normalizedConditionContext = isRecord(conditionContext) ? conditionContext : {};\n const fieldData = isRecord(field._data) ? field._data : {};\n\n return {\n ...values,\n ...scopedObject,\n ...fieldData,\n ...normalizedConditionContext,\n };\n};\n\nconst renderSchemaItem = (schemaItem: SchemaNode, index: number, form: SchemaFormEngineApi): VNodeChild => {\n const key = typeof schemaItem._id === 'string' ? schemaItem._id : `schema-item-${index}`;\n\n return h(SchemaItem, { key, field: schemaItem, form }, {\n default: () => h(SchemaRenderer, { schema: schemaItem }),\n });\n};\n\nconst renderFormField = (schema: SchemaNode, form: SchemaFormEngineApi): VNodeChild => {\n const fieldProps = schema.$field ? { $field: schema.$field, ...schema } : { $field: schema.type, ...schema };\n const { $field, ...props } = fieldProps;\n const fieldType = String($field ?? '');\n\n return h(SchemaFormFieldNode, {\n fieldType,\n schema,\n field: { ...props },\n form,\n }, {\n default: () => (props.children ? h(SchemaRenderer, { schema: props.children as SchemaRenderable }) : null),\n });\n};\n\nconst renderHtmlElement = (schema: SchemaNode): VNodeChild => {\n const { $el, children, attrs = {} } = schema;\n const normalizedAttrs = normalizeAttrs(isRecord(attrs) ? attrs : {});\n\n if (typeof $el !== 'string' || !$el) {\n return null;\n }\n\n if ($el === 'hr') {\n return h(Separator, normalizedAttrs);\n }\n\n return h($el, normalizedAttrs, children ? () => h(SchemaRenderer, { schema: children }) : undefined);\n};\n\nconst renderFormComponent = (schema: SchemaNode): VNodeChild => {\n const {\n $cmp, props = {}, children, ...rest\n } = schema;\n const Component = getFormComponentRegistry()[$cmp as string];\n\n if (!Component) {\n console.warn(`Unknown form component: ${$cmp}`);\n return null;\n }\n\n const componentProps = { ...(isRecord(props) ? props : {}), ...rest } as Record<string, unknown>;\n const usesSchemaNode = Boolean(Component.usesSchemaNode);\n\n if (usesSchemaNode) {\n componentProps.schemaNode = schema;\n } else if ('schemaNode' in componentProps) {\n delete componentProps.schemaNode;\n }\n\n return h(Component, componentProps, {\n default: () => (children ? h(SchemaRenderer, { schema: children as SchemaRenderable }) : null),\n });\n};\n\nconst SchemaItem = defineComponent({\n name: 'SchemaItem',\n props: {\n field: { type: Object as PropType<SchemaNode>, required: true },\n form: { type: Object as PropType<SchemaFormEngineApi>, required: true },\n },\n setup(props, { slots }) {\n const shouldShow = ref(true);\n\n const resolveVisibility = (values: FormValues): boolean => {\n if (!props.field.if) {\n return true;\n }\n\n return Boolean(evaluateCondition(props.field.if, buildConditionData(props.form, props.field, values)));\n };\n\n const update = () => {\n shouldShow.value = resolveVisibility(props.form.store.state.values);\n };\n\n update();\n const unsubscribe = props.form.store.subscribe(update);\n onBeforeUnmount(unsubscribe);\n\n return () => {\n if (!shouldShow.value) {\n return props.field.hideOnIf ? h('div', { style: { display: 'none' } }, slots.default?.()) : null;\n }\n\n return slots.default?.();\n };\n },\n});\n\nconst SchemaRenderer = defineComponent({\n name: 'SchemaRenderer',\n props: {\n schema: { type: null as unknown as PropType<SchemaRenderable>, required: true },\n },\n setup(props) {\n const form = provideAwareForm();\n\n return () => {\n const schema = props.schema;\n\n if (typeof schema === 'string') {\n return schema;\n }\n\n if (Array.isArray(schema)) {\n return schema.map((schemaItem, index) => {\n if (typeof schemaItem === 'string') {\n return schemaItem;\n }\n\n if (!isRecord(schemaItem)) {\n return null;\n }\n\n return renderSchemaItem(schemaItem as SchemaNode, index, form);\n });\n }\n\n if (schema.$field || schema.$cmp === 'Field') {\n return renderFormField(schema, form);\n }\n\n if (schema.$el) {\n return renderHtmlElement(schema);\n }\n\n if (schema.$cmp) {\n return renderFormComponent(schema);\n }\n\n console.warn('Unknown schema item:', schema);\n return null;\n };\n },\n});\n\nconst provideAwareForm = (): SchemaFormEngineApi => {\n const form = inject(SchemaEngineContextKey, null);\n if (!form) {\n throw new Error('SchemaRenderer must be used within SchemaFormEngine.');\n }\n return form;\n};\n\nexport const useSchemaFormEngine = ({\n schemaIndex = null,\n defaultValues = {},\n errors,\n onChange,\n getConditionContext,\n parentForm,\n parentPath,\n}: SchemaFormEngineOptions): SchemaFormEngineApi => {\n if (!schemaIndex) {\n throw new Error('SchemaFormEngine requires a compiled schemaIndex.');\n }\n\n const index = {\n ...schemaIndex,\n schema: normalizeSchema(schemaIndex.schema),\n };\n const store = new FormStateStore(defaultValues);\n const validationEngine = createValidationEngine(index, { conditionDataResolver: getConditionContext });\n const labelMap = new Map<string, string>();\n const nestedForms = new Map<string, NestedFormApi>();\n const formRef = shallowRef<SchemaFormEngineApi | null>(null);\n const Field = createEngineFieldComponent(formRef);\n\n index.fieldEntries.forEach((entry) => {\n if (entry.path) {\n const label = String(entry.field?.label || entry.field?.name || entry.path);\n labelMap.set(entry.path, label);\n }\n });\n\n let onSubmitHandler: ((value: FormValues) => Promise<void> | void) | null = null;\n let onErrorHandler: ((errors: Record<string, unknown>) => void) | null = null;\n let onSuccessHandler: ((value: FormValues) => void) | null = null;\n let onChangeHandler: ((value: FormValues) => void) | null = onChange\n ? (value) => {\n if (formRef.value) {\n onChange(value, formRef.value);\n }\n }\n : null;\n\n const validateNestedForms = (): Record<string, string[]> => {\n const nestedErrors: Record<string, string[]> = {};\n\n nestedForms.forEach((api, path) => {\n const result = api.validate();\n if (result?.fields) {\n Object.entries(result.fields).forEach(([fieldPath, messages]) => {\n const mergedPath = fieldPath ? `${path}.${fieldPath}` : path;\n nestedErrors[mergedPath] = messages;\n });\n }\n });\n\n return nestedErrors;\n };\n\n const getGroupedErrorsForPath = (path: string): string[] => {\n if (!path) {\n return [];\n }\n\n const currentErrors = store.state.errors || {};\n const rootErrors = currentErrors[path] || [];\n const childKeys = Object.keys(currentErrors).filter((key) => key.startsWith(`${path}.`));\n\n if (!childKeys.length) {\n return rootErrors;\n }\n\n const parentLabel = labelMap.get(path);\n const groupedMessages: string[] = [];\n\n childKeys.forEach((key) => {\n const wildcardPath = key.replace(/\\.\\d+(?=\\.|$)/g, '.*');\n const childLabel = labelMap.get(wildcardPath) || key.split('.').slice(-1)[0];\n (currentErrors[key] || []).forEach((message) => {\n if (parentLabel) {\n groupedMessages.push(buildGroupedMessage(String(message), parentLabel, childLabel));\n return;\n }\n\n groupedMessages.push(String(message));\n });\n });\n\n return Array.from(new Set([...rootErrors, ...groupedMessages]));\n };\n\n const handleSubmit = async (): Promise<void> => {\n const result = validationEngine.validate(store.state.values);\n const errorsMap = result?.fields || {};\n const nestedErrors = validateNestedForms();\n const mergedErrors = { ...errorsMap, ...nestedErrors };\n\n if (Object.keys(mergedErrors).length > 0) {\n store.setErrors(mergedErrors);\n onErrorHandler?.(mergedErrors);\n return;\n }\n\n store.clearErrors();\n await onSubmitHandler?.(store.state.values);\n\n if (parentForm && parentPath) {\n parentForm.setFieldValue(parentPath, store.state.values);\n }\n\n onSuccessHandler?.(store.state.values);\n };\n\n const form: SchemaFormEngineApi = {\n schema: index.schema,\n store,\n index,\n Field,\n getFieldValue: (path: string) => store.getValue(path),\n setFieldValue: (path: string, value: unknown) => store.setValue(path, value),\n getErrorMapFields: () => store.state.errors || {},\n SchemaRenderer,\n handleSubmit,\n onChange: (handler) => {\n onChangeHandler = handler;\n },\n onSubmit: (handler) => {\n onSubmitHandler = handler;\n },\n onError: (handler) => {\n onErrorHandler = handler;\n },\n onSuccess: (handler) => {\n onSuccessHandler = handler;\n },\n registerNestedForm: (path, api) => {\n nestedForms.set(path, api);\n },\n unregisterNestedForm: (path) => {\n nestedForms.delete(path);\n },\n getGroupedErrorsForPath,\n getConditionContext: (values, field) => getConditionContext?.(values, field) || {},\n };\n\n formRef.value = form;\n\n const unsubscribeChange = store.subscribe(() => {\n onChangeHandler?.(store.state.values);\n });\n onBeforeUnmount(unsubscribeChange);\n\n const normalized = normalizeServerErrors(errors);\n if (Object.keys(normalized).length) {\n store.setErrors(normalized);\n }\n\n if (parentForm && parentPath) {\n const nestedApi: NestedFormApi = {\n path: parentPath,\n validate: () => {\n const result = validationEngine.validate(store.state.values);\n const fieldErrors = result?.fields || {};\n\n if (Object.keys(fieldErrors).length) {\n store.setErrors(fieldErrors);\n } else {\n store.clearErrors();\n }\n\n return result;\n },\n getValues: () => store.state.values,\n };\n\n parentForm.registerNestedForm(parentPath, nestedApi);\n onBeforeUnmount(() => {\n parentForm.unregisterNestedForm(parentPath);\n });\n }\n\n return form;\n};\n\nexport const SchemaFormEngine = defineComponent({\n name: 'SchemaFormEngine',\n props: {\n form: { type: Object as PropType<SchemaFormEngineApi>, required: true },\n class: { type: null as unknown as PropType<unknown>, default: undefined },\n withoutForm: { type: Boolean, default: false },\n },\n setup(props, { expose }) {\n expose(props.form);\n provide(SchemaEngineContextKey, props.form);\n\n return () => {\n const content = h(SchemaRenderer, { schema: props.form.schema });\n\n if (props.withoutForm) {\n return h('div', { class: props.class }, content);\n }\n\n return h(\n 'form',\n {\n class: props.class,\n onSubmit: (event: Event) => {\n event.preventDefault();\n event.stopPropagation();\n void props.form.handleSubmit();\n },\n },\n [\n content,\n h('button', {\n type: 'submit',\n tabindex: -1,\n 'aria-hidden': 'true',\n class: 'sr-only',\n }),\n ],\n );\n };\n },\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PropType } from 'vue';
|
|
2
|
+
import { SchemaNode } from '@verbb/plugin-kit-forms';
|
|
3
|
+
import { SchemaFormEngineApi } from './engine/context.js';
|
|
4
|
+
export declare const SchemaFormFieldNode: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
|
5
|
+
fieldType: {
|
|
6
|
+
type: StringConstructor;
|
|
7
|
+
required: true;
|
|
8
|
+
};
|
|
9
|
+
schema: {
|
|
10
|
+
type: PropType<SchemaNode>;
|
|
11
|
+
required: true;
|
|
12
|
+
};
|
|
13
|
+
field: {
|
|
14
|
+
type: PropType<SchemaNode>;
|
|
15
|
+
required: true;
|
|
16
|
+
};
|
|
17
|
+
form: {
|
|
18
|
+
type: PropType<SchemaFormEngineApi>;
|
|
19
|
+
required: true;
|
|
20
|
+
};
|
|
21
|
+
}>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
}> | null, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
|
24
|
+
fieldType: {
|
|
25
|
+
type: StringConstructor;
|
|
26
|
+
required: true;
|
|
27
|
+
};
|
|
28
|
+
schema: {
|
|
29
|
+
type: PropType<SchemaNode>;
|
|
30
|
+
required: true;
|
|
31
|
+
};
|
|
32
|
+
field: {
|
|
33
|
+
type: PropType<SchemaNode>;
|
|
34
|
+
required: true;
|
|
35
|
+
};
|
|
36
|
+
form: {
|
|
37
|
+
type: PropType<SchemaFormEngineApi>;
|
|
38
|
+
required: true;
|
|
39
|
+
};
|
|
40
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
41
|
+
//# sourceMappingURL=SchemaFormFieldNode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaFormFieldNode.d.ts","sourceRoot":"","sources":["../../src/forms/SchemaFormFieldNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,KAAK,QAAQ,EAChB,MAAM,KAAK,CAAC;AACb,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,KAAK,EAAE,mBAAmB,EAA4B,MAAM,qBAAqB,CAAC;AAMzF,eAAO,MAAM,mBAAmB;;;;;;cAIE,QAAQ,CAAC,UAAU,CAAC;;;;cACrB,QAAQ,CAAC,UAAU,CAAC;;;;cACrB,QAAQ,CAAC,mBAAmB,CAAC;;;;;;;;;;;cAF3B,QAAQ,CAAC,UAAU,CAAC;;;;cACrB,QAAQ,CAAC,UAAU,CAAC;;;;cACrB,QAAQ,CAAC,mBAAmB,CAAC;;;iGAiE3D,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { cacheLoadedBuiltinFormField, getRegisteredFormField } from "./registry.js";
|
|
2
|
+
import { isBuiltinFormFieldType, loadBuiltinFormField } from "./builtin-field-loaders.js";
|
|
3
|
+
import { defineComponent, h, onMounted, ref, watch } from "vue";
|
|
4
|
+
//#region src/forms/SchemaFormFieldNode.ts
|
|
5
|
+
var SchemaFormFieldNode = defineComponent({
|
|
6
|
+
name: "SchemaFormFieldNode",
|
|
7
|
+
props: {
|
|
8
|
+
fieldType: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true
|
|
11
|
+
},
|
|
12
|
+
schema: {
|
|
13
|
+
type: Object,
|
|
14
|
+
required: true
|
|
15
|
+
},
|
|
16
|
+
field: {
|
|
17
|
+
type: Object,
|
|
18
|
+
required: true
|
|
19
|
+
},
|
|
20
|
+
form: {
|
|
21
|
+
type: Object,
|
|
22
|
+
required: true
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
setup(props, { slots }) {
|
|
26
|
+
const component = ref(getRegisteredFormField(props.fieldType) ?? null);
|
|
27
|
+
const loadFailed = ref(false);
|
|
28
|
+
const loadComponent = async (fieldType) => {
|
|
29
|
+
const registeredField = getRegisteredFormField(fieldType);
|
|
30
|
+
if (registeredField) {
|
|
31
|
+
component.value = registeredField;
|
|
32
|
+
loadFailed.value = false;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!isBuiltinFormFieldType(fieldType)) {
|
|
36
|
+
console.warn(`Unknown form field type: ${fieldType}`);
|
|
37
|
+
component.value = null;
|
|
38
|
+
loadFailed.value = true;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
loadFailed.value = false;
|
|
42
|
+
try {
|
|
43
|
+
const loaded = await loadBuiltinFormField(fieldType);
|
|
44
|
+
if (!loaded || fieldType !== props.fieldType) return;
|
|
45
|
+
cacheLoadedBuiltinFormField(fieldType, loaded);
|
|
46
|
+
component.value = loaded;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (fieldType !== props.fieldType) return;
|
|
49
|
+
console.error(`Failed to load form field "${fieldType}":`, error);
|
|
50
|
+
component.value = null;
|
|
51
|
+
loadFailed.value = true;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
onMounted(() => {
|
|
55
|
+
loadComponent(props.fieldType);
|
|
56
|
+
});
|
|
57
|
+
watch(() => props.fieldType, (fieldType) => {
|
|
58
|
+
loadComponent(fieldType);
|
|
59
|
+
});
|
|
60
|
+
return () => {
|
|
61
|
+
if (loadFailed.value || !component.value) return null;
|
|
62
|
+
return h(component.value, {
|
|
63
|
+
schema: props.schema,
|
|
64
|
+
field: props.field,
|
|
65
|
+
form: props.form
|
|
66
|
+
}, slots);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
//#endregion
|
|
71
|
+
export { SchemaFormFieldNode };
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=SchemaFormFieldNode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaFormFieldNode.js","names":[],"sources":["../../src/forms/SchemaFormFieldNode.ts"],"sourcesContent":["import {\n defineComponent,\n h,\n onMounted,\n ref,\n watch,\n type PropType,\n} from 'vue';\nimport type { SchemaNode } from '@verbb/plugin-kit-forms';\n\nimport { isBuiltinFormFieldType, loadBuiltinFormField } from './builtin-field-loaders.js';\nimport type { SchemaFormEngineApi, SchemaFormFieldComponent } from './engine/context.js';\nimport {\n cacheLoadedBuiltinFormField,\n getRegisteredFormField,\n} from './registry.js';\n\nexport const SchemaFormFieldNode = defineComponent({\n name: 'SchemaFormFieldNode',\n props: {\n fieldType: { type: String, required: true },\n schema: { type: Object as PropType<SchemaNode>, required: true },\n field: { type: Object as PropType<SchemaNode>, required: true },\n form: { type: Object as PropType<SchemaFormEngineApi>, required: true },\n },\n setup(props, { slots }) {\n const component = ref<SchemaFormFieldComponent | null>(getRegisteredFormField(props.fieldType) ?? null);\n const loadFailed = ref(false);\n\n const loadComponent = async (fieldType: string): Promise<void> => {\n const registeredField = getRegisteredFormField(fieldType);\n if (registeredField) {\n component.value = registeredField;\n loadFailed.value = false;\n return;\n }\n\n if (!isBuiltinFormFieldType(fieldType)) {\n console.warn(`Unknown form field type: ${fieldType}`);\n component.value = null;\n loadFailed.value = true;\n return;\n }\n\n loadFailed.value = false;\n\n try {\n const loaded = await loadBuiltinFormField(fieldType);\n if (!loaded || fieldType !== props.fieldType) {\n return;\n }\n\n cacheLoadedBuiltinFormField(fieldType, loaded);\n component.value = loaded;\n } catch (error) {\n if (fieldType !== props.fieldType) {\n return;\n }\n\n console.error(`Failed to load form field \"${fieldType}\":`, error);\n component.value = null;\n loadFailed.value = true;\n }\n };\n\n onMounted(() => {\n void loadComponent(props.fieldType);\n });\n watch(() => props.fieldType, (fieldType) => {\n void loadComponent(fieldType);\n });\n\n return () => {\n if (loadFailed.value || !component.value) {\n return null;\n }\n\n return h(\n component.value,\n {\n schema: props.schema,\n field: props.field,\n form: props.form,\n },\n slots,\n );\n };\n },\n});\n"],"mappings":";;;;AAiBA,IAAa,sBAAsB,gBAAgB;CAC/C,MAAM;CACN,OAAO;EACH,WAAW;GAAE,MAAM;GAAQ,UAAU;GAAM;EAC3C,QAAQ;GAAE,MAAM;GAAgC,UAAU;GAAM;EAChE,OAAO;GAAE,MAAM;GAAgC,UAAU;GAAM;EAC/D,MAAM;GAAE,MAAM;GAAyC,UAAU;GAAM;EAC1E;CACD,MAAM,OAAO,EAAE,SAAS;EACpB,MAAM,YAAY,IAAqC,uBAAuB,MAAM,UAAU,IAAI,KAAK;EACvG,MAAM,aAAa,IAAI,MAAM;EAE7B,MAAM,gBAAgB,OAAO,cAAqC;GAC9D,MAAM,kBAAkB,uBAAuB,UAAU;AACzD,OAAI,iBAAiB;AACjB,cAAU,QAAQ;AAClB,eAAW,QAAQ;AACnB;;AAGJ,OAAI,CAAC,uBAAuB,UAAU,EAAE;AACpC,YAAQ,KAAK,4BAA4B,YAAY;AACrD,cAAU,QAAQ;AAClB,eAAW,QAAQ;AACnB;;AAGJ,cAAW,QAAQ;AAEnB,OAAI;IACA,MAAM,SAAS,MAAM,qBAAqB,UAAU;AACpD,QAAI,CAAC,UAAU,cAAc,MAAM,UAC/B;AAGJ,gCAA4B,WAAW,OAAO;AAC9C,cAAU,QAAQ;YACb,OAAO;AACZ,QAAI,cAAc,MAAM,UACpB;AAGJ,YAAQ,MAAM,8BAA8B,UAAU,KAAK,MAAM;AACjE,cAAU,QAAQ;AAClB,eAAW,QAAQ;;;AAI3B,kBAAgB;AACP,iBAAc,MAAM,UAAU;IACrC;AACF,cAAY,MAAM,YAAY,cAAc;AACnC,iBAAc,UAAU;IAC/B;AAEF,eAAa;AACT,OAAI,WAAW,SAAS,CAAC,UAAU,MAC/B,QAAO;AAGX,UAAO,EACH,UAAU,OACV;IACI,QAAQ,MAAM;IACd,OAAO,MAAM;IACb,MAAM,MAAM;IACf,EACD,MACH;;;CAGZ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SchemaIndex, SchemaRenderable } from '@verbb/plugin-kit-forms';
|
|
2
|
+
export type AssertSchemaRegistryOptions = {
|
|
3
|
+
/** When true, throw on the first missing registry key instead of collecting all. */
|
|
4
|
+
failFast?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export type SchemaRegistryIssue = {
|
|
7
|
+
path: string;
|
|
8
|
+
kind: 'field' | 'component';
|
|
9
|
+
key: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Walk a SchemaForm tree and verify every `$field` / `$cmp` key can resolve.
|
|
13
|
+
* Useful in dev/test bootstraps before shipping large CP schemas.
|
|
14
|
+
*/
|
|
15
|
+
export declare const assertSchemaRegistry: (schema: SchemaRenderable, options?: AssertSchemaRegistryOptions) => SchemaRegistryIssue[];
|
|
16
|
+
export declare const debugSchemaRegistry: (schemaIndex: SchemaIndex | null | undefined, options?: AssertSchemaRegistryOptions) => SchemaRegistryIssue[];
|
|
17
|
+
//# sourceMappingURL=assertSchemaRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertSchemaRegistry.d.ts","sourceRoot":"","sources":["../../src/forms/assertSchemaRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAc,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMzF,MAAM,MAAM,2BAA2B,GAAG;IACtC,oFAAoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,WAAW,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAwCF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAC7B,QAAQ,gBAAgB,EACxB,UAAS,2BAAgC,KAC1C,mBAAmB,EA+BrB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC5B,aAAa,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,UAAU,2BAA2B,KACtC,mBAAmB,EAYrB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { getFormComponentRegistry, getFormFieldRegistry } from "./registry.js";
|
|
2
|
+
import { isBuiltinFormFieldType } from "./builtin-field-loaders.js";
|
|
3
|
+
import { isRecord } from "./utils.js";
|
|
4
|
+
//#region src/forms/assertSchemaRegistry.ts
|
|
5
|
+
var walkSchema = (schema, path, visit) => {
|
|
6
|
+
if (typeof schema === "string") return;
|
|
7
|
+
if (Array.isArray(schema)) {
|
|
8
|
+
schema.forEach((item, index) => {
|
|
9
|
+
if (typeof item === "string" || !isRecord(item)) return;
|
|
10
|
+
const itemPath = `${path}[${index}]`;
|
|
11
|
+
visit(item, itemPath);
|
|
12
|
+
walkSchema(item, itemPath, visit);
|
|
13
|
+
});
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (!isRecord(schema)) return;
|
|
17
|
+
const node = schema;
|
|
18
|
+
visit(node, path);
|
|
19
|
+
if (node.children) walkSchema(node.children, `${path}.children`, visit);
|
|
20
|
+
if (node.schema) walkSchema(node.schema, `${path}.schema`, visit);
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Walk a SchemaForm tree and verify every `$field` / `$cmp` key can resolve.
|
|
24
|
+
* Useful in dev/test bootstraps before shipping large CP schemas.
|
|
25
|
+
*/
|
|
26
|
+
var assertSchemaRegistry = (schema, options = {}) => {
|
|
27
|
+
const { failFast = false } = options;
|
|
28
|
+
const fieldRegistry = getFormFieldRegistry();
|
|
29
|
+
const componentRegistry = getFormComponentRegistry();
|
|
30
|
+
const issues = [];
|
|
31
|
+
walkSchema(schema, "schema", (node, nodePath) => {
|
|
32
|
+
if (node.$field) {
|
|
33
|
+
const key = String(node.$field);
|
|
34
|
+
if (!fieldRegistry[key] && !isBuiltinFormFieldType(key)) {
|
|
35
|
+
const issue = {
|
|
36
|
+
path: nodePath,
|
|
37
|
+
kind: "field",
|
|
38
|
+
key
|
|
39
|
+
};
|
|
40
|
+
issues.push(issue);
|
|
41
|
+
if (failFast) throw new Error(`SchemaForm: unregistered field "${key}" at ${nodePath}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (node.$cmp) {
|
|
45
|
+
const key = String(node.$cmp);
|
|
46
|
+
if (!componentRegistry[key]) {
|
|
47
|
+
const issue = {
|
|
48
|
+
path: nodePath,
|
|
49
|
+
kind: "component",
|
|
50
|
+
key
|
|
51
|
+
};
|
|
52
|
+
issues.push(issue);
|
|
53
|
+
if (failFast) throw new Error(`SchemaForm: unregistered component "${key}" at ${nodePath}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return issues;
|
|
58
|
+
};
|
|
59
|
+
var debugSchemaRegistry = (schemaIndex, options) => {
|
|
60
|
+
if (!schemaIndex?.schema) return [];
|
|
61
|
+
const issues = assertSchemaRegistry(schemaIndex.schema, options);
|
|
62
|
+
if (issues.length) console.warn("[plugin-kit] SchemaForm registry gaps:", issues);
|
|
63
|
+
return issues;
|
|
64
|
+
};
|
|
65
|
+
//#endregion
|
|
66
|
+
export { assertSchemaRegistry, debugSchemaRegistry };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=assertSchemaRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertSchemaRegistry.js","names":[],"sources":["../../src/forms/assertSchemaRegistry.ts"],"sourcesContent":["import type { SchemaIndex, SchemaNode, SchemaRenderable } from '@verbb/plugin-kit-forms';\n\nimport { isBuiltinFormFieldType } from './builtin-field-loaders.js';\nimport { getFormComponentRegistry, getFormFieldRegistry } from './registry.js';\nimport { isRecord } from './utils.js';\n\nexport type AssertSchemaRegistryOptions = {\n /** When true, throw on the first missing registry key instead of collecting all. */\n failFast?: boolean;\n};\n\nexport type SchemaRegistryIssue = {\n path: string;\n kind: 'field' | 'component';\n key: string;\n};\n\nconst walkSchema = (\n schema: SchemaRenderable,\n path: string,\n visit: (node: SchemaNode, path: string) => void,\n): void => {\n if (typeof schema === 'string') {\n return;\n }\n\n if (Array.isArray(schema)) {\n schema.forEach((item, index) => {\n if (typeof item === 'string' || !isRecord(item)) {\n return;\n }\n\n const itemPath = `${path}[${index}]`;\n visit(item as SchemaNode, itemPath);\n walkSchema(item as SchemaRenderable, itemPath, visit);\n });\n return;\n }\n\n if (!isRecord(schema)) {\n return;\n }\n\n const node = schema as SchemaNode;\n visit(node, path);\n\n if (node.children) {\n walkSchema(node.children as SchemaRenderable, `${path}.children`, visit);\n }\n\n if (node.schema) {\n walkSchema(node.schema as SchemaRenderable, `${path}.schema`, visit);\n }\n};\n\n/**\n * Walk a SchemaForm tree and verify every `$field` / `$cmp` key can resolve.\n * Useful in dev/test bootstraps before shipping large CP schemas.\n */\nexport const assertSchemaRegistry = (\n schema: SchemaRenderable,\n options: AssertSchemaRegistryOptions = {},\n): SchemaRegistryIssue[] => {\n const { failFast = false } = options;\n const fieldRegistry = getFormFieldRegistry();\n const componentRegistry = getFormComponentRegistry();\n const issues: SchemaRegistryIssue[] = [];\n\n walkSchema(schema, 'schema', (node, nodePath) => {\n if (node.$field) {\n const key = String(node.$field);\n if (!fieldRegistry[key] && !isBuiltinFormFieldType(key)) {\n const issue: SchemaRegistryIssue = { path: nodePath, kind: 'field', key };\n issues.push(issue);\n if (failFast) {\n throw new Error(`SchemaForm: unregistered field \"${key}\" at ${nodePath}`);\n }\n }\n }\n\n if (node.$cmp) {\n const key = String(node.$cmp);\n if (!componentRegistry[key]) {\n const issue: SchemaRegistryIssue = { path: nodePath, kind: 'component', key };\n issues.push(issue);\n if (failFast) {\n throw new Error(`SchemaForm: unregistered component \"${key}\" at ${nodePath}`);\n }\n }\n }\n });\n\n return issues;\n};\n\nexport const debugSchemaRegistry = (\n schemaIndex: SchemaIndex | null | undefined,\n options?: AssertSchemaRegistryOptions,\n): SchemaRegistryIssue[] => {\n if (!schemaIndex?.schema) {\n return [];\n }\n\n const issues = assertSchemaRegistry(schemaIndex.schema, options);\n\n if (issues.length) {\n console.warn('[plugin-kit] SchemaForm registry gaps:', issues);\n }\n\n return issues;\n};\n"],"mappings":";;;;AAiBA,IAAM,cACF,QACA,MACA,UACO;AACP,KAAI,OAAO,WAAW,SAClB;AAGJ,KAAI,MAAM,QAAQ,OAAO,EAAE;AACvB,SAAO,SAAS,MAAM,UAAU;AAC5B,OAAI,OAAO,SAAS,YAAY,CAAC,SAAS,KAAK,CAC3C;GAGJ,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM;AAClC,SAAM,MAAoB,SAAS;AACnC,cAAW,MAA0B,UAAU,MAAM;IACvD;AACF;;AAGJ,KAAI,CAAC,SAAS,OAAO,CACjB;CAGJ,MAAM,OAAO;AACb,OAAM,MAAM,KAAK;AAEjB,KAAI,KAAK,SACL,YAAW,KAAK,UAA8B,GAAG,KAAK,YAAY,MAAM;AAG5E,KAAI,KAAK,OACL,YAAW,KAAK,QAA4B,GAAG,KAAK,UAAU,MAAM;;;;;;AAQ5E,IAAa,wBACT,QACA,UAAuC,EAAE,KACjB;CACxB,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,gBAAgB,sBAAsB;CAC5C,MAAM,oBAAoB,0BAA0B;CACpD,MAAM,SAAgC,EAAE;AAExC,YAAW,QAAQ,WAAW,MAAM,aAAa;AAC7C,MAAI,KAAK,QAAQ;GACb,MAAM,MAAM,OAAO,KAAK,OAAO;AAC/B,OAAI,CAAC,cAAc,QAAQ,CAAC,uBAAuB,IAAI,EAAE;IACrD,MAAM,QAA6B;KAAE,MAAM;KAAU,MAAM;KAAS;KAAK;AACzE,WAAO,KAAK,MAAM;AAClB,QAAI,SACA,OAAM,IAAI,MAAM,mCAAmC,IAAI,OAAO,WAAW;;;AAKrF,MAAI,KAAK,MAAM;GACX,MAAM,MAAM,OAAO,KAAK,KAAK;AAC7B,OAAI,CAAC,kBAAkB,MAAM;IACzB,MAAM,QAA6B;KAAE,MAAM;KAAU,MAAM;KAAa;KAAK;AAC7E,WAAO,KAAK,MAAM;AAClB,QAAI,SACA,OAAM,IAAI,MAAM,uCAAuC,IAAI,OAAO,WAAW;;;GAI3F;AAEF,QAAO;;AAGX,IAAa,uBACT,aACA,YACwB;AACxB,KAAI,CAAC,aAAa,OACd,QAAO,EAAE;CAGb,MAAM,SAAS,qBAAqB,YAAY,QAAQ,QAAQ;AAEhE,KAAI,OAAO,OACP,SAAQ,KAAK,0CAA0C,OAAO;AAGlE,QAAO"}
|