@vielzeug/forge 2.3.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +17 -16
  2. package/dist/_field.cjs +1 -1
  3. package/dist/_field.cjs.map +1 -1
  4. package/dist/_field.d.ts +13 -10
  5. package/dist/_field.d.ts.map +1 -1
  6. package/dist/_field.js +33 -33
  7. package/dist/_field.js.map +1 -1
  8. package/dist/_notify.cjs +1 -1
  9. package/dist/_notify.cjs.map +1 -1
  10. package/dist/_notify.d.ts +6 -5
  11. package/dist/_notify.d.ts.map +1 -1
  12. package/dist/_notify.js +22 -8
  13. package/dist/_notify.js.map +1 -1
  14. package/dist/core/path.cjs +1 -1
  15. package/dist/core/path.cjs.map +1 -1
  16. package/dist/core/path.d.ts +8 -11
  17. package/dist/core/path.d.ts.map +1 -1
  18. package/dist/core/path.js +122 -110
  19. package/dist/core/path.js.map +1 -1
  20. package/dist/dom.cjs +1 -1
  21. package/dist/dom.cjs.map +1 -1
  22. package/dist/dom.d.ts +5 -6
  23. package/dist/dom.d.ts.map +1 -1
  24. package/dist/dom.js +7 -7
  25. package/dist/dom.js.map +1 -1
  26. package/dist/errors.cjs +1 -1
  27. package/dist/errors.cjs.map +1 -1
  28. package/dist/errors.d.ts +6 -1
  29. package/dist/errors.d.ts.map +1 -1
  30. package/dist/errors.js +10 -2
  31. package/dist/errors.js.map +1 -1
  32. package/dist/forge.cjs +1 -1
  33. package/dist/forge.cjs.map +1 -1
  34. package/dist/forge.iife.js +1 -1
  35. package/dist/forge.iife.js.map +1 -1
  36. package/dist/forge.js +1 -1
  37. package/dist/forge.js.map +1 -1
  38. package/dist/form-data.cjs +1 -1
  39. package/dist/form-data.cjs.map +1 -1
  40. package/dist/form-data.d.ts +2 -2
  41. package/dist/form-data.d.ts.map +1 -1
  42. package/dist/form-data.js +23 -16
  43. package/dist/form-data.js.map +1 -1
  44. package/dist/form.cjs +1 -1
  45. package/dist/form.cjs.map +1 -1
  46. package/dist/form.d.ts +1 -1
  47. package/dist/form.d.ts.map +1 -1
  48. package/dist/form.js +122 -86
  49. package/dist/form.js.map +1 -1
  50. package/dist/index.d.ts +3 -3
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/persist.cjs +2 -0
  53. package/dist/persist.cjs.map +1 -0
  54. package/dist/persist.d.ts +18 -0
  55. package/dist/persist.d.ts.map +1 -0
  56. package/dist/persist.js +19 -0
  57. package/dist/persist.js.map +1 -0
  58. package/dist/schema.cjs +2 -0
  59. package/dist/schema.cjs.map +1 -0
  60. package/dist/schema.d.ts +22 -0
  61. package/dist/schema.d.ts.map +1 -0
  62. package/dist/schema.js +26 -0
  63. package/dist/schema.js.map +1 -0
  64. package/dist/types.d.ts +24 -20
  65. package/dist/types.d.ts.map +1 -1
  66. package/package.json +25 -33
  67. package/dist/spell.cjs +0 -2
  68. package/dist/spell.cjs.map +0 -1
  69. package/dist/spell.d.ts +0 -5
  70. package/dist/spell.d.ts.map +0 -1
  71. package/dist/spell.js +0 -48
  72. package/dist/spell.js.map +0 -1
  73. package/dist/vault.cjs +0 -2
  74. package/dist/vault.cjs.map +0 -1
  75. package/dist/vault.d.ts +0 -10
  76. package/dist/vault.d.ts.map +0 -1
  77. package/dist/vault.js +0 -14
  78. package/dist/vault.js.map +0 -1
package/dist/core/path.js CHANGED
@@ -1,162 +1,174 @@
1
1
  import { ForgeConfigError as e } from "../errors.js";
2
+ import { isPlainObject as t } from "@vielzeug/arsenal";
2
3
  //#region src/core/path.ts
3
- var t = /* @__PURE__ */ new Set([
4
+ var n = /* @__PURE__ */ new Set([
4
5
  "__proto__",
5
6
  "constructor",
6
7
  "prototype"
7
8
  ]);
8
- function n(e) {
9
- return !e || t.has(e);
10
- }
11
9
  function r(e) {
12
- if (typeof e != "object" || !e || Array.isArray(e)) return !1;
13
- let t = Object.getPrototypeOf(e);
14
- return t === Object.prototype || t === null;
10
+ return !e || n.has(e);
15
11
  }
16
12
  function i(t) {
17
- if (n(t)) throw new e(`Invalid field key '${t}'.`);
18
- }
19
- function a(e) {
20
- return typeof Blob < "u" && e instanceof Blob || typeof File < "u" && e instanceof File || e instanceof Date;
21
- }
22
- function o(t) {
23
- if (Array.isArray(t)) return Object.freeze(t.map(o));
24
- if (typeof t != "object" || !t || a(t)) return t;
25
- if (!r(t)) throw new e("Form values must contain only plain objects, arrays, Date, File, Blob, or primitive values.");
26
- return Object.freeze(Object.fromEntries(Object.entries(t).map(([e, t]) => [e, o(t)])));
27
- }
28
- function s(e, t) {
29
- let n = e;
30
- for (let e of t) if (typeof e == "number") {
31
- if (!Array.isArray(n) || e < 0 || e >= n.length) return;
32
- n = n[e];
13
+ if (r(t)) throw new e(`Invalid field key '${t}'.`);
14
+ }
15
+ function a(t) {
16
+ if (!Number.isSafeInteger(t) || t < 0) throw new e(`Invalid array index ${t}.`);
17
+ }
18
+ function o(e) {
19
+ return Object.prototype.toString.call(e);
20
+ }
21
+ function s(e) {
22
+ return o(e) === "[object Blob]" || o(e) === "[object File]";
23
+ }
24
+ function c() {
25
+ throw new e("Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob.");
26
+ }
27
+ function l(n, r = /* @__PURE__ */ new Set()) {
28
+ if (n == null || typeof n == "string" || typeof n == "boolean") return n;
29
+ if (typeof n == "number") return Number.isFinite(n) ? n : c();
30
+ if (typeof n != "object") return c();
31
+ let a = n;
32
+ if (o(n) === "[object Date]" && typeof a.getTime == "function") {
33
+ let e = a.getTime();
34
+ return Number.isFinite(e) ? Object.freeze(new Date(e)) : c();
35
+ }
36
+ if (s(n)) return n;
37
+ if (r.has(n)) throw new e("Form values must not contain circular references.");
38
+ r.add(n);
39
+ try {
40
+ if (Array.isArray(n)) {
41
+ let t = [];
42
+ for (let i = 0; i < n.length; i++) {
43
+ if (!Object.hasOwn(n, i)) throw new e("Form arrays must not contain empty slots.");
44
+ t.push(l(n[i], r));
45
+ }
46
+ return Object.freeze(t);
47
+ }
48
+ if (!t(n)) return c();
49
+ let a = Object.entries(n).map(([e, t]) => (i(e), [e, l(t, r)]));
50
+ return Object.freeze(Object.fromEntries(a));
51
+ } finally {
52
+ r.delete(n);
53
+ }
54
+ }
55
+ function u(e, n) {
56
+ let r = e;
57
+ for (let e of n) if (typeof e == "number") {
58
+ if (!Array.isArray(r) || !Number.isSafeInteger(e) || e < 0 || e >= r.length || !Object.hasOwn(r, e)) return;
59
+ r = r[e];
33
60
  } else {
34
- if (!r(n) || !Object.hasOwn(n, e)) return;
35
- n = n[e];
61
+ if (!t(r) || !Object.hasOwn(r, e)) return;
62
+ r = r[e];
36
63
  }
37
- return n;
64
+ return r;
38
65
  }
39
- function c(e, t) {
40
- let n = e;
41
- for (let e of t) if (typeof e == "number") {
42
- if (!Array.isArray(n) || e < 0 || e >= n.length) return !1;
43
- n = n[e];
66
+ function d(e, n) {
67
+ let r = e;
68
+ for (let e of n) if (typeof e == "number") {
69
+ if (!Array.isArray(r) || !Number.isSafeInteger(e) || e < 0 || e >= r.length || !Object.hasOwn(r, e)) return !1;
70
+ r = r[e];
44
71
  } else {
45
- if (!r(n) || !Object.hasOwn(n, e)) return !1;
46
- n = n[e];
72
+ if (!t(r) || !Object.hasOwn(r, e)) return !1;
73
+ r = r[e];
47
74
  }
48
75
  return !0;
49
76
  }
50
- function l(t, n, a) {
51
- let [s, ...c] = n;
77
+ function f(n, r, o) {
78
+ let [s, ...c] = r;
52
79
  if (typeof s == "number") {
53
- if (!Array.isArray(t)) throw new e(`Cannot index ${s} because the current value is not an array.`);
54
- if (s < 0 || s >= t.length) throw new e(`Index ${s} is out of range for array of length ${t.length}.`);
80
+ if (a(s), !Array.isArray(n)) throw new e(`Cannot index ${s} because the current value is not an array.`);
81
+ if (s < 0 || s >= n.length) throw new e(`Index ${s} is out of range for array of length ${n.length}.`);
55
82
  if (c.length === 0) {
56
- let e = [...t];
57
- return e[s] = o(a), Object.freeze(e);
83
+ let e = [...n];
84
+ return e[s] = l(o), Object.freeze(e);
58
85
  }
59
- let n = [...t];
60
- return n[s] = l(t[s], c, a), Object.freeze(n);
86
+ let t = [...n];
87
+ return t[s] = f(n[s], c, o), Object.freeze(t);
61
88
  }
62
- if (i(s), !r(t)) throw new e(`Cannot select '${s}' because the current value is not an object.`);
89
+ if (i(s), !t(n)) throw new e(`Cannot select '${s}' because the current value is not an object.`);
63
90
  if (c.length === 0) return Object.freeze({
64
- ...t,
65
- [s]: o(a)
91
+ ...n,
92
+ [s]: l(o)
66
93
  });
67
- let u = t[s];
68
- if (u !== void 0 && !r(u) && !Array.isArray(u)) throw new e(`Cannot select '${s}' because it is not an object or array.`);
94
+ let u = n[s];
95
+ if (u !== void 0 && !t(u) && !Array.isArray(u)) throw new e(`Cannot select '${s}' because it is not an object or array.`);
69
96
  let d = u ?? {};
70
97
  return Object.freeze({
71
- ...t,
72
- [s]: l(d, c, a)
98
+ ...n,
99
+ [s]: f(d, c, o)
73
100
  });
74
101
  }
75
- function u(e, t, n) {
76
- let [i, ...a] = n;
102
+ function p(e, n, r) {
103
+ let [i, ...o] = r;
77
104
  if (typeof i == "number") {
78
- if (!Array.isArray(e) || !Array.isArray(t) || i >= t.length || i >= e.length) return e;
79
- if (a.length === 0) {
80
- let n = [...e];
81
- return n[i] = t[i], Object.freeze(n);
105
+ if (a(i), !Array.isArray(e) || !Array.isArray(n) || i >= n.length || i >= e.length) return e;
106
+ if (o.length === 0) {
107
+ let t = [...e];
108
+ return t[i] = n[i], Object.freeze(t);
82
109
  }
83
- let n = [...e];
84
- return n[i] = u(e[i], t[i], a), Object.freeze(n);
110
+ let t = [...e];
111
+ return t[i] = p(e[i], n[i], o), Object.freeze(t);
85
112
  }
86
- if (!r(e)) return e;
87
- if (a.length === 0) {
88
- if (Object.hasOwn(t, i)) return Object.freeze({
113
+ if (!t(e)) return e;
114
+ if (o.length === 0) {
115
+ if (Object.hasOwn(n, i)) return Object.freeze({
89
116
  ...e,
90
- [i]: t[i]
117
+ [i]: n[i]
91
118
  });
92
- let { [i]: n, ...r } = e;
119
+ let { [i]: t, ...r } = e;
93
120
  return Object.freeze(r);
94
121
  }
95
- let o = t[i];
96
- if (!r(o) && !Array.isArray(o)) {
97
- if (Object.hasOwn(t, i)) return Object.freeze({
122
+ let s = n[i];
123
+ if (!t(s) && !Array.isArray(s)) {
124
+ if (Object.hasOwn(n, i)) return Object.freeze({
98
125
  ...e,
99
- [i]: o
126
+ [i]: s
100
127
  });
101
- let { [i]: n, ...r } = e;
128
+ let { [i]: t, ...r } = e;
102
129
  return Object.freeze(r);
103
130
  }
104
- let s = e[i], c = r(s) || Array.isArray(s) ? s : {};
131
+ let c = e[i], l = t(c) || Array.isArray(c) ? c : {};
105
132
  return Object.freeze({
106
133
  ...e,
107
- [i]: u(c, o, a)
134
+ [i]: p(l, s, o)
108
135
  });
109
136
  }
110
- function d(e, t, n) {
111
- let [i, ...a] = t, o = String(i), s = { ...e };
112
- if (a.length === 0) n ? s[o] = !0 : delete s[o];
137
+ function m(e, n, r) {
138
+ let [i, ...o] = n;
139
+ typeof i == "number" && a(i);
140
+ let s = String(i), c = { ...e };
141
+ if (o.length === 0) r ? c[s] = !0 : delete c[s];
113
142
  else {
114
- let t = d(r(e[o]) ? e[o] : {}, a, n);
115
- Object.keys(t).length === 0 ? delete s[o] : s[o] = t;
143
+ let n = m(t(e[s]) ? e[s] : {}, o, r);
144
+ Object.keys(n).length === 0 ? delete c[s] : c[s] = n;
116
145
  }
117
- return Object.freeze(s);
118
- }
119
- function f(e, t) {
120
- let n = e;
121
- for (let e of t) {
122
- let t = String(e);
123
- if (!r(n) || !Object.hasOwn(n, t)) return !1;
124
- n = n[t];
146
+ return Object.freeze(c);
147
+ }
148
+ function h(e, n) {
149
+ let r = e;
150
+ for (let e of n) {
151
+ if (typeof e == "number" && (!Number.isSafeInteger(e) || e < 0)) return !1;
152
+ let n = String(e);
153
+ if (!t(r) || !Object.hasOwn(r, n)) return !1;
154
+ r = r[n];
125
155
  }
126
- return n === !0;
156
+ return r === !0;
127
157
  }
128
- function p(e) {
129
- return Array.isArray(e) ? Object.freeze(Object.fromEntries(e.map((e, t) => [String(t), r(e) || Array.isArray(e) ? p(e) : !0]))) : r(e) ? Object.freeze(Object.fromEntries(Object.entries(e).map(([e, t]) => [e, r(t) || Array.isArray(t) ? p(t) : !0]))) : {};
158
+ function g(e) {
159
+ return Array.isArray(e) ? Object.freeze(Object.fromEntries(e.map((e, n) => [String(n), t(e) || Array.isArray(e) ? g(e) : !0]))) : t(e) ? Object.freeze(Object.fromEntries(Object.entries(e).map(([e, n]) => [e, t(n) || Array.isArray(n) ? g(n) : !0]))) : {};
130
160
  }
131
- function m(e, t) {
132
- let n = s(e, t);
133
- return typeof n == "string" ? n : void 0;
161
+ function _(e, t) {
162
+ if (e.length !== t.length) return !1;
163
+ for (let n = 0; n < e.length; n++) if (e[n] !== t[n]) return !1;
164
+ return !0;
134
165
  }
135
- function h(e, t, i) {
136
- let [a, ...o] = t;
137
- if (typeof a == "number") {
138
- let t = Array.isArray(e) ? [...e] : [];
139
- return o.length === 0 ? t[a] === void 0 && (t[a] = i) : t[a] = h(t[a], o, i), t;
140
- }
141
- if (n(a)) return e ?? {};
142
- let s = r(e) ? { ...e } : {};
143
- return o.length === 0 ? s[a] === void 0 && (s[a] = i) : s[a] = h(s[a], o, i), s;
144
- }
145
- function g(e, t, n) {
146
- let i = h(e, t, n);
147
- return r(i) ? i : e;
148
- }
149
- function _(e) {
150
- if (typeof e == "string") return e;
151
- if (Array.isArray(e)) {
152
- let t = e.map((e) => _(e));
153
- return t.every((e) => e === void 0) ? void 0 : Object.freeze(t);
166
+ function v(e, t) {
167
+ if (e) {
168
+ for (let n of e) if (_(n.path, t)) return n.message;
154
169
  }
155
- if (!r(e)) return;
156
- let t = Object.entries(e).map(([e, t]) => [e, _(t)]).filter(([, e]) => e !== void 0);
157
- return t.length === 0 ? void 0 : Object.freeze(Object.fromEntries(t));
158
170
  }
159
171
  //#endregion
160
- export { i as assertSafeKey, c as hasAtPath, o as immutable, r as isRecord, n as isUnsafeKey, _ as normalizeErrors, s as readAtPath, m as readError, f as readMeta, u as resetAtPath, p as touchAll, l as writeAtPath, g as writeError, d as writeMeta };
172
+ export { a as assertArrayIndex, i as assertSafeKey, v as findIssue, d as hasAtPath, l as immutable, t as isRecord, r as isUnsafeKey, _ as pathEquals, u as readAtPath, h as readMeta, p as resetAtPath, g as touchAll, f as writeAtPath, m as writeMeta };
161
173
 
162
174
  //# sourceMappingURL=path.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"path.js","names":[],"sources":["../../src/core/path.ts"],"sourcesContent":["import { ForgeConfigError } from '../errors';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nexport function isUnsafeKey(key: string): boolean {\n return !key || unsafeKeys.has(key);\n}\n\ntype ErrorNode = string | ErrorTree | ErrorArray;\nexport interface ErrorTree {\n readonly [key: string]: ErrorNode;\n}\ntype ErrorArray = ErrorNode[];\ntype MutableErrorTree = Record<string, ErrorNode>;\ntype RecordValue = Record<string, unknown>;\ntype TreeValue = RecordValue | readonly unknown[];\ntype MetaTree = true | MetaNode;\ninterface MetaNode {\n readonly [key: string]: MetaTree;\n}\nexport type MetaRoot = MetaNode;\n\nexport function isRecord(value: unknown): value is RecordValue {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n\nexport function assertSafeKey(key: string): void {\n if (isUnsafeKey(key)) throw new ForgeConfigError(`Invalid field key '${key}'.`);\n}\n\nfunction isAtomicLeaf(value: unknown): boolean {\n return (\n (typeof Blob !== 'undefined' && value instanceof Blob) ||\n (typeof File !== 'undefined' && value instanceof File) ||\n value instanceof Date\n );\n}\n\nexport function immutable<T>(value: T): T {\n if (Array.isArray(value)) return Object.freeze(value.map(immutable)) as T;\n\n if (value === null || typeof value !== 'object' || isAtomicLeaf(value)) return value;\n\n if (!isRecord(value)) {\n throw new ForgeConfigError(\n 'Form values must contain only plain objects, arrays, Date, File, Blob, or primitive values.',\n );\n }\n\n return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, child]) => [key, immutable(child)]))) as T;\n}\n\nexport function readAtPath<T>(value: unknown, path: readonly (string | number)[]): T | undefined {\n let current: unknown = value;\n\n for (const key of path) {\n if (typeof key === 'number') {\n if (!Array.isArray(current) || key < 0 || key >= current.length) return undefined;\n\n current = current[key];\n } else {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return undefined;\n\n current = current[key];\n }\n }\n\n return current as T | undefined;\n}\n\nexport function hasAtPath(value: unknown, path: readonly (string | number)[]): boolean {\n let current: unknown = value;\n\n for (const key of path) {\n if (typeof key === 'number') {\n if (!Array.isArray(current) || key < 0 || key >= current.length) return false;\n\n current = current[key];\n } else {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key];\n }\n }\n\n return true;\n}\n\nexport function writeAtPath<T extends TreeValue>(value: T, path: readonly (string | number)[], next: unknown): T {\n const [key, ...rest] = path;\n\n if (typeof key === 'number') {\n if (!Array.isArray(value)) {\n throw new ForgeConfigError(`Cannot index ${key} because the current value is not an array.`);\n }\n\n if (key < 0 || key >= value.length) {\n throw new ForgeConfigError(`Index ${key} is out of range for array of length ${value.length}.`);\n }\n\n if (rest.length === 0) {\n const copy = [...value];\n\n copy[key] = immutable(next);\n\n return Object.freeze(copy) as T;\n }\n\n const copy = [...value];\n\n copy[key] = writeAtPath(value[key] as TreeValue, rest, next);\n\n return Object.freeze(copy) as T;\n }\n\n assertSafeKey(key);\n\n if (!isRecord(value)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current value is not an object.`);\n }\n\n if (rest.length === 0) return Object.freeze({ ...value, [key]: immutable(next) }) as T;\n\n const child = value[key];\n\n if (child !== undefined && !isRecord(child) && !Array.isArray(child)) {\n throw new ForgeConfigError(`Cannot select '${key}' because it is not an object or array.`);\n }\n\n const childTree = (child ?? {}) as TreeValue;\n\n return Object.freeze({ ...value, [key]: writeAtPath(childTree, rest, next) }) as T;\n}\n\nexport function resetAtPath<T extends TreeValue>(value: T, baseline: T, path: readonly (string | number)[]): T {\n const [key, ...rest] = path;\n\n if (typeof key === 'number') {\n if (!Array.isArray(value)) return value;\n if (!Array.isArray(baseline) || key >= baseline.length || key >= value.length) return value;\n\n if (rest.length === 0) {\n const copy = [...value];\n\n copy[key] = baseline[key];\n\n return Object.freeze(copy) as T;\n }\n\n const copy = [...value];\n\n copy[key] = resetAtPath(value[key] as TreeValue, baseline[key] as TreeValue, rest);\n\n return Object.freeze(copy) as T;\n }\n\n if (!isRecord(value)) return value;\n\n if (rest.length === 0) {\n if (Object.hasOwn(baseline, key)) return Object.freeze({ ...value, [key]: (baseline as RecordValue)[key] }) as T;\n\n const { [key]: _removed, ...next } = value;\n\n return Object.freeze(next) as T;\n }\n\n const baselineChild = (baseline as RecordValue)[key];\n\n if (!isRecord(baselineChild) && !Array.isArray(baselineChild)) {\n if (Object.hasOwn(baseline, key)) return Object.freeze({ ...value, [key]: baselineChild }) as T;\n\n const { [key]: _removed, ...next } = value;\n\n return Object.freeze(next) as T;\n }\n\n const currentChild = value[key];\n const childTree = (isRecord(currentChild) || Array.isArray(currentChild) ? currentChild : {}) as TreeValue;\n\n return Object.freeze({ ...value, [key]: resetAtPath(childTree, baselineChild as TreeValue, rest) }) as T;\n}\n\nexport function writeMeta(meta: MetaRoot, path: readonly (string | number)[], next: boolean): MetaRoot {\n const [key, ...rest] = path;\n const stringKey = String(key);\n const copy: Record<string, MetaTree> = { ...meta };\n\n if (rest.length === 0) {\n if (next) copy[stringKey] = true;\n else delete copy[stringKey];\n } else {\n const child = isRecord(meta[stringKey]) ? (meta[stringKey] as MetaRoot) : {};\n const updated = writeMeta(child, rest, next);\n\n if (Object.keys(updated).length === 0) delete copy[stringKey];\n else copy[stringKey] = updated;\n }\n\n return Object.freeze(copy);\n}\n\nexport function readMeta(meta: MetaRoot, path: readonly (string | number)[]): boolean {\n let current: MetaTree | undefined = meta;\n\n for (const key of path) {\n const stringKey = String(key);\n\n if (!isRecord(current) || !Object.hasOwn(current, stringKey)) return false;\n\n current = current[stringKey] as MetaTree;\n }\n\n return current === true;\n}\n\nexport function touchAll(value: unknown): MetaRoot {\n if (Array.isArray(value)) {\n return Object.freeze(\n Object.fromEntries(\n value.map((child, i) => [\n String(i),\n isRecord(child) || Array.isArray(child) ? touchAll(child) : (true as const),\n ]),\n ),\n );\n }\n\n if (!isRecord(value)) return {};\n\n return Object.freeze(\n Object.fromEntries(\n Object.entries(value).map(([key, child]) => [\n key,\n isRecord(child) || Array.isArray(child) ? touchAll(child) : (true as const),\n ]),\n ),\n );\n}\n\nexport function readError(errors: unknown, path: readonly (string | number)[]): string | undefined {\n const error = readAtPath(errors, path);\n\n return typeof error === 'string' ? error : undefined;\n}\n\nfunction writeErrorNode(\n node: ErrorTree | ErrorArray | undefined,\n path: readonly (string | number)[],\n message: string,\n): ErrorTree | ErrorArray {\n const [key, ...rest] = path;\n\n if (typeof key === 'number') {\n const arr: ErrorNode[] = Array.isArray(node) ? [...node] : [];\n\n if (rest.length === 0) {\n if (arr[key] === undefined) arr[key] = message;\n } else {\n arr[key] = writeErrorNode(arr[key] as ErrorTree | ErrorArray | undefined, rest, message);\n }\n\n return arr;\n }\n\n if (isUnsafeKey(key)) return node ?? {};\n\n const record: MutableErrorTree = isRecord(node) ? { ...node } : {};\n\n if (rest.length === 0) {\n if (record[key] === undefined) record[key] = message;\n } else {\n record[key] = writeErrorNode(record[key] as ErrorTree | ErrorArray | undefined, rest, message);\n }\n\n return record;\n}\n\nexport function writeError(tree: ErrorTree, path: readonly (string | number)[], message: string): ErrorTree {\n const result = writeErrorNode(tree, path, message);\n\n return isRecord(result) ? result : tree;\n}\n\nexport function normalizeErrors<T>(errors: T): T | undefined {\n if (typeof errors === 'string') return errors;\n\n if (Array.isArray(errors)) {\n const normalized = errors.map((item) => normalizeErrors(item));\n\n if (normalized.every((value) => value === undefined)) return undefined;\n\n return Object.freeze(normalized) as T;\n }\n\n if (!isRecord(errors)) return undefined;\n\n const entries = Object.entries(errors)\n .map(([key, value]) => [key, normalizeErrors(value)] as const)\n .filter(([, value]) => value !== undefined);\n\n return entries.length === 0 ? undefined : (Object.freeze(Object.fromEntries(entries)) as T);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"path.js","names":[],"sources":["../../src/core/path.ts"],"sourcesContent":["import { isPlainObject as isRecord } from '@vielzeug/arsenal';\n\nimport { ForgeConfigError } from '../errors.js';\nimport type { ValidationIssue } from '../types.js';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nexport { isRecord };\n\nexport function isUnsafeKey(key: string): boolean {\n return !key || unsafeKeys.has(key);\n}\n\ntype RecordValue = Record<string, unknown>;\ntype TreeValue = RecordValue | readonly unknown[];\ntype MetaTree = true | MetaNode;\ninterface MetaNode {\n readonly [key: string]: MetaTree;\n}\nexport type MetaRoot = MetaNode;\n\nexport function assertSafeKey(key: string): void {\n if (isUnsafeKey(key)) throw new ForgeConfigError(`Invalid field key '${key}'.`);\n}\n\nexport function assertArrayIndex(index: number): void {\n if (!Number.isSafeInteger(index) || index < 0) throw new ForgeConfigError(`Invalid array index ${index}.`);\n}\n\nfunction tag(value: object): string {\n return Object.prototype.toString.call(value);\n}\n\nfunction isBlobLeaf(value: object): boolean {\n return tag(value) === '[object Blob]' || tag(value) === '[object File]';\n}\n\nfunction invalidValue(): never {\n throw new ForgeConfigError(\n 'Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob.',\n );\n}\n\nexport function immutable<T>(value: T, ancestors = new Set<object>()): T {\n if (value === null || value === undefined || typeof value === 'string' || typeof value === 'boolean') return value;\n if (typeof value === 'number') return Number.isFinite(value) ? value : invalidValue();\n if (typeof value !== 'object') return invalidValue();\n\n const date = value as unknown as Date;\n if (tag(value) === '[object Date]' && typeof date.getTime === 'function') {\n const time = date.getTime();\n if (!Number.isFinite(time)) return invalidValue();\n return Object.freeze(new Date(time)) as T;\n }\n\n if (isBlobLeaf(value)) return value;\n if (ancestors.has(value)) throw new ForgeConfigError('Form values must not contain circular references.');\n\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n const copy: unknown[] = [];\n for (let index = 0; index < value.length; index++) {\n if (!Object.hasOwn(value, index)) throw new ForgeConfigError('Form arrays must not contain empty slots.');\n copy.push(immutable(value[index], ancestors));\n }\n return Object.freeze(copy) as T;\n }\n\n if (!isRecord(value)) return invalidValue();\n const entries = Object.entries(value).map(([key, child]) => {\n assertSafeKey(key);\n return [key, immutable(child, ancestors)] as const;\n });\n return Object.freeze(Object.fromEntries(entries)) as T;\n } finally {\n ancestors.delete(value);\n }\n}\n\nexport function readAtPath<T>(value: unknown, path: readonly (string | number)[]): T | undefined {\n let current: unknown = value;\n\n for (const key of path) {\n if (typeof key === 'number') {\n if (\n !Array.isArray(current) ||\n !Number.isSafeInteger(key) ||\n key < 0 ||\n key >= current.length ||\n !Object.hasOwn(current, key)\n )\n return undefined;\n\n current = current[key];\n } else {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return undefined;\n\n current = current[key];\n }\n }\n\n return current as T | undefined;\n}\n\nexport function hasAtPath(value: unknown, path: readonly (string | number)[]): boolean {\n let current: unknown = value;\n\n for (const key of path) {\n if (typeof key === 'number') {\n if (\n !Array.isArray(current) ||\n !Number.isSafeInteger(key) ||\n key < 0 ||\n key >= current.length ||\n !Object.hasOwn(current, key)\n )\n return false;\n\n current = current[key];\n } else {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key];\n }\n }\n\n return true;\n}\n\nexport function writeAtPath<T extends TreeValue>(value: T, path: readonly (string | number)[], next: unknown): T {\n const [key, ...rest] = path;\n\n if (typeof key === 'number') {\n assertArrayIndex(key);\n if (!Array.isArray(value)) {\n throw new ForgeConfigError(`Cannot index ${key} because the current value is not an array.`);\n }\n\n if (key < 0 || key >= value.length) {\n throw new ForgeConfigError(`Index ${key} is out of range for array of length ${value.length}.`);\n }\n\n if (rest.length === 0) {\n const copy = [...value];\n\n copy[key] = immutable(next);\n\n return Object.freeze(copy) as T;\n }\n\n const copy = [...value];\n\n copy[key] = writeAtPath(value[key] as TreeValue, rest, next);\n\n return Object.freeze(copy) as T;\n }\n\n assertSafeKey(key);\n\n if (!isRecord(value)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current value is not an object.`);\n }\n\n if (rest.length === 0) return Object.freeze({ ...value, [key]: immutable(next) }) as T;\n\n const child = value[key];\n\n if (child !== undefined && !isRecord(child) && !Array.isArray(child)) {\n throw new ForgeConfigError(`Cannot select '${key}' because it is not an object or array.`);\n }\n\n const childTree = (child ?? {}) as TreeValue;\n\n return Object.freeze({ ...value, [key]: writeAtPath(childTree, rest, next) }) as T;\n}\n\nexport function resetAtPath<T extends TreeValue>(value: T, baseline: T, path: readonly (string | number)[]): T {\n const [key, ...rest] = path;\n\n if (typeof key === 'number') {\n assertArrayIndex(key);\n if (!Array.isArray(value)) return value;\n if (!Array.isArray(baseline) || key >= baseline.length || key >= value.length) return value;\n\n if (rest.length === 0) {\n const copy = [...value];\n\n copy[key] = baseline[key];\n\n return Object.freeze(copy) as T;\n }\n\n const copy = [...value];\n\n copy[key] = resetAtPath(value[key] as TreeValue, baseline[key] as TreeValue, rest);\n\n return Object.freeze(copy) as T;\n }\n\n if (!isRecord(value)) return value;\n\n if (rest.length === 0) {\n if (Object.hasOwn(baseline, key)) return Object.freeze({ ...value, [key]: (baseline as RecordValue)[key] }) as T;\n\n const { [key]: _removed, ...next } = value;\n\n return Object.freeze(next) as T;\n }\n\n const baselineChild = (baseline as RecordValue)[key];\n\n if (!isRecord(baselineChild) && !Array.isArray(baselineChild)) {\n if (Object.hasOwn(baseline, key)) return Object.freeze({ ...value, [key]: baselineChild }) as T;\n\n const { [key]: _removed, ...next } = value;\n\n return Object.freeze(next) as T;\n }\n\n const currentChild = value[key];\n const childTree = (isRecord(currentChild) || Array.isArray(currentChild) ? currentChild : {}) as TreeValue;\n\n return Object.freeze({ ...value, [key]: resetAtPath(childTree, baselineChild as TreeValue, rest) }) as T;\n}\n\nexport function writeMeta(meta: MetaRoot, path: readonly (string | number)[], next: boolean): MetaRoot {\n const [key, ...rest] = path;\n if (typeof key === 'number') assertArrayIndex(key);\n const stringKey = String(key);\n const copy: Record<string, MetaTree> = { ...meta };\n\n if (rest.length === 0) {\n if (next) copy[stringKey] = true;\n else delete copy[stringKey];\n } else {\n const child = isRecord(meta[stringKey]) ? (meta[stringKey] as MetaRoot) : {};\n const updated = writeMeta(child, rest, next);\n\n if (Object.keys(updated).length === 0) delete copy[stringKey];\n else copy[stringKey] = updated;\n }\n\n return Object.freeze(copy);\n}\n\nexport function readMeta(meta: MetaRoot, path: readonly (string | number)[]): boolean {\n let current: MetaTree | undefined = meta;\n\n for (const key of path) {\n if (typeof key === 'number' && (!Number.isSafeInteger(key) || key < 0)) return false;\n const stringKey = String(key);\n\n if (!isRecord(current) || !Object.hasOwn(current, stringKey)) return false;\n\n current = current[stringKey] as MetaTree;\n }\n\n return current === true;\n}\n\nexport function touchAll(value: unknown): MetaRoot {\n if (Array.isArray(value)) {\n return Object.freeze(\n Object.fromEntries(\n value.map((child, i) => [\n String(i),\n isRecord(child) || Array.isArray(child) ? touchAll(child) : (true as const),\n ]),\n ),\n );\n }\n\n if (!isRecord(value)) return {};\n\n return Object.freeze(\n Object.fromEntries(\n Object.entries(value).map(([key, child]) => [\n key,\n isRecord(child) || Array.isArray(child) ? touchAll(child) : (true as const),\n ]),\n ),\n );\n}\n\nexport function pathEquals(a: readonly (string | number)[], b: readonly (string | number)[]): boolean {\n if (a.length !== b.length) return false;\n\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n\n return true;\n}\n\n/** Derives a single field's error message from the flat issue list. */\nexport function findIssue(\n issues: readonly ValidationIssue[] | undefined,\n path: readonly (string | number)[],\n): string | undefined {\n if (!issues) return undefined;\n\n for (const issue of issues) {\n if (pathEquals(issue.path, path)) return issue.message;\n }\n\n return undefined;\n}\n"],"mappings":"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"}
package/dist/dom.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,t,n){let r=n.event??`input`,i=!1,a=()=>{i=!0;try{t.set(n.read(e))}finally{i=!1}},o=()=>t.touch(),s=!1,c=t.value,l=n.write?t.subscribe(({value:t})=>{if(i){s=!0,c=t;return}s&&t===c||(s=!0,c=t,n.write?.(e,t))},{immediate:!0}):()=>{};return e.addEventListener(r,a),e.addEventListener(`blur`,o),()=>{e.removeEventListener(r,a),e.removeEventListener(`blur`,o),l()}}exports.bindField=e;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,t,n){let r=n.event??`input`,i=!1,a=!1,o=t.value,s=()=>{i=!0;try{t.set(n.read(e))}finally{i=!1}},c=()=>t.touch(),l=n.write?t.subscribe(({value:t})=>{if(i){a=!0,o=t;return}a&&Object.is(t,o)||(a=!0,o=t,n.write?.(e,t))},{immediate:!0}):()=>void 0;return e.addEventListener(r,s),e.addEventListener(`blur`,c),()=>{e.removeEventListener(r,s),e.removeEventListener(`blur`,c),l()}}exports.bindField=e;
2
2
  //# sourceMappingURL=dom.cjs.map
package/dist/dom.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dom.cjs","names":[],"sources":["../src/dom.ts"],"sourcesContent":["import type { Field, ReadonlyDeep } from './types';\n\nexport type FieldBindingOptions<Element extends HTMLElement, V> = Readonly<{\n event?: keyof HTMLElementEventMap;\n read(element: Element): V;\n write?: (element: Element, value: ReadonlyDeep<V>) => void;\n}>;\n\n/** Binds one field to one element without imposing parsing, debounce, or validation policy. */\nexport function bindField<Element extends HTMLElement, V>(\n element: Element,\n field: Field<V>,\n options: FieldBindingOptions<Element, V>,\n): () => void {\n const event = options.event ?? 'input';\n let updatingFromElement = false;\n const onInput = () => {\n updatingFromElement = true;\n\n try {\n field.set(options.read(element));\n } finally {\n updatingFromElement = false;\n }\n };\n const onBlur = () => field.touch();\n let hasRendered = false;\n let rendered = field.value;\n const unsubscribe = options.write\n ? field.subscribe(\n ({ value }) => {\n if (updatingFromElement) {\n hasRendered = true;\n rendered = value;\n\n return;\n }\n\n if (hasRendered && value === rendered) return;\n\n hasRendered = true;\n rendered = value;\n options.write?.(element, value);\n },\n { immediate: true },\n )\n : () => {};\n\n element.addEventListener(event, onInput);\n element.addEventListener('blur', onBlur);\n\n return () => {\n element.removeEventListener(event, onInput);\n element.removeEventListener('blur', onBlur);\n unsubscribe();\n };\n}\n"],"mappings":"mEASA,SAAgB,EACd,EACA,EACA,EACY,CACZ,IAAM,EAAQ,EAAQ,OAAS,QAC3B,EAAsB,GACpB,MAAgB,CACpB,EAAsB,GAEtB,GAAI,CACF,EAAM,IAAI,EAAQ,KAAK,CAAO,CAAC,CACjC,QAAU,CACR,EAAsB,EACxB,CACF,EACM,MAAe,EAAM,MAAM,EAC7B,EAAc,GACd,EAAW,EAAM,MACf,EAAc,EAAQ,MACxB,EAAM,WACH,CAAE,WAAY,CACb,GAAI,EAAqB,CACvB,EAAc,GACd,EAAW,EAEX,MACF,CAEI,GAAe,IAAU,IAE7B,EAAc,GACd,EAAW,EACX,EAAQ,QAAQ,EAAS,CAAK,EAChC,EACA,CAAE,UAAW,EAAK,CACpB,MACM,CAAC,EAKX,OAHA,EAAQ,iBAAiB,EAAO,CAAO,EACvC,EAAQ,iBAAiB,OAAQ,CAAM,MAE1B,CACX,EAAQ,oBAAoB,EAAO,CAAO,EAC1C,EAAQ,oBAAoB,OAAQ,CAAM,EAC1C,EAAY,CACd,CACF"}
1
+ {"version":3,"file":"dom.cjs","names":[],"sources":["../src/dom.ts"],"sourcesContent":["import type { Field, FieldState } from './types.js';\n\nexport type FieldBindingOptions<Element extends HTMLElement, Value> = Readonly<{\n event?: keyof HTMLElementEventMap;\n read(element: Element): Value;\n write?: (element: Element, value: FieldState<Value>['value']) => void;\n}>;\n\nexport function bindField<Element extends HTMLElement, Value>(\n element: Element,\n field: Field<Value>,\n options: FieldBindingOptions<Element, Value>,\n): () => void {\n const event = options.event ?? 'input';\n let updatingFromElement = false;\n let hasRendered = false;\n let rendered = field.value;\n\n const onInput = (): void => {\n updatingFromElement = true;\n try {\n field.set(options.read(element));\n } finally {\n updatingFromElement = false;\n }\n };\n const onBlur = (): void => field.touch();\n const unsubscribe = options.write\n ? field.subscribe(\n ({ value }) => {\n if (updatingFromElement) {\n hasRendered = true;\n rendered = value;\n return;\n }\n if (hasRendered && Object.is(value, rendered)) return;\n hasRendered = true;\n rendered = value;\n options.write?.(element, value);\n },\n { immediate: true },\n )\n : () => undefined;\n\n element.addEventListener(event, onInput);\n element.addEventListener('blur', onBlur);\n\n return () => {\n element.removeEventListener(event, onInput);\n element.removeEventListener('blur', onBlur);\n unsubscribe();\n };\n}\n"],"mappings":"mEAQA,SAAgB,EACd,EACA,EACA,EACY,CACZ,IAAM,EAAQ,EAAQ,OAAS,QAC3B,EAAsB,GACtB,EAAc,GACd,EAAW,EAAM,MAEf,MAAsB,CAC1B,EAAsB,GACtB,GAAI,CACF,EAAM,IAAI,EAAQ,KAAK,CAAO,CAAC,CACjC,QAAU,CACR,EAAsB,EACxB,CACF,EACM,MAAqB,EAAM,MAAM,EACjC,EAAc,EAAQ,MACxB,EAAM,WACH,CAAE,WAAY,CACb,GAAI,EAAqB,CACvB,EAAc,GACd,EAAW,EACX,MACF,CACI,GAAe,OAAO,GAAG,EAAO,CAAQ,IAC5C,EAAc,GACd,EAAW,EACX,EAAQ,QAAQ,EAAS,CAAK,EAChC,EACA,CAAE,UAAW,EAAK,CACpB,MACM,IAAA,GAKV,OAHA,EAAQ,iBAAiB,EAAO,CAAO,EACvC,EAAQ,iBAAiB,OAAQ,CAAM,MAE1B,CACX,EAAQ,oBAAoB,EAAO,CAAO,EAC1C,EAAQ,oBAAoB,OAAQ,CAAM,EAC1C,EAAY,CACd,CACF"}
package/dist/dom.d.ts CHANGED
@@ -1,9 +1,8 @@
1
- import type { Field, ReadonlyDeep } from './types';
2
- export type FieldBindingOptions<Element extends HTMLElement, V> = Readonly<{
1
+ import type { Field, FieldState } from './types.js';
2
+ export type FieldBindingOptions<Element extends HTMLElement, Value> = Readonly<{
3
3
  event?: keyof HTMLElementEventMap;
4
- read(element: Element): V;
5
- write?: (element: Element, value: ReadonlyDeep<V>) => void;
4
+ read(element: Element): Value;
5
+ write?: (element: Element, value: FieldState<Value>['value']) => void;
6
6
  }>;
7
- /** Binds one field to one element without imposing parsing, debounce, or validation policy. */
8
- export declare function bindField<Element extends HTMLElement, V>(element: Element, field: Field<V>, options: FieldBindingOptions<Element, V>): () => void;
7
+ export declare function bindField<Element extends HTMLElement, Value>(element: Element, field: Field<Value>, options: FieldBindingOptions<Element, Value>): () => void;
9
8
  //# sourceMappingURL=dom.d.ts.map
package/dist/dom.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,MAAM,mBAAmB,CAAC,OAAO,SAAS,WAAW,EAAE,CAAC,IAAI,QAAQ,CAAC;IACzE,KAAK,CAAC,EAAE,MAAM,mBAAmB,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,CAAC,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CAC5D,CAAC,CAAC;AAEH,+FAA+F;AAC/F,wBAAgB,SAAS,CAAC,OAAO,SAAS,WAAW,EAAE,CAAC,EACtD,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,CAAC,CAAC,GACvC,MAAM,IAAI,CA2CZ"}
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,MAAM,mBAAmB,CAAC,OAAO,SAAS,WAAW,EAAE,KAAK,IAAI,QAAQ,CAAC;IAC7E,KAAK,CAAC,EAAE,MAAM,mBAAmB,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,KAAK,CAAC;IAC9B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;CACvE,CAAC,CAAC;AAEH,wBAAgB,SAAS,CAAC,OAAO,SAAS,WAAW,EAAE,KAAK,EAC1D,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EACnB,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,GAC3C,MAAM,IAAI,CAwCZ"}
package/dist/dom.js CHANGED
@@ -1,21 +1,21 @@
1
1
  //#region src/dom.ts
2
2
  function e(e, t, n) {
3
- let r = n.event ?? "input", i = !1, a = () => {
3
+ let r = n.event ?? "input", i = !1, a = !1, o = t.value, s = () => {
4
4
  i = !0;
5
5
  try {
6
6
  t.set(n.read(e));
7
7
  } finally {
8
8
  i = !1;
9
9
  }
10
- }, o = () => t.touch(), s = !1, c = t.value, l = n.write ? t.subscribe(({ value: t }) => {
10
+ }, c = () => t.touch(), l = n.write ? t.subscribe(({ value: t }) => {
11
11
  if (i) {
12
- s = !0, c = t;
12
+ a = !0, o = t;
13
13
  return;
14
14
  }
15
- s && t === c || (s = !0, c = t, n.write?.(e, t));
16
- }, { immediate: !0 }) : () => {};
17
- return e.addEventListener(r, a), e.addEventListener("blur", o), () => {
18
- e.removeEventListener(r, a), e.removeEventListener("blur", o), l();
15
+ a && Object.is(t, o) || (a = !0, o = t, n.write?.(e, t));
16
+ }, { immediate: !0 }) : () => void 0;
17
+ return e.addEventListener(r, s), e.addEventListener("blur", c), () => {
18
+ e.removeEventListener(r, s), e.removeEventListener("blur", c), l();
19
19
  };
20
20
  }
21
21
  //#endregion
package/dist/dom.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dom.js","names":[],"sources":["../src/dom.ts"],"sourcesContent":["import type { Field, ReadonlyDeep } from './types';\n\nexport type FieldBindingOptions<Element extends HTMLElement, V> = Readonly<{\n event?: keyof HTMLElementEventMap;\n read(element: Element): V;\n write?: (element: Element, value: ReadonlyDeep<V>) => void;\n}>;\n\n/** Binds one field to one element without imposing parsing, debounce, or validation policy. */\nexport function bindField<Element extends HTMLElement, V>(\n element: Element,\n field: Field<V>,\n options: FieldBindingOptions<Element, V>,\n): () => void {\n const event = options.event ?? 'input';\n let updatingFromElement = false;\n const onInput = () => {\n updatingFromElement = true;\n\n try {\n field.set(options.read(element));\n } finally {\n updatingFromElement = false;\n }\n };\n const onBlur = () => field.touch();\n let hasRendered = false;\n let rendered = field.value;\n const unsubscribe = options.write\n ? field.subscribe(\n ({ value }) => {\n if (updatingFromElement) {\n hasRendered = true;\n rendered = value;\n\n return;\n }\n\n if (hasRendered && value === rendered) return;\n\n hasRendered = true;\n rendered = value;\n options.write?.(element, value);\n },\n { immediate: true },\n )\n : () => {};\n\n element.addEventListener(event, onInput);\n element.addEventListener('blur', onBlur);\n\n return () => {\n element.removeEventListener(event, onInput);\n element.removeEventListener('blur', onBlur);\n unsubscribe();\n };\n}\n"],"mappings":";AASA,SAAgB,EACd,GACA,GACA,GACY;CACZ,IAAM,IAAQ,EAAQ,SAAS,SAC3B,IAAsB,IACpB,UAAgB;EACpB,IAAsB;EAEtB,IAAI;GACF,EAAM,IAAI,EAAQ,KAAK,CAAO,CAAC;EACjC,UAAU;GACR,IAAsB;EACxB;CACF,GACM,UAAe,EAAM,MAAM,GAC7B,IAAc,IACd,IAAW,EAAM,OACf,IAAc,EAAQ,QACxB,EAAM,WACH,EAAE,eAAY;EACb,IAAI,GAAqB;GAEvB,AADA,IAAc,IACd,IAAW;GAEX;EACF;EAEI,KAAe,MAAU,MAE7B,IAAc,IACd,IAAW,GACX,EAAQ,QAAQ,GAAS,CAAK;CAChC,GACA,EAAE,WAAW,GAAK,CACpB,UACM,CAAC;CAKX,OAHA,EAAQ,iBAAiB,GAAO,CAAO,GACvC,EAAQ,iBAAiB,QAAQ,CAAM,SAE1B;EAGX,AAFA,EAAQ,oBAAoB,GAAO,CAAO,GAC1C,EAAQ,oBAAoB,QAAQ,CAAM,GAC1C,EAAY;CACd;AACF"}
1
+ {"version":3,"file":"dom.js","names":[],"sources":["../src/dom.ts"],"sourcesContent":["import type { Field, FieldState } from './types.js';\n\nexport type FieldBindingOptions<Element extends HTMLElement, Value> = Readonly<{\n event?: keyof HTMLElementEventMap;\n read(element: Element): Value;\n write?: (element: Element, value: FieldState<Value>['value']) => void;\n}>;\n\nexport function bindField<Element extends HTMLElement, Value>(\n element: Element,\n field: Field<Value>,\n options: FieldBindingOptions<Element, Value>,\n): () => void {\n const event = options.event ?? 'input';\n let updatingFromElement = false;\n let hasRendered = false;\n let rendered = field.value;\n\n const onInput = (): void => {\n updatingFromElement = true;\n try {\n field.set(options.read(element));\n } finally {\n updatingFromElement = false;\n }\n };\n const onBlur = (): void => field.touch();\n const unsubscribe = options.write\n ? field.subscribe(\n ({ value }) => {\n if (updatingFromElement) {\n hasRendered = true;\n rendered = value;\n return;\n }\n if (hasRendered && Object.is(value, rendered)) return;\n hasRendered = true;\n rendered = value;\n options.write?.(element, value);\n },\n { immediate: true },\n )\n : () => undefined;\n\n element.addEventListener(event, onInput);\n element.addEventListener('blur', onBlur);\n\n return () => {\n element.removeEventListener(event, onInput);\n element.removeEventListener('blur', onBlur);\n unsubscribe();\n };\n}\n"],"mappings":";AAQA,SAAgB,EACd,GACA,GACA,GACY;CACZ,IAAM,IAAQ,EAAQ,SAAS,SAC3B,IAAsB,IACtB,IAAc,IACd,IAAW,EAAM,OAEf,UAAsB;EAC1B,IAAsB;EACtB,IAAI;GACF,EAAM,IAAI,EAAQ,KAAK,CAAO,CAAC;EACjC,UAAU;GACR,IAAsB;EACxB;CACF,GACM,UAAqB,EAAM,MAAM,GACjC,IAAc,EAAQ,QACxB,EAAM,WACH,EAAE,eAAY;EACb,IAAI,GAAqB;GAEvB,AADA,IAAc,IACd,IAAW;GACX;EACF;EACI,KAAe,OAAO,GAAG,GAAO,CAAQ,MAC5C,IAAc,IACd,IAAW,GACX,EAAQ,QAAQ,GAAS,CAAK;CAChC,GACA,EAAE,WAAW,GAAK,CACpB,UACM,KAAA;CAKV,OAHA,EAAQ,iBAAiB,GAAO,CAAO,GACvC,EAAQ,iBAAiB,QAAQ,CAAM,SAE1B;EAGX,AAFA,EAAQ,oBAAoB,GAAO,CAAO,GAC1C,EAAQ,oBAAoB,QAAQ,CAAM,GAC1C,EAAY;CACd;AACF"}
package/dist/errors.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},n=class extends e{},r=class extends e{},i=class extends e{};exports.ForgeConfigError=n,exports.ForgeDisposedError=t,exports.ForgeError=e,exports.ForgeSubmitError=r,exports.ForgeValidationError=i;
1
+ var e=class extends Error{static errorName=`ForgeError`;constructor(e,t){super(e,t),this.name=new.target.errorName,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{static errorName=`ForgeDisposedError`;constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},n=class extends e{static errorName=`ForgeConfigError`},r=class extends e{static errorName=`ForgeSubmitError`},i=class extends e{static errorName=`ForgeValidationError`};exports.ForgeConfigError=n,exports.ForgeDisposedError=t,exports.ForgeError=e,exports.ForgeSubmitError=r,exports.ForgeValidationError=i;
2
2
  //# sourceMappingURL=errors.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all forge errors. Use `instanceof ForgeError` to catch any forge-originated error. */\nexport class ForgeError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when any method is called on a disposed form. */\nexport class ForgeDisposedError extends ForgeError {\n /** @param op The public method name that was called (e.g. `'set'`) — included in the\n * message so a stack trace tells you *what* to guard, not just *that* it's disposed. */\n constructor(op?: string) {\n super(op ? `Cannot call ${op}() on a disposed form` : 'Cannot modify a disposed form');\n }\n}\n\n/** Thrown when a form key contains reserved prototype-polluting segments. */\nexport class ForgeConfigError extends ForgeError {}\n\n/** Thrown when `submit()` is called while a submission is already in progress. */\nexport class ForgeSubmitError extends ForgeError {}\n\n/** Wraps unexpected exceptions from a form validator without converting validation failures into exceptions. */\nexport class ForgeValidationError extends ForgeError {}\n"],"mappings":"AACA,IAAa,EAAb,cAAgC,KAAM,CACpC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,EAAb,cAAwC,CAAW,CAGjD,YAAY,EAAa,CACvB,MAAM,EAAK,eAAe,EAAG,uBAAyB,+BAA+B,CACvF,CACF,EAGa,EAAb,cAAsC,CAAW,CAAC,EAGrC,EAAb,cAAsC,CAAW,CAAC,EAGrC,EAAb,cAA0C,CAAW,CAAC"}
1
+ {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all forge errors. Use `instanceof ForgeError` to catch any forge-originated error. */\nexport class ForgeError extends Error {\n protected static readonly errorName: string = 'ForgeError';\n\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = (new.target as typeof ForgeError).errorName;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when any method is called on a disposed form. */\nexport class ForgeDisposedError extends ForgeError {\n protected static override readonly errorName = 'ForgeDisposedError';\n\n /** @param op The public method name that was called (e.g. `'set'`) — included in the\n * message so a stack trace tells you *what* to guard, not just *that* it's disposed. */\n constructor(op?: string) {\n super(op ? `Cannot call ${op}() on a disposed form` : 'Cannot modify a disposed form');\n }\n}\n\n/** Thrown when form configuration or value structure is invalid. */\nexport class ForgeConfigError extends ForgeError {\n protected static override readonly errorName = 'ForgeConfigError';\n}\n\n/** Thrown when `submit()` is called while a submission is already in progress. */\nexport class ForgeSubmitError extends ForgeError {\n protected static override readonly errorName = 'ForgeSubmitError';\n}\n\n/** Wraps unexpected exceptions from a form validator without converting validation failures into exceptions. */\nexport class ForgeValidationError extends ForgeError {\n protected static override readonly errorName = 'ForgeValidationError';\n}\n"],"mappings":"AACA,IAAa,EAAb,cAAgC,KAAM,CACpC,OAA0B,UAAoB,aAE9C,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAQ,WAAiC,UAC9C,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,EAAb,cAAwC,CAAW,CACjD,OAAmC,UAAY,qBAI/C,YAAY,EAAa,CACvB,MAAM,EAAK,eAAe,EAAG,uBAAyB,+BAA+B,CACvF,CACF,EAGa,EAAb,cAAsC,CAAW,CAC/C,OAAmC,UAAY,kBACjD,EAGa,EAAb,cAAsC,CAAW,CAC/C,OAAmC,UAAY,kBACjD,EAGa,EAAb,cAA0C,CAAW,CACnD,OAAmC,UAAY,sBACjD"}
package/dist/errors.d.ts CHANGED
@@ -1,20 +1,25 @@
1
1
  /** Base class for all forge errors. Use `instanceof ForgeError` to catch any forge-originated error. */
2
2
  export declare class ForgeError extends Error {
3
+ protected static readonly errorName: string;
3
4
  constructor(message: string, opts?: ErrorOptions);
4
5
  }
5
6
  /** Thrown when any method is called on a disposed form. */
6
7
  export declare class ForgeDisposedError extends ForgeError {
8
+ protected static readonly errorName = "ForgeDisposedError";
7
9
  /** @param op The public method name that was called (e.g. `'set'`) — included in the
8
10
  * message so a stack trace tells you *what* to guard, not just *that* it's disposed. */
9
11
  constructor(op?: string);
10
12
  }
11
- /** Thrown when a form key contains reserved prototype-polluting segments. */
13
+ /** Thrown when form configuration or value structure is invalid. */
12
14
  export declare class ForgeConfigError extends ForgeError {
15
+ protected static readonly errorName = "ForgeConfigError";
13
16
  }
14
17
  /** Thrown when `submit()` is called while a submission is already in progress. */
15
18
  export declare class ForgeSubmitError extends ForgeError {
19
+ protected static readonly errorName = "ForgeSubmitError";
16
20
  }
17
21
  /** Wraps unexpected exceptions from a form validator without converting validation failures into exceptions. */
18
22
  export declare class ForgeValidationError extends ForgeError {
23
+ protected static readonly errorName = "ForgeValidationError";
19
24
  }
20
25
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAKjD;AAED,2DAA2D;AAC3D,qBAAa,kBAAmB,SAAQ,UAAU;IAChD;4FACwF;gBAC5E,EAAE,CAAC,EAAE,MAAM;CAGxB;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,SAAQ,UAAU;CAAG;AAEnD,kFAAkF;AAClF,qBAAa,gBAAiB,SAAQ,UAAU;CAAG;AAEnD,gHAAgH;AAChH,qBAAa,oBAAqB,SAAQ,UAAU;CAAG"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,qBAAa,UAAW,SAAQ,KAAK;IACnC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAgB;gBAE/C,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAKjD;AAED,2DAA2D;AAC3D,qBAAa,kBAAmB,SAAQ,UAAU;IAChD,0BAAmC,SAAS,wBAAwB;IAEpE;4FACwF;gBAC5E,EAAE,CAAC,EAAE,MAAM;CAGxB;AAED,oEAAoE;AACpE,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,0BAAmC,SAAS,sBAAsB;CACnE;AAED,kFAAkF;AAClF,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,0BAAmC,SAAS,sBAAsB;CACnE;AAED,gHAAgH;AAChH,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,0BAAmC,SAAS,0BAA0B;CACvE"}
package/dist/errors.js CHANGED
@@ -1,13 +1,21 @@
1
1
  //#region src/errors.ts
2
2
  var e = class extends Error {
3
+ static errorName = "ForgeError";
3
4
  constructor(e, t) {
4
- super(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);
5
+ super(e, t), this.name = new.target.errorName, Object.setPrototypeOf(this, new.target.prototype);
5
6
  }
6
7
  }, t = class extends e {
8
+ static errorName = "ForgeDisposedError";
7
9
  constructor(e) {
8
10
  super(e ? `Cannot call ${e}() on a disposed form` : "Cannot modify a disposed form");
9
11
  }
10
- }, n = class extends e {}, r = class extends e {}, i = class extends e {};
12
+ }, n = class extends e {
13
+ static errorName = "ForgeConfigError";
14
+ }, r = class extends e {
15
+ static errorName = "ForgeSubmitError";
16
+ }, i = class extends e {
17
+ static errorName = "ForgeValidationError";
18
+ };
11
19
  //#endregion
12
20
  export { n as ForgeConfigError, t as ForgeDisposedError, e as ForgeError, r as ForgeSubmitError, i as ForgeValidationError };
13
21
 
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all forge errors. Use `instanceof ForgeError` to catch any forge-originated error. */\nexport class ForgeError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when any method is called on a disposed form. */\nexport class ForgeDisposedError extends ForgeError {\n /** @param op The public method name that was called (e.g. `'set'`) — included in the\n * message so a stack trace tells you *what* to guard, not just *that* it's disposed. */\n constructor(op?: string) {\n super(op ? `Cannot call ${op}() on a disposed form` : 'Cannot modify a disposed form');\n }\n}\n\n/** Thrown when a form key contains reserved prototype-polluting segments. */\nexport class ForgeConfigError extends ForgeError {}\n\n/** Thrown when `submit()` is called while a submission is already in progress. */\nexport class ForgeSubmitError extends ForgeError {}\n\n/** Wraps unexpected exceptions from a form validator without converting validation failures into exceptions. */\nexport class ForgeValidationError extends ForgeError {}\n"],"mappings":";AACA,IAAa,IAAb,cAAgC,MAAM;CACpC,YAAY,GAAiB,GAAqB;EAGhD,AAFA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAO,WAAW,MACvB,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;AACF,GAGa,IAAb,cAAwC,EAAW;CAGjD,YAAY,GAAa;EACvB,MAAM,IAAK,eAAe,EAAG,yBAAyB,+BAA+B;CACvF;AACF,GAGa,IAAb,cAAsC,EAAW,CAAC,GAGrC,IAAb,cAAsC,EAAW,CAAC,GAGrC,IAAb,cAA0C,EAAW,CAAC"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all forge errors. Use `instanceof ForgeError` to catch any forge-originated error. */\nexport class ForgeError extends Error {\n protected static readonly errorName: string = 'ForgeError';\n\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = (new.target as typeof ForgeError).errorName;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when any method is called on a disposed form. */\nexport class ForgeDisposedError extends ForgeError {\n protected static override readonly errorName = 'ForgeDisposedError';\n\n /** @param op The public method name that was called (e.g. `'set'`) — included in the\n * message so a stack trace tells you *what* to guard, not just *that* it's disposed. */\n constructor(op?: string) {\n super(op ? `Cannot call ${op}() on a disposed form` : 'Cannot modify a disposed form');\n }\n}\n\n/** Thrown when form configuration or value structure is invalid. */\nexport class ForgeConfigError extends ForgeError {\n protected static override readonly errorName = 'ForgeConfigError';\n}\n\n/** Thrown when `submit()` is called while a submission is already in progress. */\nexport class ForgeSubmitError extends ForgeError {\n protected static override readonly errorName = 'ForgeSubmitError';\n}\n\n/** Wraps unexpected exceptions from a form validator without converting validation failures into exceptions. */\nexport class ForgeValidationError extends ForgeError {\n protected static override readonly errorName = 'ForgeValidationError';\n}\n"],"mappings":";AACA,IAAa,IAAb,cAAgC,MAAM;CACpC,OAA0B,YAAoB;CAE9C,YAAY,GAAiB,GAAqB;EAGhD,AAFA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAQ,WAAiC,WAC9C,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;AACF,GAGa,IAAb,cAAwC,EAAW;CACjD,OAAmC,YAAY;CAI/C,YAAY,GAAa;EACvB,MAAM,IAAK,eAAe,EAAG,yBAAyB,+BAA+B;CACvF;AACF,GAGa,IAAb,cAAsC,EAAW;CAC/C,OAAmC,YAAY;AACjD,GAGa,IAAb,cAAsC,EAAW;CAC/C,OAAmC,YAAY;AACjD,GAGa,IAAb,cAA0C,EAAW;CACnD,OAAmC,YAAY;AACjD"}
package/dist/forge.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},n=class extends e{},r=class extends e{},i=class extends e{},a=new Set([`__proto__`,`constructor`,`prototype`]);function o(e){return!e||a.has(e)}function s(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function c(e){if(o(e))throw new n(`Invalid field key '${e}'.`)}function l(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File||e instanceof Date}function u(e){if(Array.isArray(e))return Object.freeze(e.map(u));if(typeof e!=`object`||!e||l(e))return e;if(!s(e))throw new n(`Form values must contain only plain objects, arrays, Date, File, Blob, or primitive values.`);return Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,u(t)])))}function d(e,t){let n=e;for(let e of t)if(typeof e==`number`){if(!Array.isArray(n)||e<0||e>=n.length)return;n=n[e]}else{if(!s(n)||!Object.hasOwn(n,e))return;n=n[e]}return n}function f(e,t){let n=e;for(let e of t)if(typeof e==`number`){if(!Array.isArray(n)||e<0||e>=n.length)return!1;n=n[e]}else{if(!s(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return!0}function p(e,t,r){let[i,...a]=t;if(typeof i==`number`){if(!Array.isArray(e))throw new n(`Cannot index ${i} because the current value is not an array.`);if(i<0||i>=e.length)throw new n(`Index ${i} is out of range for array of length ${e.length}.`);if(a.length===0){let t=[...e];return t[i]=u(r),Object.freeze(t)}let t=[...e];return t[i]=p(e[i],a,r),Object.freeze(t)}if(c(i),!s(e))throw new n(`Cannot select '${i}' because the current value is not an object.`);if(a.length===0)return Object.freeze({...e,[i]:u(r)});let o=e[i];if(o!==void 0&&!s(o)&&!Array.isArray(o))throw new n(`Cannot select '${i}' because it is not an object or array.`);let l=o??{};return Object.freeze({...e,[i]:p(l,a,r)})}function m(e,t,n){let[r,...i]=n;if(typeof r==`number`){if(!Array.isArray(e)||!Array.isArray(t)||r>=t.length||r>=e.length)return e;if(i.length===0){let n=[...e];return n[r]=t[r],Object.freeze(n)}let n=[...e];return n[r]=m(e[r],t[r],i),Object.freeze(n)}if(!s(e))return e;if(i.length===0){if(Object.hasOwn(t,r))return Object.freeze({...e,[r]:t[r]});let{[r]:n,...i}=e;return Object.freeze(i)}let a=t[r];if(!s(a)&&!Array.isArray(a)){if(Object.hasOwn(t,r))return Object.freeze({...e,[r]:a});let{[r]:n,...i}=e;return Object.freeze(i)}let o=e[r],c=s(o)||Array.isArray(o)?o:{};return Object.freeze({...e,[r]:m(c,a,i)})}function h(e,t,n){let[r,...i]=t,a=String(r),o={...e};if(i.length===0)n?o[a]=!0:delete o[a];else{let t=h(s(e[a])?e[a]:{},i,n);Object.keys(t).length===0?delete o[a]:o[a]=t}return Object.freeze(o)}function g(e,t){let n=e;for(let e of t){let t=String(e);if(!s(n)||!Object.hasOwn(n,t))return!1;n=n[t]}return n===!0}function _(e){return Array.isArray(e)?Object.freeze(Object.fromEntries(e.map((e,t)=>[String(t),s(e)||Array.isArray(e)?_(e):!0]))):s(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,s(t)||Array.isArray(t)?_(t):!0]))):{}}function v(e,t){let n=d(e,t);return typeof n==`string`?n:void 0}function y(e){if(typeof e==`string`)return e;if(Array.isArray(e)){let t=e.map(e=>y(e));return t.every(e=>e===void 0)?void 0:Object.freeze(t)}if(!s(e))return;let t=Object.entries(e).map(([e,t])=>[e,y(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}function b(e,t){let n=d(e.value,t),r=d(e.baseline,t);return Object.freeze({dirty:n!==r||f(e.value,t)!==f(e.baseline,t),error:v(e.errors,t),touched:g(e.touched,t),value:n})}function x(e,t){return Object.assign({get dirty(){return b(t.readState(),e).dirty},get error(){return b(t.readState(),e).error},reset(){t.ensureActive(`field().reset`),t.abortValidation(),t.resetValue(e)},set(n){t.ensureActive(`field().set`),t.abortValidation();let r=d(t.readState().value,e),i=typeof n==`function`?n(r):n;t.setValue(e,i)},get state(){return b(t.readState(),e)},subscribe(n,r={}){t.ensureActive(`field().subscribe`);let i=b(t.readState(),e);return r.immediate&&n(i),t.addListener(()=>{let r=b(t.readState(),e);(r.value!==i.value||r.error!==i.error||r.touched!==i.touched||r.dirty!==i.dirty)&&(i=r,n(r))})},touch(){t.ensureActive(`field().touch`),t.setTouched(e,!0)},get touched(){return b(t.readState(),e).touched},get value(){return b(t.readState(),e).value}},{field(r){if(typeof r==`number`){let i=d(t.readState().value,e);if(i!==void 0&&!Array.isArray(i))throw new n(`Cannot index ${r} because the current field value is not an array.`);return x([...e,r],t)}c(r);let i=d(t.readState().value,e);if(i!==void 0&&!s(i))throw new n(`Cannot select '${r}' because the current field value is not an object.`);return x([...e,r],t)}})}function S(e){queueMicrotask(()=>{throw e})}function C(e){let t=new Set;function n(t){if(!e){S(t);return}try{e(t)}catch(e){S(e)}}return{add(e){return t.add(e),()=>t.delete(e)},clear(){t.clear()},notify(){for(let e of[...t])try{e()}catch(e){n(e)}}}}function w(e){return Object.freeze({errors:e.errors,formError:e.formError,hasErrors:e.formError!==void 0||e.errors!==void 0,submitCount:e.submitCount,submitting:e.isSubmitting,touched:Object.keys(e.touched).length>0,validating:e.isValidating,validity:e.validity})}function T(e){let a=u(e.initialValues),o=C(e.onSubscriberError),l=new AbortController,d=!1,f,g={baseline:a,errors:void 0,formError:void 0,isSubmitting:!1,isValidating:!1,submitCount:0,touched:{},validity:`unknown`,value:a};function v(e){if(d)throw new t(e)}function b(e){g=Object.freeze(e(g)),o.notify()}function S(){f?.abort()}let T={abortValidation:S,addListener:o.add,ensureActive:v,readState:()=>g,resetValue(e){b(t=>({...t,touched:h(t.touched,e,!1),validity:`unknown`,value:m(t.value,t.baseline,e)}))},setTouched(e,t){b(n=>({...n,touched:h(n.touched,e,t)}))},setValue(e,t){b(n=>({...n,validity:`unknown`,value:p(n.value,e,t)}))}};async function E(t){v(`validate`),S();let n=new AbortController,r=t?AbortSignal.any([n.signal,t]):n.signal;f=n,b(e=>({...e,isValidating:!0}));try{let t=e.validate?await e.validate(g.value,r):void 0;if(r.aborted||f!==n)return Object.freeze({status:`aborted`});let i=t?.fields?y(u(t.fields)):void 0,a=t?.formError,o=i===void 0&&a===void 0?`valid`:`invalid`;return b(e=>({...e,errors:i,formError:a,validity:o})),Object.freeze(o===`valid`?{status:`valid`}:{errors:i,formError:a,status:`invalid`})}catch(e){if(r.aborted||f!==n)return Object.freeze({status:`aborted`});throw new i(`Form validation failed.`,{cause:e})}finally{f===n&&(f=void 0,d||b(e=>({...e,isValidating:!1})))}}let D={get disposalSignal(){return l.signal},dispose(){d||(d=!0,l.abort(),S(),o.clear())},get disposed(){return d},field(e){if(c(e),!s(g.value))throw new n(`Form value must be an object.`);return x([e],T)},reset(e){v(`reset`),S();let t=e===void 0?g.baseline:u(e);b(e=>({...e,baseline:t,errors:void 0,formError:void 0,touched:{},validity:`unknown`,value:t}))},set(e){v(`set`),S();let t=typeof e==`function`?e(D.value):e;b(e=>({...e,errors:void 0,formError:void 0,validity:`unknown`,value:u(t)}))},get state(){return w(g)},async submit(e,t){if(v(`submit`),g.isSubmitting)throw new r(`submit() called while a submission is already in progress`);let n=t?AbortSignal.any([l.signal,t]):l.signal;b(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:_(e.value)}));try{let r=await E(t);if(r.status===`aborted`)return Object.freeze({status:`aborted`});if(r.status===`invalid`)return Object.freeze({errors:r.errors,formError:r.formError,status:`invalid`});try{return Object.freeze({status:`ok`,value:await e(D.value,n)})}catch(e){if(n.aborted)return Object.freeze({status:`aborted`});throw e}}finally{d||b(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){return v(`subscribe`),t.immediate&&e(w(g)),o.add(()=>e(w(g)))},[Symbol.dispose](){D.dispose()},validate:E,get value(){return g.value}};return D}exports.ForgeConfigError=n,exports.ForgeDisposedError=t,exports.ForgeError=e,exports.ForgeSubmitError=r,exports.ForgeValidationError=i,exports.createForm=T;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@vielzeug/arsenal");var t=class extends Error{static errorName=`ForgeError`;constructor(e,t){super(e,t),this.name=new.target.errorName,Object.setPrototypeOf(this,new.target.prototype)}},n=class extends t{static errorName=`ForgeDisposedError`;constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},r=class extends t{static errorName=`ForgeConfigError`},i=class extends t{static errorName=`ForgeSubmitError`},a=class extends t{static errorName=`ForgeValidationError`},o=new Set([`__proto__`,`constructor`,`prototype`]);function s(e){return!e||o.has(e)}function c(e){if(s(e))throw new r(`Invalid field key '${e}'.`)}function l(e){if(!Number.isSafeInteger(e)||e<0)throw new r(`Invalid array index ${e}.`)}function u(e){return Object.prototype.toString.call(e)}function d(e){return u(e)===`[object Blob]`||u(e)===`[object File]`}function f(){throw new r(`Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob.`)}function p(t,n=new Set){if(t==null||typeof t==`string`||typeof t==`boolean`)return t;if(typeof t==`number`)return Number.isFinite(t)?t:f();if(typeof t!=`object`)return f();let i=t;if(u(t)===`[object Date]`&&typeof i.getTime==`function`){let e=i.getTime();return Number.isFinite(e)?Object.freeze(new Date(e)):f()}if(d(t))return t;if(n.has(t))throw new r(`Form values must not contain circular references.`);n.add(t);try{if(Array.isArray(t)){let e=[];for(let i=0;i<t.length;i++){if(!Object.hasOwn(t,i))throw new r(`Form arrays must not contain empty slots.`);e.push(p(t[i],n))}return Object.freeze(e)}if(!(0,e.isPlainObject)(t))return f();let i=Object.entries(t).map(([e,t])=>(c(e),[e,p(t,n)]));return Object.freeze(Object.fromEntries(i))}finally{n.delete(t)}}function m(t,n){let r=t;for(let t of n)if(typeof t==`number`){if(!Array.isArray(r)||!Number.isSafeInteger(t)||t<0||t>=r.length||!Object.hasOwn(r,t))return;r=r[t]}else{if(!(0,e.isPlainObject)(r)||!Object.hasOwn(r,t))return;r=r[t]}return r}function h(t,n){let r=t;for(let t of n)if(typeof t==`number`){if(!Array.isArray(r)||!Number.isSafeInteger(t)||t<0||t>=r.length||!Object.hasOwn(r,t))return!1;r=r[t]}else{if(!(0,e.isPlainObject)(r)||!Object.hasOwn(r,t))return!1;r=r[t]}return!0}function g(t,n,i){let[a,...o]=n;if(typeof a==`number`){if(l(a),!Array.isArray(t))throw new r(`Cannot index ${a} because the current value is not an array.`);if(a<0||a>=t.length)throw new r(`Index ${a} is out of range for array of length ${t.length}.`);if(o.length===0){let e=[...t];return e[a]=p(i),Object.freeze(e)}let e=[...t];return e[a]=g(t[a],o,i),Object.freeze(e)}if(c(a),!(0,e.isPlainObject)(t))throw new r(`Cannot select '${a}' because the current value is not an object.`);if(o.length===0)return Object.freeze({...t,[a]:p(i)});let s=t[a];if(s!==void 0&&!(0,e.isPlainObject)(s)&&!Array.isArray(s))throw new r(`Cannot select '${a}' because it is not an object or array.`);let u=s??{};return Object.freeze({...t,[a]:g(u,o,i)})}function _(t,n,r){let[i,...a]=r;if(typeof i==`number`){if(l(i),!Array.isArray(t)||!Array.isArray(n)||i>=n.length||i>=t.length)return t;if(a.length===0){let e=[...t];return e[i]=n[i],Object.freeze(e)}let e=[...t];return e[i]=_(t[i],n[i],a),Object.freeze(e)}if(!(0,e.isPlainObject)(t))return t;if(a.length===0){if(Object.hasOwn(n,i))return Object.freeze({...t,[i]:n[i]});let{[i]:e,...r}=t;return Object.freeze(r)}let o=n[i];if(!(0,e.isPlainObject)(o)&&!Array.isArray(o)){if(Object.hasOwn(n,i))return Object.freeze({...t,[i]:o});let{[i]:e,...r}=t;return Object.freeze(r)}let s=t[i],c=(0,e.isPlainObject)(s)||Array.isArray(s)?s:{};return Object.freeze({...t,[i]:_(c,o,a)})}function v(t,n,r){let[i,...a]=n;typeof i==`number`&&l(i);let o=String(i),s={...t};if(a.length===0)r?s[o]=!0:delete s[o];else{let n=v((0,e.isPlainObject)(t[o])?t[o]:{},a,r);Object.keys(n).length===0?delete s[o]:s[o]=n}return Object.freeze(s)}function y(t,n){let r=t;for(let t of n){if(typeof t==`number`&&(!Number.isSafeInteger(t)||t<0))return!1;let n=String(t);if(!(0,e.isPlainObject)(r)||!Object.hasOwn(r,n))return!1;r=r[n]}return r===!0}function b(t){return Array.isArray(t)?Object.freeze(Object.fromEntries(t.map((t,n)=>[String(n),(0,e.isPlainObject)(t)||Array.isArray(t)?b(t):!0]))):(0,e.isPlainObject)(t)?Object.freeze(Object.fromEntries(Object.entries(t).map(([t,n])=>[t,(0,e.isPlainObject)(n)||Array.isArray(n)?b(n):!0]))):{}}function x(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function S(e,t){if(e){for(let n of e)if(x(n.path,t))return n.message}}function C(t,n){let r=m(t.value,n),i=m(t.baseline,n);return Object.freeze({dirty:!(0,e.isEqual)(r,i)||h(t.value,n)!==h(t.baseline,n),error:S(t.issues,n),touched:y(t.touched,n),value:r})}function w(t,n){return Object.assign({get dirty(){return C(n.readState(),t).dirty},get error(){return C(n.readState(),t).error},reset(){n.ensureActive(`field().reset`),n.abortValidation(),n.resetValue(t)},set(e){n.ensureActive(`field().set`),n.abortValidation(),n.setValue(t,e)},get state(){return C(n.readState(),t)},subscribe(e,r={}){n.ensureActive(`field().subscribe`);let i=C(n.readState(),t);return r.immediate&&n.invokeListener(()=>e(i)),n.addListener(n=>{let r=C(n,t);(r.value!==i.value||r.error!==i.error||r.touched!==i.touched||r.dirty!==i.dirty)&&(i=r,e(r))})},touch(){n.ensureActive(`field().touch`),n.setTouched(t,!0)},get touched(){return C(n.readState(),t).touched},get value(){return C(n.readState(),t).value}},{field(i){if(typeof i==`number`){l(i);let e=m(n.readState().value,t);if(e!==void 0&&!Array.isArray(e))throw new r(`Cannot index ${i} because the current field value is not an array.`);return w([...t,i],n)}c(i);let a=m(n.readState().value,t);if(a!==void 0&&!(0,e.isPlainObject)(a))throw new r(`Cannot select '${i}' because the current field value is not an object.`);return w([...t,i],n)}})}function T(e){queueMicrotask(()=>{throw e})}function E(e){let t=new Set,n=[],r=!1;function i(t){if(!e){T(t);return}try{e(t)}catch(e){T(e)}}let a=e=>{try{e()}catch(e){i(e)}};return{add(e){return t.add(e),()=>t.delete(e)},call:a,clear(){t.clear(),n.length=0},notify(e){if(n.push(e),!r){r=!0;try{for(;n.length>0;){let e=n.shift();for(let n of[...t])t.has(n)&&a(()=>n(e))}}finally{r=!1}}}}}function D(e){if(e!==void 0&&e.length!==0)return Object.freeze(e.map(e=>{if(!e||typeof e.message!=`string`||!Array.isArray(e.path))throw new r(`Validators must return issues with a string message and array path.`);let t=e.path.map(e=>{if(typeof e==`number`){if(!Number.isSafeInteger(e)||e<0)throw new r(`Invalid issue path index ${e}.`);return e}if(typeof e==`string`)return c(e),e;throw new r(`Issue paths may contain only string keys and non-negative integer indexes.`)});return Object.freeze({message:e.message,path:Object.freeze(t)})}))}function O(e){return Object.freeze({formError:e.issues?.find(e=>e.path.length===0)?.message,hasErrors:(e.issues?.length??0)>0,issues:e.issues,submitCount:e.submitCount,submitting:e.isSubmitting,touched:Object.keys(e.touched).length>0,validating:e.isValidating,validity:e.validity})}function k(t){let o=p(t.initialValues),s=E(t.onSubscriberError),l=new AbortController,u=!1,d=!1,f=[],h,y=0,x,S={baseline:o,isSubmitting:!1,issues:void 0,isValidating:!1,submitCount:0,touched:{},validity:`unknown`,value:o},C=O(S);function T(e){if(u)throw new n(e)}function k(e){if(f.push(e),!d){d=!0;try{for(;f.length>0;)S=Object.freeze(f.shift()(S)),C=O(S),s.notify(S)}finally{d=!1}}}function A(){h?.abort()}let j={abortValidation:A,addListener:s.add,ensureActive:T,invokeListener:s.call,readState:()=>S,resetValue(e){k(t=>(y++,x=void 0,{...t,touched:v(t.touched,e,!1),validity:`unknown`,value:_(t.value,t.baseline,e)}))},setTouched(e,t){k(n=>({...n,touched:v(n.touched,e,t)}))},setValue(e,t){k(n=>{let r=m(n.value,e),i=typeof t==`function`?t(r):t;return y++,x=void 0,{...n,validity:`unknown`,value:g(n.value,e,i)}})}};async function M(n){T(`validate`),A();let r=new AbortController,i=n?AbortSignal.any([r.signal,n]):r.signal;if(i.aborted)return Object.freeze({status:`aborted`});let o=S.value,s=y;h=r,x=void 0,k(e=>({...e,isValidating:!0}));try{if(i.aborted||y!==s)return Object.freeze({status:`aborted`});let n=t.validate?await(0,e.abortable)(Promise.resolve(t.validate(o,i)),i):void 0;if(i.aborted||h!==r||y!==s)return Object.freeze({status:`aborted`});let a=D(n),c=a===void 0?`valid`:`invalid`;return h=void 0,k(e=>({...e,issues:a,isValidating:!1,validity:c})),i.aborted||y!==s||h!==void 0?Object.freeze({status:`aborted`}):(x=c===`valid`?{revision:y,value:o}:void 0,Object.freeze(c===`valid`?{status:`valid`}:{issues:a,status:`invalid`}))}catch(e){if(i.aborted||h!==r)return Object.freeze({status:`aborted`});throw new a(`Form validation failed.`,{cause:e})}finally{h===r&&(h=void 0,u||k(e=>({...e,isValidating:!1})))}}let N={get disposalSignal(){return l.signal},dispose(){u||(u=!0,f.length=0,x=void 0,l.abort(),A(),s.clear())},get disposed(){return u},field(t){if(c(t),!(0,e.isPlainObject)(S.value))throw new r(`Form value must be an object.`);return w([t],j)},reset(e){T(`reset`),A();let t=e===void 0?void 0:p(e);k(e=>{let n=t??e.baseline;return y++,x=void 0,{...e,baseline:n,issues:void 0,touched:{},validity:`unknown`,value:n}})},set(e){T(`set`),A(),k(t=>{let n=typeof e==`function`?e(t.value):e;return y++,x=void 0,{...t,issues:void 0,validity:`unknown`,value:p(n)}})},get state(){return C},async submit(e,t){if(T(`submit`),S.isSubmitting)throw new i(`submit() called while a submission is already in progress`);let n=t?AbortSignal.any([l.signal,t]):l.signal;k(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:b(e.value)}));try{let r=await M(t);if(r.status===`aborted`)return Object.freeze({status:`aborted`});if(r.status===`invalid`)return Object.freeze({issues:r.issues,status:`invalid`});let i=x;if(!i||i.revision!==y||n.aborted)return Object.freeze({status:`aborted`});try{return Object.freeze({status:`ok`,value:await e(i.value,n)})}catch(e){if(n.aborted)return Object.freeze({status:`aborted`});throw e}}finally{u||k(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){return T(`subscribe`),t.immediate&&s.call(()=>e(C)),s.add(()=>e(C))},[Symbol.dispose](){N.dispose()},validate:M,get value(){return S.value}};return N}exports.ForgeConfigError=r,exports.ForgeDisposedError=n,exports.ForgeError=t,exports.ForgeSubmitError=i,exports.ForgeValidationError=a,exports.createForm=k;
2
2
  //# sourceMappingURL=forge.cjs.map