@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 +161 -11
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/formatica-core.es.js +99 -90
- package/dist/formatica-core.es.js.map +1 -1
- package/dist/formatica-core.umd.cjs +1 -1
- package/dist/formatica-core.umd.cjs.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/schemaParser.d.ts.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
-
|
|
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
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
//
|
|
26
|
-
const
|
|
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
|
-
//
|
|
29
|
-
|
|
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)
|
package/dist/config.d.ts
ADDED
|
@@ -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 (
|
|
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
|
|
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
|
|
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
|
-
]),
|
|
93
|
+
]), z = /* @__PURE__ */ new Set(["row", "group", "steps", "tabs", "divider", "html"]);
|
|
42
94
|
let p = null;
|
|
43
|
-
function
|
|
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
|
|
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' }) : !
|
|
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
|
|
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
|
-
|
|
167
|
+
M(e, t, n, r);
|
|
116
168
|
return;
|
|
117
169
|
}
|
|
118
|
-
if (!
|
|
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
|
-
|
|
250
|
+
C(e[i], `${t}[${i}]`, n, r);
|
|
199
251
|
}
|
|
200
|
-
function
|
|
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
|
|
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 &&
|
|
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
|
|
318
|
+
function L(e) {
|
|
248
319
|
h.delete(e);
|
|
249
320
|
}
|
|
250
|
-
function
|
|
321
|
+
function k(e) {
|
|
251
322
|
return h.get(e);
|
|
252
323
|
}
|
|
253
|
-
function
|
|
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
|
-
|
|
453
|
+
F as configureFormatica,
|
|
454
|
+
E as deepMerge,
|
|
447
455
|
w as evaluateCondition,
|
|
448
456
|
g as extractFields,
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
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
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,
|
|
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":"
|
|
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