@formatica/core 0.1.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,34 +1,184 @@
1
1
  # @formatica/core
2
2
 
3
- Framework-agnostic schema-driven form engine. Provides types, validation, parsing, and conditional logic used by `@formatica/vue` and `@formatica/react`.
3
+ Framework-agnostic schema-driven form engine. Provides types, validation, schema parsing, condition evaluation, field extraction, and global configuration used by `@formatica/vue` and `@formatica/react`.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install @formatica/core
9
+ # or
10
+ yarn add @formatica/core
11
+ ```
12
+
13
+ Zero external dependencies. Lightweight and framework-agnostic.
14
+
15
+ ## What's Included
16
+
17
+ - **Types** -- `FormSchema`, `FieldSchema`, `SchemaNode`, `ThemeConfig`, `Condition`, and all related interfaces
18
+ - **Validation** -- Rule registry with 14+ built-in rules, custom sync/async rules, `registerRule`, `getRule`, `hasRule`, `unregisterRule`
19
+ - **Schema parsing** -- `parseFormSchema()` validates and parses raw JSON into typed `FormSchema` objects
20
+ - **Field extraction** -- `extractFields()` flattens the schema tree into a plain array of `FieldSchema`
21
+ - **Condition evaluation** -- `evaluateCondition()` resolves show/hide conditions against form values
22
+ - **Global configuration** -- `configureFormatica()` sets default theme and locale
23
+
24
+ ## Global Configuration
25
+
26
+ ```ts
27
+ import { configureFormatica, getFormaticaConfig } from "@formatica/core";
28
+
29
+ configureFormatica({
30
+ theme: {
31
+ name: "my-theme",
32
+ colors: { primary: "#059669" },
33
+ },
34
+ locale: "en",
35
+ });
36
+
37
+ // Access later
38
+ const config = getFormaticaConfig();
39
+ ```
40
+
41
+ ### FormaticaCoreConfig
42
+
43
+ ```ts
44
+ interface FormaticaCoreConfig {
45
+ theme?: ThemeConfig;
46
+ locale?: string;
47
+ }
9
48
  ```
10
49
 
11
50
  ## Usage
12
51
 
13
- `@formatica/core` is typically used indirectly through `@formatica/vue` or `@formatica/react`. You can also use it directly to work with form schemas, validators, and parsers.
52
+ ### Parse a schema
53
+
54
+ ```ts
55
+ import { parseFormSchema } from "@formatica/core";
56
+
57
+ const json = '{ "fields": [{ "type": "text", "name": "email", "label": "Email" }] }';
58
+
59
+ try {
60
+ const schema = parseFormSchema(JSON.parse(json));
61
+ console.log("Valid schema:", schema);
62
+ } catch (err) {
63
+ // SchemaValidationError with details
64
+ console.error("Invalid schema:", err.message);
65
+ }
66
+ ```
67
+
68
+ ### Extract fields
14
69
 
15
70
  ```ts
16
- import type { FormSchema, FieldConfig } from "@formatica/core";
17
- import { validateField, parseFieldValue } from "@formatica/core";
71
+ import { extractFields, isFieldNode } from "@formatica/core";
72
+
73
+ // Flatten the schema tree into a plain array of FieldSchema
74
+ const fields = extractFields(schema.fields);
75
+
76
+ for (const field of fields) {
77
+ console.log(field.name, field.type, field.rules);
78
+ }
18
79
 
19
- const schema: FormSchema = {
20
- fields: [
21
- { name: "email", type: "email", label: "Email", required: true },
80
+ // Check if a node is a field (not a layout container)
81
+ for (const node of schema.fields) {
82
+ if (isFieldNode(node)) {
83
+ console.log("Field:", node.name);
84
+ } else {
85
+ console.log("Layout:", node.type);
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### Evaluate conditions
91
+
92
+ ```ts
93
+ import { evaluateCondition } from "@formatica/core";
94
+
95
+ const condition = { field: "country", operator: "eq", value: "NL" };
96
+ const values = { country: "NL", city: "Amsterdam" };
97
+
98
+ const visible = evaluateCondition(condition, values);
99
+ console.log(visible); // true
100
+
101
+ // Complex condition group
102
+ const group = {
103
+ and: [
104
+ { field: "age", operator: "gte", value: 18 },
105
+ {
106
+ or: [
107
+ { field: "country", operator: "eq", value: "NL" },
108
+ { field: "country", operator: "eq", value: "DE" },
109
+ ],
110
+ },
22
111
  ],
23
112
  };
113
+ ```
114
+
115
+ ### Validate data
116
+
117
+ ```ts
118
+ import { getRule, registerRule, hasRule, unregisterRule } from "@formatica/core";
119
+
120
+ // Register a custom rule
121
+ registerRule("postalCode", (value) => {
122
+ if (!value) return true;
123
+ return /^\d{4}\s?[A-Za-z]{2}$/.test(String(value)) || "Enter a valid Dutch postal code";
124
+ });
125
+
126
+ // Check if a rule exists
127
+ console.log(hasRule("postalCode")); // true
24
128
 
25
- // Validate a field value
26
- const error = validateField(schema.fields[0], "user@example.com");
129
+ // Get and run a rule
130
+ const ruleFn = getRule("required");
131
+ if (ruleFn) {
132
+ const result = await ruleFn(value, {}, ctx);
133
+ if (typeof result === "string") {
134
+ console.error("Validation error:", result);
135
+ }
136
+ }
27
137
 
28
- // Parse a field value
29
- const parsed = parseFieldValue(schema.fields[0], "user@example.com");
138
+ // Remove a rule
139
+ unregisterRule("postalCode");
30
140
  ```
31
141
 
142
+ ## All Exports
143
+
144
+ ### Functions
145
+
146
+ | Export | Description |
147
+ | --- | --- |
148
+ | `configureFormatica()` | Set global theme and locale |
149
+ | `getFormaticaConfig()` | Get current global config |
150
+ | `parseFormSchema()` | Parse and validate raw JSON into `FormSchema` |
151
+ | `extractFields()` | Flatten schema tree into `FieldSchema[]` |
152
+ | `isFieldNode()` | Type guard: is a `SchemaNode` a field? |
153
+ | `evaluateCondition()` | Evaluate a condition against form values |
154
+ | `registerRule()` | Register a custom validation rule |
155
+ | `unregisterRule()` | Remove a validation rule |
156
+ | `getRule()` | Get a validation rule function by name |
157
+ | `hasRule()` | Check if a rule is registered |
158
+ | `setFieldTypeChecker()` | Override field type validation |
159
+ | `deepMerge()` | Deep-merge utility |
160
+ | `sanitizeHtml()` | Sanitize HTML for safe rendering |
161
+ | `titleCase()` | Convert string to title case |
162
+
163
+ ### Types
164
+
165
+ | Export | Description |
166
+ | --- | --- |
167
+ | `FormSchema` | Root schema interface |
168
+ | `FieldSchema` | Field configuration |
169
+ | `SchemaNode` | Union of field and layout node types |
170
+ | `ThemeConfig` | Theme configuration (colors, typography, spacing, borders, etc.) |
171
+ | `FormaticaCoreConfig` | Global config interface |
172
+ | `Condition` | Show/hide condition |
173
+ | `I18nContext` | Internationalization context |
174
+ | `SchemaValidationError` | Error thrown by `parseFormSchema()` |
175
+
176
+ ### Error Classes
177
+
178
+ | Export | Description |
179
+ | --- | --- |
180
+ | `SchemaValidationError` | Thrown when schema parsing fails with details |
181
+
32
182
  ## License
33
183
 
34
184
  [MIT](../../LICENSE)
@@ -0,0 +1,8 @@
1
+ import type { ThemeConfig } from "./types/theme";
2
+ export interface FormaticaCoreConfig {
3
+ theme?: ThemeConfig;
4
+ locale?: string;
5
+ }
6
+ export declare function configureFormatica(config: FormaticaCoreConfig): void;
7
+ export declare function getFormaticaConfig(): FormaticaCoreConfig;
8
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAChC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAEpE;AAED,wBAAgB,kBAAkB,IAAI,mBAAmB,CAExD"}
@@ -1,7 +1,59 @@
1
+ function S(e, t, n) {
2
+ switch (t) {
3
+ case "eq":
4
+ return e === n;
5
+ case "neq":
6
+ return e !== n;
7
+ case "gt":
8
+ return Number(e) > Number(n);
9
+ case "gte":
10
+ return Number(e) >= Number(n);
11
+ case "lt":
12
+ return Number(e) < Number(n);
13
+ case "lte":
14
+ return Number(e) <= Number(n);
15
+ case "in":
16
+ return Array.isArray(n) && n.includes(e);
17
+ case "notIn":
18
+ return Array.isArray(n) && !n.includes(e);
19
+ case "contains":
20
+ return typeof e == "string" ? e.includes(String(n)) : Array.isArray(e) ? e.includes(n) : !1;
21
+ case "empty":
22
+ return e == null || e === "" || Array.isArray(e) && e.length === 0;
23
+ case "notEmpty":
24
+ return !(e == null || e === "" || Array.isArray(e) && e.length === 0);
25
+ case "matches": {
26
+ if (typeof n != "string") return !1;
27
+ try {
28
+ return new RegExp(n).test(String(e));
29
+ } catch {
30
+ return !1;
31
+ }
32
+ }
33
+ default:
34
+ return !1;
35
+ }
36
+ }
37
+ function x(e) {
38
+ return "and" in e || "or" in e;
39
+ }
40
+ function w(e, t) {
41
+ if (x(e))
42
+ return e.and ? e.and.every((r) => w(r, t)) : e.or ? e.or.some((r) => w(r, t)) : !0;
43
+ const n = t[e.field];
44
+ return S(n, e.operator, e.value);
45
+ }
46
+ let N = {};
47
+ function F(e) {
48
+ N = { ...e };
49
+ }
50
+ function R() {
51
+ return N;
52
+ }
1
53
  function g(e) {
2
54
  const t = [];
3
55
  for (const n of e)
4
- if (N(n))
56
+ if (j(n))
5
57
  t.push(n);
6
58
  else if (n.type === "row" || n.type === "group")
7
59
  t.push(...g(n.children));
@@ -13,7 +65,7 @@ function g(e) {
13
65
  t.push(...g(r.children));
14
66
  return t;
15
67
  }
16
- function N(e) {
68
+ function j(e) {
17
69
  return "name" in e && typeof e.name == "string";
18
70
  }
19
71
  class b extends Error {
@@ -22,7 +74,7 @@ class b extends Error {
22
74
  super(`Schema validation failed: ${n}`), this.name = "SchemaValidationError", this.errors = t;
23
75
  }
24
76
  }
25
- const S = /* @__PURE__ */ new Set([
77
+ const T = /* @__PURE__ */ new Set([
26
78
  "text",
27
79
  "number",
28
80
  "textarea",
@@ -38,9 +90,9 @@ const S = /* @__PURE__ */ new Set([
38
90
  "richtext",
39
91
  "hidden",
40
92
  "phone"
41
- ]), x = /* @__PURE__ */ new Set(["row", "group", "steps", "tabs", "divider", "html"]);
93
+ ]), z = /* @__PURE__ */ new Set(["row", "group", "steps", "tabs", "divider", "html"]);
42
94
  let p = null;
43
- function E(e) {
95
+ function v(e) {
44
96
  p = e;
45
97
  }
46
98
  function m(e) {
@@ -85,13 +137,13 @@ function A(e, t, n, r) {
85
137
  message: 'Condition must have an "operator" property'
86
138
  });
87
139
  }
88
- function j(e, t, n, r) {
140
+ function M(e, t, n, r) {
89
141
  if (!m(e)) {
90
142
  r.push({ field: t, rule: "type", message: "Field must be an object" });
91
143
  return;
92
144
  }
93
145
  const i = e;
94
- (typeof i.name != "string" || i.name.length === 0) && r.push({ field: t, rule: "name", message: 'Field must have a non-empty "name"' }), typeof i.type != "string" ? r.push({ field: t, rule: "type", message: 'Field must have a "type" string' }) : !S.has(i.type) && !(p != null && p(i.type)) && r.push({
146
+ (typeof i.name != "string" || i.name.length === 0) && r.push({ field: t, rule: "name", message: 'Field must have a non-empty "name"' }), typeof i.type != "string" ? r.push({ field: t, rule: "type", message: 'Field must have a "type" string' }) : !T.has(i.type) && !(p != null && p(i.type)) && r.push({
95
147
  field: `${t}.${i.name}`,
96
148
  rule: "type",
97
149
  message: `Unknown field type "${i.type}"`
@@ -101,7 +153,7 @@ function j(e, t, n, r) {
101
153
  message: `Field type "${i.type}" requires an "options" property`
102
154
  }), i.condition && A(i.condition, `${t}.${i.name}`, n, r);
103
155
  }
104
- function T(e, t, n, r) {
156
+ function C(e, t, n, r) {
105
157
  if (!m(e)) {
106
158
  r.push({ field: t, rule: "type", message: "Node must be an object" });
107
159
  return;
@@ -112,10 +164,10 @@ function T(e, t, n, r) {
112
164
  return;
113
165
  }
114
166
  if (typeof i.name == "string") {
115
- j(e, t, n, r);
167
+ M(e, t, n, r);
116
168
  return;
117
169
  }
118
- if (!x.has(s)) {
170
+ if (!z.has(s)) {
119
171
  r.push({
120
172
  field: t,
121
173
  rule: "type",
@@ -195,9 +247,9 @@ function T(e, t, n, r) {
195
247
  }
196
248
  function y(e, t, n, r) {
197
249
  for (let i = 0; i < e.length; i++)
198
- T(e[i], `${t}[${i}]`, n, r);
250
+ C(e[i], `${t}[${i}]`, n, r);
199
251
  }
200
- function z(e, t) {
252
+ function q(e, t) {
201
253
  if (!m(e)) {
202
254
  t.push({ field: "settings", rule: "type", message: "Settings must be an object" });
203
255
  return;
@@ -213,7 +265,7 @@ function z(e, t) {
213
265
  message: 'Size must be "small", "medium", or "large"'
214
266
  });
215
267
  }
216
- function R(e) {
268
+ function I(e) {
217
269
  const t = [];
218
270
  if (!m(e))
219
271
  throw t.push({ field: "$root", rule: "type", message: "Schema must be a plain object" }), new b(t);
@@ -230,7 +282,7 @@ function R(e) {
230
282
  message: `Duplicate field name "${a.name}"`
231
283
  });
232
284
  }
233
- if (y(n.fields, "fields", i, t), n.settings !== void 0 && z(n.settings, t), t.length > 0)
285
+ if (y(n.fields, "fields", i, t), n.settings !== void 0 && q(n.settings, t), t.length > 0)
234
286
  throw new b(t);
235
287
  return {
236
288
  id: typeof n.id == "string" ? n.id : void 0,
@@ -240,17 +292,36 @@ function R(e) {
240
292
  translations: n.translations
241
293
  };
242
294
  }
295
+ function $(e) {
296
+ if (typeof e != "object" || e === null) return !1;
297
+ const t = Object.getPrototypeOf(e);
298
+ return t === Object.prototype || t === null;
299
+ }
300
+ function E(e, t) {
301
+ const n = { ...e };
302
+ for (const r of Object.keys(t)) {
303
+ const i = t[r], s = n[r];
304
+ $(i) && $(s) ? n[r] = E(s, i) : n[r] = i;
305
+ }
306
+ return n;
307
+ }
308
+ function O(e) {
309
+ return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "").replace(/\s+on\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "").replace(/(href|src|action)\s*=\s*(?:"javascript:[^"]*"|'javascript:[^']*')/gi, '$1=""');
310
+ }
311
+ function D(e) {
312
+ return e.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").replace(/\b\w/g, (t) => t.toUpperCase()).trim();
313
+ }
243
314
  const h = /* @__PURE__ */ new Map();
244
315
  function o(e, t) {
245
316
  h.set(e, t);
246
317
  }
247
- function v(e) {
318
+ function L(e) {
248
319
  h.delete(e);
249
320
  }
250
- function F(e) {
321
+ function k(e) {
251
322
  return h.get(e);
252
323
  }
253
- function I(e) {
324
+ function P(e) {
254
325
  return h.has(e);
255
326
  }
256
327
  function u(e) {
@@ -377,83 +448,21 @@ o("maxFiles", (e, t) => {
377
448
  });
378
449
  o("unique", (e) => u(e) || !Array.isArray(e) ? !0 : new Set(e).size === e.length || "All values must be unique");
379
450
  o("custom", (e, t) => !0);
380
- function M(e, t, n) {
381
- switch (t) {
382
- case "eq":
383
- return e === n;
384
- case "neq":
385
- return e !== n;
386
- case "gt":
387
- return Number(e) > Number(n);
388
- case "gte":
389
- return Number(e) >= Number(n);
390
- case "lt":
391
- return Number(e) < Number(n);
392
- case "lte":
393
- return Number(e) <= Number(n);
394
- case "in":
395
- return Array.isArray(n) && n.includes(e);
396
- case "notIn":
397
- return Array.isArray(n) && !n.includes(e);
398
- case "contains":
399
- return typeof e == "string" ? e.includes(String(n)) : Array.isArray(e) ? e.includes(n) : !1;
400
- case "empty":
401
- return e == null || e === "" || Array.isArray(e) && e.length === 0;
402
- case "notEmpty":
403
- return !(e == null || e === "" || Array.isArray(e) && e.length === 0);
404
- case "matches": {
405
- if (typeof n != "string") return !1;
406
- try {
407
- return new RegExp(n).test(String(e));
408
- } catch {
409
- return !1;
410
- }
411
- }
412
- default:
413
- return !1;
414
- }
415
- }
416
- function q(e) {
417
- return "and" in e || "or" in e;
418
- }
419
- function w(e, t) {
420
- if (q(e))
421
- return e.and ? e.and.every((r) => w(r, t)) : e.or ? e.or.some((r) => w(r, t)) : !0;
422
- const n = t[e.field];
423
- return M(n, e.operator, e.value);
424
- }
425
- function $(e) {
426
- if (typeof e != "object" || e === null) return !1;
427
- const t = Object.getPrototypeOf(e);
428
- return t === Object.prototype || t === null;
429
- }
430
- function C(e, t) {
431
- const n = { ...e };
432
- for (const r of Object.keys(t)) {
433
- const i = t[r], s = n[r];
434
- $(i) && $(s) ? n[r] = C(s, i) : n[r] = i;
435
- }
436
- return n;
437
- }
438
- function O(e) {
439
- return e.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").replace(/\b\w/g, (t) => t.toUpperCase()).trim();
440
- }
441
- function D(e) {
442
- return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "").replace(/\s+on\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "").replace(/(href|src|action)\s*=\s*(?:"javascript:[^"]*"|'javascript:[^']*')/gi, '$1=""');
443
- }
444
451
  export {
445
452
  b as SchemaValidationError,
446
- C as deepMerge,
453
+ F as configureFormatica,
454
+ E as deepMerge,
447
455
  w as evaluateCondition,
448
456
  g as extractFields,
449
- F as getRule,
450
- I as hasRule,
451
- N as isFieldNode,
452
- R as parseFormSchema,
457
+ R as getFormaticaConfig,
458
+ k as getRule,
459
+ P as hasRule,
460
+ j as isFieldNode,
461
+ I as parseFormSchema,
453
462
  o as registerRule,
454
- D as sanitizeHtml,
455
- E as setFieldTypeChecker,
456
- O as titleCase,
457
- v as unregisterRule
463
+ O as sanitizeHtml,
464
+ v as setFieldTypeChecker,
465
+ D as titleCase,
466
+ L as unregisterRule
458
467
  };
459
468
  //# sourceMappingURL=formatica-core.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatica-core.es.js","sources":["../src/extractFields.ts","../src/schemaParser.ts","../src/validation/ruleRegistry.ts","../src/conditions.ts","../src/utils/deepMerge.ts","../src/utils/titleCase.ts","../src/utils/sanitize.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Formatica Core – Utility to extract field schemas from a unified schema tree\n// ---------------------------------------------------------------------------\n\nimport type { FieldSchema, SchemaNode } from \"./types/schema\";\n\n/**\n * Recursively walks a `SchemaNode[]` tree and collects every node that is an\n * actual field (i.e. has a `name` property), ignoring layout containers.\n */\nexport function extractFields(nodes: SchemaNode[]): FieldSchema[] {\n const fields: FieldSchema[] = [];\n for (const node of nodes) {\n if (isFieldNode(node)) {\n fields.push(node);\n } else if (node.type === \"row\" || node.type === \"group\") {\n fields.push(...extractFields(node.children));\n } else if (node.type === \"steps\") {\n for (const step of node.steps) {\n fields.push(...extractFields(step.children));\n }\n } else if (node.type === \"tabs\") {\n for (const tab of node.tabs) {\n fields.push(...extractFields(tab.children));\n }\n }\n }\n return fields;\n}\n\n/**\n * Type-guard that distinguishes field nodes from layout container nodes.\n */\nexport function isFieldNode(node: SchemaNode): node is FieldSchema {\n return \"name\" in node && typeof node.name === \"string\";\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Schema parser & validator\n// ---------------------------------------------------------------------------\n\nimport type {\n Condition,\n ConditionGroup,\n FormSchema,\n FormSettings,\n SchemaNode,\n} from \"./types/schema\";\nimport type { SchemaError } from \"./types/validation\";\nimport { extractFields } from \"./extractFields\";\n\n// ---------------------------------------------------------------------------\n// Error class\n// ---------------------------------------------------------------------------\n\nexport class SchemaValidationError extends Error {\n public readonly errors: SchemaError[];\n\n constructor(errors: SchemaError[]) {\n const summary = errors.map((e) => `[${e.field}] ${e.message}`).join(\"; \");\n super(`Schema validation failed: ${summary}`);\n this.name = \"SchemaValidationError\";\n this.errors = errors;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Known field types\n// ---------------------------------------------------------------------------\n\nconst KNOWN_FIELD_TYPES = new Set([\n \"text\",\n \"number\",\n \"textarea\",\n \"select\",\n \"checkbox\",\n \"checkbox-group\",\n \"radio\",\n \"switch\",\n \"date\",\n \"file\",\n \"slider\",\n \"tags\",\n \"richtext\",\n \"hidden\",\n \"phone\",\n]);\n\nconst CONTAINER_TYPES = new Set([\"row\", \"group\", \"steps\", \"tabs\", \"divider\", \"html\"]);\n\n// ---------------------------------------------------------------------------\n// Custom field type checker (pluggable for framework-specific registries)\n// ---------------------------------------------------------------------------\n\nlet customFieldTypeChecker: ((type: string) => boolean) | null = null;\n\n/**\n * Register a custom field type checker. This allows framework-specific packages\n * (e.g. @formatica/vue) to hook their field registry into schema validation.\n */\nexport function setFieldTypeChecker(checker: ((type: string) => boolean) | null): void {\n customFieldTypeChecker = checker;\n}\n\n// ---------------------------------------------------------------------------\n// Validation helpers\n// ---------------------------------------------------------------------------\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateCondition(\n condition: unknown,\n fieldPath: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(condition)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: \"Condition must be an object\",\n });\n return;\n }\n\n const cond = condition as Record<string, unknown>;\n\n // Compound conditions\n if (\"and\" in cond || \"or\" in cond) {\n const group = cond as ConditionGroup;\n const children = group.and ?? group.or ?? [];\n if (!Array.isArray(children)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: \"Compound condition must have an array of sub-conditions\",\n });\n return;\n }\n for (let i = 0; i < children.length; i++) {\n validateCondition(children[i], `${fieldPath}.condition[${i}]`, allFieldNames, errors);\n }\n return;\n }\n\n // Simple condition\n const simple = cond as unknown as Condition;\n if (typeof simple.field !== \"string\") {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: 'Condition must have a \"field\" property of type string',\n });\n } else if (!allFieldNames.has(simple.field)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: `Condition references unknown field \"${simple.field}\"`,\n });\n }\n\n if (typeof simple.operator !== \"string\") {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: 'Condition must have an \"operator\" property',\n });\n }\n}\n\nfunction validateFieldNode(\n field: unknown,\n path: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(field)) {\n errors.push({ field: path, rule: \"type\", message: \"Field must be an object\" });\n return;\n }\n\n const f = field as Record<string, unknown>;\n\n // name\n if (typeof f.name !== \"string\" || f.name.length === 0) {\n errors.push({ field: path, rule: \"name\", message: 'Field must have a non-empty \"name\"' });\n }\n\n // type\n if (typeof f.type !== \"string\") {\n errors.push({ field: path, rule: \"type\", message: 'Field must have a \"type\" string' });\n } else if (!KNOWN_FIELD_TYPES.has(f.type) && !customFieldTypeChecker?.(f.type)) {\n errors.push({\n field: `${path}.${f.name as string}`,\n rule: \"type\",\n message: `Unknown field type \"${f.type}\"`,\n });\n }\n\n // options required for select, radio, checkbox-group\n if ([\"select\", \"radio\", \"checkbox-group\"].includes(f.type as string)) {\n if (f.options === undefined || f.options === null) {\n errors.push({\n field: `${path}.${f.name as string}`,\n rule: \"options\",\n message: `Field type \"${f.type as string}\" requires an \"options\" property`,\n });\n }\n }\n\n // condition references\n if (f.condition) {\n validateCondition(f.condition, `${path}.${f.name as string}`, allFieldNames, errors);\n }\n}\n\nfunction validateNode(\n node: unknown,\n path: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(node)) {\n errors.push({ field: path, rule: \"type\", message: \"Node must be an object\" });\n return;\n }\n\n const n = node as Record<string, unknown>;\n const type = n.type as string;\n\n if (typeof type !== \"string\") {\n errors.push({ field: path, rule: \"type\", message: 'Node must have a \"type\" string' });\n return;\n }\n\n // If it's a field node (has a name), validate as field\n if (typeof n.name === \"string\") {\n validateFieldNode(node, path, allFieldNames, errors);\n return;\n }\n\n // Container nodes\n if (!CONTAINER_TYPES.has(type)) {\n errors.push({\n field: path,\n rule: \"type\",\n message: `Unknown node type \"${type}\"`,\n });\n return;\n }\n\n if (type === \"row\" || type === \"group\") {\n if (!Array.isArray(n.children)) {\n errors.push({\n field: path,\n rule: \"children\",\n message: `\"${type}\" node must have a \"children\" array`,\n });\n } else {\n validateNodes(n.children, `${path}.children`, allFieldNames, errors);\n }\n if (type === \"group\" && n.condition) {\n validateCondition(n.condition, `${path}.condition`, allFieldNames, errors);\n }\n } else if (type === \"steps\") {\n if (!Array.isArray(n.steps)) {\n errors.push({\n field: path,\n rule: \"steps\",\n message: '\"steps\" node must have a \"steps\" array',\n });\n } else {\n for (let i = 0; i < n.steps.length; i++) {\n const step = n.steps[i] as Record<string, unknown>;\n if (!isPlainObject(step)) {\n errors.push({\n field: `${path}.steps[${i}]`,\n rule: \"type\",\n message: \"Step item must be an object\",\n });\n continue;\n }\n if (typeof step.title !== \"string\") {\n errors.push({\n field: `${path}.steps[${i}]`,\n rule: \"title\",\n message: 'Step item must have a \"title\" string',\n });\n }\n if (Array.isArray(step.children)) {\n validateNodes(\n step.children,\n `${path}.steps[${i}].children`,\n allFieldNames,\n errors,\n );\n }\n }\n }\n } else if (type === \"tabs\") {\n if (!Array.isArray(n.tabs)) {\n errors.push({\n field: path,\n rule: \"tabs\",\n message: '\"tabs\" node must have a \"tabs\" array',\n });\n } else {\n for (let i = 0; i < n.tabs.length; i++) {\n const tab = n.tabs[i] as Record<string, unknown>;\n if (!isPlainObject(tab)) {\n errors.push({\n field: `${path}.tabs[${i}]`,\n rule: \"type\",\n message: \"Tab item must be an object\",\n });\n continue;\n }\n if (typeof tab.title !== \"string\") {\n errors.push({\n field: `${path}.tabs[${i}]`,\n rule: \"title\",\n message: 'Tab item must have a \"title\" string',\n });\n }\n if (Array.isArray(tab.children)) {\n validateNodes(\n tab.children,\n `${path}.tabs[${i}].children`,\n allFieldNames,\n errors,\n );\n }\n }\n }\n } else if (type === \"html\") {\n if (typeof n.content !== \"string\") {\n errors.push({\n field: path,\n rule: \"content\",\n message: '\"html\" node must have a \"content\" string',\n });\n }\n }\n // \"divider\" has no required children/content — always valid if type matches\n}\n\nfunction validateNodes(\n nodes: unknown[],\n basePath: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n for (let i = 0; i < nodes.length; i++) {\n validateNode(nodes[i], `${basePath}[${i}]`, allFieldNames, errors);\n }\n}\n\nfunction validateSettings(settings: unknown, errors: SchemaError[]): void {\n if (!isPlainObject(settings)) {\n errors.push({ field: \"settings\", rule: \"type\", message: \"Settings must be an object\" });\n return;\n }\n\n const s = settings as Record<string, unknown>;\n\n if (\n s.layout !== undefined &&\n ![\"vertical\", \"horizontal\", \"inline\"].includes(s.layout as string)\n ) {\n errors.push({\n field: \"settings.layout\",\n rule: \"enum\",\n message: 'Layout must be \"vertical\", \"horizontal\", or \"inline\"',\n });\n }\n\n if (s.size !== undefined && ![\"small\", \"medium\", \"large\"].includes(s.size as string)) {\n errors.push({\n field: \"settings.size\",\n rule: \"enum\",\n message: 'Size must be \"small\", \"medium\", or \"large\"',\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse and validate a JSON schema, returning a typed FormSchema.\n * Collects all validation errors before throwing a single SchemaValidationError.\n */\nexport function parseFormSchema(json: unknown): FormSchema {\n const errors: SchemaError[] = [];\n\n if (!isPlainObject(json)) {\n errors.push({ field: \"$root\", rule: \"type\", message: \"Schema must be a plain object\" });\n throw new SchemaValidationError(errors);\n }\n\n const raw = json as Record<string, unknown>;\n\n // fields\n if (!Array.isArray(raw.fields)) {\n errors.push({ field: \"fields\", rule: \"type\", message: '\"fields\" must be an array' });\n throw new SchemaValidationError(errors);\n }\n\n // Collect all field names recursively for cross-reference validation\n const allFields = extractFields(raw.fields as SchemaNode[]);\n const allFieldNames = new Set<string>();\n const nameTracker = new Map<string, number>();\n for (const f of allFields) {\n allFieldNames.add(f.name);\n const count = (nameTracker.get(f.name) ?? 0) + 1;\n nameTracker.set(f.name, count);\n if (count > 1) {\n errors.push({\n field: f.name,\n rule: \"unique\",\n message: `Duplicate field name \"${f.name}\"`,\n });\n }\n }\n\n // Validate each node recursively (fields and containers)\n validateNodes(raw.fields, \"fields\", allFieldNames, errors);\n\n // Validate settings\n if (raw.settings !== undefined) {\n validateSettings(raw.settings, errors);\n }\n\n if (errors.length > 0) {\n throw new SchemaValidationError(errors);\n }\n\n return {\n id: typeof raw.id === \"string\" ? raw.id : undefined,\n version: typeof raw.version === \"string\" ? raw.version : undefined,\n fields: raw.fields as SchemaNode[],\n settings: raw.settings as FormSettings | undefined,\n translations: raw.translations as FormSchema[\"translations\"],\n };\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Validation rule registry\n// ---------------------------------------------------------------------------\n\nimport type { RuleFn } from \"../types/validation\";\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\nconst rules = new Map<string, RuleFn>();\n\nexport function registerRule(name: string, fn: RuleFn): void {\n rules.set(name, fn);\n}\n\nexport function unregisterRule(name: string): void {\n rules.delete(name);\n}\n\nexport function getRule(name: string): RuleFn | undefined {\n return rules.get(name);\n}\n\nexport function hasRule(name: string): boolean {\n return rules.has(name);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isEmpty(value: unknown): boolean {\n if (value === null || value === undefined || value === \"\") return true;\n if (Array.isArray(value) && value.length === 0) return true;\n return false;\n}\n\nfunction interpolate(template: string, params: Record<string, unknown>): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) => {\n return params[key] !== undefined ? String(params[key]) : `{${key}}`;\n });\n}\n\nfunction toNumber(value: unknown): number | null {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const n = Number(value);\n return Number.isNaN(n) ? null : n;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in rules\n// ---------------------------------------------------------------------------\n\nregisterRule(\"required\", (value) => {\n if (isEmpty(value)) return \"This field is required\";\n return true;\n});\n\nregisterRule(\"email\", (value) => {\n if (isEmpty(value)) return true;\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value)) || \"Please enter a valid email address\";\n});\n\nregisterRule(\"phone\", async (value) => {\n if (isEmpty(value)) return true;\n const str = String(value);\n try {\n const lib = await import(\"libphonenumber-js\");\n return lib.isValidPhoneNumber(str) || \"Please enter a valid phone number\";\n } catch {\n // Fallback if libphonenumber-js not available\n if (/^\\+[1-9]\\d{6,14}$/.test(str.replace(/[\\s\\-().]/g, \"\"))) return true;\n return \"Please enter a valid phone number\";\n }\n});\n\nregisterRule(\"url\", (value) => {\n if (isEmpty(value)) return true;\n try {\n new URL(String(value));\n return true;\n } catch {\n return \"Please enter a valid URL\";\n }\n});\n\nregisterRule(\"min\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const min = toNumber(params.min);\n if (num === null || min === null) return true;\n return num >= min || interpolate(\"Must be at least {min}\", params);\n});\n\nregisterRule(\"max\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const max = toNumber(params.max);\n if (num === null || max === null) return true;\n return num <= max || interpolate(\"Must be at most {max}\", params);\n});\n\nregisterRule(\"minLength\", (value, params) => {\n if (isEmpty(value)) return true;\n const len = typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : 0;\n const min = toNumber(params.min) ?? toNumber(params.minLength) ?? 0;\n return len >= min || interpolate(\"Must be at least {min} characters\", { min, ...params });\n});\n\nregisterRule(\"maxLength\", (value, params) => {\n if (isEmpty(value)) return true;\n const len = typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : 0;\n const max = toNumber(params.max) ?? toNumber(params.maxLength) ?? Infinity;\n return len <= max || interpolate(\"Must be at most {max} characters\", { max, ...params });\n});\n\nregisterRule(\"between\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const min = toNumber(params.min);\n const max = toNumber(params.max);\n if (num === null || min === null || max === null) return true;\n return (num >= min && num <= max) || interpolate(\"Must be between {min} and {max}\", params);\n});\n\nregisterRule(\"pattern\", (value, params) => {\n if (isEmpty(value)) return true;\n const pattern = params.pattern ?? params.regex;\n if (typeof pattern !== \"string\") return true;\n const re = new RegExp(pattern);\n return re.test(String(value)) || interpolate(\"Does not match the required pattern\", params);\n});\n\nregisterRule(\"numeric\", (value) => {\n if (isEmpty(value)) return true;\n return toNumber(value) !== null || \"Must be a number\";\n});\n\nregisterRule(\"integer\", (value) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n return (num !== null && Number.isInteger(num)) || \"Must be an integer\";\n});\n\nregisterRule(\"alpha\", (value) => {\n if (isEmpty(value)) return true;\n return /^[a-zA-Z]+$/.test(String(value)) || \"Must contain only letters\";\n});\n\nregisterRule(\"alphaNumeric\", (value) => {\n if (isEmpty(value)) return true;\n return /^[a-zA-Z0-9]+$/.test(String(value)) || \"Must contain only letters and numbers\";\n});\n\nregisterRule(\"confirmed\", (value, params, ctx) => {\n if (isEmpty(value)) return true;\n const target = String(params.target ?? \"\");\n const other = ctx.values[target] ?? ctx.values[`${target}_confirmation`];\n return value === other || \"Confirmation does not match\";\n});\n\nregisterRule(\"requiredIf\", (value, params, ctx) => {\n const targetField = String(params.field ?? \"\");\n const targetValue = params.value;\n const actual = ctx.values[targetField];\n const shouldRequire = targetValue !== undefined ? actual === targetValue : !isEmpty(actual);\n if (!shouldRequire) return true;\n return !isEmpty(value) || interpolate(\"This field is required when {field} is set\", params);\n});\n\nregisterRule(\"date\", (value) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n return !Number.isNaN(d.getTime()) || \"Please enter a valid date\";\n});\n\nregisterRule(\"before\", (value, params) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n const before = new Date(String(params.date ?? params.before));\n if (Number.isNaN(d.getTime()) || Number.isNaN(before.getTime())) return true;\n return d < before || interpolate(\"Must be before {date}\", params);\n});\n\nregisterRule(\"after\", (value, params) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n const after = new Date(String(params.date ?? params.after));\n if (Number.isNaN(d.getTime()) || Number.isNaN(after.getTime())) return true;\n return d > after || interpolate(\"Must be after {date}\", params);\n});\n\nregisterRule(\"in\", (value, params) => {\n if (isEmpty(value)) return true;\n const allowed = Array.isArray(params.values) ? params.values : [];\n return (allowed as unknown[]).includes(value) || \"The selected value is not valid\";\n});\n\nregisterRule(\"notIn\", (value, params) => {\n if (isEmpty(value)) return true;\n const disallowed = Array.isArray(params.values) ? params.values : [];\n return !(disallowed as unknown[]).includes(value) || \"The selected value is not allowed\";\n});\n\nregisterRule(\"fileSize\", (value, params) => {\n if (isEmpty(value)) return true;\n const maxBytes = toNumber(params.max) ?? Infinity;\n const files = Array.isArray(value) ? value : [value];\n for (const file of files) {\n const size =\n typeof file === \"object\" && file !== null && \"size\" in file\n ? toNumber((file as { size: unknown }).size)\n : null;\n if (size !== null && size > maxBytes) {\n return interpolate(\"File must be smaller than {max} bytes\", params);\n }\n }\n return true;\n});\n\nregisterRule(\"mimeType\", (value, params) => {\n if (isEmpty(value)) return true;\n const allowed = Array.isArray(params.types)\n ? (params.types as string[])\n : typeof params.types === \"string\"\n ? params.types.split(\",\").map((s: string) => s.trim())\n : [];\n const files = Array.isArray(value) ? value : [value];\n for (const file of files) {\n const fileType =\n typeof file === \"object\" && file !== null && \"type\" in file\n ? String((file as { type: unknown }).type)\n : \"\";\n if (fileType && !allowed.some((t) => fileType.match(new RegExp(t.replace(\"*\", \".*\"))))) {\n return interpolate(\"File type is not allowed. Allowed: {types}\", params);\n }\n }\n return true;\n});\n\nregisterRule(\"maxFiles\", (value, params) => {\n if (isEmpty(value)) return true;\n const max = toNumber(params.max) ?? Infinity;\n const count = Array.isArray(value) ? value.length : 1;\n return count <= max || interpolate(\"Maximum {max} files allowed\", params);\n});\n\nregisterRule(\"unique\", (value) => {\n if (isEmpty(value)) return true;\n if (!Array.isArray(value)) return true;\n const set = new Set(value as unknown[]);\n return set.size === value.length || \"All values must be unique\";\n});\n\nregisterRule(\"custom\", (value, params) => {\n // Custom rules are handled at the ValidationRule level via validator fn.\n // This is a no-op fallback.\n void value;\n void params;\n return true;\n});\n","// ---------------------------------------------------------------------------\n// Formatica Core – Condition evaluation\n// ---------------------------------------------------------------------------\n\nimport type { Condition, ConditionGroup, ConditionOperator } from \"./types/schema\";\n\n// ---------------------------------------------------------------------------\n// Single condition evaluation\n// ---------------------------------------------------------------------------\n\nfunction evaluateOperator(\n fieldValue: unknown,\n operator: ConditionOperator,\n conditionValue: unknown,\n): boolean {\n switch (operator) {\n case \"eq\":\n return fieldValue === conditionValue;\n case \"neq\":\n return fieldValue !== conditionValue;\n case \"gt\":\n return Number(fieldValue) > Number(conditionValue);\n case \"gte\":\n return Number(fieldValue) >= Number(conditionValue);\n case \"lt\":\n return Number(fieldValue) < Number(conditionValue);\n case \"lte\":\n return Number(fieldValue) <= Number(conditionValue);\n case \"in\":\n return (\n Array.isArray(conditionValue) && (conditionValue as unknown[]).includes(fieldValue)\n );\n case \"notIn\":\n return (\n Array.isArray(conditionValue) && !(conditionValue as unknown[]).includes(fieldValue)\n );\n case \"contains\": {\n if (typeof fieldValue === \"string\") return fieldValue.includes(String(conditionValue));\n if (Array.isArray(fieldValue))\n return (fieldValue as unknown[]).includes(conditionValue);\n return false;\n }\n case \"empty\":\n return (\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === \"\" ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n );\n case \"notEmpty\":\n return !(\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === \"\" ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n );\n case \"matches\": {\n if (typeof conditionValue !== \"string\") return false;\n try {\n return new RegExp(conditionValue).test(String(fieldValue));\n } catch {\n return false;\n }\n }\n default:\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nfunction isConditionGroup(cond: Condition | ConditionGroup): cond is ConditionGroup {\n return \"and\" in cond || \"or\" in cond;\n}\n\n/**\n * Evaluate a single condition or a compound condition group against the\n * current form values.\n */\nexport function evaluateCondition(\n condition: Condition | ConditionGroup,\n values: Record<string, unknown>,\n): boolean {\n if (isConditionGroup(condition)) {\n if (condition.and) {\n return condition.and.every((c) => evaluateCondition(c, values));\n }\n if (condition.or) {\n return condition.or.some((c) => evaluateCondition(c, values));\n }\n // Empty group evaluates to true\n return true;\n }\n\n const fieldValue = values[condition.field];\n return evaluateOperator(fieldValue, condition.operator, condition.value);\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Deep merge utility\n// ---------------------------------------------------------------------------\n\ntype PlainObject = Record<string, unknown>;\n\nfunction isPlainObject(value: unknown): value is PlainObject {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Deep-merge two objects. Arrays are replaced (not concatenated).\n * Returns a new object – neither source is mutated.\n */\nexport function deepMerge<T extends PlainObject>(target: T, source: Partial<T>): T {\n const result: PlainObject = { ...target };\n\n for (const key of Object.keys(source)) {\n const srcVal = (source as PlainObject)[key];\n const tgtVal = result[key];\n\n if (isPlainObject(srcVal) && isPlainObject(tgtVal)) {\n result[key] = deepMerge(tgtVal, srcVal);\n } else {\n result[key] = srcVal;\n }\n }\n\n return result as T;\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Title case conversion utility\n// ---------------------------------------------------------------------------\n\n/**\n * Convert camelCase, kebab-case, or snake_case field names to Title Case.\n *\n * @example\n * titleCase('firstName') // \"First Name\"\n * titleCase('last-name') // \"Last Name\"\n * titleCase('email_address') // \"Email Address\"\n */\nexport function titleCase(input: string): string {\n return (\n input\n // Insert space before uppercase letters in camelCase\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n // Replace kebab-case and snake_case separators with spaces\n .replace(/[-_]+/g, \" \")\n // Capitalize first letter of each word\n .replace(/\\b\\w/g, (char) => char.toUpperCase())\n .trim()\n );\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Simple HTML sanitizer for HtmlLayout content\n// ---------------------------------------------------------------------------\n\n/**\n * Strip `<script>` tags and inline event handlers (on*=\"...\") from HTML strings.\n * This is a lightweight sanitizer for use with the HtmlLayout node type.\n */\nexport function sanitizeHtml(html: string): string {\n return (\n html\n // Remove <script> tags and their content\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, \"\")\n // Remove event handler attributes (onclick, onload, onerror, etc.)\n .replace(/\\s+on\\w+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi, \"\")\n // Remove javascript: protocol in href/src/action attributes\n .replace(/(href|src|action)\\s*=\\s*(?:\"javascript:[^\"]*\"|'javascript:[^']*')/gi, '$1=\"\"')\n );\n}\n"],"names":["extractFields","nodes","fields","node","isFieldNode","step","tab","SchemaValidationError","errors","summary","e","KNOWN_FIELD_TYPES","CONTAINER_TYPES","customFieldTypeChecker","setFieldTypeChecker","checker","isPlainObject","value","validateCondition","condition","fieldPath","allFieldNames","cond","group","children","i","simple","validateFieldNode","field","path","f","validateNode","n","type","validateNodes","basePath","validateSettings","settings","s","parseFormSchema","json","raw","allFields","nameTracker","count","rules","registerRule","name","fn","unregisterRule","getRule","hasRule","isEmpty","interpolate","template","params","_","key","toNumber","str","num","min","max","len","pattern","ctx","target","other","targetField","targetValue","actual","d","before","after","maxBytes","files","file","size","allowed","fileType","t","evaluateOperator","fieldValue","operator","conditionValue","isConditionGroup","evaluateCondition","values","c","proto","deepMerge","source","result","srcVal","tgtVal","titleCase","input","char","sanitizeHtml","html"],"mappings":"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"}
1
+ {"version":3,"file":"formatica-core.es.js","sources":["../src/conditions.ts","../src/config.ts","../src/extractFields.ts","../src/schemaParser.ts","../src/utils/deepMerge.ts","../src/utils/sanitize.ts","../src/utils/titleCase.ts","../src/validation/ruleRegistry.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Formatica Core – Condition evaluation\n// ---------------------------------------------------------------------------\n\nimport type { Condition, ConditionGroup, ConditionOperator } from \"./types/schema\";\n\n// ---------------------------------------------------------------------------\n// Single condition evaluation\n// ---------------------------------------------------------------------------\n\nfunction evaluateOperator(\n fieldValue: unknown,\n operator: ConditionOperator,\n conditionValue: unknown,\n): boolean {\n switch (operator) {\n case \"eq\":\n return fieldValue === conditionValue;\n case \"neq\":\n return fieldValue !== conditionValue;\n case \"gt\":\n return Number(fieldValue) > Number(conditionValue);\n case \"gte\":\n return Number(fieldValue) >= Number(conditionValue);\n case \"lt\":\n return Number(fieldValue) < Number(conditionValue);\n case \"lte\":\n return Number(fieldValue) <= Number(conditionValue);\n case \"in\":\n return (\n Array.isArray(conditionValue) && (conditionValue as unknown[]).includes(fieldValue)\n );\n case \"notIn\":\n return (\n Array.isArray(conditionValue) && !(conditionValue as unknown[]).includes(fieldValue)\n );\n case \"contains\": {\n if (typeof fieldValue === \"string\") return fieldValue.includes(String(conditionValue));\n if (Array.isArray(fieldValue))\n return (fieldValue as unknown[]).includes(conditionValue);\n return false;\n }\n case \"empty\":\n return (\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === \"\" ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n );\n case \"notEmpty\":\n return !(\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === \"\" ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n );\n case \"matches\": {\n if (typeof conditionValue !== \"string\") return false;\n try {\n return new RegExp(conditionValue).test(String(fieldValue));\n } catch {\n return false;\n }\n }\n default:\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nfunction isConditionGroup(cond: Condition | ConditionGroup): cond is ConditionGroup {\n return \"and\" in cond || \"or\" in cond;\n}\n\n/**\n * Evaluate a single condition or a compound condition group against the\n * current form values.\n */\nexport function evaluateCondition(\n condition: Condition | ConditionGroup,\n values: Record<string, unknown>,\n): boolean {\n if (isConditionGroup(condition)) {\n if (condition.and) {\n return condition.and.every((c) => evaluateCondition(c, values));\n }\n if (condition.or) {\n return condition.or.some((c) => evaluateCondition(c, values));\n }\n // Empty group evaluates to true\n return true;\n }\n\n const fieldValue = values[condition.field];\n return evaluateOperator(fieldValue, condition.operator, condition.value);\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Global configuration\n// ---------------------------------------------------------------------------\n\nimport type { ThemeConfig } from \"./types/theme\";\n\nexport interface FormaticaCoreConfig {\n theme?: ThemeConfig;\n locale?: string;\n}\n\nlet globalConfig: FormaticaCoreConfig = {};\n\nexport function configureFormatica(config: FormaticaCoreConfig): void {\n globalConfig = { ...config };\n}\n\nexport function getFormaticaConfig(): FormaticaCoreConfig {\n return globalConfig;\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Utility to extract field schemas from a unified schema tree\n// ---------------------------------------------------------------------------\n\nimport type { FieldSchema, SchemaNode } from \"./types/schema\";\n\n/**\n * Recursively walks a `SchemaNode[]` tree and collects every node that is an\n * actual field (i.e. has a `name` property), ignoring layout containers.\n */\nexport function extractFields(nodes: SchemaNode[]): FieldSchema[] {\n const fields: FieldSchema[] = [];\n for (const node of nodes) {\n if (isFieldNode(node)) {\n fields.push(node);\n } else if (node.type === \"row\" || node.type === \"group\") {\n fields.push(...extractFields(node.children));\n } else if (node.type === \"steps\") {\n for (const step of node.steps) {\n fields.push(...extractFields(step.children));\n }\n } else if (node.type === \"tabs\") {\n for (const tab of node.tabs) {\n fields.push(...extractFields(tab.children));\n }\n }\n }\n return fields;\n}\n\n/**\n * Type-guard that distinguishes field nodes from layout container nodes.\n */\nexport function isFieldNode(node: SchemaNode): node is FieldSchema {\n return \"name\" in node && typeof node.name === \"string\";\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Schema parser & validator\n// ---------------------------------------------------------------------------\n\nimport { extractFields } from \"./extractFields\";\nimport type {\n Condition,\n ConditionGroup,\n FormSchema,\n FormSettings,\n SchemaNode,\n} from \"./types/schema\";\nimport type { SchemaError } from \"./types/validation\";\n\n// ---------------------------------------------------------------------------\n// Error class\n// ---------------------------------------------------------------------------\n\nexport class SchemaValidationError extends Error {\n public readonly errors: SchemaError[];\n\n constructor(errors: SchemaError[]) {\n const summary = errors.map((e) => `[${e.field}] ${e.message}`).join(\"; \");\n super(`Schema validation failed: ${summary}`);\n this.name = \"SchemaValidationError\";\n this.errors = errors;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Known field types\n// ---------------------------------------------------------------------------\n\nconst KNOWN_FIELD_TYPES = new Set([\n \"text\",\n \"number\",\n \"textarea\",\n \"select\",\n \"checkbox\",\n \"checkbox-group\",\n \"radio\",\n \"switch\",\n \"date\",\n \"file\",\n \"slider\",\n \"tags\",\n \"richtext\",\n \"hidden\",\n \"phone\",\n]);\n\nconst CONTAINER_TYPES = new Set([\"row\", \"group\", \"steps\", \"tabs\", \"divider\", \"html\"]);\n\n// ---------------------------------------------------------------------------\n// Custom field type checker (pluggable for framework-specific registries)\n// ---------------------------------------------------------------------------\n\nlet customFieldTypeChecker: ((type: string) => boolean) | null = null;\n\n/**\n * Register a custom field type checker. This allows framework-specific packages\n * (e.g. @formatica/vue) to hook their field registry into schema validation.\n */\nexport function setFieldTypeChecker(checker: ((type: string) => boolean) | null): void {\n customFieldTypeChecker = checker;\n}\n\n// ---------------------------------------------------------------------------\n// Validation helpers\n// ---------------------------------------------------------------------------\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateCondition(\n condition: unknown,\n fieldPath: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(condition)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: \"Condition must be an object\",\n });\n return;\n }\n\n const cond = condition as Record<string, unknown>;\n\n // Compound conditions\n if (\"and\" in cond || \"or\" in cond) {\n const group = cond as ConditionGroup;\n const children = group.and ?? group.or ?? [];\n if (!Array.isArray(children)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: \"Compound condition must have an array of sub-conditions\",\n });\n return;\n }\n for (let i = 0; i < children.length; i++) {\n validateCondition(children[i], `${fieldPath}.condition[${i}]`, allFieldNames, errors);\n }\n return;\n }\n\n // Simple condition\n const simple = cond as unknown as Condition;\n if (typeof simple.field !== \"string\") {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: 'Condition must have a \"field\" property of type string',\n });\n } else if (!allFieldNames.has(simple.field)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: `Condition references unknown field \"${simple.field}\"`,\n });\n }\n\n if (typeof simple.operator !== \"string\") {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: 'Condition must have an \"operator\" property',\n });\n }\n}\n\nfunction validateFieldNode(\n field: unknown,\n path: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(field)) {\n errors.push({ field: path, rule: \"type\", message: \"Field must be an object\" });\n return;\n }\n\n const f = field as Record<string, unknown>;\n\n // name\n if (typeof f.name !== \"string\" || f.name.length === 0) {\n errors.push({ field: path, rule: \"name\", message: 'Field must have a non-empty \"name\"' });\n }\n\n // type\n if (typeof f.type !== \"string\") {\n errors.push({ field: path, rule: \"type\", message: 'Field must have a \"type\" string' });\n } else if (!KNOWN_FIELD_TYPES.has(f.type) && !customFieldTypeChecker?.(f.type)) {\n errors.push({\n field: `${path}.${f.name as string}`,\n rule: \"type\",\n message: `Unknown field type \"${f.type}\"`,\n });\n }\n\n // options required for select, radio, checkbox-group\n if ([\"select\", \"radio\", \"checkbox-group\"].includes(f.type as string)) {\n if (f.options === undefined || f.options === null) {\n errors.push({\n field: `${path}.${f.name as string}`,\n rule: \"options\",\n message: `Field type \"${f.type as string}\" requires an \"options\" property`,\n });\n }\n }\n\n // condition references\n if (f.condition) {\n validateCondition(f.condition, `${path}.${f.name as string}`, allFieldNames, errors);\n }\n}\n\nfunction validateNode(\n node: unknown,\n path: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(node)) {\n errors.push({ field: path, rule: \"type\", message: \"Node must be an object\" });\n return;\n }\n\n const n = node as Record<string, unknown>;\n const type = n.type as string;\n\n if (typeof type !== \"string\") {\n errors.push({ field: path, rule: \"type\", message: 'Node must have a \"type\" string' });\n return;\n }\n\n // If it's a field node (has a name), validate as field\n if (typeof n.name === \"string\") {\n validateFieldNode(node, path, allFieldNames, errors);\n return;\n }\n\n // Container nodes\n if (!CONTAINER_TYPES.has(type)) {\n errors.push({\n field: path,\n rule: \"type\",\n message: `Unknown node type \"${type}\"`,\n });\n return;\n }\n\n if (type === \"row\" || type === \"group\") {\n if (!Array.isArray(n.children)) {\n errors.push({\n field: path,\n rule: \"children\",\n message: `\"${type}\" node must have a \"children\" array`,\n });\n } else {\n validateNodes(n.children, `${path}.children`, allFieldNames, errors);\n }\n if (type === \"group\" && n.condition) {\n validateCondition(n.condition, `${path}.condition`, allFieldNames, errors);\n }\n } else if (type === \"steps\") {\n if (!Array.isArray(n.steps)) {\n errors.push({\n field: path,\n rule: \"steps\",\n message: '\"steps\" node must have a \"steps\" array',\n });\n } else {\n for (let i = 0; i < n.steps.length; i++) {\n const step = n.steps[i] as Record<string, unknown>;\n if (!isPlainObject(step)) {\n errors.push({\n field: `${path}.steps[${i}]`,\n rule: \"type\",\n message: \"Step item must be an object\",\n });\n continue;\n }\n if (typeof step.title !== \"string\") {\n errors.push({\n field: `${path}.steps[${i}]`,\n rule: \"title\",\n message: 'Step item must have a \"title\" string',\n });\n }\n if (Array.isArray(step.children)) {\n validateNodes(\n step.children,\n `${path}.steps[${i}].children`,\n allFieldNames,\n errors,\n );\n }\n }\n }\n } else if (type === \"tabs\") {\n if (!Array.isArray(n.tabs)) {\n errors.push({\n field: path,\n rule: \"tabs\",\n message: '\"tabs\" node must have a \"tabs\" array',\n });\n } else {\n for (let i = 0; i < n.tabs.length; i++) {\n const tab = n.tabs[i] as Record<string, unknown>;\n if (!isPlainObject(tab)) {\n errors.push({\n field: `${path}.tabs[${i}]`,\n rule: \"type\",\n message: \"Tab item must be an object\",\n });\n continue;\n }\n if (typeof tab.title !== \"string\") {\n errors.push({\n field: `${path}.tabs[${i}]`,\n rule: \"title\",\n message: 'Tab item must have a \"title\" string',\n });\n }\n if (Array.isArray(tab.children)) {\n validateNodes(\n tab.children,\n `${path}.tabs[${i}].children`,\n allFieldNames,\n errors,\n );\n }\n }\n }\n } else if (type === \"html\") {\n if (typeof n.content !== \"string\") {\n errors.push({\n field: path,\n rule: \"content\",\n message: '\"html\" node must have a \"content\" string',\n });\n }\n }\n // \"divider\" has no required children/content — always valid if type matches\n}\n\nfunction validateNodes(\n nodes: unknown[],\n basePath: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n for (let i = 0; i < nodes.length; i++) {\n validateNode(nodes[i], `${basePath}[${i}]`, allFieldNames, errors);\n }\n}\n\nfunction validateSettings(settings: unknown, errors: SchemaError[]): void {\n if (!isPlainObject(settings)) {\n errors.push({ field: \"settings\", rule: \"type\", message: \"Settings must be an object\" });\n return;\n }\n\n const s = settings as Record<string, unknown>;\n\n if (\n s.layout !== undefined &&\n ![\"vertical\", \"horizontal\", \"inline\"].includes(s.layout as string)\n ) {\n errors.push({\n field: \"settings.layout\",\n rule: \"enum\",\n message: 'Layout must be \"vertical\", \"horizontal\", or \"inline\"',\n });\n }\n\n if (s.size !== undefined && ![\"small\", \"medium\", \"large\"].includes(s.size as string)) {\n errors.push({\n field: \"settings.size\",\n rule: \"enum\",\n message: 'Size must be \"small\", \"medium\", or \"large\"',\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse and validate a JSON schema, returning a typed FormSchema.\n * Collects all validation errors before throwing a single SchemaValidationError.\n */\nexport function parseFormSchema(json: unknown): FormSchema {\n const errors: SchemaError[] = [];\n\n if (!isPlainObject(json)) {\n errors.push({ field: \"$root\", rule: \"type\", message: \"Schema must be a plain object\" });\n throw new SchemaValidationError(errors);\n }\n\n const raw = json as Record<string, unknown>;\n\n // fields\n if (!Array.isArray(raw.fields)) {\n errors.push({ field: \"fields\", rule: \"type\", message: '\"fields\" must be an array' });\n throw new SchemaValidationError(errors);\n }\n\n // Collect all field names recursively for cross-reference validation\n const allFields = extractFields(raw.fields as SchemaNode[]);\n const allFieldNames = new Set<string>();\n const nameTracker = new Map<string, number>();\n for (const f of allFields) {\n allFieldNames.add(f.name);\n const count = (nameTracker.get(f.name) ?? 0) + 1;\n nameTracker.set(f.name, count);\n if (count > 1) {\n errors.push({\n field: f.name,\n rule: \"unique\",\n message: `Duplicate field name \"${f.name}\"`,\n });\n }\n }\n\n // Validate each node recursively (fields and containers)\n validateNodes(raw.fields, \"fields\", allFieldNames, errors);\n\n // Validate settings\n if (raw.settings !== undefined) {\n validateSettings(raw.settings, errors);\n }\n\n if (errors.length > 0) {\n throw new SchemaValidationError(errors);\n }\n\n return {\n id: typeof raw.id === \"string\" ? raw.id : undefined,\n version: typeof raw.version === \"string\" ? raw.version : undefined,\n fields: raw.fields as SchemaNode[],\n settings: raw.settings as FormSettings | undefined,\n translations: raw.translations as FormSchema[\"translations\"],\n };\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Deep merge utility\n// ---------------------------------------------------------------------------\n\ntype PlainObject = Record<string, unknown>;\n\nfunction isPlainObject(value: unknown): value is PlainObject {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Deep-merge two objects. Arrays are replaced (not concatenated).\n * Returns a new object – neither source is mutated.\n */\nexport function deepMerge<T extends PlainObject>(target: T, source: Partial<T>): T {\n const result: PlainObject = { ...target };\n\n for (const key of Object.keys(source)) {\n const srcVal = (source as PlainObject)[key];\n const tgtVal = result[key];\n\n if (isPlainObject(srcVal) && isPlainObject(tgtVal)) {\n result[key] = deepMerge(tgtVal, srcVal);\n } else {\n result[key] = srcVal;\n }\n }\n\n return result as T;\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Simple HTML sanitizer for HtmlLayout content\n// ---------------------------------------------------------------------------\n\n/**\n * Strip `<script>` tags and inline event handlers (on*=\"...\") from HTML strings.\n * This is a lightweight sanitizer for use with the HtmlLayout node type.\n */\nexport function sanitizeHtml(html: string): string {\n return (\n html\n // Remove <script> tags and their content\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, \"\")\n // Remove event handler attributes (onclick, onload, onerror, etc.)\n .replace(/\\s+on\\w+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi, \"\")\n // Remove javascript: protocol in href/src/action attributes\n .replace(/(href|src|action)\\s*=\\s*(?:\"javascript:[^\"]*\"|'javascript:[^']*')/gi, '$1=\"\"')\n );\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Title case conversion utility\n// ---------------------------------------------------------------------------\n\n/**\n * Convert camelCase, kebab-case, or snake_case field names to Title Case.\n *\n * @example\n * titleCase('firstName') // \"First Name\"\n * titleCase('last-name') // \"Last Name\"\n * titleCase('email_address') // \"Email Address\"\n */\nexport function titleCase(input: string): string {\n return (\n input\n // Insert space before uppercase letters in camelCase\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n // Replace kebab-case and snake_case separators with spaces\n .replace(/[-_]+/g, \" \")\n // Capitalize first letter of each word\n .replace(/\\b\\w/g, (char) => char.toUpperCase())\n .trim()\n );\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Validation rule registry\n// ---------------------------------------------------------------------------\n\nimport type { RuleFn } from \"../types/validation\";\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\nconst rules = new Map<string, RuleFn>();\n\nexport function registerRule(name: string, fn: RuleFn): void {\n rules.set(name, fn);\n}\n\nexport function unregisterRule(name: string): void {\n rules.delete(name);\n}\n\nexport function getRule(name: string): RuleFn | undefined {\n return rules.get(name);\n}\n\nexport function hasRule(name: string): boolean {\n return rules.has(name);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isEmpty(value: unknown): boolean {\n if (value === null || value === undefined || value === \"\") return true;\n if (Array.isArray(value) && value.length === 0) return true;\n return false;\n}\n\nfunction interpolate(template: string, params: Record<string, unknown>): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) => {\n return params[key] !== undefined ? String(params[key]) : `{${key}}`;\n });\n}\n\nfunction toNumber(value: unknown): number | null {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const n = Number(value);\n return Number.isNaN(n) ? null : n;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in rules\n// ---------------------------------------------------------------------------\n\nregisterRule(\"required\", (value) => {\n if (isEmpty(value)) return \"This field is required\";\n return true;\n});\n\nregisterRule(\"email\", (value) => {\n if (isEmpty(value)) return true;\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value)) || \"Please enter a valid email address\";\n});\n\nregisterRule(\"phone\", async (value) => {\n if (isEmpty(value)) return true;\n const str = String(value);\n try {\n const lib = await import(\"libphonenumber-js\");\n return lib.isValidPhoneNumber(str) || \"Please enter a valid phone number\";\n } catch {\n // Fallback if libphonenumber-js not available\n if (/^\\+[1-9]\\d{6,14}$/.test(str.replace(/[\\s\\-().]/g, \"\"))) return true;\n return \"Please enter a valid phone number\";\n }\n});\n\nregisterRule(\"url\", (value) => {\n if (isEmpty(value)) return true;\n try {\n new URL(String(value));\n return true;\n } catch {\n return \"Please enter a valid URL\";\n }\n});\n\nregisterRule(\"min\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const min = toNumber(params.min);\n if (num === null || min === null) return true;\n return num >= min || interpolate(\"Must be at least {min}\", params);\n});\n\nregisterRule(\"max\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const max = toNumber(params.max);\n if (num === null || max === null) return true;\n return num <= max || interpolate(\"Must be at most {max}\", params);\n});\n\nregisterRule(\"minLength\", (value, params) => {\n if (isEmpty(value)) return true;\n const len = typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : 0;\n const min = toNumber(params.min) ?? toNumber(params.minLength) ?? 0;\n return len >= min || interpolate(\"Must be at least {min} characters\", { min, ...params });\n});\n\nregisterRule(\"maxLength\", (value, params) => {\n if (isEmpty(value)) return true;\n const len = typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : 0;\n const max = toNumber(params.max) ?? toNumber(params.maxLength) ?? Infinity;\n return len <= max || interpolate(\"Must be at most {max} characters\", { max, ...params });\n});\n\nregisterRule(\"between\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const min = toNumber(params.min);\n const max = toNumber(params.max);\n if (num === null || min === null || max === null) return true;\n return (num >= min && num <= max) || interpolate(\"Must be between {min} and {max}\", params);\n});\n\nregisterRule(\"pattern\", (value, params) => {\n if (isEmpty(value)) return true;\n const pattern = params.pattern ?? params.regex;\n if (typeof pattern !== \"string\") return true;\n const re = new RegExp(pattern);\n return re.test(String(value)) || interpolate(\"Does not match the required pattern\", params);\n});\n\nregisterRule(\"numeric\", (value) => {\n if (isEmpty(value)) return true;\n return toNumber(value) !== null || \"Must be a number\";\n});\n\nregisterRule(\"integer\", (value) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n return (num !== null && Number.isInteger(num)) || \"Must be an integer\";\n});\n\nregisterRule(\"alpha\", (value) => {\n if (isEmpty(value)) return true;\n return /^[a-zA-Z]+$/.test(String(value)) || \"Must contain only letters\";\n});\n\nregisterRule(\"alphaNumeric\", (value) => {\n if (isEmpty(value)) return true;\n return /^[a-zA-Z0-9]+$/.test(String(value)) || \"Must contain only letters and numbers\";\n});\n\nregisterRule(\"confirmed\", (value, params, ctx) => {\n if (isEmpty(value)) return true;\n const target = String(params.target ?? \"\");\n const other = ctx.values[target] ?? ctx.values[`${target}_confirmation`];\n return value === other || \"Confirmation does not match\";\n});\n\nregisterRule(\"requiredIf\", (value, params, ctx) => {\n const targetField = String(params.field ?? \"\");\n const targetValue = params.value;\n const actual = ctx.values[targetField];\n const shouldRequire = targetValue !== undefined ? actual === targetValue : !isEmpty(actual);\n if (!shouldRequire) return true;\n return !isEmpty(value) || interpolate(\"This field is required when {field} is set\", params);\n});\n\nregisterRule(\"date\", (value) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n return !Number.isNaN(d.getTime()) || \"Please enter a valid date\";\n});\n\nregisterRule(\"before\", (value, params) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n const before = new Date(String(params.date ?? params.before));\n if (Number.isNaN(d.getTime()) || Number.isNaN(before.getTime())) return true;\n return d < before || interpolate(\"Must be before {date}\", params);\n});\n\nregisterRule(\"after\", (value, params) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n const after = new Date(String(params.date ?? params.after));\n if (Number.isNaN(d.getTime()) || Number.isNaN(after.getTime())) return true;\n return d > after || interpolate(\"Must be after {date}\", params);\n});\n\nregisterRule(\"in\", (value, params) => {\n if (isEmpty(value)) return true;\n const allowed = Array.isArray(params.values) ? params.values : [];\n return (allowed as unknown[]).includes(value) || \"The selected value is not valid\";\n});\n\nregisterRule(\"notIn\", (value, params) => {\n if (isEmpty(value)) return true;\n const disallowed = Array.isArray(params.values) ? params.values : [];\n return !(disallowed as unknown[]).includes(value) || \"The selected value is not allowed\";\n});\n\nregisterRule(\"fileSize\", (value, params) => {\n if (isEmpty(value)) return true;\n const maxBytes = toNumber(params.max) ?? Infinity;\n const files = Array.isArray(value) ? value : [value];\n for (const file of files) {\n const size =\n typeof file === \"object\" && file !== null && \"size\" in file\n ? toNumber((file as { size: unknown }).size)\n : null;\n if (size !== null && size > maxBytes) {\n return interpolate(\"File must be smaller than {max} bytes\", params);\n }\n }\n return true;\n});\n\nregisterRule(\"mimeType\", (value, params) => {\n if (isEmpty(value)) return true;\n const allowed = Array.isArray(params.types)\n ? (params.types as string[])\n : typeof params.types === \"string\"\n ? params.types.split(\",\").map((s: string) => s.trim())\n : [];\n const files = Array.isArray(value) ? value : [value];\n for (const file of files) {\n const fileType =\n typeof file === \"object\" && file !== null && \"type\" in file\n ? String((file as { type: unknown }).type)\n : \"\";\n if (fileType && !allowed.some((t) => fileType.match(new RegExp(t.replace(\"*\", \".*\"))))) {\n return interpolate(\"File type is not allowed. Allowed: {types}\", params);\n }\n }\n return true;\n});\n\nregisterRule(\"maxFiles\", (value, params) => {\n if (isEmpty(value)) return true;\n const max = toNumber(params.max) ?? Infinity;\n const count = Array.isArray(value) ? value.length : 1;\n return count <= max || interpolate(\"Maximum {max} files allowed\", params);\n});\n\nregisterRule(\"unique\", (value) => {\n if (isEmpty(value)) return true;\n if (!Array.isArray(value)) return true;\n const set = new Set(value as unknown[]);\n return set.size === value.length || \"All values must be unique\";\n});\n\nregisterRule(\"custom\", (value, params) => {\n // Custom rules are handled at the ValidationRule level via validator fn.\n // This is a no-op fallback.\n void value;\n void params;\n return true;\n});\n"],"names":["evaluateOperator","fieldValue","operator","conditionValue","isConditionGroup","cond","evaluateCondition","condition","values","c","globalConfig","configureFormatica","config","getFormaticaConfig","extractFields","nodes","fields","node","isFieldNode","step","tab","SchemaValidationError","errors","summary","e","KNOWN_FIELD_TYPES","CONTAINER_TYPES","customFieldTypeChecker","setFieldTypeChecker","checker","isPlainObject","value","validateCondition","fieldPath","allFieldNames","group","children","i","simple","validateFieldNode","field","path","f","validateNode","n","type","validateNodes","basePath","validateSettings","settings","s","parseFormSchema","json","raw","allFields","nameTracker","count","proto","deepMerge","target","source","result","key","srcVal","tgtVal","sanitizeHtml","html","titleCase","input","char","rules","registerRule","name","fn","unregisterRule","getRule","hasRule","isEmpty","interpolate","template","params","_","toNumber","str","num","min","max","len","pattern","ctx","other","targetField","targetValue","actual","d","before","after","maxBytes","files","file","size","allowed","fileType","t"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- (function(l,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(l=typeof globalThis<"u"?globalThis:l||self,d(l.FormaticaCore={}))})(this,function(l){"use strict";function d(e){const t=[];for(const n of e)if(N(n))t.push(n);else if(n.type==="row"||n.type==="group")t.push(...d(n.children));else if(n.type==="steps")for(const r of n.steps)t.push(...d(r.children));else if(n.type==="tabs")for(const r of n.tabs)t.push(...d(r.children));return t}function N(e){return"name"in e&&typeof e.name=="string"}class y extends Error{constructor(t){const n=t.map(r=>`[${r.field}] ${r.message}`).join("; ");super(`Schema validation failed: ${n}`),this.name="SchemaValidationError",this.errors=t}}const T=new Set(["text","number","textarea","select","checkbox","checkbox-group","radio","switch","date","file","slider","tags","richtext","hidden","phone"]),j=new Set(["row","group","steps","tabs","divider","html"]);let p=null;function M(e){p=e}function g(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function w(e,t,n,r){if(!g(e)){r.push({field:t,rule:"condition",message:"Condition must be an object"});return}const i=e;if("and"in i||"or"in i){const a=i,c=a.and??a.or??[];if(!Array.isArray(c)){r.push({field:t,rule:"condition",message:"Compound condition must have an array of sub-conditions"});return}for(let A=0;A<c.length;A++)w(c[A],`${t}.condition[${A}]`,n,r);return}const s=i;typeof s.field!="string"?r.push({field:t,rule:"condition",message:'Condition must have a "field" property of type string'}):n.has(s.field)||r.push({field:t,rule:"condition",message:`Condition references unknown field "${s.field}"`}),typeof s.operator!="string"&&r.push({field:t,rule:"condition",message:'Condition must have an "operator" property'})}function z(e,t,n,r){if(!g(e)){r.push({field:t,rule:"type",message:"Field must be an object"});return}const i=e;(typeof i.name!="string"||i.name.length===0)&&r.push({field:t,rule:"name",message:'Field must have a non-empty "name"'}),typeof i.type!="string"?r.push({field:t,rule:"type",message:'Field must have a "type" string'}):!T.has(i.type)&&!(p!=null&&p(i.type))&&r.push({field:`${t}.${i.name}`,rule:"type",message:`Unknown field type "${i.type}"`}),["select","radio","checkbox-group"].includes(i.type)&&(i.options===void 0||i.options===null)&&r.push({field:`${t}.${i.name}`,rule:"options",message:`Field type "${i.type}" requires an "options" property`}),i.condition&&w(i.condition,`${t}.${i.name}`,n,r)}function C(e,t,n,r){if(!g(e)){r.push({field:t,rule:"type",message:"Node must be an object"});return}const i=e,s=i.type;if(typeof s!="string"){r.push({field:t,rule:"type",message:'Node must have a "type" string'});return}if(typeof i.name=="string"){z(e,t,n,r);return}if(!j.has(s)){r.push({field:t,rule:"type",message:`Unknown node type "${s}"`});return}if(s==="row"||s==="group")Array.isArray(i.children)?h(i.children,`${t}.children`,n,r):r.push({field:t,rule:"children",message:`"${s}" node must have a "children" array`}),s==="group"&&i.condition&&w(i.condition,`${t}.condition`,n,r);else if(s==="steps")if(!Array.isArray(i.steps))r.push({field:t,rule:"steps",message:'"steps" node must have a "steps" array'});else for(let a=0;a<i.steps.length;a++){const c=i.steps[a];if(!g(c)){r.push({field:`${t}.steps[${a}]`,rule:"type",message:"Step item must be an object"});continue}typeof c.title!="string"&&r.push({field:`${t}.steps[${a}]`,rule:"title",message:'Step item must have a "title" string'}),Array.isArray(c.children)&&h(c.children,`${t}.steps[${a}].children`,n,r)}else if(s==="tabs")if(!Array.isArray(i.tabs))r.push({field:t,rule:"tabs",message:'"tabs" node must have a "tabs" array'});else for(let a=0;a<i.tabs.length;a++){const c=i.tabs[a];if(!g(c)){r.push({field:`${t}.tabs[${a}]`,rule:"type",message:"Tab item must be an object"});continue}typeof c.title!="string"&&r.push({field:`${t}.tabs[${a}]`,rule:"title",message:'Tab item must have a "title" string'}),Array.isArray(c.children)&&h(c.children,`${t}.tabs[${a}].children`,n,r)}else s==="html"&&typeof i.content!="string"&&r.push({field:t,rule:"content",message:'"html" node must have a "content" string'})}function h(e,t,n,r){for(let i=0;i<e.length;i++)C(e[i],`${t}[${i}]`,n,r)}function R(e,t){if(!g(e)){t.push({field:"settings",rule:"type",message:"Settings must be an object"});return}const n=e;n.layout!==void 0&&!["vertical","horizontal","inline"].includes(n.layout)&&t.push({field:"settings.layout",rule:"enum",message:'Layout must be "vertical", "horizontal", or "inline"'}),n.size!==void 0&&!["small","medium","large"].includes(n.size)&&t.push({field:"settings.size",rule:"enum",message:'Size must be "small", "medium", or "large"'})}function F(e){const t=[];if(!g(e))throw t.push({field:"$root",rule:"type",message:"Schema must be a plain object"}),new y(t);const n=e;if(!Array.isArray(n.fields))throw t.push({field:"fields",rule:"type",message:'"fields" must be an array'}),new y(t);const r=d(n.fields),i=new Set,s=new Map;for(const a of r){i.add(a.name);const c=(s.get(a.name)??0)+1;s.set(a.name,c),c>1&&t.push({field:a.name,rule:"unique",message:`Duplicate field name "${a.name}"`})}if(h(n.fields,"fields",i,t),n.settings!==void 0&&R(n.settings,t),t.length>0)throw new y(t);return{id:typeof n.id=="string"?n.id:void 0,version:typeof n.version=="string"?n.version:void 0,fields:n.fields,settings:n.settings,translations:n.translations}}const b=new Map;function u(e,t){b.set(e,t)}function q(e){b.delete(e)}function E(e){return b.get(e)}function v(e){return b.has(e)}function o(e){return!!(e==null||e===""||Array.isArray(e)&&e.length===0)}function m(e,t){return e.replace(/\{(\w+)\}/g,(n,r)=>t[r]!==void 0?String(t[r]):`{${r}}`)}function f(e){if(typeof e=="number")return e;if(typeof e=="string"){const t=Number(e);return Number.isNaN(t)?null:t}return null}u("required",e=>o(e)?"This field is required":!0),u("email",e=>o(e)?!0:/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(e))||"Please enter a valid email address"),u("phone",async e=>{if(o(e))return!0;const t=String(e);try{return(await import("libphonenumber-js")).isValidPhoneNumber(t)||"Please enter a valid phone number"}catch{return/^\+[1-9]\d{6,14}$/.test(t.replace(/[\s\-().]/g,""))?!0:"Please enter a valid phone number"}}),u("url",e=>{if(o(e))return!0;try{return new URL(String(e)),!0}catch{return"Please enter a valid URL"}}),u("min",(e,t)=>{if(o(e))return!0;const n=f(e),r=f(t.min);return n===null||r===null?!0:n>=r||m("Must be at least {min}",t)}),u("max",(e,t)=>{if(o(e))return!0;const n=f(e),r=f(t.max);return n===null||r===null?!0:n<=r||m("Must be at most {max}",t)}),u("minLength",(e,t)=>{if(o(e))return!0;const n=typeof e=="string"||Array.isArray(e)?e.length:0,r=f(t.min)??f(t.minLength)??0;return n>=r||m("Must be at least {min} characters",{min:r,...t})}),u("maxLength",(e,t)=>{if(o(e))return!0;const n=typeof e=="string"||Array.isArray(e)?e.length:0,r=f(t.max)??f(t.maxLength)??1/0;return n<=r||m("Must be at most {max} characters",{max:r,...t})}),u("between",(e,t)=>{if(o(e))return!0;const n=f(e),r=f(t.min),i=f(t.max);return n===null||r===null||i===null?!0:n>=r&&n<=i||m("Must be between {min} and {max}",t)}),u("pattern",(e,t)=>{if(o(e))return!0;const n=t.pattern??t.regex;return typeof n!="string"?!0:new RegExp(n).test(String(e))||m("Does not match the required pattern",t)}),u("numeric",e=>o(e)?!0:f(e)!==null||"Must be a number"),u("integer",e=>{if(o(e))return!0;const t=f(e);return t!==null&&Number.isInteger(t)||"Must be an integer"}),u("alpha",e=>o(e)?!0:/^[a-zA-Z]+$/.test(String(e))||"Must contain only letters"),u("alphaNumeric",e=>o(e)?!0:/^[a-zA-Z0-9]+$/.test(String(e))||"Must contain only letters and numbers"),u("confirmed",(e,t,n)=>{if(o(e))return!0;const r=String(t.target??""),i=n.values[r]??n.values[`${r}_confirmation`];return e===i||"Confirmation does not match"}),u("requiredIf",(e,t,n)=>{const r=String(t.field??""),i=t.value,s=n.values[r];return(i!==void 0?s===i:!o(s))?!o(e)||m("This field is required when {field} is set",t):!0}),u("date",e=>{if(o(e))return!0;const t=new Date(String(e));return!Number.isNaN(t.getTime())||"Please enter a valid date"}),u("before",(e,t)=>{if(o(e))return!0;const n=new Date(String(e)),r=new Date(String(t.date??t.before));return Number.isNaN(n.getTime())||Number.isNaN(r.getTime())?!0:n<r||m("Must be before {date}",t)}),u("after",(e,t)=>{if(o(e))return!0;const n=new Date(String(e)),r=new Date(String(t.date??t.after));return Number.isNaN(n.getTime())||Number.isNaN(r.getTime())?!0:n>r||m("Must be after {date}",t)}),u("in",(e,t)=>o(e)?!0:(Array.isArray(t.values)?t.values:[]).includes(e)||"The selected value is not valid"),u("notIn",(e,t)=>o(e)?!0:!(Array.isArray(t.values)?t.values:[]).includes(e)||"The selected value is not allowed"),u("fileSize",(e,t)=>{if(o(e))return!0;const n=f(t.max)??1/0,r=Array.isArray(e)?e:[e];for(const i of r){const s=typeof i=="object"&&i!==null&&"size"in i?f(i.size):null;if(s!==null&&s>n)return m("File must be smaller than {max} bytes",t)}return!0}),u("mimeType",(e,t)=>{if(o(e))return!0;const n=Array.isArray(t.types)?t.types:typeof t.types=="string"?t.types.split(",").map(i=>i.trim()):[],r=Array.isArray(e)?e:[e];for(const i of r){const s=typeof i=="object"&&i!==null&&"type"in i?String(i.type):"";if(s&&!n.some(a=>s.match(new RegExp(a.replace("*",".*")))))return m("File type is not allowed. Allowed: {types}",t)}return!0}),u("maxFiles",(e,t)=>{if(o(e))return!0;const n=f(t.max)??1/0;return(Array.isArray(e)?e.length:1)<=n||m("Maximum {max} files allowed",t)}),u("unique",e=>o(e)||!Array.isArray(e)?!0:new Set(e).size===e.length||"All values must be unique"),u("custom",(e,t)=>!0);function O(e,t,n){switch(t){case"eq":return e===n;case"neq":return e!==n;case"gt":return Number(e)>Number(n);case"gte":return Number(e)>=Number(n);case"lt":return Number(e)<Number(n);case"lte":return Number(e)<=Number(n);case"in":return Array.isArray(n)&&n.includes(e);case"notIn":return Array.isArray(n)&&!n.includes(e);case"contains":return typeof e=="string"?e.includes(String(n)):Array.isArray(e)?e.includes(n):!1;case"empty":return e==null||e===""||Array.isArray(e)&&e.length===0;case"notEmpty":return!(e==null||e===""||Array.isArray(e)&&e.length===0);case"matches":{if(typeof n!="string")return!1;try{return new RegExp(n).test(String(e))}catch{return!1}}default:return!1}}function I(e){return"and"in e||"or"in e}function $(e,t){if(I(e))return e.and?e.and.every(r=>$(r,t)):e.or?e.or.some(r=>$(r,t)):!0;const n=t[e.field];return O(n,e.operator,e.value)}function S(e){if(typeof e!="object"||e===null)return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function x(e,t){const n={...e};for(const r of Object.keys(t)){const i=t[r],s=n[r];S(i)&&S(s)?n[r]=x(s,i):n[r]=i}return n}function k(e){return e.replace(/([a-z])([A-Z])/g,"$1 $2").replace(/[-_]+/g," ").replace(/\b\w/g,t=>t.toUpperCase()).trim()}function D(e){return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/\s+on\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi,"").replace(/(href|src|action)\s*=\s*(?:"javascript:[^"]*"|'javascript:[^']*')/gi,'$1=""')}l.SchemaValidationError=y,l.deepMerge=x,l.evaluateCondition=$,l.extractFields=d,l.getRule=E,l.hasRule=v,l.isFieldNode=N,l.parseFormSchema=F,l.registerRule=u,l.sanitizeHtml=D,l.setFieldTypeChecker=M,l.titleCase=k,l.unregisterRule=q,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
1
+ (function(l,g){typeof exports=="object"&&typeof module<"u"?g(exports):typeof define=="function"&&define.amd?define(["exports"],g):(l=typeof globalThis<"u"?globalThis:l||self,g(l.FormaticaCore={}))})(this,function(l){"use strict";function g(e,t,n){switch(t){case"eq":return e===n;case"neq":return e!==n;case"gt":return Number(e)>Number(n);case"gte":return Number(e)>=Number(n);case"lt":return Number(e)<Number(n);case"lte":return Number(e)<=Number(n);case"in":return Array.isArray(n)&&n.includes(e);case"notIn":return Array.isArray(n)&&!n.includes(e);case"contains":return typeof e=="string"?e.includes(String(n)):Array.isArray(e)?e.includes(n):!1;case"empty":return e==null||e===""||Array.isArray(e)&&e.length===0;case"notEmpty":return!(e==null||e===""||Array.isArray(e)&&e.length===0);case"matches":{if(typeof n!="string")return!1;try{return new RegExp(n).test(String(e))}catch{return!1}}default:return!1}}function C(e){return"and"in e||"or"in e}function $(e,t){if(C(e))return e.and?e.and.every(r=>$(r,t)):e.or?e.or.some(r=>$(r,t)):!0;const n=t[e.field];return g(n,e.operator,e.value)}let S={};function F(e){S={...e}}function M(){return S}function y(e){const t=[];for(const n of e)if(T(n))t.push(n);else if(n.type==="row"||n.type==="group")t.push(...y(n.children));else if(n.type==="steps")for(const r of n.steps)t.push(...y(r.children));else if(n.type==="tabs")for(const r of n.tabs)t.push(...y(r.children));return t}function T(e){return"name"in e&&typeof e.name=="string"}class p extends Error{constructor(t){const n=t.map(r=>`[${r.field}] ${r.message}`).join("; ");super(`Schema validation failed: ${n}`),this.name="SchemaValidationError",this.errors=t}}const z=new Set(["text","number","textarea","select","checkbox","checkbox-group","radio","switch","date","file","slider","tags","richtext","hidden","phone"]),R=new Set(["row","group","steps","tabs","divider","html"]);let h=null;function q(e){h=e}function d(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function N(e,t,n,r){if(!d(e)){r.push({field:t,rule:"condition",message:"Condition must be an object"});return}const i=e;if("and"in i||"or"in i){const a=i,c=a.and??a.or??[];if(!Array.isArray(c)){r.push({field:t,rule:"condition",message:"Compound condition must have an array of sub-conditions"});return}for(let w=0;w<c.length;w++)N(c[w],`${t}.condition[${w}]`,n,r);return}const s=i;typeof s.field!="string"?r.push({field:t,rule:"condition",message:'Condition must have a "field" property of type string'}):n.has(s.field)||r.push({field:t,rule:"condition",message:`Condition references unknown field "${s.field}"`}),typeof s.operator!="string"&&r.push({field:t,rule:"condition",message:'Condition must have an "operator" property'})}function E(e,t,n,r){if(!d(e)){r.push({field:t,rule:"type",message:"Field must be an object"});return}const i=e;(typeof i.name!="string"||i.name.length===0)&&r.push({field:t,rule:"name",message:'Field must have a non-empty "name"'}),typeof i.type!="string"?r.push({field:t,rule:"type",message:'Field must have a "type" string'}):!z.has(i.type)&&!(h!=null&&h(i.type))&&r.push({field:`${t}.${i.name}`,rule:"type",message:`Unknown field type "${i.type}"`}),["select","radio","checkbox-group"].includes(i.type)&&(i.options===void 0||i.options===null)&&r.push({field:`${t}.${i.name}`,rule:"options",message:`Field type "${i.type}" requires an "options" property`}),i.condition&&N(i.condition,`${t}.${i.name}`,n,r)}function v(e,t,n,r){if(!d(e)){r.push({field:t,rule:"type",message:"Node must be an object"});return}const i=e,s=i.type;if(typeof s!="string"){r.push({field:t,rule:"type",message:'Node must have a "type" string'});return}if(typeof i.name=="string"){E(e,t,n,r);return}if(!R.has(s)){r.push({field:t,rule:"type",message:`Unknown node type "${s}"`});return}if(s==="row"||s==="group")Array.isArray(i.children)?b(i.children,`${t}.children`,n,r):r.push({field:t,rule:"children",message:`"${s}" node must have a "children" array`}),s==="group"&&i.condition&&N(i.condition,`${t}.condition`,n,r);else if(s==="steps")if(!Array.isArray(i.steps))r.push({field:t,rule:"steps",message:'"steps" node must have a "steps" array'});else for(let a=0;a<i.steps.length;a++){const c=i.steps[a];if(!d(c)){r.push({field:`${t}.steps[${a}]`,rule:"type",message:"Step item must be an object"});continue}typeof c.title!="string"&&r.push({field:`${t}.steps[${a}]`,rule:"title",message:'Step item must have a "title" string'}),Array.isArray(c.children)&&b(c.children,`${t}.steps[${a}].children`,n,r)}else if(s==="tabs")if(!Array.isArray(i.tabs))r.push({field:t,rule:"tabs",message:'"tabs" node must have a "tabs" array'});else for(let a=0;a<i.tabs.length;a++){const c=i.tabs[a];if(!d(c)){r.push({field:`${t}.tabs[${a}]`,rule:"type",message:"Tab item must be an object"});continue}typeof c.title!="string"&&r.push({field:`${t}.tabs[${a}]`,rule:"title",message:'Tab item must have a "title" string'}),Array.isArray(c.children)&&b(c.children,`${t}.tabs[${a}].children`,n,r)}else s==="html"&&typeof i.content!="string"&&r.push({field:t,rule:"content",message:'"html" node must have a "content" string'})}function b(e,t,n,r){for(let i=0;i<e.length;i++)v(e[i],`${t}[${i}]`,n,r)}function O(e,t){if(!d(e)){t.push({field:"settings",rule:"type",message:"Settings must be an object"});return}const n=e;n.layout!==void 0&&!["vertical","horizontal","inline"].includes(n.layout)&&t.push({field:"settings.layout",rule:"enum",message:'Layout must be "vertical", "horizontal", or "inline"'}),n.size!==void 0&&!["small","medium","large"].includes(n.size)&&t.push({field:"settings.size",rule:"enum",message:'Size must be "small", "medium", or "large"'})}function I(e){const t=[];if(!d(e))throw t.push({field:"$root",rule:"type",message:"Schema must be a plain object"}),new p(t);const n=e;if(!Array.isArray(n.fields))throw t.push({field:"fields",rule:"type",message:'"fields" must be an array'}),new p(t);const r=y(n.fields),i=new Set,s=new Map;for(const a of r){i.add(a.name);const c=(s.get(a.name)??0)+1;s.set(a.name,c),c>1&&t.push({field:a.name,rule:"unique",message:`Duplicate field name "${a.name}"`})}if(b(n.fields,"fields",i,t),n.settings!==void 0&&O(n.settings,t),t.length>0)throw new p(t);return{id:typeof n.id=="string"?n.id:void 0,version:typeof n.version=="string"?n.version:void 0,fields:n.fields,settings:n.settings,translations:n.translations}}function j(e){if(typeof e!="object"||e===null)return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function x(e,t){const n={...e};for(const r of Object.keys(t)){const i=t[r],s=n[r];j(i)&&j(s)?n[r]=x(s,i):n[r]=i}return n}function k(e){return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/\s+on\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi,"").replace(/(href|src|action)\s*=\s*(?:"javascript:[^"]*"|'javascript:[^']*')/gi,'$1=""')}function D(e){return e.replace(/([a-z])([A-Z])/g,"$1 $2").replace(/[-_]+/g," ").replace(/\b\w/g,t=>t.toUpperCase()).trim()}const A=new Map;function u(e,t){A.set(e,t)}function L(e){A.delete(e)}function P(e){return A.get(e)}function _(e){return A.has(e)}function o(e){return!!(e==null||e===""||Array.isArray(e)&&e.length===0)}function m(e,t){return e.replace(/\{(\w+)\}/g,(n,r)=>t[r]!==void 0?String(t[r]):`{${r}}`)}function f(e){if(typeof e=="number")return e;if(typeof e=="string"){const t=Number(e);return Number.isNaN(t)?null:t}return null}u("required",e=>o(e)?"This field is required":!0),u("email",e=>o(e)?!0:/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(e))||"Please enter a valid email address"),u("phone",async e=>{if(o(e))return!0;const t=String(e);try{return(await import("libphonenumber-js")).isValidPhoneNumber(t)||"Please enter a valid phone number"}catch{return/^\+[1-9]\d{6,14}$/.test(t.replace(/[\s\-().]/g,""))?!0:"Please enter a valid phone number"}}),u("url",e=>{if(o(e))return!0;try{return new URL(String(e)),!0}catch{return"Please enter a valid URL"}}),u("min",(e,t)=>{if(o(e))return!0;const n=f(e),r=f(t.min);return n===null||r===null?!0:n>=r||m("Must be at least {min}",t)}),u("max",(e,t)=>{if(o(e))return!0;const n=f(e),r=f(t.max);return n===null||r===null?!0:n<=r||m("Must be at most {max}",t)}),u("minLength",(e,t)=>{if(o(e))return!0;const n=typeof e=="string"||Array.isArray(e)?e.length:0,r=f(t.min)??f(t.minLength)??0;return n>=r||m("Must be at least {min} characters",{min:r,...t})}),u("maxLength",(e,t)=>{if(o(e))return!0;const n=typeof e=="string"||Array.isArray(e)?e.length:0,r=f(t.max)??f(t.maxLength)??1/0;return n<=r||m("Must be at most {max} characters",{max:r,...t})}),u("between",(e,t)=>{if(o(e))return!0;const n=f(e),r=f(t.min),i=f(t.max);return n===null||r===null||i===null?!0:n>=r&&n<=i||m("Must be between {min} and {max}",t)}),u("pattern",(e,t)=>{if(o(e))return!0;const n=t.pattern??t.regex;return typeof n!="string"?!0:new RegExp(n).test(String(e))||m("Does not match the required pattern",t)}),u("numeric",e=>o(e)?!0:f(e)!==null||"Must be a number"),u("integer",e=>{if(o(e))return!0;const t=f(e);return t!==null&&Number.isInteger(t)||"Must be an integer"}),u("alpha",e=>o(e)?!0:/^[a-zA-Z]+$/.test(String(e))||"Must contain only letters"),u("alphaNumeric",e=>o(e)?!0:/^[a-zA-Z0-9]+$/.test(String(e))||"Must contain only letters and numbers"),u("confirmed",(e,t,n)=>{if(o(e))return!0;const r=String(t.target??""),i=n.values[r]??n.values[`${r}_confirmation`];return e===i||"Confirmation does not match"}),u("requiredIf",(e,t,n)=>{const r=String(t.field??""),i=t.value,s=n.values[r];return(i!==void 0?s===i:!o(s))?!o(e)||m("This field is required when {field} is set",t):!0}),u("date",e=>{if(o(e))return!0;const t=new Date(String(e));return!Number.isNaN(t.getTime())||"Please enter a valid date"}),u("before",(e,t)=>{if(o(e))return!0;const n=new Date(String(e)),r=new Date(String(t.date??t.before));return Number.isNaN(n.getTime())||Number.isNaN(r.getTime())?!0:n<r||m("Must be before {date}",t)}),u("after",(e,t)=>{if(o(e))return!0;const n=new Date(String(e)),r=new Date(String(t.date??t.after));return Number.isNaN(n.getTime())||Number.isNaN(r.getTime())?!0:n>r||m("Must be after {date}",t)}),u("in",(e,t)=>o(e)?!0:(Array.isArray(t.values)?t.values:[]).includes(e)||"The selected value is not valid"),u("notIn",(e,t)=>o(e)?!0:!(Array.isArray(t.values)?t.values:[]).includes(e)||"The selected value is not allowed"),u("fileSize",(e,t)=>{if(o(e))return!0;const n=f(t.max)??1/0,r=Array.isArray(e)?e:[e];for(const i of r){const s=typeof i=="object"&&i!==null&&"size"in i?f(i.size):null;if(s!==null&&s>n)return m("File must be smaller than {max} bytes",t)}return!0}),u("mimeType",(e,t)=>{if(o(e))return!0;const n=Array.isArray(t.types)?t.types:typeof t.types=="string"?t.types.split(",").map(i=>i.trim()):[],r=Array.isArray(e)?e:[e];for(const i of r){const s=typeof i=="object"&&i!==null&&"type"in i?String(i.type):"";if(s&&!n.some(a=>s.match(new RegExp(a.replace("*",".*")))))return m("File type is not allowed. Allowed: {types}",t)}return!0}),u("maxFiles",(e,t)=>{if(o(e))return!0;const n=f(t.max)??1/0;return(Array.isArray(e)?e.length:1)<=n||m("Maximum {max} files allowed",t)}),u("unique",e=>o(e)||!Array.isArray(e)?!0:new Set(e).size===e.length||"All values must be unique"),u("custom",(e,t)=>!0),l.SchemaValidationError=p,l.configureFormatica=F,l.deepMerge=x,l.evaluateCondition=$,l.extractFields=y,l.getFormaticaConfig=M,l.getRule=P,l.hasRule=_,l.isFieldNode=T,l.parseFormSchema=I,l.registerRule=u,l.sanitizeHtml=k,l.setFieldTypeChecker=q,l.titleCase=D,l.unregisterRule=L,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
2
2
  //# sourceMappingURL=formatica-core.umd.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatica-core.umd.cjs","sources":["../src/extractFields.ts","../src/schemaParser.ts","../src/validation/ruleRegistry.ts","../src/conditions.ts","../src/utils/deepMerge.ts","../src/utils/titleCase.ts","../src/utils/sanitize.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Formatica Core – Utility to extract field schemas from a unified schema tree\n// ---------------------------------------------------------------------------\n\nimport type { FieldSchema, SchemaNode } from \"./types/schema\";\n\n/**\n * Recursively walks a `SchemaNode[]` tree and collects every node that is an\n * actual field (i.e. has a `name` property), ignoring layout containers.\n */\nexport function extractFields(nodes: SchemaNode[]): FieldSchema[] {\n const fields: FieldSchema[] = [];\n for (const node of nodes) {\n if (isFieldNode(node)) {\n fields.push(node);\n } else if (node.type === \"row\" || node.type === \"group\") {\n fields.push(...extractFields(node.children));\n } else if (node.type === \"steps\") {\n for (const step of node.steps) {\n fields.push(...extractFields(step.children));\n }\n } else if (node.type === \"tabs\") {\n for (const tab of node.tabs) {\n fields.push(...extractFields(tab.children));\n }\n }\n }\n return fields;\n}\n\n/**\n * Type-guard that distinguishes field nodes from layout container nodes.\n */\nexport function isFieldNode(node: SchemaNode): node is FieldSchema {\n return \"name\" in node && typeof node.name === \"string\";\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Schema parser & validator\n// ---------------------------------------------------------------------------\n\nimport type {\n Condition,\n ConditionGroup,\n FormSchema,\n FormSettings,\n SchemaNode,\n} from \"./types/schema\";\nimport type { SchemaError } from \"./types/validation\";\nimport { extractFields } from \"./extractFields\";\n\n// ---------------------------------------------------------------------------\n// Error class\n// ---------------------------------------------------------------------------\n\nexport class SchemaValidationError extends Error {\n public readonly errors: SchemaError[];\n\n constructor(errors: SchemaError[]) {\n const summary = errors.map((e) => `[${e.field}] ${e.message}`).join(\"; \");\n super(`Schema validation failed: ${summary}`);\n this.name = \"SchemaValidationError\";\n this.errors = errors;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Known field types\n// ---------------------------------------------------------------------------\n\nconst KNOWN_FIELD_TYPES = new Set([\n \"text\",\n \"number\",\n \"textarea\",\n \"select\",\n \"checkbox\",\n \"checkbox-group\",\n \"radio\",\n \"switch\",\n \"date\",\n \"file\",\n \"slider\",\n \"tags\",\n \"richtext\",\n \"hidden\",\n \"phone\",\n]);\n\nconst CONTAINER_TYPES = new Set([\"row\", \"group\", \"steps\", \"tabs\", \"divider\", \"html\"]);\n\n// ---------------------------------------------------------------------------\n// Custom field type checker (pluggable for framework-specific registries)\n// ---------------------------------------------------------------------------\n\nlet customFieldTypeChecker: ((type: string) => boolean) | null = null;\n\n/**\n * Register a custom field type checker. This allows framework-specific packages\n * (e.g. @formatica/vue) to hook their field registry into schema validation.\n */\nexport function setFieldTypeChecker(checker: ((type: string) => boolean) | null): void {\n customFieldTypeChecker = checker;\n}\n\n// ---------------------------------------------------------------------------\n// Validation helpers\n// ---------------------------------------------------------------------------\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateCondition(\n condition: unknown,\n fieldPath: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(condition)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: \"Condition must be an object\",\n });\n return;\n }\n\n const cond = condition as Record<string, unknown>;\n\n // Compound conditions\n if (\"and\" in cond || \"or\" in cond) {\n const group = cond as ConditionGroup;\n const children = group.and ?? group.or ?? [];\n if (!Array.isArray(children)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: \"Compound condition must have an array of sub-conditions\",\n });\n return;\n }\n for (let i = 0; i < children.length; i++) {\n validateCondition(children[i], `${fieldPath}.condition[${i}]`, allFieldNames, errors);\n }\n return;\n }\n\n // Simple condition\n const simple = cond as unknown as Condition;\n if (typeof simple.field !== \"string\") {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: 'Condition must have a \"field\" property of type string',\n });\n } else if (!allFieldNames.has(simple.field)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: `Condition references unknown field \"${simple.field}\"`,\n });\n }\n\n if (typeof simple.operator !== \"string\") {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: 'Condition must have an \"operator\" property',\n });\n }\n}\n\nfunction validateFieldNode(\n field: unknown,\n path: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(field)) {\n errors.push({ field: path, rule: \"type\", message: \"Field must be an object\" });\n return;\n }\n\n const f = field as Record<string, unknown>;\n\n // name\n if (typeof f.name !== \"string\" || f.name.length === 0) {\n errors.push({ field: path, rule: \"name\", message: 'Field must have a non-empty \"name\"' });\n }\n\n // type\n if (typeof f.type !== \"string\") {\n errors.push({ field: path, rule: \"type\", message: 'Field must have a \"type\" string' });\n } else if (!KNOWN_FIELD_TYPES.has(f.type) && !customFieldTypeChecker?.(f.type)) {\n errors.push({\n field: `${path}.${f.name as string}`,\n rule: \"type\",\n message: `Unknown field type \"${f.type}\"`,\n });\n }\n\n // options required for select, radio, checkbox-group\n if ([\"select\", \"radio\", \"checkbox-group\"].includes(f.type as string)) {\n if (f.options === undefined || f.options === null) {\n errors.push({\n field: `${path}.${f.name as string}`,\n rule: \"options\",\n message: `Field type \"${f.type as string}\" requires an \"options\" property`,\n });\n }\n }\n\n // condition references\n if (f.condition) {\n validateCondition(f.condition, `${path}.${f.name as string}`, allFieldNames, errors);\n }\n}\n\nfunction validateNode(\n node: unknown,\n path: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(node)) {\n errors.push({ field: path, rule: \"type\", message: \"Node must be an object\" });\n return;\n }\n\n const n = node as Record<string, unknown>;\n const type = n.type as string;\n\n if (typeof type !== \"string\") {\n errors.push({ field: path, rule: \"type\", message: 'Node must have a \"type\" string' });\n return;\n }\n\n // If it's a field node (has a name), validate as field\n if (typeof n.name === \"string\") {\n validateFieldNode(node, path, allFieldNames, errors);\n return;\n }\n\n // Container nodes\n if (!CONTAINER_TYPES.has(type)) {\n errors.push({\n field: path,\n rule: \"type\",\n message: `Unknown node type \"${type}\"`,\n });\n return;\n }\n\n if (type === \"row\" || type === \"group\") {\n if (!Array.isArray(n.children)) {\n errors.push({\n field: path,\n rule: \"children\",\n message: `\"${type}\" node must have a \"children\" array`,\n });\n } else {\n validateNodes(n.children, `${path}.children`, allFieldNames, errors);\n }\n if (type === \"group\" && n.condition) {\n validateCondition(n.condition, `${path}.condition`, allFieldNames, errors);\n }\n } else if (type === \"steps\") {\n if (!Array.isArray(n.steps)) {\n errors.push({\n field: path,\n rule: \"steps\",\n message: '\"steps\" node must have a \"steps\" array',\n });\n } else {\n for (let i = 0; i < n.steps.length; i++) {\n const step = n.steps[i] as Record<string, unknown>;\n if (!isPlainObject(step)) {\n errors.push({\n field: `${path}.steps[${i}]`,\n rule: \"type\",\n message: \"Step item must be an object\",\n });\n continue;\n }\n if (typeof step.title !== \"string\") {\n errors.push({\n field: `${path}.steps[${i}]`,\n rule: \"title\",\n message: 'Step item must have a \"title\" string',\n });\n }\n if (Array.isArray(step.children)) {\n validateNodes(\n step.children,\n `${path}.steps[${i}].children`,\n allFieldNames,\n errors,\n );\n }\n }\n }\n } else if (type === \"tabs\") {\n if (!Array.isArray(n.tabs)) {\n errors.push({\n field: path,\n rule: \"tabs\",\n message: '\"tabs\" node must have a \"tabs\" array',\n });\n } else {\n for (let i = 0; i < n.tabs.length; i++) {\n const tab = n.tabs[i] as Record<string, unknown>;\n if (!isPlainObject(tab)) {\n errors.push({\n field: `${path}.tabs[${i}]`,\n rule: \"type\",\n message: \"Tab item must be an object\",\n });\n continue;\n }\n if (typeof tab.title !== \"string\") {\n errors.push({\n field: `${path}.tabs[${i}]`,\n rule: \"title\",\n message: 'Tab item must have a \"title\" string',\n });\n }\n if (Array.isArray(tab.children)) {\n validateNodes(\n tab.children,\n `${path}.tabs[${i}].children`,\n allFieldNames,\n errors,\n );\n }\n }\n }\n } else if (type === \"html\") {\n if (typeof n.content !== \"string\") {\n errors.push({\n field: path,\n rule: \"content\",\n message: '\"html\" node must have a \"content\" string',\n });\n }\n }\n // \"divider\" has no required children/content — always valid if type matches\n}\n\nfunction validateNodes(\n nodes: unknown[],\n basePath: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n for (let i = 0; i < nodes.length; i++) {\n validateNode(nodes[i], `${basePath}[${i}]`, allFieldNames, errors);\n }\n}\n\nfunction validateSettings(settings: unknown, errors: SchemaError[]): void {\n if (!isPlainObject(settings)) {\n errors.push({ field: \"settings\", rule: \"type\", message: \"Settings must be an object\" });\n return;\n }\n\n const s = settings as Record<string, unknown>;\n\n if (\n s.layout !== undefined &&\n ![\"vertical\", \"horizontal\", \"inline\"].includes(s.layout as string)\n ) {\n errors.push({\n field: \"settings.layout\",\n rule: \"enum\",\n message: 'Layout must be \"vertical\", \"horizontal\", or \"inline\"',\n });\n }\n\n if (s.size !== undefined && ![\"small\", \"medium\", \"large\"].includes(s.size as string)) {\n errors.push({\n field: \"settings.size\",\n rule: \"enum\",\n message: 'Size must be \"small\", \"medium\", or \"large\"',\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse and validate a JSON schema, returning a typed FormSchema.\n * Collects all validation errors before throwing a single SchemaValidationError.\n */\nexport function parseFormSchema(json: unknown): FormSchema {\n const errors: SchemaError[] = [];\n\n if (!isPlainObject(json)) {\n errors.push({ field: \"$root\", rule: \"type\", message: \"Schema must be a plain object\" });\n throw new SchemaValidationError(errors);\n }\n\n const raw = json as Record<string, unknown>;\n\n // fields\n if (!Array.isArray(raw.fields)) {\n errors.push({ field: \"fields\", rule: \"type\", message: '\"fields\" must be an array' });\n throw new SchemaValidationError(errors);\n }\n\n // Collect all field names recursively for cross-reference validation\n const allFields = extractFields(raw.fields as SchemaNode[]);\n const allFieldNames = new Set<string>();\n const nameTracker = new Map<string, number>();\n for (const f of allFields) {\n allFieldNames.add(f.name);\n const count = (nameTracker.get(f.name) ?? 0) + 1;\n nameTracker.set(f.name, count);\n if (count > 1) {\n errors.push({\n field: f.name,\n rule: \"unique\",\n message: `Duplicate field name \"${f.name}\"`,\n });\n }\n }\n\n // Validate each node recursively (fields and containers)\n validateNodes(raw.fields, \"fields\", allFieldNames, errors);\n\n // Validate settings\n if (raw.settings !== undefined) {\n validateSettings(raw.settings, errors);\n }\n\n if (errors.length > 0) {\n throw new SchemaValidationError(errors);\n }\n\n return {\n id: typeof raw.id === \"string\" ? raw.id : undefined,\n version: typeof raw.version === \"string\" ? raw.version : undefined,\n fields: raw.fields as SchemaNode[],\n settings: raw.settings as FormSettings | undefined,\n translations: raw.translations as FormSchema[\"translations\"],\n };\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Validation rule registry\n// ---------------------------------------------------------------------------\n\nimport type { RuleFn } from \"../types/validation\";\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\nconst rules = new Map<string, RuleFn>();\n\nexport function registerRule(name: string, fn: RuleFn): void {\n rules.set(name, fn);\n}\n\nexport function unregisterRule(name: string): void {\n rules.delete(name);\n}\n\nexport function getRule(name: string): RuleFn | undefined {\n return rules.get(name);\n}\n\nexport function hasRule(name: string): boolean {\n return rules.has(name);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isEmpty(value: unknown): boolean {\n if (value === null || value === undefined || value === \"\") return true;\n if (Array.isArray(value) && value.length === 0) return true;\n return false;\n}\n\nfunction interpolate(template: string, params: Record<string, unknown>): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) => {\n return params[key] !== undefined ? String(params[key]) : `{${key}}`;\n });\n}\n\nfunction toNumber(value: unknown): number | null {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const n = Number(value);\n return Number.isNaN(n) ? null : n;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in rules\n// ---------------------------------------------------------------------------\n\nregisterRule(\"required\", (value) => {\n if (isEmpty(value)) return \"This field is required\";\n return true;\n});\n\nregisterRule(\"email\", (value) => {\n if (isEmpty(value)) return true;\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value)) || \"Please enter a valid email address\";\n});\n\nregisterRule(\"phone\", async (value) => {\n if (isEmpty(value)) return true;\n const str = String(value);\n try {\n const lib = await import(\"libphonenumber-js\");\n return lib.isValidPhoneNumber(str) || \"Please enter a valid phone number\";\n } catch {\n // Fallback if libphonenumber-js not available\n if (/^\\+[1-9]\\d{6,14}$/.test(str.replace(/[\\s\\-().]/g, \"\"))) return true;\n return \"Please enter a valid phone number\";\n }\n});\n\nregisterRule(\"url\", (value) => {\n if (isEmpty(value)) return true;\n try {\n new URL(String(value));\n return true;\n } catch {\n return \"Please enter a valid URL\";\n }\n});\n\nregisterRule(\"min\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const min = toNumber(params.min);\n if (num === null || min === null) return true;\n return num >= min || interpolate(\"Must be at least {min}\", params);\n});\n\nregisterRule(\"max\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const max = toNumber(params.max);\n if (num === null || max === null) return true;\n return num <= max || interpolate(\"Must be at most {max}\", params);\n});\n\nregisterRule(\"minLength\", (value, params) => {\n if (isEmpty(value)) return true;\n const len = typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : 0;\n const min = toNumber(params.min) ?? toNumber(params.minLength) ?? 0;\n return len >= min || interpolate(\"Must be at least {min} characters\", { min, ...params });\n});\n\nregisterRule(\"maxLength\", (value, params) => {\n if (isEmpty(value)) return true;\n const len = typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : 0;\n const max = toNumber(params.max) ?? toNumber(params.maxLength) ?? Infinity;\n return len <= max || interpolate(\"Must be at most {max} characters\", { max, ...params });\n});\n\nregisterRule(\"between\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const min = toNumber(params.min);\n const max = toNumber(params.max);\n if (num === null || min === null || max === null) return true;\n return (num >= min && num <= max) || interpolate(\"Must be between {min} and {max}\", params);\n});\n\nregisterRule(\"pattern\", (value, params) => {\n if (isEmpty(value)) return true;\n const pattern = params.pattern ?? params.regex;\n if (typeof pattern !== \"string\") return true;\n const re = new RegExp(pattern);\n return re.test(String(value)) || interpolate(\"Does not match the required pattern\", params);\n});\n\nregisterRule(\"numeric\", (value) => {\n if (isEmpty(value)) return true;\n return toNumber(value) !== null || \"Must be a number\";\n});\n\nregisterRule(\"integer\", (value) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n return (num !== null && Number.isInteger(num)) || \"Must be an integer\";\n});\n\nregisterRule(\"alpha\", (value) => {\n if (isEmpty(value)) return true;\n return /^[a-zA-Z]+$/.test(String(value)) || \"Must contain only letters\";\n});\n\nregisterRule(\"alphaNumeric\", (value) => {\n if (isEmpty(value)) return true;\n return /^[a-zA-Z0-9]+$/.test(String(value)) || \"Must contain only letters and numbers\";\n});\n\nregisterRule(\"confirmed\", (value, params, ctx) => {\n if (isEmpty(value)) return true;\n const target = String(params.target ?? \"\");\n const other = ctx.values[target] ?? ctx.values[`${target}_confirmation`];\n return value === other || \"Confirmation does not match\";\n});\n\nregisterRule(\"requiredIf\", (value, params, ctx) => {\n const targetField = String(params.field ?? \"\");\n const targetValue = params.value;\n const actual = ctx.values[targetField];\n const shouldRequire = targetValue !== undefined ? actual === targetValue : !isEmpty(actual);\n if (!shouldRequire) return true;\n return !isEmpty(value) || interpolate(\"This field is required when {field} is set\", params);\n});\n\nregisterRule(\"date\", (value) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n return !Number.isNaN(d.getTime()) || \"Please enter a valid date\";\n});\n\nregisterRule(\"before\", (value, params) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n const before = new Date(String(params.date ?? params.before));\n if (Number.isNaN(d.getTime()) || Number.isNaN(before.getTime())) return true;\n return d < before || interpolate(\"Must be before {date}\", params);\n});\n\nregisterRule(\"after\", (value, params) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n const after = new Date(String(params.date ?? params.after));\n if (Number.isNaN(d.getTime()) || Number.isNaN(after.getTime())) return true;\n return d > after || interpolate(\"Must be after {date}\", params);\n});\n\nregisterRule(\"in\", (value, params) => {\n if (isEmpty(value)) return true;\n const allowed = Array.isArray(params.values) ? params.values : [];\n return (allowed as unknown[]).includes(value) || \"The selected value is not valid\";\n});\n\nregisterRule(\"notIn\", (value, params) => {\n if (isEmpty(value)) return true;\n const disallowed = Array.isArray(params.values) ? params.values : [];\n return !(disallowed as unknown[]).includes(value) || \"The selected value is not allowed\";\n});\n\nregisterRule(\"fileSize\", (value, params) => {\n if (isEmpty(value)) return true;\n const maxBytes = toNumber(params.max) ?? Infinity;\n const files = Array.isArray(value) ? value : [value];\n for (const file of files) {\n const size =\n typeof file === \"object\" && file !== null && \"size\" in file\n ? toNumber((file as { size: unknown }).size)\n : null;\n if (size !== null && size > maxBytes) {\n return interpolate(\"File must be smaller than {max} bytes\", params);\n }\n }\n return true;\n});\n\nregisterRule(\"mimeType\", (value, params) => {\n if (isEmpty(value)) return true;\n const allowed = Array.isArray(params.types)\n ? (params.types as string[])\n : typeof params.types === \"string\"\n ? params.types.split(\",\").map((s: string) => s.trim())\n : [];\n const files = Array.isArray(value) ? value : [value];\n for (const file of files) {\n const fileType =\n typeof file === \"object\" && file !== null && \"type\" in file\n ? String((file as { type: unknown }).type)\n : \"\";\n if (fileType && !allowed.some((t) => fileType.match(new RegExp(t.replace(\"*\", \".*\"))))) {\n return interpolate(\"File type is not allowed. Allowed: {types}\", params);\n }\n }\n return true;\n});\n\nregisterRule(\"maxFiles\", (value, params) => {\n if (isEmpty(value)) return true;\n const max = toNumber(params.max) ?? Infinity;\n const count = Array.isArray(value) ? value.length : 1;\n return count <= max || interpolate(\"Maximum {max} files allowed\", params);\n});\n\nregisterRule(\"unique\", (value) => {\n if (isEmpty(value)) return true;\n if (!Array.isArray(value)) return true;\n const set = new Set(value as unknown[]);\n return set.size === value.length || \"All values must be unique\";\n});\n\nregisterRule(\"custom\", (value, params) => {\n // Custom rules are handled at the ValidationRule level via validator fn.\n // This is a no-op fallback.\n void value;\n void params;\n return true;\n});\n","// ---------------------------------------------------------------------------\n// Formatica Core – Condition evaluation\n// ---------------------------------------------------------------------------\n\nimport type { Condition, ConditionGroup, ConditionOperator } from \"./types/schema\";\n\n// ---------------------------------------------------------------------------\n// Single condition evaluation\n// ---------------------------------------------------------------------------\n\nfunction evaluateOperator(\n fieldValue: unknown,\n operator: ConditionOperator,\n conditionValue: unknown,\n): boolean {\n switch (operator) {\n case \"eq\":\n return fieldValue === conditionValue;\n case \"neq\":\n return fieldValue !== conditionValue;\n case \"gt\":\n return Number(fieldValue) > Number(conditionValue);\n case \"gte\":\n return Number(fieldValue) >= Number(conditionValue);\n case \"lt\":\n return Number(fieldValue) < Number(conditionValue);\n case \"lte\":\n return Number(fieldValue) <= Number(conditionValue);\n case \"in\":\n return (\n Array.isArray(conditionValue) && (conditionValue as unknown[]).includes(fieldValue)\n );\n case \"notIn\":\n return (\n Array.isArray(conditionValue) && !(conditionValue as unknown[]).includes(fieldValue)\n );\n case \"contains\": {\n if (typeof fieldValue === \"string\") return fieldValue.includes(String(conditionValue));\n if (Array.isArray(fieldValue))\n return (fieldValue as unknown[]).includes(conditionValue);\n return false;\n }\n case \"empty\":\n return (\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === \"\" ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n );\n case \"notEmpty\":\n return !(\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === \"\" ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n );\n case \"matches\": {\n if (typeof conditionValue !== \"string\") return false;\n try {\n return new RegExp(conditionValue).test(String(fieldValue));\n } catch {\n return false;\n }\n }\n default:\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nfunction isConditionGroup(cond: Condition | ConditionGroup): cond is ConditionGroup {\n return \"and\" in cond || \"or\" in cond;\n}\n\n/**\n * Evaluate a single condition or a compound condition group against the\n * current form values.\n */\nexport function evaluateCondition(\n condition: Condition | ConditionGroup,\n values: Record<string, unknown>,\n): boolean {\n if (isConditionGroup(condition)) {\n if (condition.and) {\n return condition.and.every((c) => evaluateCondition(c, values));\n }\n if (condition.or) {\n return condition.or.some((c) => evaluateCondition(c, values));\n }\n // Empty group evaluates to true\n return true;\n }\n\n const fieldValue = values[condition.field];\n return evaluateOperator(fieldValue, condition.operator, condition.value);\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Deep merge utility\n// ---------------------------------------------------------------------------\n\ntype PlainObject = Record<string, unknown>;\n\nfunction isPlainObject(value: unknown): value is PlainObject {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Deep-merge two objects. Arrays are replaced (not concatenated).\n * Returns a new object – neither source is mutated.\n */\nexport function deepMerge<T extends PlainObject>(target: T, source: Partial<T>): T {\n const result: PlainObject = { ...target };\n\n for (const key of Object.keys(source)) {\n const srcVal = (source as PlainObject)[key];\n const tgtVal = result[key];\n\n if (isPlainObject(srcVal) && isPlainObject(tgtVal)) {\n result[key] = deepMerge(tgtVal, srcVal);\n } else {\n result[key] = srcVal;\n }\n }\n\n return result as T;\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Title case conversion utility\n// ---------------------------------------------------------------------------\n\n/**\n * Convert camelCase, kebab-case, or snake_case field names to Title Case.\n *\n * @example\n * titleCase('firstName') // \"First Name\"\n * titleCase('last-name') // \"Last Name\"\n * titleCase('email_address') // \"Email Address\"\n */\nexport function titleCase(input: string): string {\n return (\n input\n // Insert space before uppercase letters in camelCase\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n // Replace kebab-case and snake_case separators with spaces\n .replace(/[-_]+/g, \" \")\n // Capitalize first letter of each word\n .replace(/\\b\\w/g, (char) => char.toUpperCase())\n .trim()\n );\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Simple HTML sanitizer for HtmlLayout content\n// ---------------------------------------------------------------------------\n\n/**\n * Strip `<script>` tags and inline event handlers (on*=\"...\") from HTML strings.\n * This is a lightweight sanitizer for use with the HtmlLayout node type.\n */\nexport function sanitizeHtml(html: string): string {\n return (\n html\n // Remove <script> tags and their content\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, \"\")\n // Remove event handler attributes (onclick, onload, onerror, etc.)\n .replace(/\\s+on\\w+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi, \"\")\n // Remove javascript: protocol in href/src/action attributes\n .replace(/(href|src|action)\\s*=\\s*(?:\"javascript:[^\"]*\"|'javascript:[^']*')/gi, '$1=\"\"')\n );\n}\n"],"names":["extractFields","nodes","fields","node","isFieldNode","step","tab","SchemaValidationError","errors","summary","e","KNOWN_FIELD_TYPES","CONTAINER_TYPES","customFieldTypeChecker","setFieldTypeChecker","checker","isPlainObject","value","validateCondition","condition","fieldPath","allFieldNames","cond","group","children","i","simple","validateFieldNode","field","path","f","validateNode","n","type","validateNodes","basePath","validateSettings","settings","s","parseFormSchema","json","raw","allFields","nameTracker","count","rules","registerRule","name","fn","unregisterRule","getRule","hasRule","isEmpty","interpolate","template","params","_","key","toNumber","str","num","min","max","len","pattern","ctx","target","other","targetField","targetValue","actual","d","before","after","maxBytes","files","file","size","allowed","fileType","t","evaluateOperator","fieldValue","operator","conditionValue","isConditionGroup","evaluateCondition","values","c","proto","deepMerge","source","result","srcVal","tgtVal","titleCase","input","char","sanitizeHtml","html"],"mappings":"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"}
1
+ {"version":3,"file":"formatica-core.umd.cjs","sources":["../src/conditions.ts","../src/config.ts","../src/extractFields.ts","../src/schemaParser.ts","../src/utils/deepMerge.ts","../src/utils/sanitize.ts","../src/utils/titleCase.ts","../src/validation/ruleRegistry.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Formatica Core – Condition evaluation\n// ---------------------------------------------------------------------------\n\nimport type { Condition, ConditionGroup, ConditionOperator } from \"./types/schema\";\n\n// ---------------------------------------------------------------------------\n// Single condition evaluation\n// ---------------------------------------------------------------------------\n\nfunction evaluateOperator(\n fieldValue: unknown,\n operator: ConditionOperator,\n conditionValue: unknown,\n): boolean {\n switch (operator) {\n case \"eq\":\n return fieldValue === conditionValue;\n case \"neq\":\n return fieldValue !== conditionValue;\n case \"gt\":\n return Number(fieldValue) > Number(conditionValue);\n case \"gte\":\n return Number(fieldValue) >= Number(conditionValue);\n case \"lt\":\n return Number(fieldValue) < Number(conditionValue);\n case \"lte\":\n return Number(fieldValue) <= Number(conditionValue);\n case \"in\":\n return (\n Array.isArray(conditionValue) && (conditionValue as unknown[]).includes(fieldValue)\n );\n case \"notIn\":\n return (\n Array.isArray(conditionValue) && !(conditionValue as unknown[]).includes(fieldValue)\n );\n case \"contains\": {\n if (typeof fieldValue === \"string\") return fieldValue.includes(String(conditionValue));\n if (Array.isArray(fieldValue))\n return (fieldValue as unknown[]).includes(conditionValue);\n return false;\n }\n case \"empty\":\n return (\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === \"\" ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n );\n case \"notEmpty\":\n return !(\n fieldValue === null ||\n fieldValue === undefined ||\n fieldValue === \"\" ||\n (Array.isArray(fieldValue) && fieldValue.length === 0)\n );\n case \"matches\": {\n if (typeof conditionValue !== \"string\") return false;\n try {\n return new RegExp(conditionValue).test(String(fieldValue));\n } catch {\n return false;\n }\n }\n default:\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nfunction isConditionGroup(cond: Condition | ConditionGroup): cond is ConditionGroup {\n return \"and\" in cond || \"or\" in cond;\n}\n\n/**\n * Evaluate a single condition or a compound condition group against the\n * current form values.\n */\nexport function evaluateCondition(\n condition: Condition | ConditionGroup,\n values: Record<string, unknown>,\n): boolean {\n if (isConditionGroup(condition)) {\n if (condition.and) {\n return condition.and.every((c) => evaluateCondition(c, values));\n }\n if (condition.or) {\n return condition.or.some((c) => evaluateCondition(c, values));\n }\n // Empty group evaluates to true\n return true;\n }\n\n const fieldValue = values[condition.field];\n return evaluateOperator(fieldValue, condition.operator, condition.value);\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Global configuration\n// ---------------------------------------------------------------------------\n\nimport type { ThemeConfig } from \"./types/theme\";\n\nexport interface FormaticaCoreConfig {\n theme?: ThemeConfig;\n locale?: string;\n}\n\nlet globalConfig: FormaticaCoreConfig = {};\n\nexport function configureFormatica(config: FormaticaCoreConfig): void {\n globalConfig = { ...config };\n}\n\nexport function getFormaticaConfig(): FormaticaCoreConfig {\n return globalConfig;\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Utility to extract field schemas from a unified schema tree\n// ---------------------------------------------------------------------------\n\nimport type { FieldSchema, SchemaNode } from \"./types/schema\";\n\n/**\n * Recursively walks a `SchemaNode[]` tree and collects every node that is an\n * actual field (i.e. has a `name` property), ignoring layout containers.\n */\nexport function extractFields(nodes: SchemaNode[]): FieldSchema[] {\n const fields: FieldSchema[] = [];\n for (const node of nodes) {\n if (isFieldNode(node)) {\n fields.push(node);\n } else if (node.type === \"row\" || node.type === \"group\") {\n fields.push(...extractFields(node.children));\n } else if (node.type === \"steps\") {\n for (const step of node.steps) {\n fields.push(...extractFields(step.children));\n }\n } else if (node.type === \"tabs\") {\n for (const tab of node.tabs) {\n fields.push(...extractFields(tab.children));\n }\n }\n }\n return fields;\n}\n\n/**\n * Type-guard that distinguishes field nodes from layout container nodes.\n */\nexport function isFieldNode(node: SchemaNode): node is FieldSchema {\n return \"name\" in node && typeof node.name === \"string\";\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Schema parser & validator\n// ---------------------------------------------------------------------------\n\nimport { extractFields } from \"./extractFields\";\nimport type {\n Condition,\n ConditionGroup,\n FormSchema,\n FormSettings,\n SchemaNode,\n} from \"./types/schema\";\nimport type { SchemaError } from \"./types/validation\";\n\n// ---------------------------------------------------------------------------\n// Error class\n// ---------------------------------------------------------------------------\n\nexport class SchemaValidationError extends Error {\n public readonly errors: SchemaError[];\n\n constructor(errors: SchemaError[]) {\n const summary = errors.map((e) => `[${e.field}] ${e.message}`).join(\"; \");\n super(`Schema validation failed: ${summary}`);\n this.name = \"SchemaValidationError\";\n this.errors = errors;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Known field types\n// ---------------------------------------------------------------------------\n\nconst KNOWN_FIELD_TYPES = new Set([\n \"text\",\n \"number\",\n \"textarea\",\n \"select\",\n \"checkbox\",\n \"checkbox-group\",\n \"radio\",\n \"switch\",\n \"date\",\n \"file\",\n \"slider\",\n \"tags\",\n \"richtext\",\n \"hidden\",\n \"phone\",\n]);\n\nconst CONTAINER_TYPES = new Set([\"row\", \"group\", \"steps\", \"tabs\", \"divider\", \"html\"]);\n\n// ---------------------------------------------------------------------------\n// Custom field type checker (pluggable for framework-specific registries)\n// ---------------------------------------------------------------------------\n\nlet customFieldTypeChecker: ((type: string) => boolean) | null = null;\n\n/**\n * Register a custom field type checker. This allows framework-specific packages\n * (e.g. @formatica/vue) to hook their field registry into schema validation.\n */\nexport function setFieldTypeChecker(checker: ((type: string) => boolean) | null): void {\n customFieldTypeChecker = checker;\n}\n\n// ---------------------------------------------------------------------------\n// Validation helpers\n// ---------------------------------------------------------------------------\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateCondition(\n condition: unknown,\n fieldPath: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(condition)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: \"Condition must be an object\",\n });\n return;\n }\n\n const cond = condition as Record<string, unknown>;\n\n // Compound conditions\n if (\"and\" in cond || \"or\" in cond) {\n const group = cond as ConditionGroup;\n const children = group.and ?? group.or ?? [];\n if (!Array.isArray(children)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: \"Compound condition must have an array of sub-conditions\",\n });\n return;\n }\n for (let i = 0; i < children.length; i++) {\n validateCondition(children[i], `${fieldPath}.condition[${i}]`, allFieldNames, errors);\n }\n return;\n }\n\n // Simple condition\n const simple = cond as unknown as Condition;\n if (typeof simple.field !== \"string\") {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: 'Condition must have a \"field\" property of type string',\n });\n } else if (!allFieldNames.has(simple.field)) {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: `Condition references unknown field \"${simple.field}\"`,\n });\n }\n\n if (typeof simple.operator !== \"string\") {\n errors.push({\n field: fieldPath,\n rule: \"condition\",\n message: 'Condition must have an \"operator\" property',\n });\n }\n}\n\nfunction validateFieldNode(\n field: unknown,\n path: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(field)) {\n errors.push({ field: path, rule: \"type\", message: \"Field must be an object\" });\n return;\n }\n\n const f = field as Record<string, unknown>;\n\n // name\n if (typeof f.name !== \"string\" || f.name.length === 0) {\n errors.push({ field: path, rule: \"name\", message: 'Field must have a non-empty \"name\"' });\n }\n\n // type\n if (typeof f.type !== \"string\") {\n errors.push({ field: path, rule: \"type\", message: 'Field must have a \"type\" string' });\n } else if (!KNOWN_FIELD_TYPES.has(f.type) && !customFieldTypeChecker?.(f.type)) {\n errors.push({\n field: `${path}.${f.name as string}`,\n rule: \"type\",\n message: `Unknown field type \"${f.type}\"`,\n });\n }\n\n // options required for select, radio, checkbox-group\n if ([\"select\", \"radio\", \"checkbox-group\"].includes(f.type as string)) {\n if (f.options === undefined || f.options === null) {\n errors.push({\n field: `${path}.${f.name as string}`,\n rule: \"options\",\n message: `Field type \"${f.type as string}\" requires an \"options\" property`,\n });\n }\n }\n\n // condition references\n if (f.condition) {\n validateCondition(f.condition, `${path}.${f.name as string}`, allFieldNames, errors);\n }\n}\n\nfunction validateNode(\n node: unknown,\n path: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n if (!isPlainObject(node)) {\n errors.push({ field: path, rule: \"type\", message: \"Node must be an object\" });\n return;\n }\n\n const n = node as Record<string, unknown>;\n const type = n.type as string;\n\n if (typeof type !== \"string\") {\n errors.push({ field: path, rule: \"type\", message: 'Node must have a \"type\" string' });\n return;\n }\n\n // If it's a field node (has a name), validate as field\n if (typeof n.name === \"string\") {\n validateFieldNode(node, path, allFieldNames, errors);\n return;\n }\n\n // Container nodes\n if (!CONTAINER_TYPES.has(type)) {\n errors.push({\n field: path,\n rule: \"type\",\n message: `Unknown node type \"${type}\"`,\n });\n return;\n }\n\n if (type === \"row\" || type === \"group\") {\n if (!Array.isArray(n.children)) {\n errors.push({\n field: path,\n rule: \"children\",\n message: `\"${type}\" node must have a \"children\" array`,\n });\n } else {\n validateNodes(n.children, `${path}.children`, allFieldNames, errors);\n }\n if (type === \"group\" && n.condition) {\n validateCondition(n.condition, `${path}.condition`, allFieldNames, errors);\n }\n } else if (type === \"steps\") {\n if (!Array.isArray(n.steps)) {\n errors.push({\n field: path,\n rule: \"steps\",\n message: '\"steps\" node must have a \"steps\" array',\n });\n } else {\n for (let i = 0; i < n.steps.length; i++) {\n const step = n.steps[i] as Record<string, unknown>;\n if (!isPlainObject(step)) {\n errors.push({\n field: `${path}.steps[${i}]`,\n rule: \"type\",\n message: \"Step item must be an object\",\n });\n continue;\n }\n if (typeof step.title !== \"string\") {\n errors.push({\n field: `${path}.steps[${i}]`,\n rule: \"title\",\n message: 'Step item must have a \"title\" string',\n });\n }\n if (Array.isArray(step.children)) {\n validateNodes(\n step.children,\n `${path}.steps[${i}].children`,\n allFieldNames,\n errors,\n );\n }\n }\n }\n } else if (type === \"tabs\") {\n if (!Array.isArray(n.tabs)) {\n errors.push({\n field: path,\n rule: \"tabs\",\n message: '\"tabs\" node must have a \"tabs\" array',\n });\n } else {\n for (let i = 0; i < n.tabs.length; i++) {\n const tab = n.tabs[i] as Record<string, unknown>;\n if (!isPlainObject(tab)) {\n errors.push({\n field: `${path}.tabs[${i}]`,\n rule: \"type\",\n message: \"Tab item must be an object\",\n });\n continue;\n }\n if (typeof tab.title !== \"string\") {\n errors.push({\n field: `${path}.tabs[${i}]`,\n rule: \"title\",\n message: 'Tab item must have a \"title\" string',\n });\n }\n if (Array.isArray(tab.children)) {\n validateNodes(\n tab.children,\n `${path}.tabs[${i}].children`,\n allFieldNames,\n errors,\n );\n }\n }\n }\n } else if (type === \"html\") {\n if (typeof n.content !== \"string\") {\n errors.push({\n field: path,\n rule: \"content\",\n message: '\"html\" node must have a \"content\" string',\n });\n }\n }\n // \"divider\" has no required children/content — always valid if type matches\n}\n\nfunction validateNodes(\n nodes: unknown[],\n basePath: string,\n allFieldNames: Set<string>,\n errors: SchemaError[],\n): void {\n for (let i = 0; i < nodes.length; i++) {\n validateNode(nodes[i], `${basePath}[${i}]`, allFieldNames, errors);\n }\n}\n\nfunction validateSettings(settings: unknown, errors: SchemaError[]): void {\n if (!isPlainObject(settings)) {\n errors.push({ field: \"settings\", rule: \"type\", message: \"Settings must be an object\" });\n return;\n }\n\n const s = settings as Record<string, unknown>;\n\n if (\n s.layout !== undefined &&\n ![\"vertical\", \"horizontal\", \"inline\"].includes(s.layout as string)\n ) {\n errors.push({\n field: \"settings.layout\",\n rule: \"enum\",\n message: 'Layout must be \"vertical\", \"horizontal\", or \"inline\"',\n });\n }\n\n if (s.size !== undefined && ![\"small\", \"medium\", \"large\"].includes(s.size as string)) {\n errors.push({\n field: \"settings.size\",\n rule: \"enum\",\n message: 'Size must be \"small\", \"medium\", or \"large\"',\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse and validate a JSON schema, returning a typed FormSchema.\n * Collects all validation errors before throwing a single SchemaValidationError.\n */\nexport function parseFormSchema(json: unknown): FormSchema {\n const errors: SchemaError[] = [];\n\n if (!isPlainObject(json)) {\n errors.push({ field: \"$root\", rule: \"type\", message: \"Schema must be a plain object\" });\n throw new SchemaValidationError(errors);\n }\n\n const raw = json as Record<string, unknown>;\n\n // fields\n if (!Array.isArray(raw.fields)) {\n errors.push({ field: \"fields\", rule: \"type\", message: '\"fields\" must be an array' });\n throw new SchemaValidationError(errors);\n }\n\n // Collect all field names recursively for cross-reference validation\n const allFields = extractFields(raw.fields as SchemaNode[]);\n const allFieldNames = new Set<string>();\n const nameTracker = new Map<string, number>();\n for (const f of allFields) {\n allFieldNames.add(f.name);\n const count = (nameTracker.get(f.name) ?? 0) + 1;\n nameTracker.set(f.name, count);\n if (count > 1) {\n errors.push({\n field: f.name,\n rule: \"unique\",\n message: `Duplicate field name \"${f.name}\"`,\n });\n }\n }\n\n // Validate each node recursively (fields and containers)\n validateNodes(raw.fields, \"fields\", allFieldNames, errors);\n\n // Validate settings\n if (raw.settings !== undefined) {\n validateSettings(raw.settings, errors);\n }\n\n if (errors.length > 0) {\n throw new SchemaValidationError(errors);\n }\n\n return {\n id: typeof raw.id === \"string\" ? raw.id : undefined,\n version: typeof raw.version === \"string\" ? raw.version : undefined,\n fields: raw.fields as SchemaNode[],\n settings: raw.settings as FormSettings | undefined,\n translations: raw.translations as FormSchema[\"translations\"],\n };\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Deep merge utility\n// ---------------------------------------------------------------------------\n\ntype PlainObject = Record<string, unknown>;\n\nfunction isPlainObject(value: unknown): value is PlainObject {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Deep-merge two objects. Arrays are replaced (not concatenated).\n * Returns a new object – neither source is mutated.\n */\nexport function deepMerge<T extends PlainObject>(target: T, source: Partial<T>): T {\n const result: PlainObject = { ...target };\n\n for (const key of Object.keys(source)) {\n const srcVal = (source as PlainObject)[key];\n const tgtVal = result[key];\n\n if (isPlainObject(srcVal) && isPlainObject(tgtVal)) {\n result[key] = deepMerge(tgtVal, srcVal);\n } else {\n result[key] = srcVal;\n }\n }\n\n return result as T;\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Simple HTML sanitizer for HtmlLayout content\n// ---------------------------------------------------------------------------\n\n/**\n * Strip `<script>` tags and inline event handlers (on*=\"...\") from HTML strings.\n * This is a lightweight sanitizer for use with the HtmlLayout node type.\n */\nexport function sanitizeHtml(html: string): string {\n return (\n html\n // Remove <script> tags and their content\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, \"\")\n // Remove event handler attributes (onclick, onload, onerror, etc.)\n .replace(/\\s+on\\w+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi, \"\")\n // Remove javascript: protocol in href/src/action attributes\n .replace(/(href|src|action)\\s*=\\s*(?:\"javascript:[^\"]*\"|'javascript:[^']*')/gi, '$1=\"\"')\n );\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Title case conversion utility\n// ---------------------------------------------------------------------------\n\n/**\n * Convert camelCase, kebab-case, or snake_case field names to Title Case.\n *\n * @example\n * titleCase('firstName') // \"First Name\"\n * titleCase('last-name') // \"Last Name\"\n * titleCase('email_address') // \"Email Address\"\n */\nexport function titleCase(input: string): string {\n return (\n input\n // Insert space before uppercase letters in camelCase\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n // Replace kebab-case and snake_case separators with spaces\n .replace(/[-_]+/g, \" \")\n // Capitalize first letter of each word\n .replace(/\\b\\w/g, (char) => char.toUpperCase())\n .trim()\n );\n}\n","// ---------------------------------------------------------------------------\n// Formatica Core – Validation rule registry\n// ---------------------------------------------------------------------------\n\nimport type { RuleFn } from \"../types/validation\";\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\nconst rules = new Map<string, RuleFn>();\n\nexport function registerRule(name: string, fn: RuleFn): void {\n rules.set(name, fn);\n}\n\nexport function unregisterRule(name: string): void {\n rules.delete(name);\n}\n\nexport function getRule(name: string): RuleFn | undefined {\n return rules.get(name);\n}\n\nexport function hasRule(name: string): boolean {\n return rules.has(name);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isEmpty(value: unknown): boolean {\n if (value === null || value === undefined || value === \"\") return true;\n if (Array.isArray(value) && value.length === 0) return true;\n return false;\n}\n\nfunction interpolate(template: string, params: Record<string, unknown>): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) => {\n return params[key] !== undefined ? String(params[key]) : `{${key}}`;\n });\n}\n\nfunction toNumber(value: unknown): number | null {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const n = Number(value);\n return Number.isNaN(n) ? null : n;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in rules\n// ---------------------------------------------------------------------------\n\nregisterRule(\"required\", (value) => {\n if (isEmpty(value)) return \"This field is required\";\n return true;\n});\n\nregisterRule(\"email\", (value) => {\n if (isEmpty(value)) return true;\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value)) || \"Please enter a valid email address\";\n});\n\nregisterRule(\"phone\", async (value) => {\n if (isEmpty(value)) return true;\n const str = String(value);\n try {\n const lib = await import(\"libphonenumber-js\");\n return lib.isValidPhoneNumber(str) || \"Please enter a valid phone number\";\n } catch {\n // Fallback if libphonenumber-js not available\n if (/^\\+[1-9]\\d{6,14}$/.test(str.replace(/[\\s\\-().]/g, \"\"))) return true;\n return \"Please enter a valid phone number\";\n }\n});\n\nregisterRule(\"url\", (value) => {\n if (isEmpty(value)) return true;\n try {\n new URL(String(value));\n return true;\n } catch {\n return \"Please enter a valid URL\";\n }\n});\n\nregisterRule(\"min\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const min = toNumber(params.min);\n if (num === null || min === null) return true;\n return num >= min || interpolate(\"Must be at least {min}\", params);\n});\n\nregisterRule(\"max\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const max = toNumber(params.max);\n if (num === null || max === null) return true;\n return num <= max || interpolate(\"Must be at most {max}\", params);\n});\n\nregisterRule(\"minLength\", (value, params) => {\n if (isEmpty(value)) return true;\n const len = typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : 0;\n const min = toNumber(params.min) ?? toNumber(params.minLength) ?? 0;\n return len >= min || interpolate(\"Must be at least {min} characters\", { min, ...params });\n});\n\nregisterRule(\"maxLength\", (value, params) => {\n if (isEmpty(value)) return true;\n const len = typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : 0;\n const max = toNumber(params.max) ?? toNumber(params.maxLength) ?? Infinity;\n return len <= max || interpolate(\"Must be at most {max} characters\", { max, ...params });\n});\n\nregisterRule(\"between\", (value, params) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n const min = toNumber(params.min);\n const max = toNumber(params.max);\n if (num === null || min === null || max === null) return true;\n return (num >= min && num <= max) || interpolate(\"Must be between {min} and {max}\", params);\n});\n\nregisterRule(\"pattern\", (value, params) => {\n if (isEmpty(value)) return true;\n const pattern = params.pattern ?? params.regex;\n if (typeof pattern !== \"string\") return true;\n const re = new RegExp(pattern);\n return re.test(String(value)) || interpolate(\"Does not match the required pattern\", params);\n});\n\nregisterRule(\"numeric\", (value) => {\n if (isEmpty(value)) return true;\n return toNumber(value) !== null || \"Must be a number\";\n});\n\nregisterRule(\"integer\", (value) => {\n if (isEmpty(value)) return true;\n const num = toNumber(value);\n return (num !== null && Number.isInteger(num)) || \"Must be an integer\";\n});\n\nregisterRule(\"alpha\", (value) => {\n if (isEmpty(value)) return true;\n return /^[a-zA-Z]+$/.test(String(value)) || \"Must contain only letters\";\n});\n\nregisterRule(\"alphaNumeric\", (value) => {\n if (isEmpty(value)) return true;\n return /^[a-zA-Z0-9]+$/.test(String(value)) || \"Must contain only letters and numbers\";\n});\n\nregisterRule(\"confirmed\", (value, params, ctx) => {\n if (isEmpty(value)) return true;\n const target = String(params.target ?? \"\");\n const other = ctx.values[target] ?? ctx.values[`${target}_confirmation`];\n return value === other || \"Confirmation does not match\";\n});\n\nregisterRule(\"requiredIf\", (value, params, ctx) => {\n const targetField = String(params.field ?? \"\");\n const targetValue = params.value;\n const actual = ctx.values[targetField];\n const shouldRequire = targetValue !== undefined ? actual === targetValue : !isEmpty(actual);\n if (!shouldRequire) return true;\n return !isEmpty(value) || interpolate(\"This field is required when {field} is set\", params);\n});\n\nregisterRule(\"date\", (value) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n return !Number.isNaN(d.getTime()) || \"Please enter a valid date\";\n});\n\nregisterRule(\"before\", (value, params) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n const before = new Date(String(params.date ?? params.before));\n if (Number.isNaN(d.getTime()) || Number.isNaN(before.getTime())) return true;\n return d < before || interpolate(\"Must be before {date}\", params);\n});\n\nregisterRule(\"after\", (value, params) => {\n if (isEmpty(value)) return true;\n const d = new Date(String(value));\n const after = new Date(String(params.date ?? params.after));\n if (Number.isNaN(d.getTime()) || Number.isNaN(after.getTime())) return true;\n return d > after || interpolate(\"Must be after {date}\", params);\n});\n\nregisterRule(\"in\", (value, params) => {\n if (isEmpty(value)) return true;\n const allowed = Array.isArray(params.values) ? params.values : [];\n return (allowed as unknown[]).includes(value) || \"The selected value is not valid\";\n});\n\nregisterRule(\"notIn\", (value, params) => {\n if (isEmpty(value)) return true;\n const disallowed = Array.isArray(params.values) ? params.values : [];\n return !(disallowed as unknown[]).includes(value) || \"The selected value is not allowed\";\n});\n\nregisterRule(\"fileSize\", (value, params) => {\n if (isEmpty(value)) return true;\n const maxBytes = toNumber(params.max) ?? Infinity;\n const files = Array.isArray(value) ? value : [value];\n for (const file of files) {\n const size =\n typeof file === \"object\" && file !== null && \"size\" in file\n ? toNumber((file as { size: unknown }).size)\n : null;\n if (size !== null && size > maxBytes) {\n return interpolate(\"File must be smaller than {max} bytes\", params);\n }\n }\n return true;\n});\n\nregisterRule(\"mimeType\", (value, params) => {\n if (isEmpty(value)) return true;\n const allowed = Array.isArray(params.types)\n ? (params.types as string[])\n : typeof params.types === \"string\"\n ? params.types.split(\",\").map((s: string) => s.trim())\n : [];\n const files = Array.isArray(value) ? value : [value];\n for (const file of files) {\n const fileType =\n typeof file === \"object\" && file !== null && \"type\" in file\n ? String((file as { type: unknown }).type)\n : \"\";\n if (fileType && !allowed.some((t) => fileType.match(new RegExp(t.replace(\"*\", \".*\"))))) {\n return interpolate(\"File type is not allowed. Allowed: {types}\", params);\n }\n }\n return true;\n});\n\nregisterRule(\"maxFiles\", (value, params) => {\n if (isEmpty(value)) return true;\n const max = toNumber(params.max) ?? Infinity;\n const count = Array.isArray(value) ? value.length : 1;\n return count <= max || interpolate(\"Maximum {max} files allowed\", params);\n});\n\nregisterRule(\"unique\", (value) => {\n if (isEmpty(value)) return true;\n if (!Array.isArray(value)) return true;\n const set = new Set(value as unknown[]);\n return set.size === value.length || \"All values must be unique\";\n});\n\nregisterRule(\"custom\", (value, params) => {\n // Custom rules are handled at the ValidationRule level via validator fn.\n // This is a no-op fallback.\n void value;\n void params;\n return true;\n});\n"],"names":["evaluateOperator","fieldValue","operator","conditionValue","isConditionGroup","cond","evaluateCondition","condition","values","c","globalConfig","configureFormatica","config","getFormaticaConfig","extractFields","nodes","fields","node","isFieldNode","step","tab","SchemaValidationError","errors","summary","e","KNOWN_FIELD_TYPES","CONTAINER_TYPES","customFieldTypeChecker","setFieldTypeChecker","checker","isPlainObject","value","validateCondition","fieldPath","allFieldNames","group","children","i","simple","validateFieldNode","field","path","f","validateNode","n","type","validateNodes","basePath","validateSettings","settings","s","parseFormSchema","json","raw","allFields","nameTracker","count","proto","deepMerge","target","source","result","key","srcVal","tgtVal","sanitizeHtml","html","titleCase","input","char","rules","registerRule","name","fn","unregisterRule","getRule","hasRule","isEmpty","interpolate","template","params","_","toNumber","str","num","min","max","len","pattern","ctx","other","targetField","targetValue","actual","d","before","after","maxBytes","files","file","size","allowed","fileType","t"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
- export type * from "./types";
2
- export { parseFormSchema, SchemaValidationError, setFieldTypeChecker } from "./schemaParser";
3
- export { registerRule, unregisterRule, getRule, hasRule } from "./validation/ruleRegistry";
4
1
  export { evaluateCondition } from "./conditions";
2
+ export type { FormaticaCoreConfig } from "./config";
3
+ export { configureFormatica, getFormaticaConfig } from "./config";
5
4
  export { extractFields, isFieldNode } from "./extractFields";
5
+ export { parseFormSchema, SchemaValidationError, setFieldTypeChecker } from "./schemaParser";
6
+ export type * from "./types";
6
7
  export { deepMerge } from "./utils/deepMerge";
7
- export { titleCase } from "./utils/titleCase";
8
8
  export { sanitizeHtml } from "./utils/sanitize";
9
+ export { titleCase } from "./utils/titleCase";
10
+ export { getRule, hasRule, registerRule, unregisterRule } from "./validation/ruleRegistry";
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,mBAAmB,SAAS,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG7F,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAG3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE7F,mBAAmB,SAAS,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"schemaParser.d.ts","sourceRoot":"","sources":["../src/schemaParser.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGR,UAAU,EAGb,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAOtD,qBAAa,qBAAsB,SAAQ,KAAK;IAC5C,SAAgB,MAAM,EAAE,WAAW,EAAE,CAAC;gBAE1B,MAAM,EAAE,WAAW,EAAE;CAMpC;AAgCD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,CAErF;AAiSD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAoDzD"}
1
+ {"version":3,"file":"schemaParser.d.ts","sourceRoot":"","sources":["../src/schemaParser.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAGR,UAAU,EAGb,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMtD,qBAAa,qBAAsB,SAAQ,KAAK;IAC5C,SAAgB,MAAM,EAAE,WAAW,EAAE,CAAC;gBAE1B,MAAM,EAAE,WAAW,EAAE;CAMpC;AAgCD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,CAErF;AAiSD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAoDzD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formatica/core",
3
- "version": "0.1.2",
3
+ "version": "0.2.3",
4
4
  "description": "Framework-agnostic schema-driven form engine — types, validation, parsing, conditions",
5
5
  "type": "module",
6
6
  "main": "./dist/formatica-core.umd.cjs",