@evanschleret/formforgeclient 1.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/LICENSE +21 -0
- package/README.md +94 -0
- package/dist/module.cjs +112 -0
- package/dist/module.d.cts +20 -0
- package/dist/module.d.mts +20 -0
- package/dist/module.d.ts +20 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +109 -0
- package/dist/runtime/api/categories.d.ts +9 -0
- package/dist/runtime/api/categories.js +83 -0
- package/dist/runtime/api/client.d.ts +45 -0
- package/dist/runtime/api/client.js +148 -0
- package/dist/runtime/api/drafts.d.ts +6 -0
- package/dist/runtime/api/drafts.js +77 -0
- package/dist/runtime/api/http.d.ts +3 -0
- package/dist/runtime/api/http.js +138 -0
- package/dist/runtime/api/index.d.ts +9 -0
- package/dist/runtime/api/index.js +11 -0
- package/dist/runtime/api/management.d.ts +19 -0
- package/dist/runtime/api/management.js +180 -0
- package/dist/runtime/api/request.d.ts +8 -0
- package/dist/runtime/api/request.js +52 -0
- package/dist/runtime/api/responses.d.ts +6 -0
- package/dist/runtime/api/responses.js +61 -0
- package/dist/runtime/api/schema.d.ts +7 -0
- package/dist/runtime/api/schema.js +56 -0
- package/dist/runtime/api/submission.d.ts +11 -0
- package/dist/runtime/api/submission.js +47 -0
- package/dist/runtime/api/upload.d.ts +8 -0
- package/dist/runtime/api/upload.js +37 -0
- package/dist/runtime/composables/index.d.ts +31 -0
- package/dist/runtime/composables/index.js +16 -0
- package/dist/runtime/composables/useFormForgeApi.d.ts +3 -0
- package/dist/runtime/composables/useFormForgeApi.js +4 -0
- package/dist/runtime/composables/useFormForgeBuilder.d.ts +57 -0
- package/dist/runtime/composables/useFormForgeBuilder.js +515 -0
- package/dist/runtime/composables/useFormForgeCategory.d.ts +61 -0
- package/dist/runtime/composables/useFormForgeCategory.js +248 -0
- package/dist/runtime/composables/useFormForgeClient.d.ts +3 -0
- package/dist/runtime/composables/useFormForgeClient.js +200 -0
- package/dist/runtime/composables/useFormForgeDrafts.d.ts +20 -0
- package/dist/runtime/composables/useFormForgeDrafts.js +78 -0
- package/dist/runtime/composables/useFormForgeForm.d.ts +26 -0
- package/dist/runtime/composables/useFormForgeForm.js +114 -0
- package/dist/runtime/composables/useFormForgeGetForm.d.ts +22 -0
- package/dist/runtime/composables/useFormForgeGetForm.js +36 -0
- package/dist/runtime/composables/useFormForgeI18n.d.ts +250 -0
- package/dist/runtime/composables/useFormForgeI18n.js +324 -0
- package/dist/runtime/composables/useFormForgeManagement.d.ts +40 -0
- package/dist/runtime/composables/useFormForgeManagement.js +153 -0
- package/dist/runtime/composables/useFormForgeResolver.d.ts +28 -0
- package/dist/runtime/composables/useFormForgeResolver.js +88 -0
- package/dist/runtime/composables/useFormForgeResponses.d.ts +45 -0
- package/dist/runtime/composables/useFormForgeResponses.js +206 -0
- package/dist/runtime/composables/useFormForgeSchema.d.ts +24 -0
- package/dist/runtime/composables/useFormForgeSchema.js +69 -0
- package/dist/runtime/composables/useFormForgeSubmission.d.ts +12 -0
- package/dist/runtime/composables/useFormForgeSubmission.js +4 -0
- package/dist/runtime/composables/useFormForgeSubmit.d.ts +29 -0
- package/dist/runtime/composables/useFormForgeSubmit.js +291 -0
- package/dist/runtime/composables/useFormForgeUploads.d.ts +21 -0
- package/dist/runtime/composables/useFormForgeUploads.js +37 -0
- package/dist/runtime/composables/useFormForgeWizard.d.ts +20 -0
- package/dist/runtime/composables/useFormForgeWizard.js +83 -0
- package/dist/runtime/index.d.ts +11 -0
- package/dist/runtime/index.js +14 -0
- package/dist/runtime/plugin.d.ts +3 -0
- package/dist/runtime/plugin.js +175 -0
- package/dist/runtime/renderers/default/FormForgeBuilder.d.vue.ts +40 -0
- package/dist/runtime/renderers/default/FormForgeBuilder.vue +1159 -0
- package/dist/runtime/renderers/default/FormForgeBuilder.vue.d.ts +40 -0
- package/dist/runtime/renderers/default/FormForgeCategoryCreateModal.d.vue.ts +16 -0
- package/dist/runtime/renderers/default/FormForgeCategoryCreateModal.vue +129 -0
- package/dist/runtime/renderers/default/FormForgeCategoryCreateModal.vue.d.ts +16 -0
- package/dist/runtime/renderers/default/FormForgeRenderer.d.vue.ts +72 -0
- package/dist/runtime/renderers/default/FormForgeRenderer.vue +1188 -0
- package/dist/runtime/renderers/default/FormForgeRenderer.vue.d.ts +72 -0
- package/dist/runtime/renderers/default/FormForgeResponse.d.vue.ts +18 -0
- package/dist/runtime/renderers/default/FormForgeResponse.vue +744 -0
- package/dist/runtime/renderers/default/FormForgeResponse.vue.d.ts +18 -0
- package/dist/runtime/renderers/default/index.d.ts +5 -0
- package/dist/runtime/renderers/default/index.js +4 -0
- package/dist/runtime/renderers/index.d.ts +2 -0
- package/dist/runtime/renderers/index.js +1 -0
- package/dist/runtime/types/api.d.ts +129 -0
- package/dist/runtime/types/api.js +0 -0
- package/dist/runtime/types/category.d.ts +42 -0
- package/dist/runtime/types/category.js +0 -0
- package/dist/runtime/types/errors.d.ts +16 -0
- package/dist/runtime/types/errors.js +0 -0
- package/dist/runtime/types/index.d.ts +8 -0
- package/dist/runtime/types/index.js +0 -0
- package/dist/runtime/types/json.d.ts +6 -0
- package/dist/runtime/types/json.js +0 -0
- package/dist/runtime/types/management.d.ts +46 -0
- package/dist/runtime/types/management.js +0 -0
- package/dist/runtime/types/nuxt.d.ts +13 -0
- package/dist/runtime/types/nuxt.js +1 -0
- package/dist/runtime/types/schema.d.ts +93 -0
- package/dist/runtime/types/schema.js +0 -0
- package/dist/runtime/utils/category.d.ts +5 -0
- package/dist/runtime/utils/category.js +101 -0
- package/dist/runtime/utils/form-data.d.ts +8 -0
- package/dist/runtime/utils/form-data.js +64 -0
- package/dist/runtime/utils/object.d.ts +8 -0
- package/dist/runtime/utils/object.js +43 -0
- package/dist/runtime/utils/schema.d.ts +3 -0
- package/dist/runtime/utils/schema.js +309 -0
- package/dist/runtime/utils/submission.d.ts +4 -0
- package/dist/runtime/utils/submission.js +45 -0
- package/dist/runtime/validation/errors.d.ts +5 -0
- package/dist/runtime/validation/errors.js +130 -0
- package/dist/runtime/validation/zod.d.ts +6 -0
- package/dist/runtime/validation/zod.js +203 -0
- package/dist/runtime.cjs +16 -0
- package/dist/runtime.d.cts +1 -0
- package/dist/runtime.d.mts +1 -0
- package/dist/runtime.d.ts +1 -0
- package/dist/runtime.mjs +1 -0
- package/dist/types.d.mts +3 -0
- package/package.json +60 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { getFormForgeStringArray, isFormForgeJsonObject, pickFormForgeDataEnvelope } from "./object.js";
|
|
2
|
+
import { normalizeFormForgeCategory } from "./category.js";
|
|
3
|
+
const FIELD_TYPES = [
|
|
4
|
+
"text",
|
|
5
|
+
"textarea",
|
|
6
|
+
"email",
|
|
7
|
+
"number",
|
|
8
|
+
"select",
|
|
9
|
+
"select_menu",
|
|
10
|
+
"radio",
|
|
11
|
+
"checkbox",
|
|
12
|
+
"checkbox_group",
|
|
13
|
+
"switch",
|
|
14
|
+
"date",
|
|
15
|
+
"time",
|
|
16
|
+
"datetime",
|
|
17
|
+
"date_range",
|
|
18
|
+
"datetime_range",
|
|
19
|
+
"file"
|
|
20
|
+
];
|
|
21
|
+
const CONDITION_TARGET_TYPES = ["page", "field"];
|
|
22
|
+
const CONDITION_ACTIONS = ["show", "hide", "skip", "require", "disable"];
|
|
23
|
+
const CONDITION_MATCHES = ["all", "any"];
|
|
24
|
+
const CONDITION_OPERATORS = [
|
|
25
|
+
"eq",
|
|
26
|
+
"neq",
|
|
27
|
+
"in",
|
|
28
|
+
"not_in",
|
|
29
|
+
"gt",
|
|
30
|
+
"gte",
|
|
31
|
+
"lt",
|
|
32
|
+
"lte",
|
|
33
|
+
"contains",
|
|
34
|
+
"not_contains",
|
|
35
|
+
"is_empty",
|
|
36
|
+
"not_empty"
|
|
37
|
+
];
|
|
38
|
+
function isFieldType(value) {
|
|
39
|
+
return FIELD_TYPES.includes(value);
|
|
40
|
+
}
|
|
41
|
+
function isConditionTargetType(value) {
|
|
42
|
+
return CONDITION_TARGET_TYPES.includes(value);
|
|
43
|
+
}
|
|
44
|
+
function isConditionAction(value) {
|
|
45
|
+
return CONDITION_ACTIONS.includes(value);
|
|
46
|
+
}
|
|
47
|
+
function isConditionMatch(value) {
|
|
48
|
+
return CONDITION_MATCHES.includes(value);
|
|
49
|
+
}
|
|
50
|
+
function isConditionOperator(value) {
|
|
51
|
+
return CONDITION_OPERATORS.includes(value);
|
|
52
|
+
}
|
|
53
|
+
function toBoolean(value, fallback) {
|
|
54
|
+
if (typeof value === "boolean") {
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
return fallback;
|
|
58
|
+
}
|
|
59
|
+
function toString(value, fallback) {
|
|
60
|
+
if (typeof value === "string") {
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
return fallback;
|
|
64
|
+
}
|
|
65
|
+
function toNullableString(value) {
|
|
66
|
+
if (typeof value === "string" || value === null) {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
function toNumberOrStringOrNull(value) {
|
|
72
|
+
if (typeof value === "number" || typeof value === "string" || value === null) {
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
77
|
+
function normalizeOption(option) {
|
|
78
|
+
if (typeof option === "string" || typeof option === "number" || typeof option === "boolean" || option === null) {
|
|
79
|
+
return option;
|
|
80
|
+
}
|
|
81
|
+
if (isFormForgeJsonObject(option)) {
|
|
82
|
+
const value = option.value;
|
|
83
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
|
|
84
|
+
return {
|
|
85
|
+
...option,
|
|
86
|
+
value
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
function normalizeOptions(value) {
|
|
93
|
+
if (!Array.isArray(value)) {
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
const options = [];
|
|
97
|
+
for (const option of value) {
|
|
98
|
+
const normalizedOption = normalizeOption(option);
|
|
99
|
+
if (normalizedOption !== null) {
|
|
100
|
+
options.push(normalizedOption);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return options;
|
|
104
|
+
}
|
|
105
|
+
function normalizeField(field, index, fallbackPageKey) {
|
|
106
|
+
const rawType = toString(field.type, "text");
|
|
107
|
+
const fieldType = isFieldType(rawType) ? rawType : "text";
|
|
108
|
+
const name = toString(field.name, `field_${index}`);
|
|
109
|
+
const fieldKey = toString(field.field_key, `${name}_${index}`);
|
|
110
|
+
const pageKey = toString(field.page_key, fallbackPageKey);
|
|
111
|
+
const metaValue = field.meta;
|
|
112
|
+
const meta = isFormForgeJsonObject(metaValue) ? metaValue : {};
|
|
113
|
+
const rulesValue = field.rules;
|
|
114
|
+
const rules = getFormForgeStringArray(rulesValue) ?? [];
|
|
115
|
+
const normalizedField = {
|
|
116
|
+
field_key: fieldKey,
|
|
117
|
+
type: fieldType,
|
|
118
|
+
name,
|
|
119
|
+
page_key: pageKey,
|
|
120
|
+
label: typeof field.label === "string" ? field.label : void 0,
|
|
121
|
+
required: toBoolean(field.required, false),
|
|
122
|
+
nullable: toBoolean(field.nullable, false),
|
|
123
|
+
default: field.default ?? null,
|
|
124
|
+
rules,
|
|
125
|
+
meta,
|
|
126
|
+
placeholder: typeof field.placeholder === "string" ? field.placeholder : void 0,
|
|
127
|
+
help_text: typeof field.help_text === "string" ? field.help_text : void 0,
|
|
128
|
+
min: toNumberOrStringOrNull(field.min),
|
|
129
|
+
max: toNumberOrStringOrNull(field.max),
|
|
130
|
+
step: toNumberOrStringOrNull(field.step),
|
|
131
|
+
multiple: toBoolean(field.multiple, false),
|
|
132
|
+
disabled: toBoolean(field.disabled, false),
|
|
133
|
+
readonly: toBoolean(field.readonly, false),
|
|
134
|
+
options: normalizeOptions(field.options)
|
|
135
|
+
};
|
|
136
|
+
if (fieldType === "file") {
|
|
137
|
+
const accept = getFormForgeStringArray(field.accept);
|
|
138
|
+
const maxSize = typeof field.max_size === "number" || field.max_size === null ? field.max_size : void 0;
|
|
139
|
+
const maxFiles = typeof field.max_files === "number" || field.max_files === null ? field.max_files : void 0;
|
|
140
|
+
const storageValue = field.storage;
|
|
141
|
+
const storage = isFormForgeJsonObject(storageValue) ? storageValue : null;
|
|
142
|
+
return {
|
|
143
|
+
...normalizedField,
|
|
144
|
+
type: "file",
|
|
145
|
+
accept,
|
|
146
|
+
max_size: maxSize,
|
|
147
|
+
max_files: maxFiles,
|
|
148
|
+
storage
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return normalizedField;
|
|
152
|
+
}
|
|
153
|
+
function normalizeFieldsList(value, fallbackPageKey, indexOffset = 0) {
|
|
154
|
+
if (!Array.isArray(value)) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const fields = [];
|
|
158
|
+
for (const [index, item] of value.entries()) {
|
|
159
|
+
if (!isFormForgeJsonObject(item)) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
fields.push(normalizeField(item, indexOffset + index, fallbackPageKey));
|
|
163
|
+
}
|
|
164
|
+
return fields;
|
|
165
|
+
}
|
|
166
|
+
function normalizePageFieldsFromSections(value, pageKey, indexOffset) {
|
|
167
|
+
if (!Array.isArray(value)) {
|
|
168
|
+
return [];
|
|
169
|
+
}
|
|
170
|
+
const fields = [];
|
|
171
|
+
for (const sectionValue of value) {
|
|
172
|
+
if (!isFormForgeJsonObject(sectionValue)) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const sectionFields = normalizeFieldsList(sectionValue.fields, pageKey, indexOffset + fields.length);
|
|
176
|
+
fields.push(...sectionFields);
|
|
177
|
+
}
|
|
178
|
+
return fields;
|
|
179
|
+
}
|
|
180
|
+
function normalizePages(value) {
|
|
181
|
+
if (!Array.isArray(value)) {
|
|
182
|
+
return {
|
|
183
|
+
pages: [],
|
|
184
|
+
fields: []
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const pages = [];
|
|
188
|
+
const fields = [];
|
|
189
|
+
for (const [pageIndex, pageValue] of value.entries()) {
|
|
190
|
+
if (!isFormForgeJsonObject(pageValue)) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const pageKey = toString(pageValue.page_key, `page_${pageIndex + 1}`);
|
|
194
|
+
const pageMetaValue = pageValue.meta;
|
|
195
|
+
const pageMeta = isFormForgeJsonObject(pageMetaValue) ? pageMetaValue : {};
|
|
196
|
+
const pageFields = Array.isArray(pageValue.fields) ? normalizeFieldsList(pageValue.fields, pageKey, fields.length) : normalizePageFieldsFromSections(pageValue.sections, pageKey, fields.length);
|
|
197
|
+
fields.push(...pageFields);
|
|
198
|
+
pages.push({
|
|
199
|
+
page_key: pageKey,
|
|
200
|
+
title: toString(pageValue.title, ""),
|
|
201
|
+
description: toNullableString(pageValue.description),
|
|
202
|
+
meta: pageMeta,
|
|
203
|
+
fields: pageFields
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
pages,
|
|
208
|
+
fields
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function buildPagesFromFlatFields(fields) {
|
|
212
|
+
const pages = [];
|
|
213
|
+
for (const field of fields) {
|
|
214
|
+
let page = pages.find((item) => item.page_key === field.page_key);
|
|
215
|
+
if (page === void 0) {
|
|
216
|
+
page = {
|
|
217
|
+
page_key: field.page_key,
|
|
218
|
+
title: "",
|
|
219
|
+
description: null,
|
|
220
|
+
meta: {},
|
|
221
|
+
fields: []
|
|
222
|
+
};
|
|
223
|
+
pages.push(page);
|
|
224
|
+
}
|
|
225
|
+
page.fields.push(field);
|
|
226
|
+
}
|
|
227
|
+
return pages;
|
|
228
|
+
}
|
|
229
|
+
function normalizeConditionClause(value, index) {
|
|
230
|
+
if (!isFormForgeJsonObject(value)) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
const operatorRaw = toString(value.operator, "eq");
|
|
234
|
+
return {
|
|
235
|
+
field_key: toString(value.field_key, `field_${index + 1}`),
|
|
236
|
+
operator: isConditionOperator(operatorRaw) ? operatorRaw : "eq",
|
|
237
|
+
value: value.value ?? null
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function normalizeConditions(value) {
|
|
241
|
+
if (!Array.isArray(value)) {
|
|
242
|
+
return [];
|
|
243
|
+
}
|
|
244
|
+
const conditions = [];
|
|
245
|
+
for (const [index, item] of value.entries()) {
|
|
246
|
+
if (!isFormForgeJsonObject(item)) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
const targetTypeRaw = toString(item.target_type, "field");
|
|
250
|
+
const actionRaw = toString(item.action, "show");
|
|
251
|
+
const matchRaw = toString(item.match, "all");
|
|
252
|
+
const whenValue = item.when;
|
|
253
|
+
const when = [];
|
|
254
|
+
if (Array.isArray(whenValue)) {
|
|
255
|
+
for (const [whenIndex, clause] of whenValue.entries()) {
|
|
256
|
+
const normalizedClause = normalizeConditionClause(clause, whenIndex);
|
|
257
|
+
if (normalizedClause !== null) {
|
|
258
|
+
when.push(normalizedClause);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
conditions.push({
|
|
263
|
+
condition_key: toString(item.condition_key, `condition_${index + 1}`),
|
|
264
|
+
target_type: isConditionTargetType(targetTypeRaw) ? targetTypeRaw : "field",
|
|
265
|
+
target_key: toString(item.target_key, ""),
|
|
266
|
+
action: isConditionAction(actionRaw) ? actionRaw : "show",
|
|
267
|
+
match: isConditionMatch(matchRaw) ? matchRaw : "all",
|
|
268
|
+
when
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
return conditions;
|
|
272
|
+
}
|
|
273
|
+
function normalizeDraftSettings(value) {
|
|
274
|
+
if (!isFormForgeJsonObject(value)) {
|
|
275
|
+
return {
|
|
276
|
+
enabled: false
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
...value,
|
|
281
|
+
enabled: toBoolean(value.enabled, false)
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
export function normalizeFormForgeSchema(payload) {
|
|
285
|
+
const data = pickFormForgeDataEnvelope(payload);
|
|
286
|
+
const rootFields = normalizeFieldsList(data.fields, "page_1");
|
|
287
|
+
const normalizedPages = normalizePages(data.pages);
|
|
288
|
+
const fields = normalizedPages.fields.length > 0 ? normalizedPages.fields : rootFields;
|
|
289
|
+
const pages = normalizedPages.pages.length > 0 ? normalizedPages.pages : buildPagesFromFlatFields(fields);
|
|
290
|
+
const apiValue = data.api;
|
|
291
|
+
const api = isFormForgeJsonObject(apiValue) ? apiValue : {};
|
|
292
|
+
const metaValue = data.meta;
|
|
293
|
+
const meta = isFormForgeJsonObject(metaValue) ? metaValue : void 0;
|
|
294
|
+
const categoryItem = data.category_item === null ? null : normalizeFormForgeCategory(data.category_item);
|
|
295
|
+
return {
|
|
296
|
+
key: toString(data.key, ""),
|
|
297
|
+
version: toString(data.version, ""),
|
|
298
|
+
title: toString(data.title, ""),
|
|
299
|
+
category: typeof data.category === "string" || data.category === null ? data.category : void 0,
|
|
300
|
+
category_item: categoryItem ?? void 0,
|
|
301
|
+
is_published: toBoolean(data.is_published, false),
|
|
302
|
+
fields,
|
|
303
|
+
pages,
|
|
304
|
+
conditions: normalizeConditions(data.conditions),
|
|
305
|
+
drafts: normalizeDraftSettings(data.drafts),
|
|
306
|
+
api,
|
|
307
|
+
meta
|
|
308
|
+
};
|
|
309
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FormForgeJsonSubmissionPayload, FormForgeJsonSubmissionValue, FormForgeSubmissionPayload, FormForgeSubmissionValue } from '../types/index.js';
|
|
2
|
+
export declare function toFormForgeJsonSubmissionValue(value: FormForgeSubmissionValue | undefined): FormForgeJsonSubmissionValue | undefined;
|
|
3
|
+
export declare function toFormForgeJsonSubmissionPayload(payload: FormForgeSubmissionPayload): FormForgeJsonSubmissionPayload;
|
|
4
|
+
//# sourceMappingURL=submission.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
function isFileValue(value) {
|
|
2
|
+
if (typeof File === "undefined") {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
return value instanceof File;
|
|
6
|
+
}
|
|
7
|
+
export function toFormForgeJsonSubmissionValue(value) {
|
|
8
|
+
if (value === void 0) {
|
|
9
|
+
return void 0;
|
|
10
|
+
}
|
|
11
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
if (isFileValue(value)) {
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
const arrayValue = [];
|
|
19
|
+
for (const item of value) {
|
|
20
|
+
const normalizedItem = toFormForgeJsonSubmissionValue(item);
|
|
21
|
+
if (normalizedItem !== void 0) {
|
|
22
|
+
arrayValue.push(normalizedItem);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return arrayValue;
|
|
26
|
+
}
|
|
27
|
+
const objectValue = {};
|
|
28
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
29
|
+
const normalizedNestedValue = toFormForgeJsonSubmissionValue(nestedValue);
|
|
30
|
+
if (normalizedNestedValue !== void 0) {
|
|
31
|
+
objectValue[key] = normalizedNestedValue;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return objectValue;
|
|
35
|
+
}
|
|
36
|
+
export function toFormForgeJsonSubmissionPayload(payload) {
|
|
37
|
+
const normalizedPayload = {};
|
|
38
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
39
|
+
const normalizedValue = toFormForgeJsonSubmissionValue(value);
|
|
40
|
+
if (normalizedValue !== void 0) {
|
|
41
|
+
normalizedPayload[key] = normalizedValue;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return normalizedPayload;
|
|
45
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FormForgeClientError, FormForgeJsonObject, FormForgeValidationErrorPayload } from '../types/index.js';
|
|
2
|
+
export declare function normalizeFormForgeClientError(status: number, payload: FormForgeJsonObject | null): FormForgeClientError;
|
|
3
|
+
export declare function normalizeNetworkFormForgeError(message: string): FormForgeClientError;
|
|
4
|
+
export declare function parseFormForgeValidationPayload(payload: FormForgeJsonObject | null): FormForgeValidationErrorPayload;
|
|
5
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { isFormForgeJsonObject } from "../utils/object.js";
|
|
2
|
+
function mapStatusToCode(status) {
|
|
3
|
+
if (status === 401) {
|
|
4
|
+
return "unauthorized";
|
|
5
|
+
}
|
|
6
|
+
if (status === 403) {
|
|
7
|
+
return "forbidden";
|
|
8
|
+
}
|
|
9
|
+
if (status === 404) {
|
|
10
|
+
return "not_found";
|
|
11
|
+
}
|
|
12
|
+
if (status === 409) {
|
|
13
|
+
return "conflict";
|
|
14
|
+
}
|
|
15
|
+
if (status === 422) {
|
|
16
|
+
return "validation";
|
|
17
|
+
}
|
|
18
|
+
if (status === 429) {
|
|
19
|
+
return "rate_limited";
|
|
20
|
+
}
|
|
21
|
+
if (status >= 500) {
|
|
22
|
+
return "server_error";
|
|
23
|
+
}
|
|
24
|
+
return "network_error";
|
|
25
|
+
}
|
|
26
|
+
function extractValidationErrors(payload) {
|
|
27
|
+
if (payload === null) {
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
const rawErrors = payload.errors;
|
|
31
|
+
if (!isFormForgeJsonObject(rawErrors)) {
|
|
32
|
+
return void 0;
|
|
33
|
+
}
|
|
34
|
+
const fieldErrors = {};
|
|
35
|
+
for (const [fieldName, fieldValue] of Object.entries(rawErrors)) {
|
|
36
|
+
if (!Array.isArray(fieldValue)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const messages = [];
|
|
40
|
+
for (const item of fieldValue) {
|
|
41
|
+
if (typeof item === "string") {
|
|
42
|
+
messages.push(item);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (messages.length > 0) {
|
|
46
|
+
fieldErrors[fieldName] = messages;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (Object.keys(fieldErrors).length === 0) {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
return fieldErrors;
|
|
53
|
+
}
|
|
54
|
+
function extractMessage(payload) {
|
|
55
|
+
if (payload === null) {
|
|
56
|
+
return "Network error";
|
|
57
|
+
}
|
|
58
|
+
const messageValue = payload.message;
|
|
59
|
+
if (typeof messageValue === "string" && messageValue.length > 0) {
|
|
60
|
+
return messageValue;
|
|
61
|
+
}
|
|
62
|
+
return "Request failed";
|
|
63
|
+
}
|
|
64
|
+
function collectPayloadMessages(payload) {
|
|
65
|
+
if (payload === null) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
const messages = [];
|
|
69
|
+
const messageValue = payload.message;
|
|
70
|
+
if (typeof messageValue === "string" && messageValue.trim() !== "") {
|
|
71
|
+
messages.push(messageValue.trim());
|
|
72
|
+
}
|
|
73
|
+
const validationErrors = extractValidationErrors(payload);
|
|
74
|
+
if (validationErrors !== void 0) {
|
|
75
|
+
for (const [fieldName, fieldMessages] of Object.entries(validationErrors)) {
|
|
76
|
+
messages.push(fieldName);
|
|
77
|
+
for (const fieldMessage of fieldMessages) {
|
|
78
|
+
if (fieldMessage.trim() !== "") {
|
|
79
|
+
messages.push(fieldMessage.trim());
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return messages;
|
|
85
|
+
}
|
|
86
|
+
function hasCategoryInUseConflict(status, payload) {
|
|
87
|
+
if (status !== 409) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const flattened = collectPayloadMessages(payload).map((message) => message.toLowerCase()).join(" ");
|
|
91
|
+
if (flattened === "") {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
const mentionsCategory = flattened.includes("category") || flattened.includes("cat\xE9gorie");
|
|
95
|
+
const mentionsInUse = flattened.includes("in use") || flattened.includes("linked") || flattened.includes("attach") || flattened.includes("used") || flattened.includes("utilis") || flattened.includes("li\xE9e");
|
|
96
|
+
return mentionsCategory && mentionsInUse;
|
|
97
|
+
}
|
|
98
|
+
export function normalizeFormForgeClientError(status, payload) {
|
|
99
|
+
return {
|
|
100
|
+
status,
|
|
101
|
+
code: mapStatusToCode(status),
|
|
102
|
+
message: extractMessage(payload),
|
|
103
|
+
businessCode: hasCategoryInUseConflict(status, payload) ? "CATEGORY_IN_USE" : void 0,
|
|
104
|
+
fieldErrors: extractValidationErrors(payload),
|
|
105
|
+
raw: payload
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export function normalizeNetworkFormForgeError(message) {
|
|
109
|
+
return {
|
|
110
|
+
status: 0,
|
|
111
|
+
code: "network_error",
|
|
112
|
+
message,
|
|
113
|
+
raw: null
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
export function parseFormForgeValidationPayload(payload) {
|
|
117
|
+
if (payload === null) {
|
|
118
|
+
return {};
|
|
119
|
+
}
|
|
120
|
+
const response = {};
|
|
121
|
+
const messageValue = payload.message;
|
|
122
|
+
if (typeof messageValue === "string") {
|
|
123
|
+
response.message = messageValue;
|
|
124
|
+
}
|
|
125
|
+
const errors = extractValidationErrors(payload);
|
|
126
|
+
if (errors !== void 0) {
|
|
127
|
+
response.errors = errors;
|
|
128
|
+
}
|
|
129
|
+
return response;
|
|
130
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { FormForgeFormSchema, FormForgeSubmissionPayload } from '../types/index.js';
|
|
3
|
+
export declare function createFormForgeZodSchema(form: FormForgeFormSchema): z.ZodTypeAny;
|
|
4
|
+
export declare function mapFormForgeZodIssues(error: z.ZodError): Record<string, string[]>;
|
|
5
|
+
export declare function validateFormForgePayload(schema: z.ZodTypeAny, payload: FormForgeSubmissionPayload): Record<string, string[]>;
|
|
6
|
+
//# sourceMappingURL=zod.d.ts.map
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const scalarOptionSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
3
|
+
function applySharedStringRules(baseSchema, rules) {
|
|
4
|
+
let schema = baseSchema;
|
|
5
|
+
for (const rawRule of rules) {
|
|
6
|
+
const [ruleName, ruleArgument] = rawRule.split(":");
|
|
7
|
+
if (ruleName === "email") {
|
|
8
|
+
schema = schema.email();
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
if (ruleName === "min" && ruleArgument !== void 0) {
|
|
12
|
+
const parsedMin = Number.parseInt(ruleArgument, 10);
|
|
13
|
+
if (!Number.isNaN(parsedMin)) {
|
|
14
|
+
schema = schema.min(parsedMin);
|
|
15
|
+
}
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (ruleName === "max" && ruleArgument !== void 0) {
|
|
19
|
+
const parsedMax = Number.parseInt(ruleArgument, 10);
|
|
20
|
+
if (!Number.isNaN(parsedMax)) {
|
|
21
|
+
schema = schema.max(parsedMax);
|
|
22
|
+
}
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return schema;
|
|
27
|
+
}
|
|
28
|
+
function applyArrayRules(baseSchema, rules) {
|
|
29
|
+
let schema = baseSchema;
|
|
30
|
+
for (const rawRule of rules) {
|
|
31
|
+
const [ruleName, ruleArgument] = rawRule.split(":");
|
|
32
|
+
if (ruleName === "min" && ruleArgument !== void 0) {
|
|
33
|
+
const parsedMin = Number.parseInt(ruleArgument, 10);
|
|
34
|
+
if (!Number.isNaN(parsedMin)) {
|
|
35
|
+
schema = schema.min(parsedMin);
|
|
36
|
+
}
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (ruleName === "max" && ruleArgument !== void 0) {
|
|
40
|
+
const parsedMax = Number.parseInt(ruleArgument, 10);
|
|
41
|
+
if (!Number.isNaN(parsedMax)) {
|
|
42
|
+
schema = schema.max(parsedMax);
|
|
43
|
+
}
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return schema;
|
|
48
|
+
}
|
|
49
|
+
function applyNumberRules(baseSchema, rules) {
|
|
50
|
+
let schema = baseSchema;
|
|
51
|
+
for (const rawRule of rules) {
|
|
52
|
+
const [ruleName, ruleArgument] = rawRule.split(":");
|
|
53
|
+
if (ruleName === "min" && ruleArgument !== void 0) {
|
|
54
|
+
const parsedMin = Number.parseFloat(ruleArgument);
|
|
55
|
+
if (!Number.isNaN(parsedMin)) {
|
|
56
|
+
schema = schema.min(parsedMin);
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (ruleName === "max" && ruleArgument !== void 0) {
|
|
61
|
+
const parsedMax = Number.parseFloat(ruleArgument);
|
|
62
|
+
if (!Number.isNaN(parsedMax)) {
|
|
63
|
+
schema = schema.max(parsedMax);
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return schema;
|
|
69
|
+
}
|
|
70
|
+
function buildFieldBaseSchema(field) {
|
|
71
|
+
if (field.type === "text" || field.type === "textarea" || field.type === "email") {
|
|
72
|
+
return applySharedStringRules(z.string(), field.rules);
|
|
73
|
+
}
|
|
74
|
+
if (field.type === "number") {
|
|
75
|
+
return applyNumberRules(z.number(), field.rules);
|
|
76
|
+
}
|
|
77
|
+
if (field.type === "select" || field.type === "select_menu" || field.type === "radio") {
|
|
78
|
+
return scalarOptionSchema;
|
|
79
|
+
}
|
|
80
|
+
if (field.type === "checkbox" || field.type === "switch") {
|
|
81
|
+
return z.boolean();
|
|
82
|
+
}
|
|
83
|
+
if (field.type === "checkbox_group") {
|
|
84
|
+
return applyArrayRules(z.array(scalarOptionSchema), field.rules);
|
|
85
|
+
}
|
|
86
|
+
if (field.type === "date" || field.type === "time" || field.type === "datetime") {
|
|
87
|
+
return applySharedStringRules(z.string(), field.rules);
|
|
88
|
+
}
|
|
89
|
+
if (field.type === "date_range" || field.type === "datetime_range") {
|
|
90
|
+
return z.object({
|
|
91
|
+
start: z.string().nullable(),
|
|
92
|
+
end: z.string().nullable()
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (field.type === "file") {
|
|
96
|
+
const fileSchema = z.custom((value) => {
|
|
97
|
+
if (typeof File === "undefined") {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return value instanceof File;
|
|
101
|
+
});
|
|
102
|
+
if (field.multiple === true) {
|
|
103
|
+
return z.array(fileSchema);
|
|
104
|
+
}
|
|
105
|
+
return fileSchema;
|
|
106
|
+
}
|
|
107
|
+
return scalarOptionSchema;
|
|
108
|
+
}
|
|
109
|
+
function applyRequiredAndNullable(schema, field) {
|
|
110
|
+
const optionalSchema = schema.optional();
|
|
111
|
+
if (field.required === false) {
|
|
112
|
+
return z.preprocess((value) => {
|
|
113
|
+
if (value === void 0 || value === null) {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
if (typeof value === "string" && value.trim() === "") {
|
|
117
|
+
return void 0;
|
|
118
|
+
}
|
|
119
|
+
if ((field.type === "date_range" || field.type === "datetime_range") && typeof value === "object" && value !== null) {
|
|
120
|
+
const rangeValue = value;
|
|
121
|
+
const isStartEmpty = rangeValue.start === void 0 || rangeValue.start === null || rangeValue.start === "";
|
|
122
|
+
const isEndEmpty = rangeValue.end === void 0 || rangeValue.end === null || rangeValue.end === "";
|
|
123
|
+
if (isStartEmpty && isEndEmpty) {
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (field.type === "checkbox_group" && Array.isArray(value) && value.length === 0) {
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
return value;
|
|
131
|
+
}, optionalSchema);
|
|
132
|
+
}
|
|
133
|
+
if (field.type === "text" || field.type === "textarea" || field.type === "email" || field.type === "date" || field.type === "time" || field.type === "datetime") {
|
|
134
|
+
return schema.refine((value) => {
|
|
135
|
+
return typeof value === "string" && value.trim() !== "";
|
|
136
|
+
}, {
|
|
137
|
+
message: "Required"
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (field.type === "select" || field.type === "select_menu" || field.type === "radio") {
|
|
141
|
+
return schema.refine((value) => {
|
|
142
|
+
if (value === null || value === void 0) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
if (typeof value === "string" && value.trim() === "") {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return true;
|
|
149
|
+
}, {
|
|
150
|
+
message: "Required"
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (field.type === "checkbox_group") {
|
|
154
|
+
return schema.refine((value) => {
|
|
155
|
+
return Array.isArray(value) && value.length > 0;
|
|
156
|
+
}, {
|
|
157
|
+
message: "Required"
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (field.type === "date_range" || field.type === "datetime_range") {
|
|
161
|
+
return schema.refine((value) => {
|
|
162
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
const rangeValue = value;
|
|
166
|
+
const isStartValid = typeof rangeValue.start === "string" && rangeValue.start !== "";
|
|
167
|
+
const isEndValid = typeof rangeValue.end === "string" && rangeValue.end !== "";
|
|
168
|
+
return isStartValid && isEndValid;
|
|
169
|
+
}, {
|
|
170
|
+
message: "Required"
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return schema;
|
|
174
|
+
}
|
|
175
|
+
export function createFormForgeZodSchema(form) {
|
|
176
|
+
const shape = {};
|
|
177
|
+
for (const field of form.fields) {
|
|
178
|
+
const baseSchema = buildFieldBaseSchema(field);
|
|
179
|
+
shape[field.name] = applyRequiredAndNullable(baseSchema, field);
|
|
180
|
+
}
|
|
181
|
+
return z.object(shape);
|
|
182
|
+
}
|
|
183
|
+
export function mapFormForgeZodIssues(error) {
|
|
184
|
+
const fieldErrors = {};
|
|
185
|
+
for (const issue of error.issues) {
|
|
186
|
+
const [fieldName] = issue.path;
|
|
187
|
+
if (typeof fieldName !== "string") {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (fieldErrors[fieldName] === void 0) {
|
|
191
|
+
fieldErrors[fieldName] = [];
|
|
192
|
+
}
|
|
193
|
+
fieldErrors[fieldName].push(issue.message);
|
|
194
|
+
}
|
|
195
|
+
return fieldErrors;
|
|
196
|
+
}
|
|
197
|
+
export function validateFormForgePayload(schema, payload) {
|
|
198
|
+
const result = schema.safeParse(payload);
|
|
199
|
+
if (result.success) {
|
|
200
|
+
return {};
|
|
201
|
+
}
|
|
202
|
+
return mapFormForgeZodIssues(result.error);
|
|
203
|
+
}
|