@vielzeug/forge 3.0.0 → 3.1.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.
@@ -1,2 +1,2 @@
1
- const e=require("../errors.cjs");let t=require("@vielzeug/arsenal");var n=new Set([`__proto__`,`constructor`,`prototype`]);function r(e){return!e||n.has(e)}function i(t){if(r(t))throw new e.ForgeConfigError(`Invalid field key '${t}'.`)}function a(t){if(!Number.isSafeInteger(t)||t<0)throw new e.ForgeConfigError(`Invalid array index ${t}.`)}function o(e){return Object.prototype.toString.call(e)}function s(e){return o(e)===`[object Blob]`||o(e)===`[object File]`}function c(){throw new e.ForgeConfigError(`Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob.`)}function l(n,r=new Set){if(n==null||typeof n==`string`||typeof n==`boolean`)return n;if(typeof n==`number`)return Number.isFinite(n)?n:c();if(typeof n!=`object`)return c();let a=n;if(o(n)===`[object Date]`&&typeof a.getTime==`function`){let e=a.getTime();return Number.isFinite(e)?Object.freeze(new Date(e)):c()}if(s(n))return n;if(r.has(n))throw new e.ForgeConfigError(`Form values must not contain circular references.`);r.add(n);try{if(Array.isArray(n)){let t=[];for(let i=0;i<n.length;i++){if(!Object.hasOwn(n,i))throw new e.ForgeConfigError(`Form arrays must not contain empty slots.`);t.push(l(n[i],r))}return Object.freeze(t)}if(!(0,t.isPlainObject)(n))return c();let a=Object.entries(n).map(([e,t])=>(i(e),[e,l(t,r)]));return Object.freeze(Object.fromEntries(a))}finally{r.delete(n)}}function u(e,n){let r=e;for(let e of n)if(typeof e==`number`){if(!Array.isArray(r)||!Number.isSafeInteger(e)||e<0||e>=r.length||!Object.hasOwn(r,e))return;r=r[e]}else{if(!(0,t.isPlainObject)(r)||!Object.hasOwn(r,e))return;r=r[e]}return r}function d(e,n){let r=e;for(let e of n)if(typeof e==`number`){if(!Array.isArray(r)||!Number.isSafeInteger(e)||e<0||e>=r.length||!Object.hasOwn(r,e))return!1;r=r[e]}else{if(!(0,t.isPlainObject)(r)||!Object.hasOwn(r,e))return!1;r=r[e]}return!0}function f(n,r,o){let[s,...c]=r;if(typeof s==`number`){if(a(s),!Array.isArray(n))throw new e.ForgeConfigError(`Cannot index ${s} because the current value is not an array.`);if(s<0||s>=n.length)throw new e.ForgeConfigError(`Index ${s} is out of range for array of length ${n.length}.`);if(c.length===0){let e=[...n];return e[s]=l(o),Object.freeze(e)}let t=[...n];return t[s]=f(n[s],c,o),Object.freeze(t)}if(i(s),!(0,t.isPlainObject)(n))throw new e.ForgeConfigError(`Cannot select '${s}' because the current value is not an object.`);if(c.length===0)return Object.freeze({...n,[s]:l(o)});let u=n[s];if(u!==void 0&&!(0,t.isPlainObject)(u)&&!Array.isArray(u))throw new e.ForgeConfigError(`Cannot select '${s}' because it is not an object or array.`);let d=u??{};return Object.freeze({...n,[s]:f(d,c,o)})}function p(e,n,r){let[i,...o]=r;if(typeof i==`number`){if(a(i),!Array.isArray(e)||!Array.isArray(n)||i>=n.length||i>=e.length)return e;if(o.length===0){let t=[...e];return t[i]=n[i],Object.freeze(t)}let t=[...e];return t[i]=p(e[i],n[i],o),Object.freeze(t)}if(!(0,t.isPlainObject)(e))return e;if(o.length===0){if(Object.hasOwn(n,i))return Object.freeze({...e,[i]:n[i]});let{[i]:t,...r}=e;return Object.freeze(r)}let s=n[i];if(!(0,t.isPlainObject)(s)&&!Array.isArray(s)){if(Object.hasOwn(n,i))return Object.freeze({...e,[i]:s});let{[i]:t,...r}=e;return Object.freeze(r)}let c=e[i],l=(0,t.isPlainObject)(c)||Array.isArray(c)?c:{};return Object.freeze({...e,[i]:p(l,s,o)})}function m(e,n,r){let[i,...o]=n;typeof i==`number`&&a(i);let s=String(i),c={...e};if(o.length===0)r?c[s]=!0:delete c[s];else{let n=m((0,t.isPlainObject)(e[s])?e[s]:{},o,r);Object.keys(n).length===0?delete c[s]:c[s]=n}return Object.freeze(c)}function h(e,n){let r=e;for(let e of n){if(typeof e==`number`&&(!Number.isSafeInteger(e)||e<0))return!1;let n=String(e);if(!(0,t.isPlainObject)(r)||!Object.hasOwn(r,n))return!1;r=r[n]}return r===!0}function g(e){return Array.isArray(e)?Object.freeze(Object.fromEntries(e.map((e,n)=>[String(n),(0,t.isPlainObject)(e)||Array.isArray(e)?g(e):!0]))):(0,t.isPlainObject)(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,n])=>[e,(0,t.isPlainObject)(n)||Array.isArray(n)?g(n):!0]))):{}}function _(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 v(e,t){if(e){for(let n of e)if(_(n.path,t))return n.message}}exports.assertArrayIndex=a,exports.assertSafeKey=i,exports.findIssue=v,exports.hasAtPath=d,exports.immutable=l,exports.isRecord=t.isPlainObject,exports.isUnsafeKey=r,exports.pathEquals=_,exports.readAtPath=u,exports.readMeta=h,exports.resetAtPath=p,exports.touchAll=g,exports.writeAtPath=f,exports.writeMeta=m;
1
+ const e=require("../errors.cjs");let t=require("@vielzeug/arsenal");var n=new Set([`__proto__`,`constructor`,`prototype`]);function r(e){return!e||n.has(e)}function i(t){if(r(t))throw new e.ForgeConfigError(`Invalid field key '${t}'.`)}function a(t){if(!Number.isSafeInteger(t)||t<0)throw new e.ForgeConfigError(`Invalid array index ${t}.`)}function o(e){return Object.prototype.toString.call(e)}function s(e){return o(e)===`[object Blob]`||o(e)===`[object File]`}function c(e){let t=``;for(let n of e)t+=typeof n==`number`?`[${n}]`:t?`.${n}`:n;return t}function l(e){return e.length>0?` at '${c(e)}'`:``}function u(t){throw new e.ForgeConfigError(`Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob${l(t)}.`)}function d(n,r=new Set,a=[]){if(n==null||typeof n==`string`||typeof n==`boolean`)return n;if(typeof n==`number`)return Number.isFinite(n)?n:u(a);if(typeof n!=`object`)return u(a);let c=n;if(o(n)===`[object Date]`&&typeof c.getTime==`function`){let e=c.getTime();return Number.isFinite(e)?Object.freeze(new Date(e)):u(a)}if(s(n))return n;if(r.has(n))throw new e.ForgeConfigError(`Form values must not contain circular references${l(a)}.`);r.add(n);try{if(Array.isArray(n)){let t=[];for(let i=0;i<n.length;i++){a.push(i);try{if(!Object.hasOwn(n,i))throw new e.ForgeConfigError(`Form arrays must not contain empty slots${l(a)}.`);t.push(d(n[i],r,a))}finally{a.pop()}}return Object.freeze(t)}if(!(0,t.isPlainObject)(n))return u(a);let o=Object.entries(n).map(([e,t])=>{i(e),a.push(e);try{return[e,d(t,r,a)]}finally{a.pop()}});return Object.freeze(Object.fromEntries(o))}finally{r.delete(n)}}function f(e,t=new WeakSet){if(e==null||typeof e==`string`||typeof e==`boolean`)return e;if(typeof e==`number`)return Number.isFinite(e)?e:void 0;if(typeof e!=`object`)return;let n=e,i=e;if(o(n)===`[object Date]`&&typeof i.getTime==`function`){let e=i.getTime();return Number.isFinite(e)?new Date(e):void 0}if(s(n))return e;if(!t.has(n)){t.add(n);try{if(Array.isArray(e)){let n=[];for(let r=0;r<e.length;r++)Object.hasOwn(e,r)&&n.push(f(e[r],t));return n}let i={};for(let[e,a]of Object.entries(n))r(e)||(i[e]=f(a,t));return i}finally{t.delete(n)}}}function p(e,n){let r=e;for(let e of n)if(typeof e==`number`){if(!Array.isArray(r)||!Number.isSafeInteger(e)||e<0||e>=r.length||!Object.hasOwn(r,e))return;r=r[e]}else{if(!(0,t.isPlainObject)(r)||!Object.hasOwn(r,e))return;r=r[e]}return r}function m(e,n){let r=e;for(let e of n)if(typeof e==`number`){if(!Array.isArray(r)||!Number.isSafeInteger(e)||e<0||e>=r.length||!Object.hasOwn(r,e))return!1;r=r[e]}else{if(!(0,t.isPlainObject)(r)||!Object.hasOwn(r,e))return!1;r=r[e]}return!0}function h(n,r,o,s=[]){let[c,...l]=r;if(typeof c==`number`){if(a(c),!Array.isArray(n))throw new e.ForgeConfigError(`Cannot index ${c} because the current value is not an array.`);if(c<0||c>=n.length)throw new e.ForgeConfigError(`Index ${c} is out of range for array of length ${n.length}.`);if(l.length===0){let e=[...n];return e[c]=d(o,new Set,[...s,c]),Object.freeze(e)}let t=[...n];return t[c]=h(n[c],l,o,[...s,c]),Object.freeze(t)}if(i(c),!(0,t.isPlainObject)(n))throw new e.ForgeConfigError(`Cannot select '${c}' because the current value is not an object.`);if(l.length===0)return Object.freeze({...n,[c]:d(o,new Set,[...s,c])});let u=n[c];if(u!==void 0&&!(0,t.isPlainObject)(u)&&!Array.isArray(u))throw new e.ForgeConfigError(`Cannot select '${c}' because it is not an object or array.`);let f=u??{};return Object.freeze({...n,[c]:h(f,l,o,[...s,c])})}function g(e,n,r){let[i,...o]=r;if(typeof i==`number`){if(a(i),!Array.isArray(e)||!Array.isArray(n)||i>=n.length||i>=e.length)return e;if(o.length===0){let t=[...e];return t[i]=n[i],Object.freeze(t)}let t=[...e];return t[i]=g(e[i],n[i],o),Object.freeze(t)}if(!(0,t.isPlainObject)(e))return e;if(o.length===0){if(Object.hasOwn(n,i))return Object.freeze({...e,[i]:n[i]});let{[i]:t,...r}=e;return Object.freeze(r)}let s=n[i];if(!(0,t.isPlainObject)(s)&&!Array.isArray(s)){if(Object.hasOwn(n,i))return Object.freeze({...e,[i]:s});let{[i]:t,...r}=e;return Object.freeze(r)}let c=e[i],l=(0,t.isPlainObject)(c)||Array.isArray(c)?c:{};return Object.freeze({...e,[i]:g(l,s,o)})}function _(e,n,r){let[i,...o]=n;typeof i==`number`&&a(i);let s=String(i),c={...e};if(o.length===0)r?c[s]=!0:delete c[s];else{let n=_((0,t.isPlainObject)(e[s])?e[s]:{},o,r);Object.keys(n).length===0?delete c[s]:c[s]=n}return Object.freeze(c)}function v(e,n){let r=e;for(let e of n){if(typeof e==`number`&&(!Number.isSafeInteger(e)||e<0))return!1;let n=String(e);if(!(0,t.isPlainObject)(r)||!Object.hasOwn(r,n))return!1;r=r[n]}return r===!0}function y(e){return Array.isArray(e)?Object.freeze(Object.fromEntries(e.map((e,n)=>[String(n),(0,t.isPlainObject)(e)||Array.isArray(e)?y(e):!0]))):(0,t.isPlainObject)(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,n])=>[e,(0,t.isPlainObject)(n)||Array.isArray(n)?y(n):!0]))):{}}function b(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 x(e,t){if(e){for(let n of e)if(b(n.path,t))return n.message}}exports.assertArrayIndex=a,exports.assertSafeKey=i,exports.findIssue=x,exports.formatValuePath=c,exports.hasAtPath=m,exports.immutable=d,exports.isRecord=t.isPlainObject,exports.isUnsafeKey=r,exports.pathEquals=b,exports.readAtPath=p,exports.readMeta=v,exports.resetAtPath=g,exports.toPlainValues=f,exports.touchAll=y,exports.writeAtPath=h,exports.writeMeta=_;
2
2
  //# sourceMappingURL=path.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"path.cjs","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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"}
1
+ {"version":3,"file":"path.cjs","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\n/** Formats a value path as `list[0].name` for error messages. */\nexport function formatValuePath(path: readonly (string | number)[]): string {\n let out = '';\n for (const segment of path) {\n if (typeof segment === 'number') out += `[${segment}]`;\n else out += out ? `.${segment}` : segment;\n }\n return out;\n}\n\nfunction pathSuffix(path: readonly (string | number)[]): string {\n return path.length > 0 ? ` at '${formatValuePath(path)}'` : '';\n}\n\nfunction invalidValue(path: readonly (string | number)[]): never {\n throw new ForgeConfigError(\n `Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob${pathSuffix(path)}.`,\n );\n}\n\nexport function immutable<T>(value: T, ancestors = new Set<object>(), path: (string | number)[] = []): 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(path);\n if (typeof value !== 'object') return invalidValue(path);\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(path);\n return Object.freeze(new Date(time)) as T;\n }\n\n if (isBlobLeaf(value)) return value;\n if (ancestors.has(value))\n throw new ForgeConfigError(`Form values must not contain circular references${pathSuffix(path)}.`);\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 path.push(index);\n try {\n if (!Object.hasOwn(value, index))\n throw new ForgeConfigError(`Form arrays must not contain empty slots${pathSuffix(path)}.`);\n copy.push(immutable(value[index], ancestors, path));\n } finally {\n path.pop();\n }\n }\n return Object.freeze(copy) as T;\n }\n\n if (!isRecord(value)) return invalidValue(path);\n const entries = Object.entries(value).map(([key, child]) => {\n assertSafeKey(key);\n path.push(key);\n try {\n return [key, immutable(child, ancestors, path)] as const;\n } finally {\n path.pop();\n }\n });\n return Object.freeze(Object.fromEntries(entries)) as T;\n } finally {\n ancestors.delete(value);\n }\n}\n\n/**\n * Deeply converts a value into the plain shape `immutable()` accepts: primitives pass\n * through, `Date` is cloned, `File`/`Blob` keep identity, arrays map, and class instances\n * flatten to their own enumerable entries. Use as the `normalize` option of `createForm`\n * to hold domain-model classes in form state.\n *\n * Lossy conversions, applied instead of the error `immutable()` would throw: `Map`, `Set`,\n * and other keyless built-ins flatten to `{}` (their entries live on the prototype); sparse\n * array slots are dropped, which shifts later indexes; `NaN`, `Infinity`, functions, and\n * circular branches become `undefined`. Normalize model classes, not arbitrary graphs.\n */\nexport function toPlainValues<T>(value: T, seen = new WeakSet<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 : (undefined as T);\n if (typeof value !== 'object') return undefined as T;\n\n const object = value as unknown as object;\n const date = value as unknown as Date;\n if (tag(object) === '[object Date]' && typeof date.getTime === 'function') {\n const time = date.getTime();\n return (Number.isFinite(time) ? new Date(time) : undefined) as T;\n }\n if (isBlobLeaf(object)) return value;\n if (seen.has(object)) return undefined as T;\n\n seen.add(object);\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)) copy.push(toPlainValues(value[index], seen));\n }\n return copy as T;\n }\n\n // Plain objects and class instances both flatten to own enumerable entries;\n // unsafe keys are dropped so the result always passes immutable()'s key checks.\n const copy: RecordValue = {};\n for (const [key, child] of Object.entries(object)) {\n if (isUnsafeKey(key)) continue;\n copy[key] = toPlainValues(child, seen);\n }\n return copy as T;\n } finally {\n seen.delete(object);\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>(\n value: T,\n path: readonly (string | number)[],\n next: unknown,\n fullPath: readonly (string | number)[] = [],\n): 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, new Set<object>(), [...fullPath, key]);\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, [...fullPath, key]);\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)\n return Object.freeze({ ...value, [key]: immutable(next, new Set<object>(), [...fullPath, key]) }) 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, [...fullPath, key]) }) 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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"}
@@ -11,10 +11,24 @@ interface MetaNode {
11
11
  export type MetaRoot = MetaNode;
12
12
  export declare function assertSafeKey(key: string): void;
13
13
  export declare function assertArrayIndex(index: number): void;
14
- export declare function immutable<T>(value: T, ancestors?: Set<object>): T;
14
+ /** Formats a value path as `list[0].name` for error messages. */
15
+ export declare function formatValuePath(path: readonly (string | number)[]): string;
16
+ export declare function immutable<T>(value: T, ancestors?: Set<object>, path?: (string | number)[]): T;
17
+ /**
18
+ * Deeply converts a value into the plain shape `immutable()` accepts: primitives pass
19
+ * through, `Date` is cloned, `File`/`Blob` keep identity, arrays map, and class instances
20
+ * flatten to their own enumerable entries. Use as the `normalize` option of `createForm`
21
+ * to hold domain-model classes in form state.
22
+ *
23
+ * Lossy conversions, applied instead of the error `immutable()` would throw: `Map`, `Set`,
24
+ * and other keyless built-ins flatten to `{}` (their entries live on the prototype); sparse
25
+ * array slots are dropped, which shifts later indexes; `NaN`, `Infinity`, functions, and
26
+ * circular branches become `undefined`. Normalize model classes, not arbitrary graphs.
27
+ */
28
+ export declare function toPlainValues<T>(value: T, seen?: WeakSet<object>): T;
15
29
  export declare function readAtPath<T>(value: unknown, path: readonly (string | number)[]): T | undefined;
16
30
  export declare function hasAtPath(value: unknown, path: readonly (string | number)[]): boolean;
17
- export declare function writeAtPath<T extends TreeValue>(value: T, path: readonly (string | number)[], next: unknown): T;
31
+ export declare function writeAtPath<T extends TreeValue>(value: T, path: readonly (string | number)[], next: unknown, fullPath?: readonly (string | number)[]): T;
18
32
  export declare function resetAtPath<T extends TreeValue>(value: T, baseline: T, path: readonly (string | number)[]): T;
19
33
  export declare function writeMeta(meta: MetaRoot, path: readonly (string | number)[], next: boolean): MetaRoot;
20
34
  export declare function readMeta(meta: MetaRoot, path: readonly (string | number)[]): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/core/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC3C,KAAK,SAAS,GAAG,WAAW,GAAG,SAAS,OAAO,EAAE,CAAC;AAClD,KAAK,QAAQ,GAAG,IAAI,GAAG,QAAQ,CAAC;AAChC,UAAU,QAAQ;IAChB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC;AACD,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAEhC,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEpD;AAgBD,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,cAAoB,GAAG,CAAC,CAmCvE;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,SAAS,CAuB/F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAuBrF;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC,CA6C/G;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,CA+C7G;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAkBrG;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAapF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAsBjD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAQpG;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CACvB,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,EAC9C,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GACjC,MAAM,GAAG,SAAS,CAQpB"}
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/core/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC3C,KAAK,SAAS,GAAG,WAAW,GAAG,SAAS,OAAO,EAAE,CAAC;AAClD,KAAK,QAAQ,GAAG,IAAI,GAAG,QAAQ,CAAC;AAChC,UAAU,QAAQ;IAChB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC;AACD,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAEhC,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEpD;AAUD,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAO1E;AAYD,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,cAAoB,EAAE,IAAI,GAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAO,GAAG,CAAC,CA+CvG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,kBAAwB,GAAG,CAAC,CAmC1E;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,SAAS,CAuB/F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAuBrF;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAC7C,KAAK,EAAE,CAAC,EACR,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAClC,IAAI,EAAE,OAAO,EACb,QAAQ,GAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAO,GAC1C,CAAC,CA8CH;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,CA+C7G;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAkBrG;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAapF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAsBjD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAQpG;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CACvB,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,EAC9C,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GACjC,MAAM,GAAG,SAAS,CAQpB"}
package/dist/core/path.js CHANGED
@@ -21,38 +21,84 @@ function o(e) {
21
21
  function s(e) {
22
22
  return o(e) === "[object Blob]" || o(e) === "[object File]";
23
23
  }
24
- function c() {
25
- throw new e("Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob.");
24
+ function c(e) {
25
+ let t = "";
26
+ for (let n of e) t += typeof n == "number" ? `[${n}]` : t ? `.${n}` : n;
27
+ return t;
26
28
  }
27
- function l(n, r = /* @__PURE__ */ new Set()) {
29
+ function l(e) {
30
+ return e.length > 0 ? ` at '${c(e)}'` : "";
31
+ }
32
+ function u(t) {
33
+ throw new e(`Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob${l(t)}.`);
34
+ }
35
+ function d(n, r = /* @__PURE__ */ new Set(), a = []) {
28
36
  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();
37
+ if (typeof n == "number") return Number.isFinite(n) ? n : u(a);
38
+ if (typeof n != "object") return u(a);
39
+ let c = n;
40
+ if (o(n) === "[object Date]" && typeof c.getTime == "function") {
41
+ let e = c.getTime();
42
+ return Number.isFinite(e) ? Object.freeze(new Date(e)) : u(a);
35
43
  }
36
44
  if (s(n)) return n;
37
- if (r.has(n)) throw new e("Form values must not contain circular references.");
45
+ if (r.has(n)) throw new e(`Form values must not contain circular references${l(a)}.`);
38
46
  r.add(n);
39
47
  try {
40
48
  if (Array.isArray(n)) {
41
49
  let t = [];
42
50
  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));
51
+ a.push(i);
52
+ try {
53
+ if (!Object.hasOwn(n, i)) throw new e(`Form arrays must not contain empty slots${l(a)}.`);
54
+ t.push(d(n[i], r, a));
55
+ } finally {
56
+ a.pop();
57
+ }
45
58
  }
46
59
  return Object.freeze(t);
47
60
  }
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));
61
+ if (!t(n)) return u(a);
62
+ let o = Object.entries(n).map(([e, t]) => {
63
+ i(e), a.push(e);
64
+ try {
65
+ return [e, d(t, r, a)];
66
+ } finally {
67
+ a.pop();
68
+ }
69
+ });
70
+ return Object.freeze(Object.fromEntries(o));
51
71
  } finally {
52
72
  r.delete(n);
53
73
  }
54
74
  }
55
- function u(e, n) {
75
+ function f(e, t = /* @__PURE__ */ new WeakSet()) {
76
+ if (e == null || typeof e == "string" || typeof e == "boolean") return e;
77
+ if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
78
+ if (typeof e != "object") return;
79
+ let n = e, i = e;
80
+ if (o(n) === "[object Date]" && typeof i.getTime == "function") {
81
+ let e = i.getTime();
82
+ return Number.isFinite(e) ? new Date(e) : void 0;
83
+ }
84
+ if (s(n)) return e;
85
+ if (!t.has(n)) {
86
+ t.add(n);
87
+ try {
88
+ if (Array.isArray(e)) {
89
+ let n = [];
90
+ for (let r = 0; r < e.length; r++) Object.hasOwn(e, r) && n.push(f(e[r], t));
91
+ return n;
92
+ }
93
+ let i = {};
94
+ for (let [e, a] of Object.entries(n)) r(e) || (i[e] = f(a, t));
95
+ return i;
96
+ } finally {
97
+ t.delete(n);
98
+ }
99
+ }
100
+ }
101
+ function p(e, n) {
56
102
  let r = e;
57
103
  for (let e of n) if (typeof e == "number") {
58
104
  if (!Array.isArray(r) || !Number.isSafeInteger(e) || e < 0 || e >= r.length || !Object.hasOwn(r, e)) return;
@@ -63,7 +109,7 @@ function u(e, n) {
63
109
  }
64
110
  return r;
65
111
  }
66
- function d(e, n) {
112
+ function m(e, n) {
67
113
  let r = e;
68
114
  for (let e of n) if (typeof e == "number") {
69
115
  if (!Array.isArray(r) || !Number.isSafeInteger(e) || e < 0 || e >= r.length || !Object.hasOwn(r, e)) return !1;
@@ -74,32 +120,32 @@ function d(e, n) {
74
120
  }
75
121
  return !0;
76
122
  }
77
- function f(n, r, o) {
78
- let [s, ...c] = r;
79
- if (typeof s == "number") {
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}.`);
82
- if (c.length === 0) {
123
+ function h(n, r, o, s = []) {
124
+ let [c, ...l] = r;
125
+ if (typeof c == "number") {
126
+ if (a(c), !Array.isArray(n)) throw new e(`Cannot index ${c} because the current value is not an array.`);
127
+ if (c < 0 || c >= n.length) throw new e(`Index ${c} is out of range for array of length ${n.length}.`);
128
+ if (l.length === 0) {
83
129
  let e = [...n];
84
- return e[s] = l(o), Object.freeze(e);
130
+ return e[c] = d(o, /* @__PURE__ */ new Set(), [...s, c]), Object.freeze(e);
85
131
  }
86
132
  let t = [...n];
87
- return t[s] = f(n[s], c, o), Object.freeze(t);
133
+ return t[c] = h(n[c], l, o, [...s, c]), Object.freeze(t);
88
134
  }
89
- if (i(s), !t(n)) throw new e(`Cannot select '${s}' because the current value is not an object.`);
90
- if (c.length === 0) return Object.freeze({
135
+ if (i(c), !t(n)) throw new e(`Cannot select '${c}' because the current value is not an object.`);
136
+ if (l.length === 0) return Object.freeze({
91
137
  ...n,
92
- [s]: l(o)
138
+ [c]: d(o, /* @__PURE__ */ new Set(), [...s, c])
93
139
  });
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.`);
96
- let d = u ?? {};
140
+ let u = n[c];
141
+ if (u !== void 0 && !t(u) && !Array.isArray(u)) throw new e(`Cannot select '${c}' because it is not an object or array.`);
142
+ let f = u ?? {};
97
143
  return Object.freeze({
98
144
  ...n,
99
- [s]: f(d, c, o)
145
+ [c]: h(f, l, o, [...s, c])
100
146
  });
101
147
  }
102
- function p(e, n, r) {
148
+ function g(e, n, r) {
103
149
  let [i, ...o] = r;
104
150
  if (typeof i == "number") {
105
151
  if (a(i), !Array.isArray(e) || !Array.isArray(n) || i >= n.length || i >= e.length) return e;
@@ -108,7 +154,7 @@ function p(e, n, r) {
108
154
  return t[i] = n[i], Object.freeze(t);
109
155
  }
110
156
  let t = [...e];
111
- return t[i] = p(e[i], n[i], o), Object.freeze(t);
157
+ return t[i] = g(e[i], n[i], o), Object.freeze(t);
112
158
  }
113
159
  if (!t(e)) return e;
114
160
  if (o.length === 0) {
@@ -131,21 +177,21 @@ function p(e, n, r) {
131
177
  let c = e[i], l = t(c) || Array.isArray(c) ? c : {};
132
178
  return Object.freeze({
133
179
  ...e,
134
- [i]: p(l, s, o)
180
+ [i]: g(l, s, o)
135
181
  });
136
182
  }
137
- function m(e, n, r) {
183
+ function _(e, n, r) {
138
184
  let [i, ...o] = n;
139
185
  typeof i == "number" && a(i);
140
186
  let s = String(i), c = { ...e };
141
187
  if (o.length === 0) r ? c[s] = !0 : delete c[s];
142
188
  else {
143
- let n = m(t(e[s]) ? e[s] : {}, o, r);
189
+ let n = _(t(e[s]) ? e[s] : {}, o, r);
144
190
  Object.keys(n).length === 0 ? delete c[s] : c[s] = n;
145
191
  }
146
192
  return Object.freeze(c);
147
193
  }
148
- function h(e, n) {
194
+ function v(e, n) {
149
195
  let r = e;
150
196
  for (let e of n) {
151
197
  if (typeof e == "number" && (!Number.isSafeInteger(e) || e < 0)) return !1;
@@ -155,20 +201,20 @@ function h(e, n) {
155
201
  }
156
202
  return r === !0;
157
203
  }
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]))) : {};
204
+ function y(e) {
205
+ return Array.isArray(e) ? Object.freeze(Object.fromEntries(e.map((e, n) => [String(n), t(e) || Array.isArray(e) ? y(e) : !0]))) : t(e) ? Object.freeze(Object.fromEntries(Object.entries(e).map(([e, n]) => [e, t(n) || Array.isArray(n) ? y(n) : !0]))) : {};
160
206
  }
161
- function _(e, t) {
207
+ function b(e, t) {
162
208
  if (e.length !== t.length) return !1;
163
209
  for (let n = 0; n < e.length; n++) if (e[n] !== t[n]) return !1;
164
210
  return !0;
165
211
  }
166
- function v(e, t) {
212
+ function x(e, t) {
167
213
  if (e) {
168
- for (let n of e) if (_(n.path, t)) return n.message;
214
+ for (let n of e) if (b(n.path, t)) return n.message;
169
215
  }
170
216
  }
171
217
  //#endregion
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 };
218
+ export { a as assertArrayIndex, i as assertSafeKey, x as findIssue, c as formatValuePath, m as hasAtPath, d as immutable, t as isRecord, r as isUnsafeKey, b as pathEquals, p as readAtPath, v as readMeta, g as resetAtPath, f as toPlainValues, y as touchAll, h as writeAtPath, _ as writeMeta };
173
219
 
174
220
  //# sourceMappingURL=path.js.map
@@ -1 +1 @@
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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"}
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\n/** Formats a value path as `list[0].name` for error messages. */\nexport function formatValuePath(path: readonly (string | number)[]): string {\n let out = '';\n for (const segment of path) {\n if (typeof segment === 'number') out += `[${segment}]`;\n else out += out ? `.${segment}` : segment;\n }\n return out;\n}\n\nfunction pathSuffix(path: readonly (string | number)[]): string {\n return path.length > 0 ? ` at '${formatValuePath(path)}'` : '';\n}\n\nfunction invalidValue(path: readonly (string | number)[]): never {\n throw new ForgeConfigError(\n `Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob${pathSuffix(path)}.`,\n );\n}\n\nexport function immutable<T>(value: T, ancestors = new Set<object>(), path: (string | number)[] = []): 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(path);\n if (typeof value !== 'object') return invalidValue(path);\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(path);\n return Object.freeze(new Date(time)) as T;\n }\n\n if (isBlobLeaf(value)) return value;\n if (ancestors.has(value))\n throw new ForgeConfigError(`Form values must not contain circular references${pathSuffix(path)}.`);\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 path.push(index);\n try {\n if (!Object.hasOwn(value, index))\n throw new ForgeConfigError(`Form arrays must not contain empty slots${pathSuffix(path)}.`);\n copy.push(immutable(value[index], ancestors, path));\n } finally {\n path.pop();\n }\n }\n return Object.freeze(copy) as T;\n }\n\n if (!isRecord(value)) return invalidValue(path);\n const entries = Object.entries(value).map(([key, child]) => {\n assertSafeKey(key);\n path.push(key);\n try {\n return [key, immutable(child, ancestors, path)] as const;\n } finally {\n path.pop();\n }\n });\n return Object.freeze(Object.fromEntries(entries)) as T;\n } finally {\n ancestors.delete(value);\n }\n}\n\n/**\n * Deeply converts a value into the plain shape `immutable()` accepts: primitives pass\n * through, `Date` is cloned, `File`/`Blob` keep identity, arrays map, and class instances\n * flatten to their own enumerable entries. Use as the `normalize` option of `createForm`\n * to hold domain-model classes in form state.\n *\n * Lossy conversions, applied instead of the error `immutable()` would throw: `Map`, `Set`,\n * and other keyless built-ins flatten to `{}` (their entries live on the prototype); sparse\n * array slots are dropped, which shifts later indexes; `NaN`, `Infinity`, functions, and\n * circular branches become `undefined`. Normalize model classes, not arbitrary graphs.\n */\nexport function toPlainValues<T>(value: T, seen = new WeakSet<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 : (undefined as T);\n if (typeof value !== 'object') return undefined as T;\n\n const object = value as unknown as object;\n const date = value as unknown as Date;\n if (tag(object) === '[object Date]' && typeof date.getTime === 'function') {\n const time = date.getTime();\n return (Number.isFinite(time) ? new Date(time) : undefined) as T;\n }\n if (isBlobLeaf(object)) return value;\n if (seen.has(object)) return undefined as T;\n\n seen.add(object);\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)) copy.push(toPlainValues(value[index], seen));\n }\n return copy as T;\n }\n\n // Plain objects and class instances both flatten to own enumerable entries;\n // unsafe keys are dropped so the result always passes immutable()'s key checks.\n const copy: RecordValue = {};\n for (const [key, child] of Object.entries(object)) {\n if (isUnsafeKey(key)) continue;\n copy[key] = toPlainValues(child, seen);\n }\n return copy as T;\n } finally {\n seen.delete(object);\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>(\n value: T,\n path: readonly (string | number)[],\n next: unknown,\n fullPath: readonly (string | number)[] = [],\n): 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, new Set<object>(), [...fullPath, key]);\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, [...fullPath, key]);\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)\n return Object.freeze({ ...value, [key]: immutable(next, new Set<object>(), [...fullPath, key]) }) 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, [...fullPath, key]) }) 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/forge.cjs CHANGED
@@ -1,2 +1,2 @@
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;
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(e){let t=``;for(let n of e)t+=typeof n==`number`?`[${n}]`:t?`.${n}`:n;return t}function p(e){return e.length>0?` at '${f(e)}'`:``}function m(e){throw new r(`Form values must contain only finite JSON primitives, plain objects, arrays, Date, File, or Blob${p(e)}.`)}function h(t,n=new Set,i=[]){if(t==null||typeof t==`string`||typeof t==`boolean`)return t;if(typeof t==`number`)return Number.isFinite(t)?t:m(i);if(typeof t!=`object`)return m(i);let a=t;if(u(t)===`[object Date]`&&typeof a.getTime==`function`){let e=a.getTime();return Number.isFinite(e)?Object.freeze(new Date(e)):m(i)}if(d(t))return t;if(n.has(t))throw new r(`Form values must not contain circular references${p(i)}.`);n.add(t);try{if(Array.isArray(t)){let e=[];for(let a=0;a<t.length;a++){i.push(a);try{if(!Object.hasOwn(t,a))throw new r(`Form arrays must not contain empty slots${p(i)}.`);e.push(h(t[a],n,i))}finally{i.pop()}}return Object.freeze(e)}if(!(0,e.isPlainObject)(t))return m(i);let a=Object.entries(t).map(([e,t])=>{c(e),i.push(e);try{return[e,h(t,n,i)]}finally{i.pop()}});return Object.freeze(Object.fromEntries(a))}finally{n.delete(t)}}function g(e,t=new WeakSet){if(e==null||typeof e==`string`||typeof e==`boolean`)return e;if(typeof e==`number`)return Number.isFinite(e)?e:void 0;if(typeof e!=`object`)return;let n=e,r=e;if(u(n)===`[object Date]`&&typeof r.getTime==`function`){let e=r.getTime();return Number.isFinite(e)?new Date(e):void 0}if(d(n))return e;if(!t.has(n)){t.add(n);try{if(Array.isArray(e)){let n=[];for(let r=0;r<e.length;r++)Object.hasOwn(e,r)&&n.push(g(e[r],t));return n}let r={};for(let[e,i]of Object.entries(n))s(e)||(r[e]=g(i,t));return r}finally{t.delete(n)}}}function _(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 v(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 y(t,n,i,a=[]){let[o,...s]=n;if(typeof o==`number`){if(l(o),!Array.isArray(t))throw new r(`Cannot index ${o} because the current value is not an array.`);if(o<0||o>=t.length)throw new r(`Index ${o} is out of range for array of length ${t.length}.`);if(s.length===0){let e=[...t];return e[o]=h(i,new Set,[...a,o]),Object.freeze(e)}let e=[...t];return e[o]=y(t[o],s,i,[...a,o]),Object.freeze(e)}if(c(o),!(0,e.isPlainObject)(t))throw new r(`Cannot select '${o}' because the current value is not an object.`);if(s.length===0)return Object.freeze({...t,[o]:h(i,new Set,[...a,o])});let u=t[o];if(u!==void 0&&!(0,e.isPlainObject)(u)&&!Array.isArray(u))throw new r(`Cannot select '${o}' because it is not an object or array.`);let d=u??{};return Object.freeze({...t,[o]:y(d,s,i,[...a,o])})}function b(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]=b(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]:b(c,o,a)})}function x(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=x((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 S(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 C(t){return Array.isArray(t)?Object.freeze(Object.fromEntries(t.map((t,n)=>[String(n),(0,e.isPlainObject)(t)||Array.isArray(t)?C(t):!0]))):(0,e.isPlainObject)(t)?Object.freeze(Object.fromEntries(Object.entries(t).map(([t,n])=>[t,(0,e.isPlainObject)(n)||Array.isArray(n)?C(n):!0]))):{}}function w(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 T(e,t){if(e){for(let n of e)if(w(n.path,t))return n.message}}function E(t,n){let r=_(t.value,n),i=_(t.baseline,n);return Object.freeze({dirty:!(0,e.isEqual)(r,i)||v(t.value,n)!==v(t.baseline,n),error:T(t.issues,n),touched:S(t.touched,n),value:r})}function D(t,n){return Object.assign({get dirty(){return E(n.readState(),t).dirty},get error(){return E(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 E(n.readState(),t)},subscribe(e,r={}){n.ensureActive(`field().subscribe`);let i=E(n.readState(),t);return r.immediate&&n.invokeListener(()=>e(i)),n.addListener(n=>{let r=E(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 E(n.readState(),t).touched},get value(){return E(n.readState(),t).value}},{field(i){if(typeof i==`number`){l(i);let e=_(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 D([...t,i],n)}c(i);let a=_(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 D([...t,i],n)}})}function O(e){queueMicrotask(()=>{throw e})}function k(e){let t=new Set,n=[],r=!1;function i(t){if(!e){O(t);return}try{e(t)}catch(e){O(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 A(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 j(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 M(t){let o=t.normalize,s=e=>o?o(e):e,l=h(s(t.initialValues)),u=k(t.onSubscriberError),d=new AbortController,f=!1,p=!1,m=[],g,v=0,S,w={baseline:l,isSubmitting:!1,issues:void 0,isValidating:!1,submitCount:0,touched:{},validity:`unknown`,value:l},T=j(w);function E(e){if(f)throw new n(e)}function O(e){if(m.push(e),!p){p=!0;try{for(;m.length>0;)w=Object.freeze(m.shift()(w)),T=j(w),u.notify(w)}finally{p=!1}}}function M(){g?.abort()}let N={abortValidation:M,addListener:u.add,ensureActive:E,invokeListener:u.call,readState:()=>w,resetValue(e){O(t=>(v++,S=void 0,{...t,touched:x(t.touched,e,!1),validity:`unknown`,value:b(t.value,t.baseline,e)}))},setTouched(e,t){O(n=>({...n,touched:x(n.touched,e,t)}))},setValue(e,t){O(n=>{let r=_(n.value,e),i=typeof t==`function`?t(r):t,a=s(i);return v++,S=void 0,{...n,validity:`unknown`,value:y(n.value,e,a)}})}};async function P(n){E(`validate`),M();let r=new AbortController,i=n?AbortSignal.any([r.signal,n]):r.signal;if(i.aborted)return Object.freeze({status:`aborted`});let o=w.value,s=v;g=r,S=void 0,O(e=>({...e,isValidating:!0}));try{if(i.aborted||v!==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||g!==r||v!==s)return Object.freeze({status:`aborted`});let a=A(n),c=a===void 0?`valid`:`invalid`;return g=void 0,O(e=>({...e,issues:a,isValidating:!1,validity:c})),i.aborted||v!==s||g!==void 0?Object.freeze({status:`aborted`}):(S=c===`valid`?{revision:v,value:o}:void 0,Object.freeze(c===`valid`?{status:`valid`}:{issues:a,status:`invalid`}))}catch(e){if(i.aborted||g!==r)return Object.freeze({status:`aborted`});throw new a(`Form validation failed.`,{cause:e})}finally{g===r&&(g=void 0,f||O(e=>({...e,isValidating:!1})))}}let F={get disposalSignal(){return d.signal},dispose(){f||(f=!0,m.length=0,S=void 0,d.abort(),M(),u.clear())},get disposed(){return f},field(t){if(c(t),!(0,e.isPlainObject)(w.value))throw new r(`Form value must be an object.`);return D([t],N)},patch(e){E(`patch`),M(),O(t=>{let n=typeof e==`function`?e(t.value):e,r={...t.value,...n};return v++,S=void 0,{...t,issues:void 0,validity:`unknown`,value:h(s(r))}})},reset(e){E(`reset`),M();let t=e===void 0?void 0:h(s(e));O(e=>{let n=t??e.baseline;return v++,S=void 0,{...e,baseline:n,issues:void 0,touched:{},validity:`unknown`,value:n}})},set(e){E(`set`),M(),O(t=>{let n=typeof e==`function`?e(t.value):e;return v++,S=void 0,{...t,issues:void 0,validity:`unknown`,value:h(s(n))}})},get state(){return T},async submit(e,t){if(E(`submit`),w.isSubmitting)throw new i(`submit() called while a submission is already in progress`);let n=t?AbortSignal.any([d.signal,t]):d.signal;O(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:C(e.value)}));try{let r=await P(t);if(r.status===`aborted`)return Object.freeze({status:`aborted`});if(r.status===`invalid`)return Object.freeze({issues:r.issues,status:`invalid`});let i=S;if(!i||i.revision!==v||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{f||O(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){return E(`subscribe`),t.immediate&&u.call(()=>e(T)),u.add(()=>e(T))},[Symbol.dispose](){F.dispose()},validate:P,get value(){return w.value}};return F}function N(e){return g(e)}exports.ForgeConfigError=r,exports.ForgeDisposedError=n,exports.ForgeError=t,exports.ForgeSubmitError=i,exports.ForgeValidationError=a,exports.createForm=M,exports.toPlainValues=N;
2
2
  //# sourceMappingURL=forge.cjs.map