@vielzeug/forge 2.3.0 → 2.3.1

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");var t=new Set([`__proto__`,`constructor`,`prototype`]);function n(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function r(n){if(!n||t.has(n))throw new e.ForgeConfigError(`Invalid field key '${n}'.`)}function i(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File||e instanceof Date}function a(t){if(Array.isArray(t))return Object.freeze(t.map(a));if(typeof t!=`object`||!t||i(t))return t;if(!n(t))throw new e.ForgeConfigError(`Form values must contain only plain objects, arrays, Date, File, Blob, or primitive values.`);return Object.freeze(Object.fromEntries(Object.entries(t).map(([e,t])=>[e,a(t)])))}function o(e,t){let r=e;for(let e of t)if(typeof e==`number`){if(!Array.isArray(r)||e<0||e>=r.length)return;r=r[e]}else{if(!n(r)||!Object.hasOwn(r,e))return;r=r[e]}return r}function s(e,t){let r=e;for(let e of t)if(typeof e==`number`){if(!Array.isArray(r)||e<0||e>=r.length)return!1;r=r[e]}else{if(!n(r)||!Object.hasOwn(r,e))return!1;r=r[e]}return!0}function c(t,i,o){let[s,...l]=i;if(typeof s==`number`){if(!Array.isArray(t))throw new e.ForgeConfigError(`Cannot index ${s} because the current value is not an array.`);if(s<0||s>=t.length)throw new e.ForgeConfigError(`Index ${s} is out of range for array of length ${t.length}.`);if(l.length===0){let e=[...t];return e[s]=a(o),Object.freeze(e)}let n=[...t];return n[s]=c(t[s],l,o),Object.freeze(n)}if(r(s),!n(t))throw new e.ForgeConfigError(`Cannot select '${s}' because the current value is not an object.`);if(l.length===0)return Object.freeze({...t,[s]:a(o)});let u=t[s];if(u!==void 0&&!n(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({...t,[s]:c(d,l,o)})}function l(e,t,r){let[i,...a]=r;if(typeof i==`number`){if(!Array.isArray(e)||!Array.isArray(t)||i>=t.length||i>=e.length)return e;if(a.length===0){let n=[...e];return n[i]=t[i],Object.freeze(n)}let n=[...e];return n[i]=l(e[i],t[i],a),Object.freeze(n)}if(!n(e))return e;if(a.length===0){if(Object.hasOwn(t,i))return Object.freeze({...e,[i]:t[i]});let{[i]:n,...r}=e;return Object.freeze(r)}let o=t[i];if(!n(o)&&!Array.isArray(o)){if(Object.hasOwn(t,i))return Object.freeze({...e,[i]:o});let{[i]:n,...r}=e;return Object.freeze(r)}let s=e[i],c=n(s)||Array.isArray(s)?s:{};return Object.freeze({...e,[i]:l(c,o,a)})}function u(e,t,r){let[i,...a]=t,o=String(i),s={...e};if(a.length===0)r?s[o]=!0:delete s[o];else{let t=u(n(e[o])?e[o]:{},a,r);Object.keys(t).length===0?delete s[o]:s[o]=t}return Object.freeze(s)}function d(e,t){let r=e;for(let e of t){let t=String(e);if(!n(r)||!Object.hasOwn(r,t))return!1;r=r[t]}return r===!0}function f(e){return Array.isArray(e)?Object.freeze(Object.fromEntries(e.map((e,t)=>[String(t),n(e)||Array.isArray(e)?f(e):!0]))):n(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,n(t)||Array.isArray(t)?f(t):!0]))):{}}function p(e,t){let n=o(e,t);return typeof n==`string`?n:void 0}function m(e,r,i){let[a,...o]=r;if(typeof a==`number`){let t=Array.isArray(e)?[...e]:[];return o.length===0?t[a]===void 0&&(t[a]=i):t[a]=m(t[a],o,i),t}if(!a||t.has(a))return e??{};let s=n(e)?{...e}:{};return o.length===0?s[a]===void 0&&(s[a]=i):s[a]=m(s[a],o,i),s}function h(e,t,r){let i=m(e,t,r);return n(i)?i:e}function g(e){if(typeof e==`string`)return e;if(Array.isArray(e)){let t=e.map(e=>g(e));return t.every(e=>e===void 0)?void 0:Object.freeze(t)}if(!n(e))return;let t=Object.entries(e).map(([e,t])=>[e,g(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}exports.assertSafeKey=r,exports.hasAtPath=s,exports.immutable=a,exports.isRecord=n,exports.normalizeErrors=g,exports.readAtPath=o,exports.readError=p,exports.readMeta=d,exports.resetAtPath=l,exports.touchAll=f,exports.writeAtPath=c,exports.writeError=h,exports.writeMeta=u;
1
+ const e=require("../errors.cjs");var t=new Set([`__proto__`,`constructor`,`prototype`]);function n(e){return!e||t.has(e)}function r(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function i(t){if(n(t))throw new e.ForgeConfigError(`Invalid field key '${t}'.`)}function a(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File||e instanceof Date}function o(t){if(Array.isArray(t))return Object.freeze(t.map(o));if(typeof t!=`object`||!t||a(t))return t;if(!r(t))throw new e.ForgeConfigError(`Form values must contain only plain objects, arrays, Date, File, Blob, or primitive values.`);return Object.freeze(Object.fromEntries(Object.entries(t).map(([e,t])=>[e,o(t)])))}function s(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(!r(n)||!Object.hasOwn(n,e))return;n=n[e]}return n}function c(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(!r(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return!0}function l(t,n,a){let[s,...c]=n;if(typeof s==`number`){if(!Array.isArray(t))throw new e.ForgeConfigError(`Cannot index ${s} because the current value is not an array.`);if(s<0||s>=t.length)throw new e.ForgeConfigError(`Index ${s} is out of range for array of length ${t.length}.`);if(c.length===0){let e=[...t];return e[s]=o(a),Object.freeze(e)}let n=[...t];return n[s]=l(t[s],c,a),Object.freeze(n)}if(i(s),!r(t))throw new e.ForgeConfigError(`Cannot select '${s}' because the current value is not an object.`);if(c.length===0)return Object.freeze({...t,[s]:o(a)});let u=t[s];if(u!==void 0&&!r(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({...t,[s]:l(d,c,a)})}function u(e,t,n){let[i,...a]=n;if(typeof i==`number`){if(!Array.isArray(e)||!Array.isArray(t)||i>=t.length||i>=e.length)return e;if(a.length===0){let n=[...e];return n[i]=t[i],Object.freeze(n)}let n=[...e];return n[i]=u(e[i],t[i],a),Object.freeze(n)}if(!r(e))return e;if(a.length===0){if(Object.hasOwn(t,i))return Object.freeze({...e,[i]:t[i]});let{[i]:n,...r}=e;return Object.freeze(r)}let o=t[i];if(!r(o)&&!Array.isArray(o)){if(Object.hasOwn(t,i))return Object.freeze({...e,[i]:o});let{[i]:n,...r}=e;return Object.freeze(r)}let s=e[i],c=r(s)||Array.isArray(s)?s:{};return Object.freeze({...e,[i]:u(c,o,a)})}function d(e,t,n){let[i,...a]=t,o=String(i),s={...e};if(a.length===0)n?s[o]=!0:delete s[o];else{let t=d(r(e[o])?e[o]:{},a,n);Object.keys(t).length===0?delete s[o]:s[o]=t}return Object.freeze(s)}function f(e,t){let n=e;for(let e of t){let t=String(e);if(!r(n)||!Object.hasOwn(n,t))return!1;n=n[t]}return n===!0}function p(e){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]))):{}}function m(e,t){let n=s(e,t);return typeof n==`string`?n:void 0}function h(e,t,i){let[a,...o]=t;if(typeof a==`number`){let t=Array.isArray(e)?[...e]:[];return o.length===0?t[a]===void 0&&(t[a]=i):t[a]=h(t[a],o,i),t}if(n(a))return e??{};let s=r(e)?{...e}:{};return o.length===0?s[a]===void 0&&(s[a]=i):s[a]=h(s[a],o,i),s}function g(e,t,n){let i=h(e,t,n);return r(i)?i:e}function _(e){if(typeof e==`string`)return e;if(Array.isArray(e)){let t=e.map(e=>_(e));return t.every(e=>e===void 0)?void 0:Object.freeze(t)}if(!r(e))return;let t=Object.entries(e).map(([e,t])=>[e,_(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}exports.assertSafeKey=i,exports.hasAtPath=c,exports.immutable=o,exports.isRecord=r,exports.isUnsafeKey=n,exports.normalizeErrors=_,exports.readAtPath=s,exports.readError=m,exports.readMeta=f,exports.resetAtPath=u,exports.touchAll=p,exports.writeAtPath=l,exports.writeError=g,exports.writeMeta=d;
2
2
  //# sourceMappingURL=path.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"path.cjs","names":[],"sources":["../../src/core/path.ts"],"sourcesContent":["import { ForgeConfigError } from '../errors';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\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 (!key || unsafeKeys.has(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 (!key || unsafeKeys.has(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.cjs","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":"iCAEA,IAAM,EAAa,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAEpE,SAAgB,EAAY,EAAsB,CAChD,MAAO,CAAC,GAAO,EAAW,IAAI,CAAG,CACnC,CAgBA,SAAgB,EAAS,EAAsC,CAC7D,GAAsB,OAAO,GAAU,WAAnC,GAA+C,MAAM,QAAQ,CAAK,EAAG,MAAO,GAEhF,IAAM,EAAY,OAAO,eAAe,CAAK,EAE7C,OAAO,IAAc,OAAO,WAAa,IAAc,IACzD,CAEA,SAAgB,EAAc,EAAmB,CAC/C,GAAI,EAAY,CAAG,EAAG,MAAM,IAAI,EAAA,iBAAiB,sBAAsB,EAAI,GAAG,CAChF,CAEA,SAAS,EAAa,EAAyB,CAC7C,OACG,OAAO,KAAS,KAAe,aAAiB,MAChD,OAAO,KAAS,KAAe,aAAiB,MACjD,aAAiB,IAErB,CAEA,SAAgB,EAAa,EAAa,CACxC,GAAI,MAAM,QAAQ,CAAK,EAAG,OAAO,OAAO,OAAO,EAAM,IAAI,CAAS,CAAC,EAEnE,GAAsB,OAAO,GAAU,WAAnC,GAA+C,EAAa,CAAK,EAAG,OAAO,EAE/E,GAAI,CAAC,EAAS,CAAK,EACjB,MAAM,IAAI,EAAA,iBACR,6FACF,EAGF,OAAO,OAAO,OAAO,OAAO,YAAY,OAAO,QAAQ,CAAK,CAAC,CAAC,KAAK,CAAC,EAAK,KAAW,CAAC,EAAK,EAAU,CAAK,CAAC,CAAC,CAAC,CAAC,CAC/G,CAEA,SAAgB,EAAc,EAAgB,EAAmD,CAC/F,IAAI,EAAmB,EAEvB,IAAK,IAAM,KAAO,EAChB,GAAI,OAAO,GAAQ,SAAU,CAC3B,GAAI,CAAC,MAAM,QAAQ,CAAO,GAAK,EAAM,GAAK,GAAO,EAAQ,OAAQ,OAEjE,EAAU,EAAQ,EACpB,KAAO,CACL,GAAI,CAAC,EAAS,CAAO,GAAK,CAAC,OAAO,OAAO,EAAS,CAAG,EAAG,OAExD,EAAU,EAAQ,EACpB,CAGF,OAAO,CACT,CAEA,SAAgB,EAAU,EAAgB,EAA6C,CACrF,IAAI,EAAmB,EAEvB,IAAK,IAAM,KAAO,EAChB,GAAI,OAAO,GAAQ,SAAU,CAC3B,GAAI,CAAC,MAAM,QAAQ,CAAO,GAAK,EAAM,GAAK,GAAO,EAAQ,OAAQ,MAAO,GAExE,EAAU,EAAQ,EACpB,KAAO,CACL,GAAI,CAAC,EAAS,CAAO,GAAK,CAAC,OAAO,OAAO,EAAS,CAAG,EAAG,MAAO,GAE/D,EAAU,EAAQ,EACpB,CAGF,MAAO,EACT,CAEA,SAAgB,EAAiC,EAAU,EAAoC,EAAkB,CAC/G,GAAM,CAAC,EAAK,GAAG,GAAQ,EAEvB,GAAI,OAAO,GAAQ,SAAU,CAC3B,GAAI,CAAC,MAAM,QAAQ,CAAK,EACtB,MAAM,IAAI,EAAA,iBAAiB,gBAAgB,EAAI,4CAA4C,EAG7F,GAAI,EAAM,GAAK,GAAO,EAAM,OAC1B,MAAM,IAAI,EAAA,iBAAiB,SAAS,EAAI,uCAAuC,EAAM,OAAO,EAAE,EAGhG,GAAI,EAAK,SAAW,EAAG,CACrB,IAAM,EAAO,CAAC,GAAG,CAAK,EAItB,MAFA,GAAK,GAAO,EAAU,CAAI,EAEnB,OAAO,OAAO,CAAI,CAC3B,CAEA,IAAM,EAAO,CAAC,GAAG,CAAK,EAItB,MAFA,GAAK,GAAO,EAAY,EAAM,GAAmB,EAAM,CAAI,EAEpD,OAAO,OAAO,CAAI,CAC3B,CAIA,GAFA,EAAc,CAAG,EAEb,CAAC,EAAS,CAAK,EACjB,MAAM,IAAI,EAAA,iBAAiB,kBAAkB,EAAI,8CAA8C,EAGjG,GAAI,EAAK,SAAW,EAAG,OAAO,OAAO,OAAO,CAAE,GAAG,GAAQ,GAAM,EAAU,CAAI,CAAE,CAAC,EAEhF,IAAM,EAAQ,EAAM,GAEpB,GAAI,IAAU,IAAA,IAAa,CAAC,EAAS,CAAK,GAAK,CAAC,MAAM,QAAQ,CAAK,EACjE,MAAM,IAAI,EAAA,iBAAiB,kBAAkB,EAAI,wCAAwC,EAG3F,IAAM,EAAa,GAAS,CAAC,EAE7B,OAAO,OAAO,OAAO,CAAE,GAAG,GAAQ,GAAM,EAAY,EAAW,EAAM,CAAI,CAAE,CAAC,CAC9E,CAEA,SAAgB,EAAiC,EAAU,EAAa,EAAuC,CAC7G,GAAM,CAAC,EAAK,GAAG,GAAQ,EAEvB,GAAI,OAAO,GAAQ,SAAU,CAE3B,GADI,CAAC,MAAM,QAAQ,CAAK,GACpB,CAAC,MAAM,QAAQ,CAAQ,GAAK,GAAO,EAAS,QAAU,GAAO,EAAM,OAAQ,OAAO,EAEtF,GAAI,EAAK,SAAW,EAAG,CACrB,IAAM,EAAO,CAAC,GAAG,CAAK,EAItB,MAFA,GAAK,GAAO,EAAS,GAEd,OAAO,OAAO,CAAI,CAC3B,CAEA,IAAM,EAAO,CAAC,GAAG,CAAK,EAItB,MAFA,GAAK,GAAO,EAAY,EAAM,GAAmB,EAAS,GAAmB,CAAI,EAE1E,OAAO,OAAO,CAAI,CAC3B,CAEA,GAAI,CAAC,EAAS,CAAK,EAAG,OAAO,EAE7B,GAAI,EAAK,SAAW,EAAG,CACrB,GAAI,OAAO,OAAO,EAAU,CAAG,EAAG,OAAO,OAAO,OAAO,CAAE,GAAG,GAAQ,GAAO,EAAyB,EAAK,CAAC,EAE1G,GAAM,EAAG,GAAM,EAAU,GAAG,GAAS,EAErC,OAAO,OAAO,OAAO,CAAI,CAC3B,CAEA,IAAM,EAAiB,EAAyB,GAEhD,GAAI,CAAC,EAAS,CAAa,GAAK,CAAC,MAAM,QAAQ,CAAa,EAAG,CAC7D,GAAI,OAAO,OAAO,EAAU,CAAG,EAAG,OAAO,OAAO,OAAO,CAAE,GAAG,GAAQ,GAAM,CAAc,CAAC,EAEzF,GAAM,EAAG,GAAM,EAAU,GAAG,GAAS,EAErC,OAAO,OAAO,OAAO,CAAI,CAC3B,CAEA,IAAM,EAAe,EAAM,GACrB,EAAa,EAAS,CAAY,GAAK,MAAM,QAAQ,CAAY,EAAI,EAAe,CAAC,EAE3F,OAAO,OAAO,OAAO,CAAE,GAAG,GAAQ,GAAM,EAAY,EAAW,EAA4B,CAAI,CAAE,CAAC,CACpG,CAEA,SAAgB,EAAU,EAAgB,EAAoC,EAAyB,CACrG,GAAM,CAAC,EAAK,GAAG,GAAQ,EACjB,EAAY,OAAO,CAAG,EACtB,EAAiC,CAAE,GAAG,CAAK,EAEjD,GAAI,EAAK,SAAW,EACd,EAAM,EAAK,GAAa,GACvB,OAAO,EAAK,OACZ,CAEL,IAAM,EAAU,EADF,EAAS,EAAK,EAAU,EAAK,EAAK,GAA0B,CAAC,EAC1C,EAAM,CAAI,EAEvC,OAAO,KAAK,CAAO,CAAC,CAAC,SAAW,EAAG,OAAO,EAAK,GAC9C,EAAK,GAAa,CACzB,CAEA,OAAO,OAAO,OAAO,CAAI,CAC3B,CAEA,SAAgB,EAAS,EAAgB,EAA6C,CACpF,IAAI,EAAgC,EAEpC,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAY,OAAO,CAAG,EAE5B,GAAI,CAAC,EAAS,CAAO,GAAK,CAAC,OAAO,OAAO,EAAS,CAAS,EAAG,MAAO,GAErE,EAAU,EAAQ,EACpB,CAEA,OAAO,IAAY,EACrB,CAEA,SAAgB,EAAS,EAA0B,CAcjD,OAbI,MAAM,QAAQ,CAAK,EACd,OAAO,OACZ,OAAO,YACL,EAAM,KAAK,EAAO,IAAM,CACtB,OAAO,CAAC,EACR,EAAS,CAAK,GAAK,MAAM,QAAQ,CAAK,EAAI,EAAS,CAAK,EAAK,EAC/D,CAAC,CACH,CACF,EAGG,EAAS,CAAK,EAEZ,OAAO,OACZ,OAAO,YACL,OAAO,QAAQ,CAAK,CAAC,CAAC,KAAK,CAAC,EAAK,KAAW,CAC1C,EACA,EAAS,CAAK,GAAK,MAAM,QAAQ,CAAK,EAAI,EAAS,CAAK,EAAK,EAC/D,CAAC,CACH,CACF,EAT6B,CAAC,CAUhC,CAEA,SAAgB,EAAU,EAAiB,EAAwD,CACjG,IAAM,EAAQ,EAAW,EAAQ,CAAI,EAErC,OAAO,OAAO,GAAU,SAAW,EAAQ,IAAA,EAC7C,CAEA,SAAS,EACP,EACA,EACA,EACwB,CACxB,GAAM,CAAC,EAAK,GAAG,GAAQ,EAEvB,GAAI,OAAO,GAAQ,SAAU,CAC3B,IAAM,EAAmB,MAAM,QAAQ,CAAI,EAAI,CAAC,GAAG,CAAI,EAAI,CAAC,EAQ5D,OANI,EAAK,SAAW,EACd,EAAI,KAAS,IAAA,KAAW,EAAI,GAAO,GAEvC,EAAI,GAAO,EAAe,EAAI,GAA4C,EAAM,CAAO,EAGlF,CACT,CAEA,GAAI,EAAY,CAAG,EAAG,OAAO,GAAQ,CAAC,EAEtC,IAAM,EAA2B,EAAS,CAAI,EAAI,CAAE,GAAG,CAAK,EAAI,CAAC,EAQjE,OANI,EAAK,SAAW,EACd,EAAO,KAAS,IAAA,KAAW,EAAO,GAAO,GAE7C,EAAO,GAAO,EAAe,EAAO,GAA4C,EAAM,CAAO,EAGxF,CACT,CAEA,SAAgB,EAAW,EAAiB,EAAoC,EAA4B,CAC1G,IAAM,EAAS,EAAe,EAAM,EAAM,CAAO,EAEjD,OAAO,EAAS,CAAM,EAAI,EAAS,CACrC,CAEA,SAAgB,EAAmB,EAA0B,CAC3D,GAAI,OAAO,GAAW,SAAU,OAAO,EAEvC,GAAI,MAAM,QAAQ,CAAM,EAAG,CACzB,IAAM,EAAa,EAAO,IAAK,GAAS,EAAgB,CAAI,CAAC,EAI7D,OAFI,EAAW,MAAO,GAAU,IAAU,IAAA,EAAS,EAAG,OAE/C,OAAO,OAAO,CAAU,CACjC,CAEA,GAAI,CAAC,EAAS,CAAM,EAAG,OAEvB,IAAM,EAAU,OAAO,QAAQ,CAAM,CAAC,CACnC,KAAK,CAAC,EAAK,KAAW,CAAC,EAAK,EAAgB,CAAK,CAAC,CAAU,CAAC,CAC7D,QAAQ,EAAG,KAAW,IAAU,IAAA,EAAS,EAE5C,OAAO,EAAQ,SAAW,EAAI,IAAA,GAAa,OAAO,OAAO,OAAO,YAAY,CAAO,CAAC,CACtF"}
@@ -1,3 +1,4 @@
1
+ export declare function isUnsafeKey(key: string): boolean;
1
2
  type ErrorNode = string | ErrorTree | ErrorArray;
2
3
  export interface ErrorTree {
3
4
  readonly [key: string]: ErrorNode;
@@ -1 +1 @@
1
- {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/core/path.ts"],"names":[],"mappings":"AAIA,KAAK,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AACjD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AACD,KAAK,UAAU,GAAG,SAAS,EAAE,CAAC;AAE9B,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,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAM7D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAUD,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAYxC;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,SAAS,CAgB/F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAgBrF;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,CA4C/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,CA8C7G;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAiBrG;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAYpF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAsBjD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,GAAG,SAAS,CAIjG;AAkCD,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAI1G;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAkB3D"}
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/core/path.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,KAAK,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AACjD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AACD,KAAK,UAAU,GAAG,SAAS,EAAE,CAAC;AAE9B,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,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAM7D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAUD,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAYxC;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,SAAS,CAgB/F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAgBrF;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,CA4C/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,CA8C7G;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAiBrG;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAYpF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAsBjD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,GAAG,SAAS,CAIjG;AAkCD,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAI1G;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAkB3D"}
package/dist/core/path.js CHANGED
@@ -6,71 +6,74 @@ var t = /* @__PURE__ */ new Set([
6
6
  "prototype"
7
7
  ]);
8
8
  function n(e) {
9
+ return !e || t.has(e);
10
+ }
11
+ function r(e) {
9
12
  if (typeof e != "object" || !e || Array.isArray(e)) return !1;
10
13
  let t = Object.getPrototypeOf(e);
11
14
  return t === Object.prototype || t === null;
12
15
  }
13
- function r(n) {
14
- if (!n || t.has(n)) throw new e(`Invalid field key '${n}'.`);
16
+ function i(t) {
17
+ if (n(t)) throw new e(`Invalid field key '${t}'.`);
15
18
  }
16
- function i(e) {
19
+ function a(e) {
17
20
  return typeof Blob < "u" && e instanceof Blob || typeof File < "u" && e instanceof File || e instanceof Date;
18
21
  }
19
- function a(t) {
20
- if (Array.isArray(t)) return Object.freeze(t.map(a));
21
- if (typeof t != "object" || !t || i(t)) return t;
22
- if (!n(t)) throw new e("Form values must contain only plain objects, arrays, Date, File, Blob, or primitive values.");
23
- return Object.freeze(Object.fromEntries(Object.entries(t).map(([e, t]) => [e, a(t)])));
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)])));
24
27
  }
25
- function o(e, t) {
26
- let r = e;
28
+ function s(e, t) {
29
+ let n = e;
27
30
  for (let e of t) if (typeof e == "number") {
28
- if (!Array.isArray(r) || e < 0 || e >= r.length) return;
29
- r = r[e];
31
+ if (!Array.isArray(n) || e < 0 || e >= n.length) return;
32
+ n = n[e];
30
33
  } else {
31
- if (!n(r) || !Object.hasOwn(r, e)) return;
32
- r = r[e];
34
+ if (!r(n) || !Object.hasOwn(n, e)) return;
35
+ n = n[e];
33
36
  }
34
- return r;
37
+ return n;
35
38
  }
36
- function s(e, t) {
37
- let r = e;
39
+ function c(e, t) {
40
+ let n = e;
38
41
  for (let e of t) if (typeof e == "number") {
39
- if (!Array.isArray(r) || e < 0 || e >= r.length) return !1;
40
- r = r[e];
42
+ if (!Array.isArray(n) || e < 0 || e >= n.length) return !1;
43
+ n = n[e];
41
44
  } else {
42
- if (!n(r) || !Object.hasOwn(r, e)) return !1;
43
- r = r[e];
45
+ if (!r(n) || !Object.hasOwn(n, e)) return !1;
46
+ n = n[e];
44
47
  }
45
48
  return !0;
46
49
  }
47
- function c(t, i, o) {
48
- let [s, ...l] = i;
50
+ function l(t, n, a) {
51
+ let [s, ...c] = n;
49
52
  if (typeof s == "number") {
50
53
  if (!Array.isArray(t)) throw new e(`Cannot index ${s} because the current value is not an array.`);
51
54
  if (s < 0 || s >= t.length) throw new e(`Index ${s} is out of range for array of length ${t.length}.`);
52
- if (l.length === 0) {
55
+ if (c.length === 0) {
53
56
  let e = [...t];
54
- return e[s] = a(o), Object.freeze(e);
57
+ return e[s] = o(a), Object.freeze(e);
55
58
  }
56
59
  let n = [...t];
57
- return n[s] = c(t[s], l, o), Object.freeze(n);
60
+ return n[s] = l(t[s], c, a), Object.freeze(n);
58
61
  }
59
- if (r(s), !n(t)) throw new e(`Cannot select '${s}' because the current value is not an object.`);
60
- if (l.length === 0) return Object.freeze({
62
+ if (i(s), !r(t)) throw new e(`Cannot select '${s}' because the current value is not an object.`);
63
+ if (c.length === 0) return Object.freeze({
61
64
  ...t,
62
- [s]: a(o)
65
+ [s]: o(a)
63
66
  });
64
67
  let u = t[s];
65
- if (u !== void 0 && !n(u) && !Array.isArray(u)) throw new e(`Cannot select '${s}' because it is not an object or array.`);
68
+ if (u !== void 0 && !r(u) && !Array.isArray(u)) throw new e(`Cannot select '${s}' because it is not an object or array.`);
66
69
  let d = u ?? {};
67
70
  return Object.freeze({
68
71
  ...t,
69
- [s]: c(d, l, o)
72
+ [s]: l(d, c, a)
70
73
  });
71
74
  }
72
- function l(e, t, r) {
73
- let [i, ...a] = r;
75
+ function u(e, t, n) {
76
+ let [i, ...a] = n;
74
77
  if (typeof i == "number") {
75
78
  if (!Array.isArray(e) || !Array.isArray(t) || i >= t.length || i >= e.length) return e;
76
79
  if (a.length === 0) {
@@ -78,9 +81,9 @@ function l(e, t, r) {
78
81
  return n[i] = t[i], Object.freeze(n);
79
82
  }
80
83
  let n = [...e];
81
- return n[i] = l(e[i], t[i], a), Object.freeze(n);
84
+ return n[i] = u(e[i], t[i], a), Object.freeze(n);
82
85
  }
83
- if (!n(e)) return e;
86
+ if (!r(e)) return e;
84
87
  if (a.length === 0) {
85
88
  if (Object.hasOwn(t, i)) return Object.freeze({
86
89
  ...e,
@@ -90,7 +93,7 @@ function l(e, t, r) {
90
93
  return Object.freeze(r);
91
94
  }
92
95
  let o = t[i];
93
- if (!n(o) && !Array.isArray(o)) {
96
+ if (!r(o) && !Array.isArray(o)) {
94
97
  if (Object.hasOwn(t, i)) return Object.freeze({
95
98
  ...e,
96
99
  [i]: o
@@ -98,62 +101,62 @@ function l(e, t, r) {
98
101
  let { [i]: n, ...r } = e;
99
102
  return Object.freeze(r);
100
103
  }
101
- let s = e[i], c = n(s) || Array.isArray(s) ? s : {};
104
+ let s = e[i], c = r(s) || Array.isArray(s) ? s : {};
102
105
  return Object.freeze({
103
106
  ...e,
104
- [i]: l(c, o, a)
107
+ [i]: u(c, o, a)
105
108
  });
106
109
  }
107
- function u(e, t, r) {
110
+ function d(e, t, n) {
108
111
  let [i, ...a] = t, o = String(i), s = { ...e };
109
- if (a.length === 0) r ? s[o] = !0 : delete s[o];
112
+ if (a.length === 0) n ? s[o] = !0 : delete s[o];
110
113
  else {
111
- let t = u(n(e[o]) ? e[o] : {}, a, r);
114
+ let t = d(r(e[o]) ? e[o] : {}, a, n);
112
115
  Object.keys(t).length === 0 ? delete s[o] : s[o] = t;
113
116
  }
114
117
  return Object.freeze(s);
115
118
  }
116
- function d(e, t) {
117
- let r = e;
119
+ function f(e, t) {
120
+ let n = e;
118
121
  for (let e of t) {
119
122
  let t = String(e);
120
- if (!n(r) || !Object.hasOwn(r, t)) return !1;
121
- r = r[t];
123
+ if (!r(n) || !Object.hasOwn(n, t)) return !1;
124
+ n = n[t];
122
125
  }
123
- return r === !0;
126
+ return n === !0;
124
127
  }
125
- function f(e) {
126
- return Array.isArray(e) ? Object.freeze(Object.fromEntries(e.map((e, t) => [String(t), n(e) || Array.isArray(e) ? f(e) : !0]))) : n(e) ? Object.freeze(Object.fromEntries(Object.entries(e).map(([e, t]) => [e, n(t) || Array.isArray(t) ? f(t) : !0]))) : {};
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]))) : {};
127
130
  }
128
- function p(e, t) {
129
- let n = o(e, t);
131
+ function m(e, t) {
132
+ let n = s(e, t);
130
133
  return typeof n == "string" ? n : void 0;
131
134
  }
132
- function m(e, r, i) {
133
- let [a, ...o] = r;
135
+ function h(e, t, i) {
136
+ let [a, ...o] = t;
134
137
  if (typeof a == "number") {
135
138
  let t = Array.isArray(e) ? [...e] : [];
136
- return o.length === 0 ? t[a] === void 0 && (t[a] = i) : t[a] = m(t[a], o, i), t;
139
+ return o.length === 0 ? t[a] === void 0 && (t[a] = i) : t[a] = h(t[a], o, i), t;
137
140
  }
138
- if (!a || t.has(a)) return e ?? {};
139
- let s = n(e) ? { ...e } : {};
140
- return o.length === 0 ? s[a] === void 0 && (s[a] = i) : s[a] = m(s[a], o, i), s;
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;
141
144
  }
142
- function h(e, t, r) {
143
- let i = m(e, t, r);
144
- return n(i) ? i : e;
145
+ function g(e, t, n) {
146
+ let i = h(e, t, n);
147
+ return r(i) ? i : e;
145
148
  }
146
- function g(e) {
149
+ function _(e) {
147
150
  if (typeof e == "string") return e;
148
151
  if (Array.isArray(e)) {
149
- let t = e.map((e) => g(e));
152
+ let t = e.map((e) => _(e));
150
153
  return t.every((e) => e === void 0) ? void 0 : Object.freeze(t);
151
154
  }
152
- if (!n(e)) return;
153
- let t = Object.entries(e).map(([e, t]) => [e, g(t)]).filter(([, e]) => e !== void 0);
155
+ if (!r(e)) return;
156
+ let t = Object.entries(e).map(([e, t]) => [e, _(t)]).filter(([, e]) => e !== void 0);
154
157
  return t.length === 0 ? void 0 : Object.freeze(Object.fromEntries(t));
155
158
  }
156
159
  //#endregion
157
- export { r as assertSafeKey, s as hasAtPath, a as immutable, n as isRecord, g as normalizeErrors, o as readAtPath, p as readError, d as readMeta, l as resetAtPath, f as touchAll, c as writeAtPath, h as writeError, u as writeMeta };
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 };
158
161
 
159
162
  //# 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\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 (!key || unsafeKeys.has(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 (!key || unsafeKeys.has(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 { 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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"}
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){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function s(e){if(!e||a.has(e))throw new n(`Invalid field key '${e}'.`)}function c(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File||e instanceof Date}function l(e){if(Array.isArray(e))return Object.freeze(e.map(l));if(typeof e!=`object`||!e||c(e))return e;if(!o(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,l(t)])))}function u(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(!o(n)||!Object.hasOwn(n,e))return;n=n[e]}return n}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!1;n=n[e]}else{if(!o(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return!0}function f(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]=l(r),Object.freeze(t)}let t=[...e];return t[i]=f(e[i],a,r),Object.freeze(t)}if(s(i),!o(e))throw new n(`Cannot select '${i}' because the current value is not an object.`);if(a.length===0)return Object.freeze({...e,[i]:l(r)});let c=e[i];if(c!==void 0&&!o(c)&&!Array.isArray(c))throw new n(`Cannot select '${i}' because it is not an object or array.`);let u=c??{};return Object.freeze({...e,[i]:f(u,a,r)})}function p(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]=p(e[r],t[r],i),Object.freeze(n)}if(!o(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(!o(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 s=e[r],c=o(s)||Array.isArray(s)?s:{};return Object.freeze({...e,[r]:p(c,a,i)})}function m(e,t,n){let[r,...i]=t,a=String(r),s={...e};if(i.length===0)n?s[a]=!0:delete s[a];else{let t=m(o(e[a])?e[a]:{},i,n);Object.keys(t).length===0?delete s[a]:s[a]=t}return Object.freeze(s)}function h(e,t){let n=e;for(let e of t){let t=String(e);if(!o(n)||!Object.hasOwn(n,t))return!1;n=n[t]}return n===!0}function g(e){return Array.isArray(e)?Object.freeze(Object.fromEntries(e.map((e,t)=>[String(t),o(e)||Array.isArray(e)?g(e):!0]))):o(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,o(t)||Array.isArray(t)?g(t):!0]))):{}}function _(e,t){let n=u(e,t);return typeof n==`string`?n:void 0}function v(e){if(typeof e==`string`)return e;if(Array.isArray(e)){let t=e.map(e=>v(e));return t.every(e=>e===void 0)?void 0:Object.freeze(t)}if(!o(e))return;let t=Object.entries(e).map(([e,t])=>[e,v(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}function y(e,t){let n=u(e.value,t),r=u(e.baseline,t);return Object.freeze({dirty:n!==r||d(e.value,t)!==d(e.baseline,t),error:_(e.errors,t),touched:h(e.touched,t),value:n})}function b(e,t){return Object.assign({get dirty(){return y(t.readState(),e).dirty},get error(){return y(t.readState(),e).error},reset(){t.ensureActive(`field().reset`),t.abortValidation(),t.resetValue(e)},set(n){t.ensureActive(`field().set`),t.abortValidation();let r=u(t.readState().value,e),i=typeof n==`function`?n(r):n;t.setValue(e,i)},get state(){return y(t.readState(),e)},subscribe(n,r={}){t.ensureActive(`field().subscribe`);let i=y(t.readState(),e);return r.immediate&&n(i),t.addListener(()=>{let r=y(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 y(t.readState(),e).touched},get value(){return y(t.readState(),e).value}},{field(r){if(typeof r==`number`){let i=u(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 b([...e,r],t)}s(r);let i=u(t.readState().value,e);if(i!==void 0&&!o(i))throw new n(`Cannot select '${r}' because the current field value is not an object.`);return b([...e,r],t)}})}function x(e){queueMicrotask(()=>{throw e})}function S(e){let t=new Set;function n(t){if(!e){x(t);return}try{e(t)}catch(e){x(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 C(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 w(e){let a=l(e.initialValues),c=S(e.onSubscriberError),u=new AbortController,d=!1,h,_={baseline:a,errors:void 0,formError:void 0,isSubmitting:!1,isValidating:!1,submitCount:0,touched:{},validity:`unknown`,value:a};function y(e){if(d)throw new t(e)}function x(e){_=Object.freeze(e(_)),c.notify()}function w(){h?.abort()}let T={abortValidation:w,addListener:c.add,ensureActive:y,readState:()=>_,resetValue(e){x(t=>({...t,touched:m(t.touched,e,!1),validity:`unknown`,value:p(t.value,t.baseline,e)}))},setTouched(e,t){x(n=>({...n,touched:m(n.touched,e,t)}))},setValue(e,t){x(n=>({...n,validity:`unknown`,value:f(n.value,e,t)}))}};async function E(t){y(`validate`),w();let n=new AbortController,r=t?AbortSignal.any([n.signal,t]):n.signal;h=n,x(e=>({...e,isValidating:!0}));try{let t=e.validate?await e.validate(_.value,r):void 0;if(r.aborted||h!==n)return Object.freeze({status:`aborted`});let i=t?.fields?v(l(t.fields)):void 0,a=t?.formError,o=i===void 0&&a===void 0?`valid`:`invalid`;return x(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||h!==n)return Object.freeze({status:`aborted`});throw new i(`Form validation failed.`,{cause:e})}finally{h===n&&(h=void 0,d||x(e=>({...e,isValidating:!1})))}}let D={get disposalSignal(){return u.signal},dispose(){d||(d=!0,u.abort(),w(),c.clear())},get disposed(){return d},field(e){if(s(e),!o(_.value))throw new n(`Form value must be an object.`);return b([e],T)},reset(e){y(`reset`),w();let t=e===void 0?_.baseline:l(e);x(e=>({...e,baseline:t,errors:void 0,formError:void 0,touched:{},validity:`unknown`,value:t}))},set(e){y(`set`),w();let t=typeof e==`function`?e(D.value):e;x(e=>({...e,errors:void 0,formError:void 0,validity:`unknown`,value:l(t)}))},get state(){return C(_)},async submit(e,t){if(y(`submit`),_.isSubmitting)throw new r(`submit() called while a submission is already in progress`);let n=t?AbortSignal.any([u.signal,t]):u.signal;x(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:g(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||x(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){return y(`subscribe`),t.immediate&&e(C(_)),c.add(()=>e(C(_)))},[Symbol.dispose](){D.dispose()},validate:E,get value(){return _.value}};return D}exports.ForgeConfigError=n,exports.ForgeDisposedError=t,exports.ForgeError=e,exports.ForgeSubmitError=r,exports.ForgeValidationError=i,exports.createForm=w;
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;
2
2
  //# sourceMappingURL=forge.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"forge.cjs","names":[],"sources":["../src/errors.ts","../src/core/path.ts","../src/_field.ts","../src/_notify.ts","../src/form.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","import { ForgeConfigError } from '../errors';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\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 (!key || unsafeKeys.has(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 (!key || unsafeKeys.has(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","import { assertSafeKey, hasAtPath, isRecord, type MetaRoot, readAtPath, readError, readMeta } from './core/path';\nimport { ForgeConfigError } from './errors';\nimport type { Field, FieldState, ReadonlyDeep, SubscribeOptions, Unsubscribe } from './types';\n\nexport interface FieldAccess {\n abortValidation(): void;\n addListener(listener: () => void): Unsubscribe;\n ensureActive(operation: string): void;\n readState(): { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown };\n resetValue(path: readonly (string | number)[]): void;\n setTouched(path: readonly (string | number)[], touched: boolean): void;\n setValue(path: readonly (string | number)[], next: unknown): void;\n}\n\nfunction makeFieldState<V>(\n state: { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown },\n path: readonly (string | number)[],\n): FieldState<V> {\n const value = readAtPath<V>(state.value, path);\n const baseline = readAtPath<V>(state.baseline, path);\n\n return Object.freeze({\n dirty: value !== baseline || hasAtPath(state.value, path) !== hasAtPath(state.baseline, path),\n error: readError(state.errors, path),\n touched: readMeta(state.touched, path),\n value: value as ReadonlyDeep<V>,\n });\n}\n\nexport function createField<V>(path: readonly (string | number)[], access: FieldAccess): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(access.readState(), path).dirty;\n },\n get error() {\n return makeFieldState<V>(access.readState(), path).error;\n },\n reset() {\n access.ensureActive('field().reset');\n access.abortValidation();\n access.resetValue(path);\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n access.ensureActive('field().set');\n access.abortValidation();\n\n const previous = readAtPath<V>(access.readState().value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n access.setValue(path, value);\n },\n get state() {\n return makeFieldState<V>(access.readState(), path);\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n access.ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(access.readState(), path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n const filtered = () => {\n const next = makeFieldState<V>(access.readState(), path);\n\n if (\n next.value === previous.value &&\n next.error === previous.error &&\n next.touched === previous.touched &&\n next.dirty === previous.dirty\n ) {\n return;\n }\n\n previous = next;\n listener(next);\n };\n\n return access.addListener(filtered);\n },\n touch() {\n access.ensureActive('field().touch');\n access.setTouched(path, true);\n },\n get touched() {\n return makeFieldState<V>(access.readState(), path).touched;\n },\n get value() {\n return makeFieldState<V>(access.readState(), path).value;\n },\n };\n\n return Object.assign(common, {\n field(key: string | number): Field<unknown> {\n if (typeof key === 'number') {\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !Array.isArray(currentVal)) {\n throw new ForgeConfigError(`Cannot index ${key} because the current field value is not an array.`);\n }\n\n return createField([...path, key], access);\n }\n\n assertSafeKey(key);\n\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !isRecord(currentVal)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current field value is not an object.`);\n }\n\n return createField([...path, key], access);\n },\n }) as unknown as Field<V>;\n}\n","import type { Unsubscribe } from './types';\n\nexport interface Notifier {\n add(listener: () => void): Unsubscribe;\n clear(): void;\n notify(): void;\n}\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nexport function createNotifier(onError?: (error: unknown) => void): Notifier {\n const listeners = new Set<() => void>();\n\n function reportError(error: unknown): void {\n if (!onError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n onError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n return {\n add(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n clear() {\n listeners.clear();\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n reportError(error);\n }\n }\n },\n };\n}\n","import { createField, type FieldAccess } from './_field';\nimport { createNotifier } from './_notify';\nimport {\n assertSafeKey,\n immutable,\n isRecord,\n type MetaRoot,\n normalizeErrors,\n resetAtPath,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\nimport type {\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\ntype Validity = 'invalid' | 'unknown' | 'valid';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n errors: FormErrors<TValues> | undefined;\n formError: string | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n validity: Validity;\n value: TValues;\n}>;\n\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n errors: current.errors,\n formError: current.formError,\n hasErrors: current.formError !== undefined || current.errors !== undefined,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n validating: current.isValidating,\n validity: current.validity,\n });\n}\n\n/** One immutable value tree and one explicit full-form validator keep form behavior locally understandable. */\nexport function createForm<TValues extends Record<string, unknown>>(options: FormOptions<TValues>): Form<TValues> {\n const initial = immutable(options.initialValues);\n const notifier = createNotifier(options.onSubscriberError);\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\n let current: InternalState<TValues> = {\n baseline: initial,\n errors: undefined,\n formError: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n validity: 'unknown',\n value: initial,\n };\n\n function ensureActive(operation: string): void {\n if (disposed) throw new ForgeDisposedError(operation);\n }\n\n function write(update: (current: InternalState<TValues>) => InternalState<TValues>): void {\n current = Object.freeze(update(current));\n notifier.notify();\n }\n\n function abortValidation(): void {\n validationController?.abort();\n }\n\n const access: FieldAccess = {\n abortValidation,\n addListener: notifier.add,\n ensureActive,\n readState: () => current,\n resetValue(path) {\n write((c) => ({\n ...c,\n touched: writeMeta(c.touched, path, false),\n validity: 'unknown',\n value: resetAtPath(c.value, c.baseline, path),\n }));\n },\n setTouched(path, touched) {\n write((c) => ({ ...c, touched: writeMeta(c.touched, path, touched) }));\n },\n setValue(path, next) {\n write((c) => ({\n ...c,\n validity: 'unknown',\n value: writeAtPath(c.value, path, next),\n }));\n },\n };\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n abortValidation();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((c) => ({ ...c, isValidating: true }));\n\n try {\n const result: ValidationErrors<TValues> | undefined = options.validate\n ? await options.validate(current.value as ReadonlyDeep<TValues>, signal)\n : undefined;\n\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n const errors = result?.fields\n ? (normalizeErrors(immutable(result.fields)) as FormErrors<TValues> | undefined)\n : undefined;\n const formError = result?.formError;\n const validity: Validity = errors === undefined && formError === undefined ? 'valid' : 'invalid';\n\n write((c) => ({ ...c, errors, formError, validity }));\n\n return validity === 'valid'\n ? Object.freeze({ status: 'valid' })\n : Object.freeze({ errors, formError, status: 'invalid' });\n } catch (error) {\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n throw new ForgeValidationError('Form validation failed.', { cause: error });\n } finally {\n if (validationController === controller) {\n validationController = undefined;\n\n if (!disposed) write((c) => ({ ...c, isValidating: false }));\n }\n }\n }\n\n const form: Form<TValues> = {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose() {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n abortValidation();\n notifier.clear();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n if (!isRecord(current.value)) throw new ForgeConfigError('Form value must be an object.');\n\n return createField<TValues[typeof key]>([key], access);\n },\n reset(next) {\n ensureActive('reset');\n abortValidation();\n\n const baseline = next === undefined ? current.baseline : immutable(next);\n\n write((c) => ({\n ...c,\n baseline,\n errors: undefined,\n formError: undefined,\n touched: {},\n validity: 'unknown',\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n abortValidation();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((c) => ({ ...c, errors: undefined, formError: undefined, validity: 'unknown', value: immutable(value) }));\n },\n get state() {\n return makeFormState(current);\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>, signal: AbortSignal) => MaybePromise<TResult>,\n externalSignal?: AbortSignal,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (current.isSubmitting) {\n throw new ForgeSubmitError('submit() called while a submission is already in progress');\n }\n\n const signal = externalSignal\n ? AbortSignal.any([disposalController.signal, externalSignal])\n : disposalController.signal;\n\n write((c) => ({\n ...c,\n isSubmitting: true,\n submitCount: c.submitCount + 1,\n touched: touchAll(c.value),\n }));\n\n try {\n const result = await validate(externalSignal);\n\n if (result.status === 'aborted') return Object.freeze({ status: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({ errors: result.errors, formError: result.formError, status: 'invalid' });\n }\n\n try {\n return Object.freeze({ status: 'ok', value: await handler(form.value, signal) });\n } catch (error) {\n if (signal.aborted) return Object.freeze({ status: 'aborted' });\n\n throw error;\n }\n } finally {\n if (!disposed) write((c) => ({ ...c, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(current));\n\n return notifier.add(() => listener(makeFormState(current)));\n },\n [Symbol.dispose]() {\n form.dispose();\n },\n validate,\n get value() {\n return current.value as ReadonlyDeep<TValues>;\n },\n };\n\n return form;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"forge.cjs","names":[],"sources":["../src/errors.ts","../src/core/path.ts","../src/_field.ts","../src/_notify.ts","../src/form.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","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","import { assertSafeKey, hasAtPath, isRecord, type MetaRoot, readAtPath, readError, readMeta } from './core/path';\nimport { ForgeConfigError } from './errors';\nimport type { Field, FieldState, ReadonlyDeep, SubscribeOptions, Unsubscribe } from './types';\n\nexport interface FieldAccess {\n abortValidation(): void;\n addListener(listener: () => void): Unsubscribe;\n ensureActive(operation: string): void;\n readState(): { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown };\n resetValue(path: readonly (string | number)[]): void;\n setTouched(path: readonly (string | number)[], touched: boolean): void;\n setValue(path: readonly (string | number)[], next: unknown): void;\n}\n\nfunction makeFieldState<V>(\n state: { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown },\n path: readonly (string | number)[],\n): FieldState<V> {\n const value = readAtPath<V>(state.value, path);\n const baseline = readAtPath<V>(state.baseline, path);\n\n return Object.freeze({\n dirty: value !== baseline || hasAtPath(state.value, path) !== hasAtPath(state.baseline, path),\n error: readError(state.errors, path),\n touched: readMeta(state.touched, path),\n value: value as ReadonlyDeep<V>,\n });\n}\n\nexport function createField<V>(path: readonly (string | number)[], access: FieldAccess): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(access.readState(), path).dirty;\n },\n get error() {\n return makeFieldState<V>(access.readState(), path).error;\n },\n reset() {\n access.ensureActive('field().reset');\n access.abortValidation();\n access.resetValue(path);\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n access.ensureActive('field().set');\n access.abortValidation();\n\n const previous = readAtPath<V>(access.readState().value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n access.setValue(path, value);\n },\n get state() {\n return makeFieldState<V>(access.readState(), path);\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n access.ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(access.readState(), path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n const filtered = () => {\n const next = makeFieldState<V>(access.readState(), path);\n\n if (\n next.value === previous.value &&\n next.error === previous.error &&\n next.touched === previous.touched &&\n next.dirty === previous.dirty\n ) {\n return;\n }\n\n previous = next;\n listener(next);\n };\n\n return access.addListener(filtered);\n },\n touch() {\n access.ensureActive('field().touch');\n access.setTouched(path, true);\n },\n get touched() {\n return makeFieldState<V>(access.readState(), path).touched;\n },\n get value() {\n return makeFieldState<V>(access.readState(), path).value;\n },\n };\n\n return Object.assign(common, {\n field(key: string | number): Field<unknown> {\n if (typeof key === 'number') {\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !Array.isArray(currentVal)) {\n throw new ForgeConfigError(`Cannot index ${key} because the current field value is not an array.`);\n }\n\n return createField([...path, key], access);\n }\n\n assertSafeKey(key);\n\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !isRecord(currentVal)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current field value is not an object.`);\n }\n\n return createField([...path, key], access);\n },\n }) as unknown as Field<V>;\n}\n","import type { Unsubscribe } from './types';\n\nexport interface Notifier {\n add(listener: () => void): Unsubscribe;\n clear(): void;\n notify(): void;\n}\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nexport function createNotifier(onError?: (error: unknown) => void): Notifier {\n const listeners = new Set<() => void>();\n\n function reportError(error: unknown): void {\n if (!onError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n onError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n return {\n add(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n clear() {\n listeners.clear();\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n reportError(error);\n }\n }\n },\n };\n}\n","import { createField, type FieldAccess } from './_field';\nimport { createNotifier } from './_notify';\nimport {\n assertSafeKey,\n immutable,\n isRecord,\n type MetaRoot,\n normalizeErrors,\n resetAtPath,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\nimport type {\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\ntype Validity = 'invalid' | 'unknown' | 'valid';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n errors: FormErrors<TValues> | undefined;\n formError: string | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n validity: Validity;\n value: TValues;\n}>;\n\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n errors: current.errors,\n formError: current.formError,\n hasErrors: current.formError !== undefined || current.errors !== undefined,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n validating: current.isValidating,\n validity: current.validity,\n });\n}\n\n/** One immutable value tree and one explicit full-form validator keep form behavior locally understandable. */\nexport function createForm<TValues extends Record<string, unknown>>(options: FormOptions<TValues>): Form<TValues> {\n const initial = immutable(options.initialValues);\n const notifier = createNotifier(options.onSubscriberError);\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\n let current: InternalState<TValues> = {\n baseline: initial,\n errors: undefined,\n formError: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n validity: 'unknown',\n value: initial,\n };\n\n function ensureActive(operation: string): void {\n if (disposed) throw new ForgeDisposedError(operation);\n }\n\n function write(update: (current: InternalState<TValues>) => InternalState<TValues>): void {\n current = Object.freeze(update(current));\n notifier.notify();\n }\n\n function abortValidation(): void {\n validationController?.abort();\n }\n\n const access: FieldAccess = {\n abortValidation,\n addListener: notifier.add,\n ensureActive,\n readState: () => current,\n resetValue(path) {\n write((c) => ({\n ...c,\n touched: writeMeta(c.touched, path, false),\n validity: 'unknown',\n value: resetAtPath(c.value, c.baseline, path),\n }));\n },\n setTouched(path, touched) {\n write((c) => ({ ...c, touched: writeMeta(c.touched, path, touched) }));\n },\n setValue(path, next) {\n write((c) => ({\n ...c,\n validity: 'unknown',\n value: writeAtPath(c.value, path, next),\n }));\n },\n };\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n abortValidation();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((c) => ({ ...c, isValidating: true }));\n\n try {\n const result: ValidationErrors<TValues> | undefined = options.validate\n ? await options.validate(current.value as ReadonlyDeep<TValues>, signal)\n : undefined;\n\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n const errors = result?.fields\n ? (normalizeErrors(immutable(result.fields)) as FormErrors<TValues> | undefined)\n : undefined;\n const formError = result?.formError;\n const validity: Validity = errors === undefined && formError === undefined ? 'valid' : 'invalid';\n\n write((c) => ({ ...c, errors, formError, validity }));\n\n return validity === 'valid'\n ? Object.freeze({ status: 'valid' })\n : Object.freeze({ errors, formError, status: 'invalid' });\n } catch (error) {\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n throw new ForgeValidationError('Form validation failed.', { cause: error });\n } finally {\n if (validationController === controller) {\n validationController = undefined;\n\n if (!disposed) write((c) => ({ ...c, isValidating: false }));\n }\n }\n }\n\n const form: Form<TValues> = {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose() {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n abortValidation();\n notifier.clear();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n if (!isRecord(current.value)) throw new ForgeConfigError('Form value must be an object.');\n\n return createField<TValues[typeof key]>([key], access);\n },\n reset(next) {\n ensureActive('reset');\n abortValidation();\n\n const baseline = next === undefined ? current.baseline : immutable(next);\n\n write((c) => ({\n ...c,\n baseline,\n errors: undefined,\n formError: undefined,\n touched: {},\n validity: 'unknown',\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n abortValidation();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((c) => ({ ...c, errors: undefined, formError: undefined, validity: 'unknown', value: immutable(value) }));\n },\n get state() {\n return makeFormState(current);\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>, signal: AbortSignal) => MaybePromise<TResult>,\n externalSignal?: AbortSignal,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (current.isSubmitting) {\n throw new ForgeSubmitError('submit() called while a submission is already in progress');\n }\n\n const signal = externalSignal\n ? AbortSignal.any([disposalController.signal, externalSignal])\n : disposalController.signal;\n\n write((c) => ({\n ...c,\n isSubmitting: true,\n submitCount: c.submitCount + 1,\n touched: touchAll(c.value),\n }));\n\n try {\n const result = await validate(externalSignal);\n\n if (result.status === 'aborted') return Object.freeze({ status: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({ errors: result.errors, formError: result.formError, status: 'invalid' });\n }\n\n try {\n return Object.freeze({ status: 'ok', value: await handler(form.value, signal) });\n } catch (error) {\n if (signal.aborted) return Object.freeze({ status: 'aborted' });\n\n throw error;\n }\n } finally {\n if (!disposed) write((c) => ({ ...c, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(current));\n\n return notifier.add(() => listener(makeFormState(current)));\n },\n [Symbol.dispose]() {\n form.dispose();\n },\n validate,\n get value() {\n return current.value as ReadonlyDeep<TValues>;\n },\n };\n\n return form;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- var Forge=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},n=class extends t{constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},r=class extends t{},i=class extends t{},a=class extends t{},o=new Set([`__proto__`,`constructor`,`prototype`]);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(!e||o.has(e))throw new r(`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 r(`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,n){let[i,...a]=t;if(typeof i==`number`){if(!Array.isArray(e))throw new r(`Cannot index ${i} because the current value is not an array.`);if(i<0||i>=e.length)throw new r(`Index ${i} is out of range for array of length ${e.length}.`);if(a.length===0){let t=[...e];return t[i]=u(n),Object.freeze(t)}let t=[...e];return t[i]=p(e[i],a,n),Object.freeze(t)}if(c(i),!s(e))throw new r(`Cannot select '${i}' because the current value is not an object.`);if(a.length===0)return Object.freeze({...e,[i]:u(n)});let o=e[i];if(o!==void 0&&!s(o)&&!Array.isArray(o))throw new r(`Cannot select '${i}' because it is not an object or array.`);let l=o??{};return Object.freeze({...e,[i]:p(l,a,n)})}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(n){if(typeof n==`number`){let i=d(t.readState().value,e);if(i!==void 0&&!Array.isArray(i))throw new r(`Cannot index ${n} because the current field value is not an array.`);return x([...e,n],t)}c(n);let i=d(t.readState().value,e);if(i!==void 0&&!s(i))throw new r(`Cannot select '${n}' because the current field value is not an object.`);return x([...e,n],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 t=u(e.initialValues),o=C(e.onSubscriberError),l=new AbortController,d=!1,f,g={baseline:t,errors:void 0,formError:void 0,isSubmitting:!1,isValidating:!1,submitCount:0,touched:{},validity:`unknown`,value:t};function v(e){if(d)throw new n(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 a(`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 r(`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 i(`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}return e.ForgeConfigError=r,e.ForgeDisposedError=n,e.ForgeError=t,e.ForgeSubmitError=i,e.ForgeValidationError=a,e.createForm=T,e})({});
1
+ var Forge=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},n=class extends t{constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},r=class extends t{},i=class extends t{},a=class extends t{},o=new Set([`__proto__`,`constructor`,`prototype`]);function s(e){return!e||o.has(e)}function c(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function l(e){if(s(e))throw new r(`Invalid field key '${e}'.`)}function u(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File||e instanceof Date}function d(e){if(Array.isArray(e))return Object.freeze(e.map(d));if(typeof e!=`object`||!e||u(e))return e;if(!c(e))throw new r(`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,d(t)])))}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;n=n[e]}else{if(!c(n)||!Object.hasOwn(n,e))return;n=n[e]}return n}function p(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(!c(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return!0}function m(e,t,n){let[i,...a]=t;if(typeof i==`number`){if(!Array.isArray(e))throw new r(`Cannot index ${i} because the current value is not an array.`);if(i<0||i>=e.length)throw new r(`Index ${i} is out of range for array of length ${e.length}.`);if(a.length===0){let t=[...e];return t[i]=d(n),Object.freeze(t)}let t=[...e];return t[i]=m(e[i],a,n),Object.freeze(t)}if(l(i),!c(e))throw new r(`Cannot select '${i}' because the current value is not an object.`);if(a.length===0)return Object.freeze({...e,[i]:d(n)});let o=e[i];if(o!==void 0&&!c(o)&&!Array.isArray(o))throw new r(`Cannot select '${i}' because it is not an object or array.`);let s=o??{};return Object.freeze({...e,[i]:m(s,a,n)})}function h(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]=h(e[r],t[r],i),Object.freeze(n)}if(!c(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(!c(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],s=c(o)||Array.isArray(o)?o:{};return Object.freeze({...e,[r]:h(s,a,i)})}function g(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=g(c(e[a])?e[a]:{},i,n);Object.keys(t).length===0?delete o[a]:o[a]=t}return Object.freeze(o)}function _(e,t){let n=e;for(let e of t){let t=String(e);if(!c(n)||!Object.hasOwn(n,t))return!1;n=n[t]}return n===!0}function v(e){return Array.isArray(e)?Object.freeze(Object.fromEntries(e.map((e,t)=>[String(t),c(e)||Array.isArray(e)?v(e):!0]))):c(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,c(t)||Array.isArray(t)?v(t):!0]))):{}}function y(e,t){let n=f(e,t);return typeof n==`string`?n:void 0}function b(e){if(typeof e==`string`)return e;if(Array.isArray(e)){let t=e.map(e=>b(e));return t.every(e=>e===void 0)?void 0:Object.freeze(t)}if(!c(e))return;let t=Object.entries(e).map(([e,t])=>[e,b(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}function x(e,t){let n=f(e.value,t),r=f(e.baseline,t);return Object.freeze({dirty:n!==r||p(e.value,t)!==p(e.baseline,t),error:y(e.errors,t),touched:_(e.touched,t),value:n})}function S(e,t){return Object.assign({get dirty(){return x(t.readState(),e).dirty},get error(){return x(t.readState(),e).error},reset(){t.ensureActive(`field().reset`),t.abortValidation(),t.resetValue(e)},set(n){t.ensureActive(`field().set`),t.abortValidation();let r=f(t.readState().value,e),i=typeof n==`function`?n(r):n;t.setValue(e,i)},get state(){return x(t.readState(),e)},subscribe(n,r={}){t.ensureActive(`field().subscribe`);let i=x(t.readState(),e);return r.immediate&&n(i),t.addListener(()=>{let r=x(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 x(t.readState(),e).touched},get value(){return x(t.readState(),e).value}},{field(n){if(typeof n==`number`){let i=f(t.readState().value,e);if(i!==void 0&&!Array.isArray(i))throw new r(`Cannot index ${n} because the current field value is not an array.`);return S([...e,n],t)}l(n);let i=f(t.readState().value,e);if(i!==void 0&&!c(i))throw new r(`Cannot select '${n}' because the current field value is not an object.`);return S([...e,n],t)}})}function C(e){queueMicrotask(()=>{throw e})}function w(e){let t=new Set;function n(t){if(!e){C(t);return}try{e(t)}catch(e){C(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 T(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 E(e){let t=d(e.initialValues),o=w(e.onSubscriberError),s=new AbortController,u=!1,f,p={baseline:t,errors:void 0,formError:void 0,isSubmitting:!1,isValidating:!1,submitCount:0,touched:{},validity:`unknown`,value:t};function _(e){if(u)throw new n(e)}function y(e){p=Object.freeze(e(p)),o.notify()}function x(){f?.abort()}let C={abortValidation:x,addListener:o.add,ensureActive:_,readState:()=>p,resetValue(e){y(t=>({...t,touched:g(t.touched,e,!1),validity:`unknown`,value:h(t.value,t.baseline,e)}))},setTouched(e,t){y(n=>({...n,touched:g(n.touched,e,t)}))},setValue(e,t){y(n=>({...n,validity:`unknown`,value:m(n.value,e,t)}))}};async function E(t){_(`validate`),x();let n=new AbortController,r=t?AbortSignal.any([n.signal,t]):n.signal;f=n,y(e=>({...e,isValidating:!0}));try{let t=e.validate?await e.validate(p.value,r):void 0;if(r.aborted||f!==n)return Object.freeze({status:`aborted`});let i=t?.fields?b(d(t.fields)):void 0,a=t?.formError,o=i===void 0&&a===void 0?`valid`:`invalid`;return y(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 a(`Form validation failed.`,{cause:e})}finally{f===n&&(f=void 0,u||y(e=>({...e,isValidating:!1})))}}let D={get disposalSignal(){return s.signal},dispose(){u||(u=!0,s.abort(),x(),o.clear())},get disposed(){return u},field(e){if(l(e),!c(p.value))throw new r(`Form value must be an object.`);return S([e],C)},reset(e){_(`reset`),x();let t=e===void 0?p.baseline:d(e);y(e=>({...e,baseline:t,errors:void 0,formError:void 0,touched:{},validity:`unknown`,value:t}))},set(e){_(`set`),x();let t=typeof e==`function`?e(D.value):e;y(e=>({...e,errors:void 0,formError:void 0,validity:`unknown`,value:d(t)}))},get state(){return T(p)},async submit(e,t){if(_(`submit`),p.isSubmitting)throw new i(`submit() called while a submission is already in progress`);let n=t?AbortSignal.any([s.signal,t]):s.signal;y(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:v(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{u||y(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){return _(`subscribe`),t.immediate&&e(T(p)),o.add(()=>e(T(p)))},[Symbol.dispose](){D.dispose()},validate:E,get value(){return p.value}};return D}return e.ForgeConfigError=r,e.ForgeDisposedError=n,e.ForgeError=t,e.ForgeSubmitError=i,e.ForgeValidationError=a,e.createForm=E,e})({});
2
2
  //# sourceMappingURL=forge.iife.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"forge.iife.js","names":[],"sources":["../src/errors.ts","../src/core/path.ts","../src/_field.ts","../src/_notify.ts","../src/form.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","import { ForgeConfigError } from '../errors';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\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 (!key || unsafeKeys.has(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 (!key || unsafeKeys.has(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","import { assertSafeKey, hasAtPath, isRecord, type MetaRoot, readAtPath, readError, readMeta } from './core/path';\nimport { ForgeConfigError } from './errors';\nimport type { Field, FieldState, ReadonlyDeep, SubscribeOptions, Unsubscribe } from './types';\n\nexport interface FieldAccess {\n abortValidation(): void;\n addListener(listener: () => void): Unsubscribe;\n ensureActive(operation: string): void;\n readState(): { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown };\n resetValue(path: readonly (string | number)[]): void;\n setTouched(path: readonly (string | number)[], touched: boolean): void;\n setValue(path: readonly (string | number)[], next: unknown): void;\n}\n\nfunction makeFieldState<V>(\n state: { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown },\n path: readonly (string | number)[],\n): FieldState<V> {\n const value = readAtPath<V>(state.value, path);\n const baseline = readAtPath<V>(state.baseline, path);\n\n return Object.freeze({\n dirty: value !== baseline || hasAtPath(state.value, path) !== hasAtPath(state.baseline, path),\n error: readError(state.errors, path),\n touched: readMeta(state.touched, path),\n value: value as ReadonlyDeep<V>,\n });\n}\n\nexport function createField<V>(path: readonly (string | number)[], access: FieldAccess): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(access.readState(), path).dirty;\n },\n get error() {\n return makeFieldState<V>(access.readState(), path).error;\n },\n reset() {\n access.ensureActive('field().reset');\n access.abortValidation();\n access.resetValue(path);\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n access.ensureActive('field().set');\n access.abortValidation();\n\n const previous = readAtPath<V>(access.readState().value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n access.setValue(path, value);\n },\n get state() {\n return makeFieldState<V>(access.readState(), path);\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n access.ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(access.readState(), path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n const filtered = () => {\n const next = makeFieldState<V>(access.readState(), path);\n\n if (\n next.value === previous.value &&\n next.error === previous.error &&\n next.touched === previous.touched &&\n next.dirty === previous.dirty\n ) {\n return;\n }\n\n previous = next;\n listener(next);\n };\n\n return access.addListener(filtered);\n },\n touch() {\n access.ensureActive('field().touch');\n access.setTouched(path, true);\n },\n get touched() {\n return makeFieldState<V>(access.readState(), path).touched;\n },\n get value() {\n return makeFieldState<V>(access.readState(), path).value;\n },\n };\n\n return Object.assign(common, {\n field(key: string | number): Field<unknown> {\n if (typeof key === 'number') {\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !Array.isArray(currentVal)) {\n throw new ForgeConfigError(`Cannot index ${key} because the current field value is not an array.`);\n }\n\n return createField([...path, key], access);\n }\n\n assertSafeKey(key);\n\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !isRecord(currentVal)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current field value is not an object.`);\n }\n\n return createField([...path, key], access);\n },\n }) as unknown as Field<V>;\n}\n","import type { Unsubscribe } from './types';\n\nexport interface Notifier {\n add(listener: () => void): Unsubscribe;\n clear(): void;\n notify(): void;\n}\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nexport function createNotifier(onError?: (error: unknown) => void): Notifier {\n const listeners = new Set<() => void>();\n\n function reportError(error: unknown): void {\n if (!onError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n onError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n return {\n add(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n clear() {\n listeners.clear();\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n reportError(error);\n }\n }\n },\n };\n}\n","import { createField, type FieldAccess } from './_field';\nimport { createNotifier } from './_notify';\nimport {\n assertSafeKey,\n immutable,\n isRecord,\n type MetaRoot,\n normalizeErrors,\n resetAtPath,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\nimport type {\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\ntype Validity = 'invalid' | 'unknown' | 'valid';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n errors: FormErrors<TValues> | undefined;\n formError: string | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n validity: Validity;\n value: TValues;\n}>;\n\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n errors: current.errors,\n formError: current.formError,\n hasErrors: current.formError !== undefined || current.errors !== undefined,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n validating: current.isValidating,\n validity: current.validity,\n });\n}\n\n/** One immutable value tree and one explicit full-form validator keep form behavior locally understandable. */\nexport function createForm<TValues extends Record<string, unknown>>(options: FormOptions<TValues>): Form<TValues> {\n const initial = immutable(options.initialValues);\n const notifier = createNotifier(options.onSubscriberError);\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\n let current: InternalState<TValues> = {\n baseline: initial,\n errors: undefined,\n formError: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n validity: 'unknown',\n value: initial,\n };\n\n function ensureActive(operation: string): void {\n if (disposed) throw new ForgeDisposedError(operation);\n }\n\n function write(update: (current: InternalState<TValues>) => InternalState<TValues>): void {\n current = Object.freeze(update(current));\n notifier.notify();\n }\n\n function abortValidation(): void {\n validationController?.abort();\n }\n\n const access: FieldAccess = {\n abortValidation,\n addListener: notifier.add,\n ensureActive,\n readState: () => current,\n resetValue(path) {\n write((c) => ({\n ...c,\n touched: writeMeta(c.touched, path, false),\n validity: 'unknown',\n value: resetAtPath(c.value, c.baseline, path),\n }));\n },\n setTouched(path, touched) {\n write((c) => ({ ...c, touched: writeMeta(c.touched, path, touched) }));\n },\n setValue(path, next) {\n write((c) => ({\n ...c,\n validity: 'unknown',\n value: writeAtPath(c.value, path, next),\n }));\n },\n };\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n abortValidation();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((c) => ({ ...c, isValidating: true }));\n\n try {\n const result: ValidationErrors<TValues> | undefined = options.validate\n ? await options.validate(current.value as ReadonlyDeep<TValues>, signal)\n : undefined;\n\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n const errors = result?.fields\n ? (normalizeErrors(immutable(result.fields)) as FormErrors<TValues> | undefined)\n : undefined;\n const formError = result?.formError;\n const validity: Validity = errors === undefined && formError === undefined ? 'valid' : 'invalid';\n\n write((c) => ({ ...c, errors, formError, validity }));\n\n return validity === 'valid'\n ? Object.freeze({ status: 'valid' })\n : Object.freeze({ errors, formError, status: 'invalid' });\n } catch (error) {\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n throw new ForgeValidationError('Form validation failed.', { cause: error });\n } finally {\n if (validationController === controller) {\n validationController = undefined;\n\n if (!disposed) write((c) => ({ ...c, isValidating: false }));\n }\n }\n }\n\n const form: Form<TValues> = {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose() {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n abortValidation();\n notifier.clear();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n if (!isRecord(current.value)) throw new ForgeConfigError('Form value must be an object.');\n\n return createField<TValues[typeof key]>([key], access);\n },\n reset(next) {\n ensureActive('reset');\n abortValidation();\n\n const baseline = next === undefined ? current.baseline : immutable(next);\n\n write((c) => ({\n ...c,\n baseline,\n errors: undefined,\n formError: undefined,\n touched: {},\n validity: 'unknown',\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n abortValidation();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((c) => ({ ...c, errors: undefined, formError: undefined, validity: 'unknown', value: immutable(value) }));\n },\n get state() {\n return makeFormState(current);\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>, signal: AbortSignal) => MaybePromise<TResult>,\n externalSignal?: AbortSignal,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (current.isSubmitting) {\n throw new ForgeSubmitError('submit() called while a submission is already in progress');\n }\n\n const signal = externalSignal\n ? AbortSignal.any([disposalController.signal, externalSignal])\n : disposalController.signal;\n\n write((c) => ({\n ...c,\n isSubmitting: true,\n submitCount: c.submitCount + 1,\n touched: touchAll(c.value),\n }));\n\n try {\n const result = await validate(externalSignal);\n\n if (result.status === 'aborted') return Object.freeze({ status: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({ errors: result.errors, formError: result.formError, status: 'invalid' });\n }\n\n try {\n return Object.freeze({ status: 'ok', value: await handler(form.value, signal) });\n } catch (error) {\n if (signal.aborted) return Object.freeze({ status: 'aborted' });\n\n throw error;\n }\n } finally {\n if (!disposed) write((c) => ({ ...c, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(current));\n\n return notifier.add(() => listener(makeFormState(current)));\n },\n [Symbol.dispose]() {\n form.dispose();\n },\n validate,\n get value() {\n return current.value as ReadonlyDeep<TValues>;\n },\n };\n\n return form;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"forge.iife.js","names":[],"sources":["../src/errors.ts","../src/core/path.ts","../src/_field.ts","../src/_notify.ts","../src/form.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","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","import { assertSafeKey, hasAtPath, isRecord, type MetaRoot, readAtPath, readError, readMeta } from './core/path';\nimport { ForgeConfigError } from './errors';\nimport type { Field, FieldState, ReadonlyDeep, SubscribeOptions, Unsubscribe } from './types';\n\nexport interface FieldAccess {\n abortValidation(): void;\n addListener(listener: () => void): Unsubscribe;\n ensureActive(operation: string): void;\n readState(): { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown };\n resetValue(path: readonly (string | number)[]): void;\n setTouched(path: readonly (string | number)[], touched: boolean): void;\n setValue(path: readonly (string | number)[], next: unknown): void;\n}\n\nfunction makeFieldState<V>(\n state: { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown },\n path: readonly (string | number)[],\n): FieldState<V> {\n const value = readAtPath<V>(state.value, path);\n const baseline = readAtPath<V>(state.baseline, path);\n\n return Object.freeze({\n dirty: value !== baseline || hasAtPath(state.value, path) !== hasAtPath(state.baseline, path),\n error: readError(state.errors, path),\n touched: readMeta(state.touched, path),\n value: value as ReadonlyDeep<V>,\n });\n}\n\nexport function createField<V>(path: readonly (string | number)[], access: FieldAccess): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(access.readState(), path).dirty;\n },\n get error() {\n return makeFieldState<V>(access.readState(), path).error;\n },\n reset() {\n access.ensureActive('field().reset');\n access.abortValidation();\n access.resetValue(path);\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n access.ensureActive('field().set');\n access.abortValidation();\n\n const previous = readAtPath<V>(access.readState().value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n access.setValue(path, value);\n },\n get state() {\n return makeFieldState<V>(access.readState(), path);\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n access.ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(access.readState(), path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n const filtered = () => {\n const next = makeFieldState<V>(access.readState(), path);\n\n if (\n next.value === previous.value &&\n next.error === previous.error &&\n next.touched === previous.touched &&\n next.dirty === previous.dirty\n ) {\n return;\n }\n\n previous = next;\n listener(next);\n };\n\n return access.addListener(filtered);\n },\n touch() {\n access.ensureActive('field().touch');\n access.setTouched(path, true);\n },\n get touched() {\n return makeFieldState<V>(access.readState(), path).touched;\n },\n get value() {\n return makeFieldState<V>(access.readState(), path).value;\n },\n };\n\n return Object.assign(common, {\n field(key: string | number): Field<unknown> {\n if (typeof key === 'number') {\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !Array.isArray(currentVal)) {\n throw new ForgeConfigError(`Cannot index ${key} because the current field value is not an array.`);\n }\n\n return createField([...path, key], access);\n }\n\n assertSafeKey(key);\n\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !isRecord(currentVal)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current field value is not an object.`);\n }\n\n return createField([...path, key], access);\n },\n }) as unknown as Field<V>;\n}\n","import type { Unsubscribe } from './types';\n\nexport interface Notifier {\n add(listener: () => void): Unsubscribe;\n clear(): void;\n notify(): void;\n}\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nexport function createNotifier(onError?: (error: unknown) => void): Notifier {\n const listeners = new Set<() => void>();\n\n function reportError(error: unknown): void {\n if (!onError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n onError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n return {\n add(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n clear() {\n listeners.clear();\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n reportError(error);\n }\n }\n },\n };\n}\n","import { createField, type FieldAccess } from './_field';\nimport { createNotifier } from './_notify';\nimport {\n assertSafeKey,\n immutable,\n isRecord,\n type MetaRoot,\n normalizeErrors,\n resetAtPath,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\nimport type {\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\ntype Validity = 'invalid' | 'unknown' | 'valid';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n errors: FormErrors<TValues> | undefined;\n formError: string | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n validity: Validity;\n value: TValues;\n}>;\n\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n errors: current.errors,\n formError: current.formError,\n hasErrors: current.formError !== undefined || current.errors !== undefined,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n validating: current.isValidating,\n validity: current.validity,\n });\n}\n\n/** One immutable value tree and one explicit full-form validator keep form behavior locally understandable. */\nexport function createForm<TValues extends Record<string, unknown>>(options: FormOptions<TValues>): Form<TValues> {\n const initial = immutable(options.initialValues);\n const notifier = createNotifier(options.onSubscriberError);\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\n let current: InternalState<TValues> = {\n baseline: initial,\n errors: undefined,\n formError: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n validity: 'unknown',\n value: initial,\n };\n\n function ensureActive(operation: string): void {\n if (disposed) throw new ForgeDisposedError(operation);\n }\n\n function write(update: (current: InternalState<TValues>) => InternalState<TValues>): void {\n current = Object.freeze(update(current));\n notifier.notify();\n }\n\n function abortValidation(): void {\n validationController?.abort();\n }\n\n const access: FieldAccess = {\n abortValidation,\n addListener: notifier.add,\n ensureActive,\n readState: () => current,\n resetValue(path) {\n write((c) => ({\n ...c,\n touched: writeMeta(c.touched, path, false),\n validity: 'unknown',\n value: resetAtPath(c.value, c.baseline, path),\n }));\n },\n setTouched(path, touched) {\n write((c) => ({ ...c, touched: writeMeta(c.touched, path, touched) }));\n },\n setValue(path, next) {\n write((c) => ({\n ...c,\n validity: 'unknown',\n value: writeAtPath(c.value, path, next),\n }));\n },\n };\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n abortValidation();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((c) => ({ ...c, isValidating: true }));\n\n try {\n const result: ValidationErrors<TValues> | undefined = options.validate\n ? await options.validate(current.value as ReadonlyDeep<TValues>, signal)\n : undefined;\n\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n const errors = result?.fields\n ? (normalizeErrors(immutable(result.fields)) as FormErrors<TValues> | undefined)\n : undefined;\n const formError = result?.formError;\n const validity: Validity = errors === undefined && formError === undefined ? 'valid' : 'invalid';\n\n write((c) => ({ ...c, errors, formError, validity }));\n\n return validity === 'valid'\n ? Object.freeze({ status: 'valid' })\n : Object.freeze({ errors, formError, status: 'invalid' });\n } catch (error) {\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n throw new ForgeValidationError('Form validation failed.', { cause: error });\n } finally {\n if (validationController === controller) {\n validationController = undefined;\n\n if (!disposed) write((c) => ({ ...c, isValidating: false }));\n }\n }\n }\n\n const form: Form<TValues> = {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose() {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n abortValidation();\n notifier.clear();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n if (!isRecord(current.value)) throw new ForgeConfigError('Form value must be an object.');\n\n return createField<TValues[typeof key]>([key], access);\n },\n reset(next) {\n ensureActive('reset');\n abortValidation();\n\n const baseline = next === undefined ? current.baseline : immutable(next);\n\n write((c) => ({\n ...c,\n baseline,\n errors: undefined,\n formError: undefined,\n touched: {},\n validity: 'unknown',\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n abortValidation();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((c) => ({ ...c, errors: undefined, formError: undefined, validity: 'unknown', value: immutable(value) }));\n },\n get state() {\n return makeFormState(current);\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>, signal: AbortSignal) => MaybePromise<TResult>,\n externalSignal?: AbortSignal,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (current.isSubmitting) {\n throw new ForgeSubmitError('submit() called while a submission is already in progress');\n }\n\n const signal = externalSignal\n ? AbortSignal.any([disposalController.signal, externalSignal])\n : disposalController.signal;\n\n write((c) => ({\n ...c,\n isSubmitting: true,\n submitCount: c.submitCount + 1,\n touched: touchAll(c.value),\n }));\n\n try {\n const result = await validate(externalSignal);\n\n if (result.status === 'aborted') return Object.freeze({ status: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({ errors: result.errors, formError: result.formError, status: 'invalid' });\n }\n\n try {\n return Object.freeze({ status: 'ok', value: await handler(form.value, signal) });\n } catch (error) {\n if (signal.aborted) return Object.freeze({ status: 'aborted' });\n\n throw error;\n }\n } finally {\n if (!disposed) write((c) => ({ ...c, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(current));\n\n return notifier.add(() => listener(makeFormState(current)));\n },\n [Symbol.dispose]() {\n form.dispose();\n },\n validate,\n get value() {\n return current.value as ReadonlyDeep<TValues>;\n },\n };\n\n return form;\n}\n"],"mappings":"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"}
package/dist/forge.js 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{},a=new Set([`__proto__`,`constructor`,`prototype`]);function o(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function s(e){if(!e||a.has(e))throw new n(`Invalid field key '${e}'.`)}function c(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File||e instanceof Date}function l(e){if(Array.isArray(e))return Object.freeze(e.map(l));if(typeof e!=`object`||!e||c(e))return e;if(!o(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,l(t)])))}function u(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(!o(n)||!Object.hasOwn(n,e))return;n=n[e]}return n}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!1;n=n[e]}else{if(!o(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return!0}function f(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]=l(r),Object.freeze(t)}let t=[...e];return t[i]=f(e[i],a,r),Object.freeze(t)}if(s(i),!o(e))throw new n(`Cannot select '${i}' because the current value is not an object.`);if(a.length===0)return Object.freeze({...e,[i]:l(r)});let c=e[i];if(c!==void 0&&!o(c)&&!Array.isArray(c))throw new n(`Cannot select '${i}' because it is not an object or array.`);let u=c??{};return Object.freeze({...e,[i]:f(u,a,r)})}function p(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]=p(e[r],t[r],i),Object.freeze(n)}if(!o(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(!o(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 s=e[r],c=o(s)||Array.isArray(s)?s:{};return Object.freeze({...e,[r]:p(c,a,i)})}function m(e,t,n){let[r,...i]=t,a=String(r),s={...e};if(i.length===0)n?s[a]=!0:delete s[a];else{let t=m(o(e[a])?e[a]:{},i,n);Object.keys(t).length===0?delete s[a]:s[a]=t}return Object.freeze(s)}function h(e,t){let n=e;for(let e of t){let t=String(e);if(!o(n)||!Object.hasOwn(n,t))return!1;n=n[t]}return n===!0}function g(e){return Array.isArray(e)?Object.freeze(Object.fromEntries(e.map((e,t)=>[String(t),o(e)||Array.isArray(e)?g(e):!0]))):o(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,o(t)||Array.isArray(t)?g(t):!0]))):{}}function _(e,t){let n=u(e,t);return typeof n==`string`?n:void 0}function v(e){if(typeof e==`string`)return e;if(Array.isArray(e)){let t=e.map(e=>v(e));return t.every(e=>e===void 0)?void 0:Object.freeze(t)}if(!o(e))return;let t=Object.entries(e).map(([e,t])=>[e,v(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}function y(e,t){let n=u(e.value,t),r=u(e.baseline,t);return Object.freeze({dirty:n!==r||d(e.value,t)!==d(e.baseline,t),error:_(e.errors,t),touched:h(e.touched,t),value:n})}function b(e,t){return Object.assign({get dirty(){return y(t.readState(),e).dirty},get error(){return y(t.readState(),e).error},reset(){t.ensureActive(`field().reset`),t.abortValidation(),t.resetValue(e)},set(n){t.ensureActive(`field().set`),t.abortValidation();let r=u(t.readState().value,e),i=typeof n==`function`?n(r):n;t.setValue(e,i)},get state(){return y(t.readState(),e)},subscribe(n,r={}){t.ensureActive(`field().subscribe`);let i=y(t.readState(),e);return r.immediate&&n(i),t.addListener(()=>{let r=y(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 y(t.readState(),e).touched},get value(){return y(t.readState(),e).value}},{field(r){if(typeof r==`number`){let i=u(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 b([...e,r],t)}s(r);let i=u(t.readState().value,e);if(i!==void 0&&!o(i))throw new n(`Cannot select '${r}' because the current field value is not an object.`);return b([...e,r],t)}})}function x(e){queueMicrotask(()=>{throw e})}function S(e){let t=new Set;function n(t){if(!e){x(t);return}try{e(t)}catch(e){x(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 C(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 w(e){let a=l(e.initialValues),c=S(e.onSubscriberError),u=new AbortController,d=!1,h,_={baseline:a,errors:void 0,formError:void 0,isSubmitting:!1,isValidating:!1,submitCount:0,touched:{},validity:`unknown`,value:a};function y(e){if(d)throw new t(e)}function x(e){_=Object.freeze(e(_)),c.notify()}function w(){h?.abort()}let T={abortValidation:w,addListener:c.add,ensureActive:y,readState:()=>_,resetValue(e){x(t=>({...t,touched:m(t.touched,e,!1),validity:`unknown`,value:p(t.value,t.baseline,e)}))},setTouched(e,t){x(n=>({...n,touched:m(n.touched,e,t)}))},setValue(e,t){x(n=>({...n,validity:`unknown`,value:f(n.value,e,t)}))}};async function E(t){y(`validate`),w();let n=new AbortController,r=t?AbortSignal.any([n.signal,t]):n.signal;h=n,x(e=>({...e,isValidating:!0}));try{let t=e.validate?await e.validate(_.value,r):void 0;if(r.aborted||h!==n)return Object.freeze({status:`aborted`});let i=t?.fields?v(l(t.fields)):void 0,a=t?.formError,o=i===void 0&&a===void 0?`valid`:`invalid`;return x(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||h!==n)return Object.freeze({status:`aborted`});throw new i(`Form validation failed.`,{cause:e})}finally{h===n&&(h=void 0,d||x(e=>({...e,isValidating:!1})))}}let D={get disposalSignal(){return u.signal},dispose(){d||(d=!0,u.abort(),w(),c.clear())},get disposed(){return d},field(e){if(s(e),!o(_.value))throw new n(`Form value must be an object.`);return b([e],T)},reset(e){y(`reset`),w();let t=e===void 0?_.baseline:l(e);x(e=>({...e,baseline:t,errors:void 0,formError:void 0,touched:{},validity:`unknown`,value:t}))},set(e){y(`set`),w();let t=typeof e==`function`?e(D.value):e;x(e=>({...e,errors:void 0,formError:void 0,validity:`unknown`,value:l(t)}))},get state(){return C(_)},async submit(e,t){if(y(`submit`),_.isSubmitting)throw new r(`submit() called while a submission is already in progress`);let n=t?AbortSignal.any([u.signal,t]):u.signal;x(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:g(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||x(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){return y(`subscribe`),t.immediate&&e(C(_)),c.add(()=>e(C(_)))},[Symbol.dispose](){D.dispose()},validate:E,get value(){return _.value}};return D}export{n as ForgeConfigError,t as ForgeDisposedError,e as ForgeError,r as ForgeSubmitError,i as ForgeValidationError,w as createForm};
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{},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}export{n as ForgeConfigError,t as ForgeDisposedError,e as ForgeError,r as ForgeSubmitError,i as ForgeValidationError,T as createForm};
2
2
  //# sourceMappingURL=forge.js.map
package/dist/forge.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"forge.js","names":[],"sources":["../src/errors.ts","../src/core/path.ts","../src/_field.ts","../src/_notify.ts","../src/form.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","import { ForgeConfigError } from '../errors';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\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 (!key || unsafeKeys.has(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 (!key || unsafeKeys.has(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","import { assertSafeKey, hasAtPath, isRecord, type MetaRoot, readAtPath, readError, readMeta } from './core/path';\nimport { ForgeConfigError } from './errors';\nimport type { Field, FieldState, ReadonlyDeep, SubscribeOptions, Unsubscribe } from './types';\n\nexport interface FieldAccess {\n abortValidation(): void;\n addListener(listener: () => void): Unsubscribe;\n ensureActive(operation: string): void;\n readState(): { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown };\n resetValue(path: readonly (string | number)[]): void;\n setTouched(path: readonly (string | number)[], touched: boolean): void;\n setValue(path: readonly (string | number)[], next: unknown): void;\n}\n\nfunction makeFieldState<V>(\n state: { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown },\n path: readonly (string | number)[],\n): FieldState<V> {\n const value = readAtPath<V>(state.value, path);\n const baseline = readAtPath<V>(state.baseline, path);\n\n return Object.freeze({\n dirty: value !== baseline || hasAtPath(state.value, path) !== hasAtPath(state.baseline, path),\n error: readError(state.errors, path),\n touched: readMeta(state.touched, path),\n value: value as ReadonlyDeep<V>,\n });\n}\n\nexport function createField<V>(path: readonly (string | number)[], access: FieldAccess): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(access.readState(), path).dirty;\n },\n get error() {\n return makeFieldState<V>(access.readState(), path).error;\n },\n reset() {\n access.ensureActive('field().reset');\n access.abortValidation();\n access.resetValue(path);\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n access.ensureActive('field().set');\n access.abortValidation();\n\n const previous = readAtPath<V>(access.readState().value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n access.setValue(path, value);\n },\n get state() {\n return makeFieldState<V>(access.readState(), path);\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n access.ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(access.readState(), path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n const filtered = () => {\n const next = makeFieldState<V>(access.readState(), path);\n\n if (\n next.value === previous.value &&\n next.error === previous.error &&\n next.touched === previous.touched &&\n next.dirty === previous.dirty\n ) {\n return;\n }\n\n previous = next;\n listener(next);\n };\n\n return access.addListener(filtered);\n },\n touch() {\n access.ensureActive('field().touch');\n access.setTouched(path, true);\n },\n get touched() {\n return makeFieldState<V>(access.readState(), path).touched;\n },\n get value() {\n return makeFieldState<V>(access.readState(), path).value;\n },\n };\n\n return Object.assign(common, {\n field(key: string | number): Field<unknown> {\n if (typeof key === 'number') {\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !Array.isArray(currentVal)) {\n throw new ForgeConfigError(`Cannot index ${key} because the current field value is not an array.`);\n }\n\n return createField([...path, key], access);\n }\n\n assertSafeKey(key);\n\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !isRecord(currentVal)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current field value is not an object.`);\n }\n\n return createField([...path, key], access);\n },\n }) as unknown as Field<V>;\n}\n","import type { Unsubscribe } from './types';\n\nexport interface Notifier {\n add(listener: () => void): Unsubscribe;\n clear(): void;\n notify(): void;\n}\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nexport function createNotifier(onError?: (error: unknown) => void): Notifier {\n const listeners = new Set<() => void>();\n\n function reportError(error: unknown): void {\n if (!onError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n onError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n return {\n add(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n clear() {\n listeners.clear();\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n reportError(error);\n }\n }\n },\n };\n}\n","import { createField, type FieldAccess } from './_field';\nimport { createNotifier } from './_notify';\nimport {\n assertSafeKey,\n immutable,\n isRecord,\n type MetaRoot,\n normalizeErrors,\n resetAtPath,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\nimport type {\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\ntype Validity = 'invalid' | 'unknown' | 'valid';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n errors: FormErrors<TValues> | undefined;\n formError: string | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n validity: Validity;\n value: TValues;\n}>;\n\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n errors: current.errors,\n formError: current.formError,\n hasErrors: current.formError !== undefined || current.errors !== undefined,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n validating: current.isValidating,\n validity: current.validity,\n });\n}\n\n/** One immutable value tree and one explicit full-form validator keep form behavior locally understandable. */\nexport function createForm<TValues extends Record<string, unknown>>(options: FormOptions<TValues>): Form<TValues> {\n const initial = immutable(options.initialValues);\n const notifier = createNotifier(options.onSubscriberError);\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\n let current: InternalState<TValues> = {\n baseline: initial,\n errors: undefined,\n formError: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n validity: 'unknown',\n value: initial,\n };\n\n function ensureActive(operation: string): void {\n if (disposed) throw new ForgeDisposedError(operation);\n }\n\n function write(update: (current: InternalState<TValues>) => InternalState<TValues>): void {\n current = Object.freeze(update(current));\n notifier.notify();\n }\n\n function abortValidation(): void {\n validationController?.abort();\n }\n\n const access: FieldAccess = {\n abortValidation,\n addListener: notifier.add,\n ensureActive,\n readState: () => current,\n resetValue(path) {\n write((c) => ({\n ...c,\n touched: writeMeta(c.touched, path, false),\n validity: 'unknown',\n value: resetAtPath(c.value, c.baseline, path),\n }));\n },\n setTouched(path, touched) {\n write((c) => ({ ...c, touched: writeMeta(c.touched, path, touched) }));\n },\n setValue(path, next) {\n write((c) => ({\n ...c,\n validity: 'unknown',\n value: writeAtPath(c.value, path, next),\n }));\n },\n };\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n abortValidation();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((c) => ({ ...c, isValidating: true }));\n\n try {\n const result: ValidationErrors<TValues> | undefined = options.validate\n ? await options.validate(current.value as ReadonlyDeep<TValues>, signal)\n : undefined;\n\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n const errors = result?.fields\n ? (normalizeErrors(immutable(result.fields)) as FormErrors<TValues> | undefined)\n : undefined;\n const formError = result?.formError;\n const validity: Validity = errors === undefined && formError === undefined ? 'valid' : 'invalid';\n\n write((c) => ({ ...c, errors, formError, validity }));\n\n return validity === 'valid'\n ? Object.freeze({ status: 'valid' })\n : Object.freeze({ errors, formError, status: 'invalid' });\n } catch (error) {\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n throw new ForgeValidationError('Form validation failed.', { cause: error });\n } finally {\n if (validationController === controller) {\n validationController = undefined;\n\n if (!disposed) write((c) => ({ ...c, isValidating: false }));\n }\n }\n }\n\n const form: Form<TValues> = {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose() {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n abortValidation();\n notifier.clear();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n if (!isRecord(current.value)) throw new ForgeConfigError('Form value must be an object.');\n\n return createField<TValues[typeof key]>([key], access);\n },\n reset(next) {\n ensureActive('reset');\n abortValidation();\n\n const baseline = next === undefined ? current.baseline : immutable(next);\n\n write((c) => ({\n ...c,\n baseline,\n errors: undefined,\n formError: undefined,\n touched: {},\n validity: 'unknown',\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n abortValidation();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((c) => ({ ...c, errors: undefined, formError: undefined, validity: 'unknown', value: immutable(value) }));\n },\n get state() {\n return makeFormState(current);\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>, signal: AbortSignal) => MaybePromise<TResult>,\n externalSignal?: AbortSignal,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (current.isSubmitting) {\n throw new ForgeSubmitError('submit() called while a submission is already in progress');\n }\n\n const signal = externalSignal\n ? AbortSignal.any([disposalController.signal, externalSignal])\n : disposalController.signal;\n\n write((c) => ({\n ...c,\n isSubmitting: true,\n submitCount: c.submitCount + 1,\n touched: touchAll(c.value),\n }));\n\n try {\n const result = await validate(externalSignal);\n\n if (result.status === 'aborted') return Object.freeze({ status: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({ errors: result.errors, formError: result.formError, status: 'invalid' });\n }\n\n try {\n return Object.freeze({ status: 'ok', value: await handler(form.value, signal) });\n } catch (error) {\n if (signal.aborted) return Object.freeze({ status: 'aborted' });\n\n throw error;\n }\n } finally {\n if (!disposed) write((c) => ({ ...c, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(current));\n\n return notifier.add(() => listener(makeFormState(current)));\n },\n [Symbol.dispose]() {\n form.dispose();\n },\n validate,\n get value() {\n return current.value as ReadonlyDeep<TValues>;\n },\n };\n\n return form;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"forge.js","names":[],"sources":["../src/errors.ts","../src/core/path.ts","../src/_field.ts","../src/_notify.ts","../src/form.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","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","import { assertSafeKey, hasAtPath, isRecord, type MetaRoot, readAtPath, readError, readMeta } from './core/path';\nimport { ForgeConfigError } from './errors';\nimport type { Field, FieldState, ReadonlyDeep, SubscribeOptions, Unsubscribe } from './types';\n\nexport interface FieldAccess {\n abortValidation(): void;\n addListener(listener: () => void): Unsubscribe;\n ensureActive(operation: string): void;\n readState(): { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown };\n resetValue(path: readonly (string | number)[]): void;\n setTouched(path: readonly (string | number)[], touched: boolean): void;\n setValue(path: readonly (string | number)[], next: unknown): void;\n}\n\nfunction makeFieldState<V>(\n state: { baseline: unknown; errors: unknown; touched: MetaRoot; value: unknown },\n path: readonly (string | number)[],\n): FieldState<V> {\n const value = readAtPath<V>(state.value, path);\n const baseline = readAtPath<V>(state.baseline, path);\n\n return Object.freeze({\n dirty: value !== baseline || hasAtPath(state.value, path) !== hasAtPath(state.baseline, path),\n error: readError(state.errors, path),\n touched: readMeta(state.touched, path),\n value: value as ReadonlyDeep<V>,\n });\n}\n\nexport function createField<V>(path: readonly (string | number)[], access: FieldAccess): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(access.readState(), path).dirty;\n },\n get error() {\n return makeFieldState<V>(access.readState(), path).error;\n },\n reset() {\n access.ensureActive('field().reset');\n access.abortValidation();\n access.resetValue(path);\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n access.ensureActive('field().set');\n access.abortValidation();\n\n const previous = readAtPath<V>(access.readState().value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n access.setValue(path, value);\n },\n get state() {\n return makeFieldState<V>(access.readState(), path);\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n access.ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(access.readState(), path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n const filtered = () => {\n const next = makeFieldState<V>(access.readState(), path);\n\n if (\n next.value === previous.value &&\n next.error === previous.error &&\n next.touched === previous.touched &&\n next.dirty === previous.dirty\n ) {\n return;\n }\n\n previous = next;\n listener(next);\n };\n\n return access.addListener(filtered);\n },\n touch() {\n access.ensureActive('field().touch');\n access.setTouched(path, true);\n },\n get touched() {\n return makeFieldState<V>(access.readState(), path).touched;\n },\n get value() {\n return makeFieldState<V>(access.readState(), path).value;\n },\n };\n\n return Object.assign(common, {\n field(key: string | number): Field<unknown> {\n if (typeof key === 'number') {\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !Array.isArray(currentVal)) {\n throw new ForgeConfigError(`Cannot index ${key} because the current field value is not an array.`);\n }\n\n return createField([...path, key], access);\n }\n\n assertSafeKey(key);\n\n const currentVal = readAtPath(access.readState().value, path);\n\n if (currentVal !== undefined && !isRecord(currentVal)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current field value is not an object.`);\n }\n\n return createField([...path, key], access);\n },\n }) as unknown as Field<V>;\n}\n","import type { Unsubscribe } from './types';\n\nexport interface Notifier {\n add(listener: () => void): Unsubscribe;\n clear(): void;\n notify(): void;\n}\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nexport function createNotifier(onError?: (error: unknown) => void): Notifier {\n const listeners = new Set<() => void>();\n\n function reportError(error: unknown): void {\n if (!onError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n onError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n return {\n add(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n clear() {\n listeners.clear();\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n reportError(error);\n }\n }\n },\n };\n}\n","import { createField, type FieldAccess } from './_field';\nimport { createNotifier } from './_notify';\nimport {\n assertSafeKey,\n immutable,\n isRecord,\n type MetaRoot,\n normalizeErrors,\n resetAtPath,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\nimport type {\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\ntype Validity = 'invalid' | 'unknown' | 'valid';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n errors: FormErrors<TValues> | undefined;\n formError: string | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n validity: Validity;\n value: TValues;\n}>;\n\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n errors: current.errors,\n formError: current.formError,\n hasErrors: current.formError !== undefined || current.errors !== undefined,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n validating: current.isValidating,\n validity: current.validity,\n });\n}\n\n/** One immutable value tree and one explicit full-form validator keep form behavior locally understandable. */\nexport function createForm<TValues extends Record<string, unknown>>(options: FormOptions<TValues>): Form<TValues> {\n const initial = immutable(options.initialValues);\n const notifier = createNotifier(options.onSubscriberError);\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\n let current: InternalState<TValues> = {\n baseline: initial,\n errors: undefined,\n formError: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n validity: 'unknown',\n value: initial,\n };\n\n function ensureActive(operation: string): void {\n if (disposed) throw new ForgeDisposedError(operation);\n }\n\n function write(update: (current: InternalState<TValues>) => InternalState<TValues>): void {\n current = Object.freeze(update(current));\n notifier.notify();\n }\n\n function abortValidation(): void {\n validationController?.abort();\n }\n\n const access: FieldAccess = {\n abortValidation,\n addListener: notifier.add,\n ensureActive,\n readState: () => current,\n resetValue(path) {\n write((c) => ({\n ...c,\n touched: writeMeta(c.touched, path, false),\n validity: 'unknown',\n value: resetAtPath(c.value, c.baseline, path),\n }));\n },\n setTouched(path, touched) {\n write((c) => ({ ...c, touched: writeMeta(c.touched, path, touched) }));\n },\n setValue(path, next) {\n write((c) => ({\n ...c,\n validity: 'unknown',\n value: writeAtPath(c.value, path, next),\n }));\n },\n };\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n abortValidation();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((c) => ({ ...c, isValidating: true }));\n\n try {\n const result: ValidationErrors<TValues> | undefined = options.validate\n ? await options.validate(current.value as ReadonlyDeep<TValues>, signal)\n : undefined;\n\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n const errors = result?.fields\n ? (normalizeErrors(immutable(result.fields)) as FormErrors<TValues> | undefined)\n : undefined;\n const formError = result?.formError;\n const validity: Validity = errors === undefined && formError === undefined ? 'valid' : 'invalid';\n\n write((c) => ({ ...c, errors, formError, validity }));\n\n return validity === 'valid'\n ? Object.freeze({ status: 'valid' })\n : Object.freeze({ errors, formError, status: 'invalid' });\n } catch (error) {\n if (signal.aborted || validationController !== controller) return Object.freeze({ status: 'aborted' });\n\n throw new ForgeValidationError('Form validation failed.', { cause: error });\n } finally {\n if (validationController === controller) {\n validationController = undefined;\n\n if (!disposed) write((c) => ({ ...c, isValidating: false }));\n }\n }\n }\n\n const form: Form<TValues> = {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose() {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n abortValidation();\n notifier.clear();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n if (!isRecord(current.value)) throw new ForgeConfigError('Form value must be an object.');\n\n return createField<TValues[typeof key]>([key], access);\n },\n reset(next) {\n ensureActive('reset');\n abortValidation();\n\n const baseline = next === undefined ? current.baseline : immutable(next);\n\n write((c) => ({\n ...c,\n baseline,\n errors: undefined,\n formError: undefined,\n touched: {},\n validity: 'unknown',\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n abortValidation();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((c) => ({ ...c, errors: undefined, formError: undefined, validity: 'unknown', value: immutable(value) }));\n },\n get state() {\n return makeFormState(current);\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>, signal: AbortSignal) => MaybePromise<TResult>,\n externalSignal?: AbortSignal,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (current.isSubmitting) {\n throw new ForgeSubmitError('submit() called while a submission is already in progress');\n }\n\n const signal = externalSignal\n ? AbortSignal.any([disposalController.signal, externalSignal])\n : disposalController.signal;\n\n write((c) => ({\n ...c,\n isSubmitting: true,\n submitCount: c.submitCount + 1,\n touched: touchAll(c.value),\n }));\n\n try {\n const result = await validate(externalSignal);\n\n if (result.status === 'aborted') return Object.freeze({ status: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({ errors: result.errors, formError: result.formError, status: 'invalid' });\n }\n\n try {\n return Object.freeze({ status: 'ok', value: await handler(form.value, signal) });\n } catch (error) {\n if (signal.aborted) return Object.freeze({ status: 'aborted' });\n\n throw error;\n }\n } finally {\n if (!disposed) write((c) => ({ ...c, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(current));\n\n return notifier.add(() => listener(makeFormState(current)));\n },\n [Symbol.dispose]() {\n form.dispose();\n },\n validate,\n get value() {\n return current.value as ReadonlyDeep<TValues>;\n },\n };\n\n return form;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=new Set([`__proto__`,`constructor`,`prototype`]);function t(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function n(r,i){let a={};for(let[o,s]of Object.entries(r)){if(e.has(o))continue;let r=i?`${i}.${o}`:o;t(s)?Object.assign(a,n(s,r)):a[r]=s}return a}function r(e){let t=new FormData,r=e=>typeof Blob<`u`&&e instanceof Blob,i=e=>typeof File<`u`&&e instanceof File,a=e=>typeof FileList<`u`&&e instanceof FileList;for(let[o,s]of Object.entries(n(e,``)))if(s!=null)if(i(s)||r(s))t.append(o,s);else if(a(s))for(let e=0;e<s.length;e++)t.append(o,s[e]);else if(Array.isArray(s))for(let e of s)t.append(o,i(e)||r(e)?e:String(e));else t.append(o,String(s));return t}exports.toFormData=r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core/path.cjs");function t(n,r){let i={};for(let[a,o]of Object.entries(n)){if(e.isUnsafeKey(a))continue;let n=r?`${r}.${a}`:a;e.isRecord(o)?Object.assign(i,t(o,n)):i[n]=o}return i}function n(e){let n=new FormData,r=e=>typeof Blob<`u`&&e instanceof Blob,i=e=>typeof File<`u`&&e instanceof File,a=e=>typeof FileList<`u`&&e instanceof FileList;for(let[o,s]of Object.entries(t(e,``)))if(s!=null)if(i(s)||r(s))n.append(o,s);else if(a(s))for(let e=0;e<s.length;e++)n.append(o,s[e]);else if(Array.isArray(s))for(let e of s)n.append(o,i(e)||r(e)?e:String(e));else n.append(o,String(s));return n}exports.toFormData=n;
2
2
  //# sourceMappingURL=form-data.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"form-data.cjs","names":[],"sources":["../src/form-data.ts"],"sourcesContent":["const unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\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\nfunction flatten(obj: Record<string, unknown>, prefix: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (unsafeKeys.has(key)) continue;\n\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (isPlainObject(value)) {\n Object.assign(result, flatten(value, fullKey));\n } else {\n result[fullKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Converts a form values object into a `FormData` instance.\n * Nested objects are flattened to dot-notation keys (e.g. `user.name`).\n * `File`, `Blob`, and `FileList` values are appended as-is; all others are coerced to strings.\n * `null` and `undefined` values are omitted.\n */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const fd = new FormData();\n\n const isBlob = (value: unknown): value is Blob => typeof Blob !== 'undefined' && value instanceof Blob;\n const isFile = (value: unknown): value is File => typeof File !== 'undefined' && value instanceof File;\n const isFileList = (value: unknown): value is FileList =>\n typeof FileList !== 'undefined' && value instanceof FileList;\n\n for (const [name, value] of Object.entries(flatten(values, ''))) {\n if (value === null || value === undefined) continue;\n\n if (isFile(value) || isBlob(value)) {\n fd.append(name, value);\n } else if (isFileList(value)) {\n for (let i = 0; i < value.length; i++) fd.append(name, value[i]);\n } else if (Array.isArray(value)) {\n for (const item of value) fd.append(name, isFile(item) || isBlob(item) ? item : String(item));\n } else {\n fd.append(name, String(value));\n }\n }\n\n return fd;\n}\n"],"mappings":"mEAAA,IAAM,EAAa,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAEpE,SAAS,EAAc,EAAkD,CACvE,GAAsB,OAAO,GAAU,WAAnC,GAA+C,MAAM,QAAQ,CAAK,EAAG,MAAO,GAEhF,IAAM,EAAY,OAAO,eAAe,CAAK,EAE7C,OAAO,IAAc,OAAO,WAAa,IAAc,IACzD,CAEA,SAAS,EAAQ,EAA8B,EAAyC,CACtF,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAG,EAAG,CAC9C,GAAI,EAAW,IAAI,CAAG,EAAG,SAEzB,IAAM,EAAU,EAAS,GAAG,EAAO,GAAG,IAAQ,EAE1C,EAAc,CAAK,EACrB,OAAO,OAAO,EAAQ,EAAQ,EAAO,CAAO,CAAC,EAE7C,EAAO,GAAW,CAEtB,CAEA,OAAO,CACT,CAQA,SAAgB,EAAW,EAA2C,CACpE,IAAM,EAAK,IAAI,SAET,EAAU,GAAkC,OAAO,KAAS,KAAe,aAAiB,KAC5F,EAAU,GAAkC,OAAO,KAAS,KAAe,aAAiB,KAC5F,EAAc,GAClB,OAAO,SAAa,KAAe,aAAiB,SAEtD,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAQ,EAAQ,EAAE,CAAC,EACxD,MAAU,KAEd,GAAI,EAAO,CAAK,GAAK,EAAO,CAAK,EAC/B,EAAG,OAAO,EAAM,CAAK,OAChB,GAAI,EAAW,CAAK,EACzB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,IAAK,EAAG,OAAO,EAAM,EAAM,EAAE,OAC1D,GAAI,MAAM,QAAQ,CAAK,EAC5B,IAAK,IAAM,KAAQ,EAAO,EAAG,OAAO,EAAM,EAAO,CAAI,GAAK,EAAO,CAAI,EAAI,EAAO,OAAO,CAAI,CAAC,OAE5F,EAAG,OAAO,EAAM,OAAO,CAAK,CAAC,EAIjC,OAAO,CACT"}
1
+ {"version":3,"file":"form-data.cjs","names":[],"sources":["../src/form-data.ts"],"sourcesContent":["import { isRecord, isUnsafeKey } from './core/path';\n\nfunction flatten(obj: Record<string, unknown>, prefix: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (isUnsafeKey(key)) continue;\n\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (isRecord(value)) {\n Object.assign(result, flatten(value, fullKey));\n } else {\n result[fullKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Converts a form values object into a `FormData` instance.\n * Nested objects are flattened to dot-notation keys (e.g. `user.name`).\n * `File`, `Blob`, and `FileList` values are appended as-is; all others are coerced to strings.\n * `null` and `undefined` values are omitted.\n */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const fd = new FormData();\n\n const isBlob = (value: unknown): value is Blob => typeof Blob !== 'undefined' && value instanceof Blob;\n const isFile = (value: unknown): value is File => typeof File !== 'undefined' && value instanceof File;\n const isFileList = (value: unknown): value is FileList =>\n typeof FileList !== 'undefined' && value instanceof FileList;\n\n for (const [name, value] of Object.entries(flatten(values, ''))) {\n if (value === null || value === undefined) continue;\n\n if (isFile(value) || isBlob(value)) {\n fd.append(name, value);\n } else if (isFileList(value)) {\n for (let i = 0; i < value.length; i++) fd.append(name, value[i]);\n } else if (Array.isArray(value)) {\n for (const item of value) fd.append(name, isFile(item) || isBlob(item) ? item : String(item));\n } else {\n fd.append(name, String(value));\n }\n }\n\n return fd;\n}\n"],"mappings":"sGAEA,SAAS,EAAQ,EAA8B,EAAyC,CACtF,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAG,EAAG,CAC9C,GAAI,EAAA,YAAY,CAAG,EAAG,SAEtB,IAAM,EAAU,EAAS,GAAG,EAAO,GAAG,IAAQ,EAE1C,EAAA,SAAS,CAAK,EAChB,OAAO,OAAO,EAAQ,EAAQ,EAAO,CAAO,CAAC,EAE7C,EAAO,GAAW,CAEtB,CAEA,OAAO,CACT,CAQA,SAAgB,EAAW,EAA2C,CACpE,IAAM,EAAK,IAAI,SAET,EAAU,GAAkC,OAAO,KAAS,KAAe,aAAiB,KAC5F,EAAU,GAAkC,OAAO,KAAS,KAAe,aAAiB,KAC5F,EAAc,GAClB,OAAO,SAAa,KAAe,aAAiB,SAEtD,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAQ,EAAQ,EAAE,CAAC,EACxD,MAAU,KAEd,GAAI,EAAO,CAAK,GAAK,EAAO,CAAK,EAC/B,EAAG,OAAO,EAAM,CAAK,OAChB,GAAI,EAAW,CAAK,EACzB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,IAAK,EAAG,OAAO,EAAM,EAAM,EAAE,OAC1D,GAAI,MAAM,QAAQ,CAAK,EAC5B,IAAK,IAAM,KAAQ,EAAO,EAAG,OAAO,EAAM,EAAO,CAAI,GAAK,EAAO,CAAI,EAAI,EAAO,OAAO,CAAI,CAAC,OAE5F,EAAG,OAAO,EAAM,OAAO,CAAK,CAAC,EAIjC,OAAO,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"form-data.d.ts","sourceRoot":"","sources":["../src/form-data.ts"],"names":[],"mappings":"AA4BA;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,CAuBpE"}
1
+ {"version":3,"file":"form-data.d.ts","sourceRoot":"","sources":["../src/form-data.ts"],"names":[],"mappings":"AAoBA;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,CAuBpE"}
package/dist/form-data.js CHANGED
@@ -1,20 +1,11 @@
1
+ import { isRecord as e, isUnsafeKey as t } from "./core/path.js";
1
2
  //#region src/form-data.ts
2
- var e = /* @__PURE__ */ new Set([
3
- "__proto__",
4
- "constructor",
5
- "prototype"
6
- ]);
7
- function t(e) {
8
- if (typeof e != "object" || !e || Array.isArray(e)) return !1;
9
- let t = Object.getPrototypeOf(e);
10
- return t === Object.prototype || t === null;
11
- }
12
3
  function n(r, i) {
13
4
  let a = {};
14
5
  for (let [o, s] of Object.entries(r)) {
15
- if (e.has(o)) continue;
6
+ if (t(o)) continue;
16
7
  let r = i ? `${i}.${o}` : o;
17
- t(s) ? Object.assign(a, n(s, r)) : a[r] = s;
8
+ e(s) ? Object.assign(a, n(s, r)) : a[r] = s;
18
9
  }
19
10
  return a;
20
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"form-data.js","names":[],"sources":["../src/form-data.ts"],"sourcesContent":["const unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\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\nfunction flatten(obj: Record<string, unknown>, prefix: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (unsafeKeys.has(key)) continue;\n\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (isPlainObject(value)) {\n Object.assign(result, flatten(value, fullKey));\n } else {\n result[fullKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Converts a form values object into a `FormData` instance.\n * Nested objects are flattened to dot-notation keys (e.g. `user.name`).\n * `File`, `Blob`, and `FileList` values are appended as-is; all others are coerced to strings.\n * `null` and `undefined` values are omitted.\n */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const fd = new FormData();\n\n const isBlob = (value: unknown): value is Blob => typeof Blob !== 'undefined' && value instanceof Blob;\n const isFile = (value: unknown): value is File => typeof File !== 'undefined' && value instanceof File;\n const isFileList = (value: unknown): value is FileList =>\n typeof FileList !== 'undefined' && value instanceof FileList;\n\n for (const [name, value] of Object.entries(flatten(values, ''))) {\n if (value === null || value === undefined) continue;\n\n if (isFile(value) || isBlob(value)) {\n fd.append(name, value);\n } else if (isFileList(value)) {\n for (let i = 0; i < value.length; i++) fd.append(name, value[i]);\n } else if (Array.isArray(value)) {\n for (const item of value) fd.append(name, isFile(item) || isBlob(item) ? item : String(item));\n } else {\n fd.append(name, String(value));\n }\n }\n\n return fd;\n}\n"],"mappings":";AAAA,IAAM,oBAAa,IAAI,IAAI;CAAC;CAAa;CAAe;AAAW,CAAC;AAEpE,SAAS,EAAc,GAAkD;CACvE,IAAsB,OAAO,KAAU,aAAnC,KAA+C,MAAM,QAAQ,CAAK,GAAG,OAAO;CAEhF,IAAM,IAAY,OAAO,eAAe,CAAK;CAE7C,OAAO,MAAc,OAAO,aAAa,MAAc;AACzD;AAEA,SAAS,EAAQ,GAA8B,GAAyC;CACtF,IAAM,IAAkC,CAAC;CAEzC,KAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAG,GAAG;EAC9C,IAAI,EAAW,IAAI,CAAG,GAAG;EAEzB,IAAM,IAAU,IAAS,GAAG,EAAO,GAAG,MAAQ;EAE9C,AAAI,EAAc,CAAK,IACrB,OAAO,OAAO,GAAQ,EAAQ,GAAO,CAAO,CAAC,IAE7C,EAAO,KAAW;CAEtB;CAEA,OAAO;AACT;AAQA,SAAgB,EAAW,GAA2C;CACpE,IAAM,IAAK,IAAI,SAAS,GAElB,KAAU,MAAkC,OAAO,OAAS,OAAe,aAAiB,MAC5F,KAAU,MAAkC,OAAO,OAAS,OAAe,aAAiB,MAC5F,KAAc,MAClB,OAAO,WAAa,OAAe,aAAiB;CAEtD,KAAK,IAAM,CAAC,GAAM,MAAU,OAAO,QAAQ,EAAQ,GAAQ,EAAE,CAAC,GACxD,SAAU,MAEd,IAAI,EAAO,CAAK,KAAK,EAAO,CAAK,GAC/B,EAAG,OAAO,GAAM,CAAK;MAChB,IAAI,EAAW,CAAK,GACzB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK,EAAG,OAAO,GAAM,EAAM,EAAE;MAC1D,IAAI,MAAM,QAAQ,CAAK,GAC5B,KAAK,IAAM,KAAQ,GAAO,EAAG,OAAO,GAAM,EAAO,CAAI,KAAK,EAAO,CAAI,IAAI,IAAO,OAAO,CAAI,CAAC;MAE5F,EAAG,OAAO,GAAM,OAAO,CAAK,CAAC;CAIjC,OAAO;AACT"}
1
+ {"version":3,"file":"form-data.js","names":[],"sources":["../src/form-data.ts"],"sourcesContent":["import { isRecord, isUnsafeKey } from './core/path';\n\nfunction flatten(obj: Record<string, unknown>, prefix: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (isUnsafeKey(key)) continue;\n\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (isRecord(value)) {\n Object.assign(result, flatten(value, fullKey));\n } else {\n result[fullKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Converts a form values object into a `FormData` instance.\n * Nested objects are flattened to dot-notation keys (e.g. `user.name`).\n * `File`, `Blob`, and `FileList` values are appended as-is; all others are coerced to strings.\n * `null` and `undefined` values are omitted.\n */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const fd = new FormData();\n\n const isBlob = (value: unknown): value is Blob => typeof Blob !== 'undefined' && value instanceof Blob;\n const isFile = (value: unknown): value is File => typeof File !== 'undefined' && value instanceof File;\n const isFileList = (value: unknown): value is FileList =>\n typeof FileList !== 'undefined' && value instanceof FileList;\n\n for (const [name, value] of Object.entries(flatten(values, ''))) {\n if (value === null || value === undefined) continue;\n\n if (isFile(value) || isBlob(value)) {\n fd.append(name, value);\n } else if (isFileList(value)) {\n for (let i = 0; i < value.length; i++) fd.append(name, value[i]);\n } else if (Array.isArray(value)) {\n for (const item of value) fd.append(name, isFile(item) || isBlob(item) ? item : String(item));\n } else {\n fd.append(name, String(value));\n }\n }\n\n return fd;\n}\n"],"mappings":";;AAEA,SAAS,EAAQ,GAA8B,GAAyC;CACtF,IAAM,IAAkC,CAAC;CAEzC,KAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAG,GAAG;EAC9C,IAAI,EAAY,CAAG,GAAG;EAEtB,IAAM,IAAU,IAAS,GAAG,EAAO,GAAG,MAAQ;EAE9C,AAAI,EAAS,CAAK,IAChB,OAAO,OAAO,GAAQ,EAAQ,GAAO,CAAO,CAAC,IAE7C,EAAO,KAAW;CAEtB;CAEA,OAAO;AACT;AAQA,SAAgB,EAAW,GAA2C;CACpE,IAAM,IAAK,IAAI,SAAS,GAElB,KAAU,MAAkC,OAAO,OAAS,OAAe,aAAiB,MAC5F,KAAU,MAAkC,OAAO,OAAS,OAAe,aAAiB,MAC5F,KAAc,MAClB,OAAO,WAAa,OAAe,aAAiB;CAEtD,KAAK,IAAM,CAAC,GAAM,MAAU,OAAO,QAAQ,EAAQ,GAAQ,EAAE,CAAC,GACxD,SAAU,MAEd,IAAI,EAAO,CAAK,KAAK,EAAO,CAAK,GAC/B,EAAG,OAAO,GAAM,CAAK;MAChB,IAAI,EAAW,CAAK,GACzB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK,EAAG,OAAO,GAAM,EAAM,EAAE;MAC1D,IAAI,MAAM,QAAQ,CAAK,GAC5B,KAAK,IAAM,KAAQ,GAAO,EAAG,OAAO,GAAM,EAAO,CAAI,KAAK,EAAO,CAAI,IAAI,IAAO,OAAO,CAAI,CAAC;MAE5F,EAAG,OAAO,GAAM,OAAO,CAAK,CAAC;CAIjC,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/forge",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "Immutable typed form state with focused fields and explicit full-form validation",
5
5
  "repository": {
6
6
  "type": "git",
@@ -77,8 +77,8 @@
77
77
  },
78
78
  "dependencies": {},
79
79
  "peerDependencies": {
80
- "@vielzeug/spell": "2.2.0",
81
- "@vielzeug/vault": "2.4.0"
80
+ "@vielzeug/spell": "2.3.0",
81
+ "@vielzeug/vault": "2.5.0"
82
82
  },
83
83
  "peerDependenciesMeta": {
84
84
  "@vielzeug/spell": {
@@ -90,8 +90,8 @@
90
90
  },
91
91
  "devDependencies": {
92
92
  "@types/node": "^26.2.0",
93
- "@vielzeug/spell": "2.2.0",
94
- "@vielzeug/vault": "2.4.0",
93
+ "@vielzeug/spell": "2.3.0",
94
+ "@vielzeug/vault": "2.5.0",
95
95
  "typescript": "^6.0.3",
96
96
  "vite": "^8.2.1",
97
97
  "vitest": "^4.1.10"
package/dist/_dev.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=_dev.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_dev.d.ts","sourceRoot":"","sources":["../src/_dev.ts"],"names":[],"mappings":""}