@vielzeug/forge 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -6
- package/dist/adapters/form-data.cjs +1 -1
- package/dist/adapters/form-data.cjs.map +1 -1
- package/dist/adapters/form-data.js +1 -1
- package/dist/adapters/form-data.js.map +1 -1
- package/dist/forge.cjs +1 -1
- package/dist/forge.cjs.map +1 -1
- package/dist/forge.iife.js +1 -1
- package/dist/forge.iife.js.map +1 -1
- package/dist/forge.js +1 -1
- package/dist/forge.js.map +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.cjs.map +1 -1
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +60 -71
- package/dist/form.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/spell.cjs +1 -1
- package/dist/spell.cjs.map +1 -1
- package/dist/spell.d.ts +1 -1
- package/dist/spell.d.ts.map +1 -1
- package/dist/spell.js +0 -1
- package/dist/spell.js.map +1 -1
- package/package.json +42 -50
- package/dist/_utils.cjs +0 -1
- package/dist/_utils.d.ts +0 -3
- package/dist/_utils.d.ts.map +0 -1
- package/dist/_utils.js +0 -2
- package/dist/devtools.cjs +0 -2
- package/dist/devtools.cjs.map +0 -1
- package/dist/devtools.d.ts +0 -7
- package/dist/devtools.d.ts.map +0 -1
- package/dist/devtools.js +0 -11
- package/dist/devtools.js.map +0 -1
package/README.md
CHANGED
|
@@ -28,12 +28,6 @@ const result = await form.submit((value) => saveProfile(value));
|
|
|
28
28
|
- `@vielzeug/forge/spell` — typed `customValidator(schema)` adapter with per-union diagnostics.
|
|
29
29
|
- `@vielzeug/forge/vault` — explicit `saveForm()` and `loadForm()` draft helpers.
|
|
30
30
|
|
|
31
|
-
## Breaking 2.0 changes
|
|
32
|
-
|
|
33
|
-
- Removed field validation, numeric array field handles, stable field identity, direct metadata getters, and Ripple runtime coupling.
|
|
34
|
-
- `validate()` returns `{ status: 'valid' | 'invalid' | 'aborted' }`.
|
|
35
|
-
- Read metadata from `form.state`; read values from `form.value`.
|
|
36
|
-
|
|
37
31
|
## Documentation
|
|
38
32
|
|
|
39
33
|
- [Overview](https://vielzeug.dev/forge/)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
let e=require("@vielzeug/arsenal/object");function t(t){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((0,e.flattenPaths)(t)))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=t;
|
|
2
2
|
//# sourceMappingURL=form-data.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-data.cjs","names":[],"sources":["../../src/adapters/form-data.ts"],"sourcesContent":["import { flattenValues } from '
|
|
1
|
+
{"version":3,"file":"form-data.cjs","names":[],"sources":["../../src/adapters/form-data.ts"],"sourcesContent":["import { flattenPaths as flattenValues } from '@vielzeug/arsenal/object';\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(flattenValues(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":"0CAQA,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,SAAA,EAAQ,EAAA,aAAA,CAAc,CAAM,CAAC,EAC1D,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,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { flattenPaths as e } from "@vielzeug/arsenal/object";
|
|
2
2
|
//#region src/adapters/form-data.ts
|
|
3
3
|
function t(t) {
|
|
4
4
|
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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-data.js","names":[],"sources":["../../src/adapters/form-data.ts"],"sourcesContent":["import { flattenValues } from '
|
|
1
|
+
{"version":3,"file":"form-data.js","names":[],"sources":["../../src/adapters/form-data.ts"],"sourcesContent":["import { flattenPaths as flattenValues } from '@vielzeug/arsenal/object';\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(flattenValues(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":";;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,EAAc,CAAM,CAAC,GAC1D,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/dist/forge.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=new Set([`__proto__`,`constructor`,`prototype`]);function t(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}var n=10;function r(i,a,o){let s={};for(let[c,l]of Object.entries(i)){if(e.has(c))continue;let i=a?`${a}.${c}`:c;t(l)&&o<n?Object.assign(s,r(l,i,o+1)):s[i]=l}return s}function i(e){return r(e,``,0)}function a(e){let t=new FormData,n=e=>typeof Blob<`u`&&e instanceof Blob,r=e=>typeof File<`u`&&e instanceof File,a=e=>typeof FileList<`u`&&e instanceof FileList;for(let[o,s]of Object.entries(i(e)))if(s!=null)if(r(s)||n(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,r(e)||n(e)?e:String(e));else t.append(o,String(s));return t}var o=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},s=class extends o{constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},c=class extends o{},l=class extends o{},u=class extends o{},d=new Set([`__proto__`,`constructor`,`prototype`]);function f(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function p(e){if(!e||d.has(e))throw new c(`Invalid field key '${e}'.`)}function m(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File}function h(e){if(Array.isArray(e))return Object.freeze(e.map(h));if(typeof e!=`object`||!e||m(e))return e;if(!f(e))throw new c(`Form values must contain only plain objects, arrays, File, Blob, or primitive values.`);return Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,h(t)])))}function g(e,t){let n=e;for(let e of t){if(!f(n)||!Object.hasOwn(n,e))return;n=n[e]}return n}function _(e,t){let n=e;for(let e of t){if(!f(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return!0}function v(e,t,n){let[r,...i]=t;if(p(r),i.length===0)return Object.freeze({...e,[r]:h(n)});let a=e[r];if(a!==void 0&&!f(a))throw new c(`Cannot select '${r}' because it is not an object.`);return Object.freeze({...e,[r]:v(a??{},i,n)})}function y(e,t,n){let[r,...i]=n;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(!f(a)){if(Object.hasOwn(t,r))return Object.freeze({...e,[r]:a});let{[r]:n,...i}=e;return Object.freeze(i)}let o=f(e[r])?e[r]:{};return Object.freeze({...e,[r]:y(o,a,i)})}function b(e,t,n){let[r,...i]=t,a={...e};if(i.length===0)n?a[r]=!0:delete a[r];else{let t=b(f(e[r])?e[r]:{},i,n);Object.keys(t).length===0?delete a[r]:a[r]=t}return Object.freeze(a)}function x(e,t){let n=e;for(let e of t){if(!f(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return n===!0}function S(e){return f(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,!f(t)||S(t)]))):{}}function C(e,t){let n=g(e,t);return typeof n==`string`?n:void 0}function w(e){if(typeof e==`string`)return e;if(!f(e))return;let t=Object.entries(e).map(([e,t])=>[e,w(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}function T(e){queueMicrotask(()=>{throw e})}function E(e,t){let n=g(e.value,t),r=g(e.baseline,t);return Object.freeze({dirty:n!==r||_(e.value,t)!==_(e.baseline,t),error:C(e.errors,t),touched:x(e.touched,t),value:n})}function D(e){return Object.freeze({error:e.error,errors:e.errors,submitCount:e.submitCount,submitting:e.isSubmitting,touched:Object.keys(e.touched).length>0,valid:e.error===void 0&&e.errors===void 0,validating:e.isValidating})}function O(e){let t=h(e.initialValues);function n(t){if(!e.onSubscriberError){T(t);return}try{e.onSubscriberError(t)}catch(e){T(e)}}let r={baseline:t,error:void 0,errors:void 0,isSubmitting:!1,isValidating:!1,submitCount:0,touched:{},value:t},i=new Set,a=new AbortController,o=!1,d;function m(e){if(o)throw new s(e)}function _(){for(let e of[...i])try{e()}catch(e){n(e)}}function x(e){r=Object.freeze(e(r)),_()}async function C(t){m(`validate`),d?.abort();let n=new AbortController,i=t?AbortSignal.any([n.signal,t]):n.signal;d=n,x(e=>({...e,isValidating:!0}));try{let t=e.validate?await e.validate(r.value,i):void 0;if(i.aborted||d!==n)return Object.freeze({status:`aborted`});let a=t?.fields?w(h(t.fields)):void 0,o=t?.formError;return x(e=>({...e,error:o,errors:a})),Object.freeze(a===void 0&&o===void 0?{status:`valid`}:{errors:a,formError:o,status:`invalid`})}catch(e){if(i.aborted||d!==n)return Object.freeze({status:`aborted`});throw new u(`Form validation failed.`,{cause:e})}finally{d===n&&(d=void 0,o||x(e=>({...e,isValidating:!1})))}}function O(e){return Object.assign({get dirty(){return E(r,e).dirty},get error(){return E(r,e).error},reset(){m(`field().reset`),d?.abort(),x(t=>({...t,touched:b(t.touched,e,!1),value:y(t.value,t.baseline,e)}))},set(t){m(`field().set`),d?.abort();let n=g(r.value,e),i=typeof t==`function`?t(n):t;x(t=>({...t,value:v(t.value,e,i)}))},subscribe(t,n={}){m(`field().subscribe`);let a=E(r,e);n.immediate&&t(a);let o=()=>{let n=E(r,e);(n.value!==a.value||n.error!==a.error||n.touched!==a.touched||n.dirty!==a.dirty)&&(a=n,t(n))};return i.add(o),()=>i.delete(o)},touch(){m(`field().touch`),x(t=>({...t,touched:b(t.touched,e,!0)}))},get touched(){return E(r,e).touched},get value(){return E(r,e).value}},{field(t){p(t);let n=g(r.value,e);if(n!==void 0&&!f(n))throw new c(`Cannot select '${t}' because the current field value is not an object.`);return O([...e,t])}})}let k={get disposalSignal(){return a.signal},dispose(){o||(o=!0,a.abort(),d?.abort(),i.clear())},get disposed(){return o},field(e){return p(e),O([e])},reset(e){m(`reset`),d?.abort();let t=e===void 0?r.baseline:h(e);x(e=>({...e,baseline:t,error:void 0,errors:void 0,touched:{},value:t}))},set(e){m(`set`),d?.abort();let t=typeof e==`function`?e(k.value):e;x(e=>({...e,error:void 0,errors:void 0,value:h(t)}))},get state(){return D(r)},async submit(e){if(m(`submit`),r.isSubmitting)throw new l(`submit() called while a submission is already in progress`);x(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:S(e.value)}));try{let t=await C();return t.status===`aborted`?Object.freeze({ok:!1,type:`aborted`}):t.status===`invalid`?Object.freeze({errors:t.errors,formError:t.formError,ok:!1,type:`validation`}):Object.freeze({ok:!0,value:await e(k.value)})}finally{o||x(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){m(`subscribe`),t.immediate&&e(D(r));let n=()=>e(D(r));return i.add(n),()=>i.delete(n)},[Symbol.dispose](){k.dispose()},validate:C,get value(){return r.value}};return k}exports.ForgeConfigError=c,exports.ForgeDisposedError=s,exports.ForgeError=o,exports.ForgeSubmitError=l,exports.ForgeValidationError=u,exports.createForm=O,exports.toFormData=a;
|
|
2
2
|
//# sourceMappingURL=forge.cjs.map
|
package/dist/forge.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forge.cjs","names":["e","e"],"sources":["../src/errors.ts","../src/core/path.ts","../src/form.ts","../../arsenal/dist/_common/unsafePaths.js","../../arsenal/dist/guards/isPlainObject.js","../../arsenal/dist/object/flattenPaths.js","../src/adapters/form-data.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 static is(err: unknown): err is ForgeError {\n return err instanceof ForgeError;\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 ErrorTree = Record<string, unknown>;\ntype RecordValue = Record<string, 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\nexport function writeError(tree: ErrorTree, path: readonly string[], message: string): ErrorTree {\n const [key, ...rest] = path;\n\n if (!key || unsafeKeys.has(key)) return tree;\n\n if (rest.length === 0) return tree[key] === undefined ? { ...tree, [key]: message } : tree;\n\n const child = tree[key];\n\n if (child !== undefined && !isRecord(child)) return tree;\n\n return { ...tree, [key]: writeError((child ?? {}) as ErrorTree, rest, message) };\n}\n\nfunction isAtomicLeaf(value: unknown): boolean {\n return (\n (typeof Blob !== 'undefined' && value instanceof Blob) || (typeof File !== 'undefined' && value instanceof File)\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('Form values must contain only plain objects, arrays, File, Blob, or primitive values.');\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[]): T | undefined {\n let current = value;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return undefined;\n\n current = current[key];\n }\n\n return current as T | undefined;\n}\n\nexport function hasAtPath(value: unknown, path: readonly string[]): boolean {\n let current = value;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key];\n }\n\n return true;\n}\n\nexport function writeAtPath<T extends RecordValue>(value: T, path: readonly string[], next: unknown): T {\n const [key, ...rest] = path;\n\n assertSafeKey(key);\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)) {\n throw new ForgeConfigError(`Cannot select '${key}' because it is not an object.`);\n }\n\n return Object.freeze({ ...value, [key]: writeAtPath((child ?? {}) as RecordValue, rest, next) }) as T;\n}\n\nexport function resetAtPath<T extends RecordValue>(value: T, baseline: T, path: readonly string[]): T {\n const [key, ...rest] = path;\n\n if (rest.length === 0) {\n if (Object.hasOwn(baseline, key)) return Object.freeze({ ...value, [key]: baseline[key] }) as T;\n\n const { [key]: _removed, ...next } = value;\n\n return Object.freeze(next) as T;\n }\n\n const baselineChild = baseline[key];\n\n if (!isRecord(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 = isRecord(value[key]) ? value[key] : {};\n\n return Object.freeze({ ...value, [key]: resetAtPath(currentChild, baselineChild, rest) }) as T;\n}\n\nexport function writeMeta(meta: MetaRoot, path: readonly string[], next: boolean): MetaRoot {\n const [key, ...rest] = path;\n const copy: Record<string, MetaTree> = { ...meta };\n\n if (rest.length === 0) {\n if (next) copy[key] = true;\n else delete copy[key];\n } else {\n const child = isRecord(meta[key]) ? (meta[key] as MetaRoot) : {};\n const updated = writeMeta(child, rest, next);\n\n if (Object.keys(updated).length === 0) delete copy[key];\n else copy[key] = updated;\n }\n\n return Object.freeze(copy);\n}\n\nexport function readMeta(meta: MetaRoot, path: readonly string[]): boolean {\n let current: MetaTree | undefined = meta;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key] as MetaTree;\n }\n\n return current === true;\n}\n\nexport function touchAll(value: unknown): MetaRoot {\n if (!isRecord(value)) return {};\n\n return Object.freeze(\n Object.fromEntries(\n Object.entries(value).map(([key, child]) => [key, isRecord(child) ? touchAll(child) : (true as const)]),\n ),\n );\n}\n\nexport function readError(errors: unknown, path: readonly string[]): string | undefined {\n const error = readAtPath(errors, path);\n\n return typeof error === 'string' ? error : undefined;\n}\n\nexport function normalizeErrors<T>(errors: T): T | undefined {\n if (typeof errors === 'string') return errors;\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 type {\n Field,\n FieldState,\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n SubscribeOptions,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\nimport {\n assertSafeKey,\n hasAtPath,\n immutable,\n isRecord,\n normalizeErrors,\n readAtPath,\n readError,\n readMeta,\n resetAtPath,\n type MetaRoot,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n error: string | undefined;\n errors: FormErrors<TValues> | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n value: TValues;\n}>;\n\ntype Store<T> = {\n dispose(): void;\n read(): T;\n subscribe(listener: () => void): Unsubscribe;\n write(next: T): void;\n};\n\nfunction createStore<T>(initial: T, onListenerError: (error: unknown) => void): Store<T> {\n let current = initial;\n const listeners = new Set<() => void>();\n\n return {\n dispose() {\n listeners.clear();\n },\n read: () => current,\n subscribe(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n write(next) {\n if (next === current) return;\n\n current = next;\n\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n onListenerError(error);\n }\n }\n },\n };\n}\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nfunction makeFieldState<V>(state: InternalState<Record<string, unknown>>, path: readonly string[]): 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\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n error: current.error,\n errors: current.errors,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n valid: current.error === undefined && current.errors === undefined,\n validating: current.isValidating,\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\n function reportListenerError(error: unknown): void {\n if (!options.onSubscriberError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n options.onSubscriberError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n const store = createStore<InternalState<TValues>>(\n {\n baseline: initial,\n error: undefined,\n errors: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n value: initial,\n },\n reportListenerError,\n );\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\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 store.write(Object.freeze(update(store.read())));\n }\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n validationController?.abort();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((current) => ({ ...current, isValidating: true }));\n\n try {\n const result: ValidationErrors<TValues> | undefined = options.validate\n ? await options.validate(store.read().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\n write((current) => ({ ...current, error: formError, errors }));\n\n return errors === undefined && formError === undefined\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((current) => ({ ...current, isValidating: false }));\n }\n }\n }\n\n function createField<V>(path: readonly string[]): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path).dirty;\n },\n get error() {\n return makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path).error;\n },\n reset() {\n ensureActive('field().reset');\n validationController?.abort();\n write((current) => ({\n ...current,\n touched: writeMeta(current.touched, path, false),\n value: resetAtPath(current.value, current.baseline, path),\n }));\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n ensureActive('field().set');\n validationController?.abort();\n\n const previous = readAtPath<V>(store.read().value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n write((current) => ({ ...current, value: writeAtPath(current.value, path, value) }));\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n return store.subscribe(() => {\n const next = makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, 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 touch() {\n ensureActive('field().touch');\n write((current) => ({ ...current, touched: writeMeta(current.touched, path, true) }));\n },\n get touched() {\n return makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path).touched;\n },\n get value() {\n return makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path).value;\n },\n };\n\n return Object.assign(common, {\n field<K extends keyof NonNullable<V> & string>(key: K): Field<NonNullable<V>[K]> {\n assertSafeKey(key);\n\n const current = readAtPath(store.read().value, path);\n\n if (current !== undefined && !isRecord(current)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current field value is not an object.`);\n }\n\n return createField<NonNullable<V>[K]>([...path, key]);\n },\n }) as Field<V>;\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 validationController?.abort();\n store.dispose();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n\n return createField<TValues[typeof key]>([key]);\n },\n reset(next) {\n ensureActive('reset');\n validationController?.abort();\n\n const baseline = next === undefined ? store.read().baseline : immutable(next);\n\n write((current) => ({\n ...current,\n baseline,\n error: undefined,\n errors: undefined,\n touched: {},\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n validationController?.abort();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((current) => ({ ...current, error: undefined, errors: undefined, value: immutable(value) }));\n },\n get state() {\n return makeFormState(store.read());\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>) => MaybePromise<TResult>,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (store.read().isSubmitting)\n throw new ForgeSubmitError('submit() called while a submission is already in progress');\n\n write((current) => ({\n ...current,\n isSubmitting: true,\n submitCount: current.submitCount + 1,\n touched: touchAll(current.value),\n }));\n\n try {\n const result = await validate();\n\n if (result.status === 'aborted') return Object.freeze({ ok: false, type: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({\n errors: result.errors,\n formError: result.formError,\n ok: false,\n type: 'validation',\n });\n }\n\n return Object.freeze({ ok: true, value: await handler(form.value) });\n } finally {\n if (!disposed) write((current) => ({ ...current, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(store.read()));\n\n return store.subscribe(() => listener(makeFormState(store.read())));\n },\n [Symbol.dispose]() {\n form.dispose();\n },\n validate,\n get value() {\n return store.read().value as ReadonlyDeep<TValues>;\n },\n };\n\n return form;\n}\n","//#region src/_common/unsafePaths.ts\nvar e = /* @__PURE__ */ new Set([\n\t\"__proto__\",\n\t\"constructor\",\n\t\"prototype\"\n]);\nfunction t(t) {\n\treturn typeof t == \"string\" && e.has(t);\n}\n//#endregion\nexport { e as UNSAFE_PATH_SEGMENTS, t as isUnsafeKey };\n\n//# sourceMappingURL=unsafePaths.js.map","//#region src/guards/isPlainObject.ts\nfunction e(e) {\n\tif (typeof e != \"object\" || !e) return !1;\n\tlet t = Object.getPrototypeOf(e);\n\treturn t === Object.prototype || t === null;\n}\n//#endregion\nexport { e as isPlainObject };\n\n//# sourceMappingURL=isPlainObject.js.map","import { UNSAFE_PATH_SEGMENTS as e } from \"../_common/unsafePaths.js\";\nimport { isPlainObject as t } from \"../guards/isPlainObject.js\";\n//#region src/object/flattenPaths.ts\nvar n = 10;\nfunction r(i, a, o) {\n\tlet s = {};\n\tfor (let [c, l] of Object.entries(i)) {\n\t\tif (e.has(c)) continue;\n\t\tlet i = a ? `${a}.${c}` : c;\n\t\tt(l) && o < n ? Object.assign(s, r(l, i, o + 1)) : s[i] = l;\n\t}\n\treturn s;\n}\nfunction i(e) {\n\treturn r(e, \"\", 0);\n}\nfunction a(n) {\n\tlet r = {};\n\tfor (let [i, a] of Object.entries(n)) {\n\t\tlet n = i.split(\".\");\n\t\tif (n.some((t) => e.has(t))) continue;\n\t\tlet o = r;\n\t\tfor (let e = 0; e < n.length - 1; e++) t(o[n[e]]) || (o[n[e]] = {}), o = o[n[e]];\n\t\to[n[n.length - 1]] = a;\n\t}\n\treturn r;\n}\n//#endregion\nexport { i as flattenPaths, a as unflattenPaths };\n\n//# sourceMappingURL=flattenPaths.js.map","import { flattenValues } from '../_utils';\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(flattenValues(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":"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"}
|
|
1
|
+
{"version":3,"file":"forge.cjs","names":["e","e"],"sources":["../../arsenal/dist/_common/unsafePaths.js","../../arsenal/dist/guards/isPlainObject.js","../../arsenal/dist/object/flattenPaths.js","../src/adapters/form-data.ts","../src/errors.ts","../src/core/path.ts","../src/form.ts"],"sourcesContent":["//#region src/_common/unsafePaths.ts\nvar e = /* @__PURE__ */ new Set([\n\t\"__proto__\",\n\t\"constructor\",\n\t\"prototype\"\n]);\nfunction t(t) {\n\treturn typeof t == \"string\" && e.has(t);\n}\n//#endregion\nexport { e as UNSAFE_PATH_SEGMENTS, t as isUnsafeKey };\n\n//# sourceMappingURL=unsafePaths.js.map","//#region src/guards/isPlainObject.ts\nfunction e(e) {\n\tif (typeof e != \"object\" || !e) return !1;\n\tlet t = Object.getPrototypeOf(e);\n\treturn t === Object.prototype || t === null;\n}\n//#endregion\nexport { e as isPlainObject };\n\n//# sourceMappingURL=isPlainObject.js.map","import { UNSAFE_PATH_SEGMENTS as e } from \"../_common/unsafePaths.js\";\nimport { isPlainObject as t } from \"../guards/isPlainObject.js\";\n//#region src/object/flattenPaths.ts\nvar n = 10;\nfunction r(i, a, o) {\n\tlet s = {};\n\tfor (let [c, l] of Object.entries(i)) {\n\t\tif (e.has(c)) continue;\n\t\tlet i = a ? `${a}.${c}` : c;\n\t\tt(l) && o < n ? Object.assign(s, r(l, i, o + 1)) : s[i] = l;\n\t}\n\treturn s;\n}\nfunction i(e) {\n\treturn r(e, \"\", 0);\n}\nfunction a(n) {\n\tlet r = {};\n\tfor (let [i, a] of Object.entries(n)) {\n\t\tlet n = i.split(\".\");\n\t\tif (n.some((t) => e.has(t))) continue;\n\t\tlet o = r;\n\t\tfor (let e = 0; e < n.length - 1; e++) t(o[n[e]]) || (o[n[e]] = {}), o = o[n[e]];\n\t\to[n[n.length - 1]] = a;\n\t}\n\treturn r;\n}\n//#endregion\nexport { i as flattenPaths, a as unflattenPaths };\n\n//# sourceMappingURL=flattenPaths.js.map","import { flattenPaths as flattenValues } from '@vielzeug/arsenal/object';\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(flattenValues(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","/** 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 static is(err: unknown): err is ForgeError {\n return err instanceof ForgeError;\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 ErrorTree = Record<string, unknown>;\ntype RecordValue = Record<string, 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\nexport function writeError(tree: ErrorTree, path: readonly string[], message: string): ErrorTree {\n const [key, ...rest] = path;\n\n if (!key || unsafeKeys.has(key)) return tree;\n\n if (rest.length === 0) return tree[key] === undefined ? { ...tree, [key]: message } : tree;\n\n const child = tree[key];\n\n if (child !== undefined && !isRecord(child)) return tree;\n\n return { ...tree, [key]: writeError((child ?? {}) as ErrorTree, rest, message) };\n}\n\nfunction isAtomicLeaf(value: unknown): boolean {\n return (\n (typeof Blob !== 'undefined' && value instanceof Blob) || (typeof File !== 'undefined' && value instanceof File)\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('Form values must contain only plain objects, arrays, File, Blob, or primitive values.');\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[]): T | undefined {\n let current = value;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return undefined;\n\n current = current[key];\n }\n\n return current as T | undefined;\n}\n\nexport function hasAtPath(value: unknown, path: readonly string[]): boolean {\n let current = value;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key];\n }\n\n return true;\n}\n\nexport function writeAtPath<T extends RecordValue>(value: T, path: readonly string[], next: unknown): T {\n const [key, ...rest] = path;\n\n assertSafeKey(key);\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)) {\n throw new ForgeConfigError(`Cannot select '${key}' because it is not an object.`);\n }\n\n return Object.freeze({ ...value, [key]: writeAtPath((child ?? {}) as RecordValue, rest, next) }) as T;\n}\n\nexport function resetAtPath<T extends RecordValue>(value: T, baseline: T, path: readonly string[]): T {\n const [key, ...rest] = path;\n\n if (rest.length === 0) {\n if (Object.hasOwn(baseline, key)) return Object.freeze({ ...value, [key]: baseline[key] }) as T;\n\n const { [key]: _removed, ...next } = value;\n\n return Object.freeze(next) as T;\n }\n\n const baselineChild = baseline[key];\n\n if (!isRecord(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 = isRecord(value[key]) ? value[key] : {};\n\n return Object.freeze({ ...value, [key]: resetAtPath(currentChild, baselineChild, rest) }) as T;\n}\n\nexport function writeMeta(meta: MetaRoot, path: readonly string[], next: boolean): MetaRoot {\n const [key, ...rest] = path;\n const copy: Record<string, MetaTree> = { ...meta };\n\n if (rest.length === 0) {\n if (next) copy[key] = true;\n else delete copy[key];\n } else {\n const child = isRecord(meta[key]) ? (meta[key] as MetaRoot) : {};\n const updated = writeMeta(child, rest, next);\n\n if (Object.keys(updated).length === 0) delete copy[key];\n else copy[key] = updated;\n }\n\n return Object.freeze(copy);\n}\n\nexport function readMeta(meta: MetaRoot, path: readonly string[]): boolean {\n let current: MetaTree | undefined = meta;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key] as MetaTree;\n }\n\n return current === true;\n}\n\nexport function touchAll(value: unknown): MetaRoot {\n if (!isRecord(value)) return {};\n\n return Object.freeze(\n Object.fromEntries(\n Object.entries(value).map(([key, child]) => [key, isRecord(child) ? touchAll(child) : (true as const)]),\n ),\n );\n}\n\nexport function readError(errors: unknown, path: readonly string[]): string | undefined {\n const error = readAtPath(errors, path);\n\n return typeof error === 'string' ? error : undefined;\n}\n\nexport function normalizeErrors<T>(errors: T): T | undefined {\n if (typeof errors === 'string') return errors;\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 {\n assertSafeKey,\n hasAtPath,\n immutable,\n isRecord,\n type MetaRoot,\n normalizeErrors,\n readAtPath,\n readError,\n readMeta,\n resetAtPath,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\nimport type {\n Field,\n FieldState,\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n SubscribeOptions,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n error: string | undefined;\n errors: FormErrors<TValues> | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n value: TValues;\n}>;\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nfunction makeFieldState<V>(state: InternalState<Record<string, unknown>>, path: readonly string[]): 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\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n error: current.error,\n errors: current.errors,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n valid: current.error === undefined && current.errors === undefined,\n validating: current.isValidating,\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\n function reportListenerError(error: unknown): void {\n if (!options.onSubscriberError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n options.onSubscriberError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n let current: InternalState<TValues> = {\n baseline: initial,\n error: undefined,\n errors: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n value: initial,\n };\n const listeners = new Set<() => void>();\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\n\n function ensureActive(operation: string): void {\n if (disposed) throw new ForgeDisposedError(operation);\n }\n\n function notify(): void {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n reportListenerError(error);\n }\n }\n }\n\n function write(update: (current: InternalState<TValues>) => InternalState<TValues>): void {\n current = Object.freeze(update(current));\n notify();\n }\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n validationController?.abort();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((current) => ({ ...current, 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\n write((current) => ({ ...current, error: formError, errors }));\n\n return errors === undefined && formError === undefined\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((current) => ({ ...current, isValidating: false }));\n }\n }\n }\n\n function createField<V>(path: readonly string[]): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(current as InternalState<Record<string, unknown>>, path).dirty;\n },\n get error() {\n return makeFieldState<V>(current as InternalState<Record<string, unknown>>, path).error;\n },\n reset() {\n ensureActive('field().reset');\n validationController?.abort();\n write((current) => ({\n ...current,\n touched: writeMeta(current.touched, path, false),\n value: resetAtPath(current.value, current.baseline, path),\n }));\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n ensureActive('field().set');\n validationController?.abort();\n\n const previous = readAtPath<V>(current.value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n write((current) => ({ ...current, value: writeAtPath(current.value, path, value) }));\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(current as InternalState<Record<string, unknown>>, path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n const filtered = () => {\n const next = makeFieldState<V>(current as InternalState<Record<string, unknown>>, 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 listeners.add(filtered);\n\n return () => listeners.delete(filtered);\n },\n touch() {\n ensureActive('field().touch');\n write((current) => ({ ...current, touched: writeMeta(current.touched, path, true) }));\n },\n get touched() {\n return makeFieldState<V>(current as InternalState<Record<string, unknown>>, path).touched;\n },\n get value() {\n return makeFieldState<V>(current as InternalState<Record<string, unknown>>, path).value;\n },\n };\n\n return Object.assign(common, {\n field<K extends keyof NonNullable<V> & string>(key: K): Field<NonNullable<V>[K]> {\n assertSafeKey(key);\n\n const currentVal = readAtPath(current.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<NonNullable<V>[K]>([...path, key]);\n },\n }) as Field<V>;\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 validationController?.abort();\n listeners.clear();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n\n return createField<TValues[typeof key]>([key]);\n },\n reset(next) {\n ensureActive('reset');\n validationController?.abort();\n\n const baseline = next === undefined ? current.baseline : immutable(next);\n\n write((current) => ({\n ...current,\n baseline,\n error: undefined,\n errors: undefined,\n touched: {},\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n validationController?.abort();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((current) => ({ ...current, error: undefined, errors: undefined, value: immutable(value) }));\n },\n get state() {\n return makeFormState(current);\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>) => MaybePromise<TResult>,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (current.isSubmitting) throw new ForgeSubmitError('submit() called while a submission is already in progress');\n\n write((current) => ({\n ...current,\n isSubmitting: true,\n submitCount: current.submitCount + 1,\n touched: touchAll(current.value),\n }));\n\n try {\n const result = await validate();\n\n if (result.status === 'aborted') return Object.freeze({ ok: false, type: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({\n errors: result.errors,\n formError: result.formError,\n ok: false,\n type: 'validation',\n });\n }\n\n return Object.freeze({ ok: true, value: await handler(form.value) });\n } finally {\n if (!disposed) write((current) => ({ ...current, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(current));\n\n const formListener = () => listener(makeFormState(current));\n\n listeners.add(formListener);\n\n return () => listeners.delete(formListener);\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.iife.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var Forge=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},
|
|
1
|
+
var Forge=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=new Set([`__proto__`,`constructor`,`prototype`]);function n(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}var r=10;function i(e,a,o){let s={};for(let[c,l]of Object.entries(e)){if(t.has(c))continue;let e=a?`${a}.${c}`:c;n(l)&&o<r?Object.assign(s,i(l,e,o+1)):s[e]=l}return s}function a(e){return i(e,``,0)}function o(e){let t=new FormData,n=e=>typeof Blob<`u`&&e instanceof Blob,r=e=>typeof File<`u`&&e instanceof File,i=e=>typeof FileList<`u`&&e instanceof FileList;for(let[o,s]of Object.entries(a(e)))if(s!=null)if(r(s)||n(s))t.append(o,s);else if(i(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,r(e)||n(e)?e:String(e));else t.append(o,String(s));return t}var s=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},c=class extends s{constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},l=class extends s{},u=class extends s{},d=class extends s{},f=new Set([`__proto__`,`constructor`,`prototype`]);function p(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function m(e){if(!e||f.has(e))throw new l(`Invalid field key '${e}'.`)}function h(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File}function g(e){if(Array.isArray(e))return Object.freeze(e.map(g));if(typeof e!=`object`||!e||h(e))return e;if(!p(e))throw new l(`Form values must contain only plain objects, arrays, File, Blob, or primitive values.`);return Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,g(t)])))}function _(e,t){let n=e;for(let e of t){if(!p(n)||!Object.hasOwn(n,e))return;n=n[e]}return n}function v(e,t){let n=e;for(let e of t){if(!p(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return!0}function y(e,t,n){let[r,...i]=t;if(m(r),i.length===0)return Object.freeze({...e,[r]:g(n)});let a=e[r];if(a!==void 0&&!p(a))throw new l(`Cannot select '${r}' because it is not an object.`);return Object.freeze({...e,[r]:y(a??{},i,n)})}function b(e,t,n){let[r,...i]=n;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(!p(a)){if(Object.hasOwn(t,r))return Object.freeze({...e,[r]:a});let{[r]:n,...i}=e;return Object.freeze(i)}let o=p(e[r])?e[r]:{};return Object.freeze({...e,[r]:b(o,a,i)})}function x(e,t,n){let[r,...i]=t,a={...e};if(i.length===0)n?a[r]=!0:delete a[r];else{let t=x(p(e[r])?e[r]:{},i,n);Object.keys(t).length===0?delete a[r]:a[r]=t}return Object.freeze(a)}function S(e,t){let n=e;for(let e of t){if(!p(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return n===!0}function C(e){return p(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,!p(t)||C(t)]))):{}}function w(e,t){let n=_(e,t);return typeof n==`string`?n:void 0}function T(e){if(typeof e==`string`)return e;if(!p(e))return;let t=Object.entries(e).map(([e,t])=>[e,T(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}function E(e){queueMicrotask(()=>{throw e})}function D(e,t){let n=_(e.value,t),r=_(e.baseline,t);return Object.freeze({dirty:n!==r||v(e.value,t)!==v(e.baseline,t),error:w(e.errors,t),touched:S(e.touched,t),value:n})}function O(e){return Object.freeze({error:e.error,errors:e.errors,submitCount:e.submitCount,submitting:e.isSubmitting,touched:Object.keys(e.touched).length>0,valid:e.error===void 0&&e.errors===void 0,validating:e.isValidating})}function k(e){let t=g(e.initialValues);function n(t){if(!e.onSubscriberError){E(t);return}try{e.onSubscriberError(t)}catch(e){E(e)}}let r={baseline:t,error:void 0,errors:void 0,isSubmitting:!1,isValidating:!1,submitCount:0,touched:{},value:t},i=new Set,a=new AbortController,o=!1,s;function f(e){if(o)throw new c(e)}function h(){for(let e of[...i])try{e()}catch(e){n(e)}}function v(e){r=Object.freeze(e(r)),h()}async function S(t){f(`validate`),s?.abort();let n=new AbortController,i=t?AbortSignal.any([n.signal,t]):n.signal;s=n,v(e=>({...e,isValidating:!0}));try{let t=e.validate?await e.validate(r.value,i):void 0;if(i.aborted||s!==n)return Object.freeze({status:`aborted`});let a=t?.fields?T(g(t.fields)):void 0,o=t?.formError;return v(e=>({...e,error:o,errors:a})),Object.freeze(a===void 0&&o===void 0?{status:`valid`}:{errors:a,formError:o,status:`invalid`})}catch(e){if(i.aborted||s!==n)return Object.freeze({status:`aborted`});throw new d(`Form validation failed.`,{cause:e})}finally{s===n&&(s=void 0,o||v(e=>({...e,isValidating:!1})))}}function w(e){return Object.assign({get dirty(){return D(r,e).dirty},get error(){return D(r,e).error},reset(){f(`field().reset`),s?.abort(),v(t=>({...t,touched:x(t.touched,e,!1),value:b(t.value,t.baseline,e)}))},set(t){f(`field().set`),s?.abort();let n=_(r.value,e),i=typeof t==`function`?t(n):t;v(t=>({...t,value:y(t.value,e,i)}))},subscribe(t,n={}){f(`field().subscribe`);let a=D(r,e);n.immediate&&t(a);let o=()=>{let n=D(r,e);(n.value!==a.value||n.error!==a.error||n.touched!==a.touched||n.dirty!==a.dirty)&&(a=n,t(n))};return i.add(o),()=>i.delete(o)},touch(){f(`field().touch`),v(t=>({...t,touched:x(t.touched,e,!0)}))},get touched(){return D(r,e).touched},get value(){return D(r,e).value}},{field(t){m(t);let n=_(r.value,e);if(n!==void 0&&!p(n))throw new l(`Cannot select '${t}' because the current field value is not an object.`);return w([...e,t])}})}let k={get disposalSignal(){return a.signal},dispose(){o||(o=!0,a.abort(),s?.abort(),i.clear())},get disposed(){return o},field(e){return m(e),w([e])},reset(e){f(`reset`),s?.abort();let t=e===void 0?r.baseline:g(e);v(e=>({...e,baseline:t,error:void 0,errors:void 0,touched:{},value:t}))},set(e){f(`set`),s?.abort();let t=typeof e==`function`?e(k.value):e;v(e=>({...e,error:void 0,errors:void 0,value:g(t)}))},get state(){return O(r)},async submit(e){if(f(`submit`),r.isSubmitting)throw new u(`submit() called while a submission is already in progress`);v(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:C(e.value)}));try{let t=await S();return t.status===`aborted`?Object.freeze({ok:!1,type:`aborted`}):t.status===`invalid`?Object.freeze({errors:t.errors,formError:t.formError,ok:!1,type:`validation`}):Object.freeze({ok:!0,value:await e(k.value)})}finally{o||v(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){f(`subscribe`),t.immediate&&e(O(r));let n=()=>e(O(r));return i.add(n),()=>i.delete(n)},[Symbol.dispose](){k.dispose()},validate:S,get value(){return r.value}};return k}return e.ForgeConfigError=l,e.ForgeDisposedError=c,e.ForgeError=s,e.ForgeSubmitError=u,e.ForgeValidationError=d,e.createForm=k,e.toFormData=o,e})({});
|
|
2
2
|
//# sourceMappingURL=forge.iife.js.map
|
package/dist/forge.iife.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forge.iife.js","names":["e","e"],"sources":["../src/errors.ts","../src/core/path.ts","../src/form.ts","../../arsenal/dist/_common/unsafePaths.js","../../arsenal/dist/guards/isPlainObject.js","../../arsenal/dist/object/flattenPaths.js","../src/adapters/form-data.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 static is(err: unknown): err is ForgeError {\n return err instanceof ForgeError;\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 ErrorTree = Record<string, unknown>;\ntype RecordValue = Record<string, 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\nexport function writeError(tree: ErrorTree, path: readonly string[], message: string): ErrorTree {\n const [key, ...rest] = path;\n\n if (!key || unsafeKeys.has(key)) return tree;\n\n if (rest.length === 0) return tree[key] === undefined ? { ...tree, [key]: message } : tree;\n\n const child = tree[key];\n\n if (child !== undefined && !isRecord(child)) return tree;\n\n return { ...tree, [key]: writeError((child ?? {}) as ErrorTree, rest, message) };\n}\n\nfunction isAtomicLeaf(value: unknown): boolean {\n return (\n (typeof Blob !== 'undefined' && value instanceof Blob) || (typeof File !== 'undefined' && value instanceof File)\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('Form values must contain only plain objects, arrays, File, Blob, or primitive values.');\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[]): T | undefined {\n let current = value;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return undefined;\n\n current = current[key];\n }\n\n return current as T | undefined;\n}\n\nexport function hasAtPath(value: unknown, path: readonly string[]): boolean {\n let current = value;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key];\n }\n\n return true;\n}\n\nexport function writeAtPath<T extends RecordValue>(value: T, path: readonly string[], next: unknown): T {\n const [key, ...rest] = path;\n\n assertSafeKey(key);\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)) {\n throw new ForgeConfigError(`Cannot select '${key}' because it is not an object.`);\n }\n\n return Object.freeze({ ...value, [key]: writeAtPath((child ?? {}) as RecordValue, rest, next) }) as T;\n}\n\nexport function resetAtPath<T extends RecordValue>(value: T, baseline: T, path: readonly string[]): T {\n const [key, ...rest] = path;\n\n if (rest.length === 0) {\n if (Object.hasOwn(baseline, key)) return Object.freeze({ ...value, [key]: baseline[key] }) as T;\n\n const { [key]: _removed, ...next } = value;\n\n return Object.freeze(next) as T;\n }\n\n const baselineChild = baseline[key];\n\n if (!isRecord(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 = isRecord(value[key]) ? value[key] : {};\n\n return Object.freeze({ ...value, [key]: resetAtPath(currentChild, baselineChild, rest) }) as T;\n}\n\nexport function writeMeta(meta: MetaRoot, path: readonly string[], next: boolean): MetaRoot {\n const [key, ...rest] = path;\n const copy: Record<string, MetaTree> = { ...meta };\n\n if (rest.length === 0) {\n if (next) copy[key] = true;\n else delete copy[key];\n } else {\n const child = isRecord(meta[key]) ? (meta[key] as MetaRoot) : {};\n const updated = writeMeta(child, rest, next);\n\n if (Object.keys(updated).length === 0) delete copy[key];\n else copy[key] = updated;\n }\n\n return Object.freeze(copy);\n}\n\nexport function readMeta(meta: MetaRoot, path: readonly string[]): boolean {\n let current: MetaTree | undefined = meta;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key] as MetaTree;\n }\n\n return current === true;\n}\n\nexport function touchAll(value: unknown): MetaRoot {\n if (!isRecord(value)) return {};\n\n return Object.freeze(\n Object.fromEntries(\n Object.entries(value).map(([key, child]) => [key, isRecord(child) ? touchAll(child) : (true as const)]),\n ),\n );\n}\n\nexport function readError(errors: unknown, path: readonly string[]): string | undefined {\n const error = readAtPath(errors, path);\n\n return typeof error === 'string' ? error : undefined;\n}\n\nexport function normalizeErrors<T>(errors: T): T | undefined {\n if (typeof errors === 'string') return errors;\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 type {\n Field,\n FieldState,\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n SubscribeOptions,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\nimport {\n assertSafeKey,\n hasAtPath,\n immutable,\n isRecord,\n normalizeErrors,\n readAtPath,\n readError,\n readMeta,\n resetAtPath,\n type MetaRoot,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n error: string | undefined;\n errors: FormErrors<TValues> | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n value: TValues;\n}>;\n\ntype Store<T> = {\n dispose(): void;\n read(): T;\n subscribe(listener: () => void): Unsubscribe;\n write(next: T): void;\n};\n\nfunction createStore<T>(initial: T, onListenerError: (error: unknown) => void): Store<T> {\n let current = initial;\n const listeners = new Set<() => void>();\n\n return {\n dispose() {\n listeners.clear();\n },\n read: () => current,\n subscribe(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n write(next) {\n if (next === current) return;\n\n current = next;\n\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n onListenerError(error);\n }\n }\n },\n };\n}\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nfunction makeFieldState<V>(state: InternalState<Record<string, unknown>>, path: readonly string[]): 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\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n error: current.error,\n errors: current.errors,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n valid: current.error === undefined && current.errors === undefined,\n validating: current.isValidating,\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\n function reportListenerError(error: unknown): void {\n if (!options.onSubscriberError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n options.onSubscriberError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n const store = createStore<InternalState<TValues>>(\n {\n baseline: initial,\n error: undefined,\n errors: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n value: initial,\n },\n reportListenerError,\n );\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\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 store.write(Object.freeze(update(store.read())));\n }\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n validationController?.abort();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((current) => ({ ...current, isValidating: true }));\n\n try {\n const result: ValidationErrors<TValues> | undefined = options.validate\n ? await options.validate(store.read().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\n write((current) => ({ ...current, error: formError, errors }));\n\n return errors === undefined && formError === undefined\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((current) => ({ ...current, isValidating: false }));\n }\n }\n }\n\n function createField<V>(path: readonly string[]): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path).dirty;\n },\n get error() {\n return makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path).error;\n },\n reset() {\n ensureActive('field().reset');\n validationController?.abort();\n write((current) => ({\n ...current,\n touched: writeMeta(current.touched, path, false),\n value: resetAtPath(current.value, current.baseline, path),\n }));\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n ensureActive('field().set');\n validationController?.abort();\n\n const previous = readAtPath<V>(store.read().value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n write((current) => ({ ...current, value: writeAtPath(current.value, path, value) }));\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n return store.subscribe(() => {\n const next = makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, 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 touch() {\n ensureActive('field().touch');\n write((current) => ({ ...current, touched: writeMeta(current.touched, path, true) }));\n },\n get touched() {\n return makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path).touched;\n },\n get value() {\n return makeFieldState<V>(store.read() as InternalState<Record<string, unknown>>, path).value;\n },\n };\n\n return Object.assign(common, {\n field<K extends keyof NonNullable<V> & string>(key: K): Field<NonNullable<V>[K]> {\n assertSafeKey(key);\n\n const current = readAtPath(store.read().value, path);\n\n if (current !== undefined && !isRecord(current)) {\n throw new ForgeConfigError(`Cannot select '${key}' because the current field value is not an object.`);\n }\n\n return createField<NonNullable<V>[K]>([...path, key]);\n },\n }) as Field<V>;\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 validationController?.abort();\n store.dispose();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n\n return createField<TValues[typeof key]>([key]);\n },\n reset(next) {\n ensureActive('reset');\n validationController?.abort();\n\n const baseline = next === undefined ? store.read().baseline : immutable(next);\n\n write((current) => ({\n ...current,\n baseline,\n error: undefined,\n errors: undefined,\n touched: {},\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n validationController?.abort();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((current) => ({ ...current, error: undefined, errors: undefined, value: immutable(value) }));\n },\n get state() {\n return makeFormState(store.read());\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>) => MaybePromise<TResult>,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (store.read().isSubmitting)\n throw new ForgeSubmitError('submit() called while a submission is already in progress');\n\n write((current) => ({\n ...current,\n isSubmitting: true,\n submitCount: current.submitCount + 1,\n touched: touchAll(current.value),\n }));\n\n try {\n const result = await validate();\n\n if (result.status === 'aborted') return Object.freeze({ ok: false, type: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({\n errors: result.errors,\n formError: result.formError,\n ok: false,\n type: 'validation',\n });\n }\n\n return Object.freeze({ ok: true, value: await handler(form.value) });\n } finally {\n if (!disposed) write((current) => ({ ...current, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(store.read()));\n\n return store.subscribe(() => listener(makeFormState(store.read())));\n },\n [Symbol.dispose]() {\n form.dispose();\n },\n validate,\n get value() {\n return store.read().value as ReadonlyDeep<TValues>;\n },\n };\n\n return form;\n}\n","//#region src/_common/unsafePaths.ts\nvar e = /* @__PURE__ */ new Set([\n\t\"__proto__\",\n\t\"constructor\",\n\t\"prototype\"\n]);\nfunction t(t) {\n\treturn typeof t == \"string\" && e.has(t);\n}\n//#endregion\nexport { e as UNSAFE_PATH_SEGMENTS, t as isUnsafeKey };\n\n//# sourceMappingURL=unsafePaths.js.map","//#region src/guards/isPlainObject.ts\nfunction e(e) {\n\tif (typeof e != \"object\" || !e) return !1;\n\tlet t = Object.getPrototypeOf(e);\n\treturn t === Object.prototype || t === null;\n}\n//#endregion\nexport { e as isPlainObject };\n\n//# sourceMappingURL=isPlainObject.js.map","import { UNSAFE_PATH_SEGMENTS as e } from \"../_common/unsafePaths.js\";\nimport { isPlainObject as t } from \"../guards/isPlainObject.js\";\n//#region src/object/flattenPaths.ts\nvar n = 10;\nfunction r(i, a, o) {\n\tlet s = {};\n\tfor (let [c, l] of Object.entries(i)) {\n\t\tif (e.has(c)) continue;\n\t\tlet i = a ? `${a}.${c}` : c;\n\t\tt(l) && o < n ? Object.assign(s, r(l, i, o + 1)) : s[i] = l;\n\t}\n\treturn s;\n}\nfunction i(e) {\n\treturn r(e, \"\", 0);\n}\nfunction a(n) {\n\tlet r = {};\n\tfor (let [i, a] of Object.entries(n)) {\n\t\tlet n = i.split(\".\");\n\t\tif (n.some((t) => e.has(t))) continue;\n\t\tlet o = r;\n\t\tfor (let e = 0; e < n.length - 1; e++) t(o[n[e]]) || (o[n[e]] = {}), o = o[n[e]];\n\t\to[n[n.length - 1]] = a;\n\t}\n\treturn r;\n}\n//#endregion\nexport { i as flattenPaths, a as unflattenPaths };\n\n//# sourceMappingURL=flattenPaths.js.map","import { flattenValues } from '../_utils';\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(flattenValues(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":"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"}
|
|
1
|
+
{"version":3,"file":"forge.iife.js","names":["e","e"],"sources":["../../arsenal/dist/_common/unsafePaths.js","../../arsenal/dist/guards/isPlainObject.js","../../arsenal/dist/object/flattenPaths.js","../src/adapters/form-data.ts","../src/errors.ts","../src/core/path.ts","../src/form.ts"],"sourcesContent":["//#region src/_common/unsafePaths.ts\nvar e = /* @__PURE__ */ new Set([\n\t\"__proto__\",\n\t\"constructor\",\n\t\"prototype\"\n]);\nfunction t(t) {\n\treturn typeof t == \"string\" && e.has(t);\n}\n//#endregion\nexport { e as UNSAFE_PATH_SEGMENTS, t as isUnsafeKey };\n\n//# sourceMappingURL=unsafePaths.js.map","//#region src/guards/isPlainObject.ts\nfunction e(e) {\n\tif (typeof e != \"object\" || !e) return !1;\n\tlet t = Object.getPrototypeOf(e);\n\treturn t === Object.prototype || t === null;\n}\n//#endregion\nexport { e as isPlainObject };\n\n//# sourceMappingURL=isPlainObject.js.map","import { UNSAFE_PATH_SEGMENTS as e } from \"../_common/unsafePaths.js\";\nimport { isPlainObject as t } from \"../guards/isPlainObject.js\";\n//#region src/object/flattenPaths.ts\nvar n = 10;\nfunction r(i, a, o) {\n\tlet s = {};\n\tfor (let [c, l] of Object.entries(i)) {\n\t\tif (e.has(c)) continue;\n\t\tlet i = a ? `${a}.${c}` : c;\n\t\tt(l) && o < n ? Object.assign(s, r(l, i, o + 1)) : s[i] = l;\n\t}\n\treturn s;\n}\nfunction i(e) {\n\treturn r(e, \"\", 0);\n}\nfunction a(n) {\n\tlet r = {};\n\tfor (let [i, a] of Object.entries(n)) {\n\t\tlet n = i.split(\".\");\n\t\tif (n.some((t) => e.has(t))) continue;\n\t\tlet o = r;\n\t\tfor (let e = 0; e < n.length - 1; e++) t(o[n[e]]) || (o[n[e]] = {}), o = o[n[e]];\n\t\to[n[n.length - 1]] = a;\n\t}\n\treturn r;\n}\n//#endregion\nexport { i as flattenPaths, a as unflattenPaths };\n\n//# sourceMappingURL=flattenPaths.js.map","import { flattenPaths as flattenValues } from '@vielzeug/arsenal/object';\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(flattenValues(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","/** 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 static is(err: unknown): err is ForgeError {\n return err instanceof ForgeError;\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 ErrorTree = Record<string, unknown>;\ntype RecordValue = Record<string, 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\nexport function writeError(tree: ErrorTree, path: readonly string[], message: string): ErrorTree {\n const [key, ...rest] = path;\n\n if (!key || unsafeKeys.has(key)) return tree;\n\n if (rest.length === 0) return tree[key] === undefined ? { ...tree, [key]: message } : tree;\n\n const child = tree[key];\n\n if (child !== undefined && !isRecord(child)) return tree;\n\n return { ...tree, [key]: writeError((child ?? {}) as ErrorTree, rest, message) };\n}\n\nfunction isAtomicLeaf(value: unknown): boolean {\n return (\n (typeof Blob !== 'undefined' && value instanceof Blob) || (typeof File !== 'undefined' && value instanceof File)\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('Form values must contain only plain objects, arrays, File, Blob, or primitive values.');\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[]): T | undefined {\n let current = value;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return undefined;\n\n current = current[key];\n }\n\n return current as T | undefined;\n}\n\nexport function hasAtPath(value: unknown, path: readonly string[]): boolean {\n let current = value;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key];\n }\n\n return true;\n}\n\nexport function writeAtPath<T extends RecordValue>(value: T, path: readonly string[], next: unknown): T {\n const [key, ...rest] = path;\n\n assertSafeKey(key);\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)) {\n throw new ForgeConfigError(`Cannot select '${key}' because it is not an object.`);\n }\n\n return Object.freeze({ ...value, [key]: writeAtPath((child ?? {}) as RecordValue, rest, next) }) as T;\n}\n\nexport function resetAtPath<T extends RecordValue>(value: T, baseline: T, path: readonly string[]): T {\n const [key, ...rest] = path;\n\n if (rest.length === 0) {\n if (Object.hasOwn(baseline, key)) return Object.freeze({ ...value, [key]: baseline[key] }) as T;\n\n const { [key]: _removed, ...next } = value;\n\n return Object.freeze(next) as T;\n }\n\n const baselineChild = baseline[key];\n\n if (!isRecord(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 = isRecord(value[key]) ? value[key] : {};\n\n return Object.freeze({ ...value, [key]: resetAtPath(currentChild, baselineChild, rest) }) as T;\n}\n\nexport function writeMeta(meta: MetaRoot, path: readonly string[], next: boolean): MetaRoot {\n const [key, ...rest] = path;\n const copy: Record<string, MetaTree> = { ...meta };\n\n if (rest.length === 0) {\n if (next) copy[key] = true;\n else delete copy[key];\n } else {\n const child = isRecord(meta[key]) ? (meta[key] as MetaRoot) : {};\n const updated = writeMeta(child, rest, next);\n\n if (Object.keys(updated).length === 0) delete copy[key];\n else copy[key] = updated;\n }\n\n return Object.freeze(copy);\n}\n\nexport function readMeta(meta: MetaRoot, path: readonly string[]): boolean {\n let current: MetaTree | undefined = meta;\n\n for (const key of path) {\n if (!isRecord(current) || !Object.hasOwn(current, key)) return false;\n\n current = current[key] as MetaTree;\n }\n\n return current === true;\n}\n\nexport function touchAll(value: unknown): MetaRoot {\n if (!isRecord(value)) return {};\n\n return Object.freeze(\n Object.fromEntries(\n Object.entries(value).map(([key, child]) => [key, isRecord(child) ? touchAll(child) : (true as const)]),\n ),\n );\n}\n\nexport function readError(errors: unknown, path: readonly string[]): string | undefined {\n const error = readAtPath(errors, path);\n\n return typeof error === 'string' ? error : undefined;\n}\n\nexport function normalizeErrors<T>(errors: T): T | undefined {\n if (typeof errors === 'string') return errors;\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 {\n assertSafeKey,\n hasAtPath,\n immutable,\n isRecord,\n type MetaRoot,\n normalizeErrors,\n readAtPath,\n readError,\n readMeta,\n resetAtPath,\n touchAll,\n writeAtPath,\n writeMeta,\n} from './core/path';\nimport { ForgeConfigError, ForgeDisposedError, ForgeSubmitError, ForgeValidationError } from './errors';\nimport type {\n Field,\n FieldState,\n Form,\n FormErrors,\n FormOptions,\n FormState,\n MaybePromise,\n ReadonlyDeep,\n SubmitResult,\n SubscribeOptions,\n Unsubscribe,\n ValidationErrors,\n ValidationResult,\n} from './types';\n\ntype InternalState<TValues extends Record<string, unknown>> = Readonly<{\n baseline: TValues;\n error: string | undefined;\n errors: FormErrors<TValues> | undefined;\n isSubmitting: boolean;\n isValidating: boolean;\n submitCount: number;\n touched: MetaRoot;\n value: TValues;\n}>;\n\nfunction rethrowAsync(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\nfunction makeFieldState<V>(state: InternalState<Record<string, unknown>>, path: readonly string[]): 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\nfunction makeFormState<TValues extends Record<string, unknown>>(current: InternalState<TValues>): FormState<TValues> {\n return Object.freeze({\n error: current.error,\n errors: current.errors,\n submitCount: current.submitCount,\n submitting: current.isSubmitting,\n touched: Object.keys(current.touched).length > 0,\n valid: current.error === undefined && current.errors === undefined,\n validating: current.isValidating,\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\n function reportListenerError(error: unknown): void {\n if (!options.onSubscriberError) {\n rethrowAsync(error);\n\n return;\n }\n\n try {\n options.onSubscriberError(error);\n } catch (reporterError) {\n rethrowAsync(reporterError);\n }\n }\n\n let current: InternalState<TValues> = {\n baseline: initial,\n error: undefined,\n errors: undefined,\n isSubmitting: false,\n isValidating: false,\n submitCount: 0,\n touched: {},\n value: initial,\n };\n const listeners = new Set<() => void>();\n const disposalController = new AbortController();\n let disposed = false;\n let validationController: AbortController | undefined;\n\n function ensureActive(operation: string): void {\n if (disposed) throw new ForgeDisposedError(operation);\n }\n\n function notify(): void {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n reportListenerError(error);\n }\n }\n }\n\n function write(update: (current: InternalState<TValues>) => InternalState<TValues>): void {\n current = Object.freeze(update(current));\n notify();\n }\n\n async function validate(externalSignal?: AbortSignal): Promise<ValidationResult<TValues>> {\n ensureActive('validate');\n validationController?.abort();\n\n const controller = new AbortController();\n const signal = externalSignal ? AbortSignal.any([controller.signal, externalSignal]) : controller.signal;\n\n validationController = controller;\n write((current) => ({ ...current, 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\n write((current) => ({ ...current, error: formError, errors }));\n\n return errors === undefined && formError === undefined\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((current) => ({ ...current, isValidating: false }));\n }\n }\n }\n\n function createField<V>(path: readonly string[]): Field<V> {\n const common = {\n get dirty() {\n return makeFieldState<V>(current as InternalState<Record<string, unknown>>, path).dirty;\n },\n get error() {\n return makeFieldState<V>(current as InternalState<Record<string, unknown>>, path).error;\n },\n reset() {\n ensureActive('field().reset');\n validationController?.abort();\n write((current) => ({\n ...current,\n touched: writeMeta(current.touched, path, false),\n value: resetAtPath(current.value, current.baseline, path),\n }));\n },\n set(next: V | ((previous: ReadonlyDeep<V>) => V)) {\n ensureActive('field().set');\n validationController?.abort();\n\n const previous = readAtPath<V>(current.value, path) as ReadonlyDeep<V>;\n const value = typeof next === 'function' ? (next as (current: ReadonlyDeep<V>) => V)(previous) : next;\n\n write((current) => ({ ...current, value: writeAtPath(current.value, path, value) }));\n },\n subscribe(listener: (state: FieldState<V>) => void, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n ensureActive('field().subscribe');\n\n let previous = makeFieldState<V>(current as InternalState<Record<string, unknown>>, path);\n\n if (subscribeOptions.immediate) listener(previous);\n\n const filtered = () => {\n const next = makeFieldState<V>(current as InternalState<Record<string, unknown>>, 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 listeners.add(filtered);\n\n return () => listeners.delete(filtered);\n },\n touch() {\n ensureActive('field().touch');\n write((current) => ({ ...current, touched: writeMeta(current.touched, path, true) }));\n },\n get touched() {\n return makeFieldState<V>(current as InternalState<Record<string, unknown>>, path).touched;\n },\n get value() {\n return makeFieldState<V>(current as InternalState<Record<string, unknown>>, path).value;\n },\n };\n\n return Object.assign(common, {\n field<K extends keyof NonNullable<V> & string>(key: K): Field<NonNullable<V>[K]> {\n assertSafeKey(key);\n\n const currentVal = readAtPath(current.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<NonNullable<V>[K]>([...path, key]);\n },\n }) as Field<V>;\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 validationController?.abort();\n listeners.clear();\n },\n get disposed() {\n return disposed;\n },\n field(key) {\n assertSafeKey(key);\n\n return createField<TValues[typeof key]>([key]);\n },\n reset(next) {\n ensureActive('reset');\n validationController?.abort();\n\n const baseline = next === undefined ? current.baseline : immutable(next);\n\n write((current) => ({\n ...current,\n baseline,\n error: undefined,\n errors: undefined,\n touched: {},\n value: baseline,\n }));\n },\n set(next) {\n ensureActive('set');\n validationController?.abort();\n\n const value =\n typeof next === 'function' ? (next as (current: ReadonlyDeep<TValues>) => TValues)(form.value) : next;\n\n write((current) => ({ ...current, error: undefined, errors: undefined, value: immutable(value) }));\n },\n get state() {\n return makeFormState(current);\n },\n async submit<TResult = void>(\n handler: (values: ReadonlyDeep<TValues>) => MaybePromise<TResult>,\n ): Promise<SubmitResult<TResult, TValues>> {\n ensureActive('submit');\n\n if (current.isSubmitting) throw new ForgeSubmitError('submit() called while a submission is already in progress');\n\n write((current) => ({\n ...current,\n isSubmitting: true,\n submitCount: current.submitCount + 1,\n touched: touchAll(current.value),\n }));\n\n try {\n const result = await validate();\n\n if (result.status === 'aborted') return Object.freeze({ ok: false, type: 'aborted' });\n\n if (result.status === 'invalid') {\n return Object.freeze({\n errors: result.errors,\n formError: result.formError,\n ok: false,\n type: 'validation',\n });\n }\n\n return Object.freeze({ ok: true, value: await handler(form.value) });\n } finally {\n if (!disposed) write((current) => ({ ...current, isSubmitting: false }));\n }\n },\n subscribe(listener, subscribeOptions: SubscribeOptions = {}): Unsubscribe {\n ensureActive('subscribe');\n\n if (subscribeOptions.immediate) listener(makeFormState(current));\n\n const formListener = () => listener(makeFormState(current));\n\n listeners.add(formListener);\n\n return () => listeners.delete(formListener);\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 e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},
|
|
1
|
+
var e=new Set([`__proto__`,`constructor`,`prototype`]);function t(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}var n=10;function r(i,a,o){let s={};for(let[c,l]of Object.entries(i)){if(e.has(c))continue;let i=a?`${a}.${c}`:c;t(l)&&o<n?Object.assign(s,r(l,i,o+1)):s[i]=l}return s}function i(e){return r(e,``,0)}function a(e){let t=new FormData,n=e=>typeof Blob<`u`&&e instanceof Blob,r=e=>typeof File<`u`&&e instanceof File,a=e=>typeof FileList<`u`&&e instanceof FileList;for(let[o,s]of Object.entries(i(e)))if(s!=null)if(r(s)||n(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,r(e)||n(e)?e:String(e));else t.append(o,String(s));return t}var o=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},s=class extends o{constructor(e){super(e?`Cannot call ${e}() on a disposed form`:`Cannot modify a disposed form`)}},c=class extends o{},l=class extends o{},u=class extends o{},d=new Set([`__proto__`,`constructor`,`prototype`]);function f(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function p(e){if(!e||d.has(e))throw new c(`Invalid field key '${e}'.`)}function m(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File}function h(e){if(Array.isArray(e))return Object.freeze(e.map(h));if(typeof e!=`object`||!e||m(e))return e;if(!f(e))throw new c(`Form values must contain only plain objects, arrays, File, Blob, or primitive values.`);return Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,h(t)])))}function g(e,t){let n=e;for(let e of t){if(!f(n)||!Object.hasOwn(n,e))return;n=n[e]}return n}function _(e,t){let n=e;for(let e of t){if(!f(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return!0}function v(e,t,n){let[r,...i]=t;if(p(r),i.length===0)return Object.freeze({...e,[r]:h(n)});let a=e[r];if(a!==void 0&&!f(a))throw new c(`Cannot select '${r}' because it is not an object.`);return Object.freeze({...e,[r]:v(a??{},i,n)})}function y(e,t,n){let[r,...i]=n;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(!f(a)){if(Object.hasOwn(t,r))return Object.freeze({...e,[r]:a});let{[r]:n,...i}=e;return Object.freeze(i)}let o=f(e[r])?e[r]:{};return Object.freeze({...e,[r]:y(o,a,i)})}function b(e,t,n){let[r,...i]=t,a={...e};if(i.length===0)n?a[r]=!0:delete a[r];else{let t=b(f(e[r])?e[r]:{},i,n);Object.keys(t).length===0?delete a[r]:a[r]=t}return Object.freeze(a)}function x(e,t){let n=e;for(let e of t){if(!f(n)||!Object.hasOwn(n,e))return!1;n=n[e]}return n===!0}function S(e){return f(e)?Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,!f(t)||S(t)]))):{}}function C(e,t){let n=g(e,t);return typeof n==`string`?n:void 0}function w(e){if(typeof e==`string`)return e;if(!f(e))return;let t=Object.entries(e).map(([e,t])=>[e,w(t)]).filter(([,e])=>e!==void 0);return t.length===0?void 0:Object.freeze(Object.fromEntries(t))}function T(e){queueMicrotask(()=>{throw e})}function E(e,t){let n=g(e.value,t),r=g(e.baseline,t);return Object.freeze({dirty:n!==r||_(e.value,t)!==_(e.baseline,t),error:C(e.errors,t),touched:x(e.touched,t),value:n})}function D(e){return Object.freeze({error:e.error,errors:e.errors,submitCount:e.submitCount,submitting:e.isSubmitting,touched:Object.keys(e.touched).length>0,valid:e.error===void 0&&e.errors===void 0,validating:e.isValidating})}function O(e){let t=h(e.initialValues);function n(t){if(!e.onSubscriberError){T(t);return}try{e.onSubscriberError(t)}catch(e){T(e)}}let r={baseline:t,error:void 0,errors:void 0,isSubmitting:!1,isValidating:!1,submitCount:0,touched:{},value:t},i=new Set,a=new AbortController,o=!1,d;function m(e){if(o)throw new s(e)}function _(){for(let e of[...i])try{e()}catch(e){n(e)}}function x(e){r=Object.freeze(e(r)),_()}async function C(t){m(`validate`),d?.abort();let n=new AbortController,i=t?AbortSignal.any([n.signal,t]):n.signal;d=n,x(e=>({...e,isValidating:!0}));try{let t=e.validate?await e.validate(r.value,i):void 0;if(i.aborted||d!==n)return Object.freeze({status:`aborted`});let a=t?.fields?w(h(t.fields)):void 0,o=t?.formError;return x(e=>({...e,error:o,errors:a})),Object.freeze(a===void 0&&o===void 0?{status:`valid`}:{errors:a,formError:o,status:`invalid`})}catch(e){if(i.aborted||d!==n)return Object.freeze({status:`aborted`});throw new u(`Form validation failed.`,{cause:e})}finally{d===n&&(d=void 0,o||x(e=>({...e,isValidating:!1})))}}function O(e){return Object.assign({get dirty(){return E(r,e).dirty},get error(){return E(r,e).error},reset(){m(`field().reset`),d?.abort(),x(t=>({...t,touched:b(t.touched,e,!1),value:y(t.value,t.baseline,e)}))},set(t){m(`field().set`),d?.abort();let n=g(r.value,e),i=typeof t==`function`?t(n):t;x(t=>({...t,value:v(t.value,e,i)}))},subscribe(t,n={}){m(`field().subscribe`);let a=E(r,e);n.immediate&&t(a);let o=()=>{let n=E(r,e);(n.value!==a.value||n.error!==a.error||n.touched!==a.touched||n.dirty!==a.dirty)&&(a=n,t(n))};return i.add(o),()=>i.delete(o)},touch(){m(`field().touch`),x(t=>({...t,touched:b(t.touched,e,!0)}))},get touched(){return E(r,e).touched},get value(){return E(r,e).value}},{field(t){p(t);let n=g(r.value,e);if(n!==void 0&&!f(n))throw new c(`Cannot select '${t}' because the current field value is not an object.`);return O([...e,t])}})}let k={get disposalSignal(){return a.signal},dispose(){o||(o=!0,a.abort(),d?.abort(),i.clear())},get disposed(){return o},field(e){return p(e),O([e])},reset(e){m(`reset`),d?.abort();let t=e===void 0?r.baseline:h(e);x(e=>({...e,baseline:t,error:void 0,errors:void 0,touched:{},value:t}))},set(e){m(`set`),d?.abort();let t=typeof e==`function`?e(k.value):e;x(e=>({...e,error:void 0,errors:void 0,value:h(t)}))},get state(){return D(r)},async submit(e){if(m(`submit`),r.isSubmitting)throw new l(`submit() called while a submission is already in progress`);x(e=>({...e,isSubmitting:!0,submitCount:e.submitCount+1,touched:S(e.value)}));try{let t=await C();return t.status===`aborted`?Object.freeze({ok:!1,type:`aborted`}):t.status===`invalid`?Object.freeze({errors:t.errors,formError:t.formError,ok:!1,type:`validation`}):Object.freeze({ok:!0,value:await e(k.value)})}finally{o||x(e=>({...e,isSubmitting:!1}))}},subscribe(e,t={}){m(`subscribe`),t.immediate&&e(D(r));let n=()=>e(D(r));return i.add(n),()=>i.delete(n)},[Symbol.dispose](){k.dispose()},validate:C,get value(){return r.value}};return k}export{c as ForgeConfigError,s as ForgeDisposedError,o as ForgeError,l as ForgeSubmitError,u as ForgeValidationError,O as createForm,a as toFormData};
|
|
2
2
|
//# sourceMappingURL=forge.js.map
|