@vielzeug/forge 2.2.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=new Set([`__proto__`,`constructor`,`prototype`]);function t(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function n(r,i){let a={};for(let[o,s]of Object.entries(r)){if(e.has(o))continue;let r=i?`${i}.${o}`:o;t(s)?Object.assign(a,n(s,r)):a[r]=s}return a}function r(e){let t=new FormData,r=e=>typeof Blob<`u`&&e instanceof Blob,i=e=>typeof File<`u`&&e instanceof File,a=e=>typeof FileList<`u`&&e instanceof FileList;for(let[o,s]of Object.entries(n(e,``)))if(s!=null)if(i(s)||r(s))t.append(o,s);else if(a(s))for(let e=0;e<s.length;e++)t.append(o,s[e]);else if(Array.isArray(s))for(let e of s)t.append(o,i(e)||r(e)?e:String(e));else t.append(o,String(s));return t}exports.toFormData=r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=new Set([`__proto__`,`constructor`,`prototype`]);function t(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function n(r,i){let a={};for(let[o,s]of Object.entries(r)){if(e.has(o))continue;let r=i?`${i}.${o}`:o;t(s)?Object.assign(a,n(s,r)):a[r]=s}return a}function r(e){let t=new FormData,r=e=>typeof Blob<`u`&&e instanceof Blob,i=e=>typeof File<`u`&&e instanceof File,a=e=>typeof FileList<`u`&&e instanceof FileList;for(let[o,s]of Object.entries(n(e,``)))if(s!=null){if(i(s)||r(s))t.append(o,s);else if(a(s))for(let e=0;e<s.length;e++)t.append(o,s[e]);else if(Array.isArray(s))for(let e of s)t.append(o,i(e)||r(e)?e:String(e));else t.append(o,String(s))}return t}exports.toFormData=r;
2
2
  //# sourceMappingURL=form-data.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"form-data.cjs","names":[],"sources":["../src/form-data.ts"],"sourcesContent":["const unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction flatten(obj: Record<string, unknown>, prefix: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (unsafeKeys.has(key)) continue;\n\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (isPlainObject(value)) {\n Object.assign(result, flatten(value, fullKey));\n } else {\n result[fullKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Converts a form values object into a `FormData` instance.\n * Nested objects are flattened to dot-notation keys (e.g. `user.name`).\n * `File`, `Blob`, and `FileList` values are appended as-is; all others are coerced to strings.\n * `null` and `undefined` values are omitted.\n */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const fd = new FormData();\n\n const isBlob = (value: unknown): value is Blob => typeof Blob !== 'undefined' && value instanceof Blob;\n const isFile = (value: unknown): value is File => typeof File !== 'undefined' && value instanceof File;\n const isFileList = (value: unknown): value is FileList =>\n typeof FileList !== 'undefined' && value instanceof FileList;\n\n for (const [name, value] of Object.entries(flatten(values, ''))) {\n if (value === null || value === undefined) continue;\n\n if (isFile(value) || isBlob(value)) {\n fd.append(name, value);\n } else if (isFileList(value)) {\n for (let i = 0; i < value.length; i++) fd.append(name, value[i]);\n } else if (Array.isArray(value)) {\n for (const item of value) fd.append(name, isFile(item) || isBlob(item) ? item : String(item));\n } else {\n fd.append(name, String(value));\n }\n }\n\n return fd;\n}\n"],"mappings":"mEAAA,IAAM,EAAa,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAEpE,SAAS,EAAc,EAAkD,CACvE,GAAsB,OAAO,GAAU,WAAnC,GAA+C,MAAM,QAAQ,CAAK,EAAG,MAAO,GAEhF,IAAM,EAAY,OAAO,eAAe,CAAK,EAE7C,OAAO,IAAc,OAAO,WAAa,IAAc,IACzD,CAEA,SAAS,EAAQ,EAA8B,EAAyC,CACtF,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAG,EAAG,CAC9C,GAAI,EAAW,IAAI,CAAG,EAAG,SAEzB,IAAM,EAAU,EAAS,GAAG,EAAO,GAAG,IAAQ,EAE1C,EAAc,CAAK,EACrB,OAAO,OAAO,EAAQ,EAAQ,EAAO,CAAO,CAAC,EAE7C,EAAO,GAAW,CAEtB,CAEA,OAAO,CACT,CAQA,SAAgB,EAAW,EAA2C,CACpE,IAAM,EAAK,IAAI,SAET,EAAU,GAAkC,OAAO,KAAS,KAAe,aAAiB,KAC5F,EAAU,GAAkC,OAAO,KAAS,KAAe,aAAiB,KAC5F,EAAc,GAClB,OAAO,SAAa,KAAe,aAAiB,SAEtD,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAQ,EAAQ,EAAE,CAAC,EACxD,MAAU,KAEd,GAAI,EAAO,CAAK,GAAK,EAAO,CAAK,EAC/B,EAAG,OAAO,EAAM,CAAK,OAChB,GAAI,EAAW,CAAK,EACzB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,IAAK,EAAG,OAAO,EAAM,EAAM,EAAE,OAC1D,GAAI,MAAM,QAAQ,CAAK,EAC5B,IAAK,IAAM,KAAQ,EAAO,EAAG,OAAO,EAAM,EAAO,CAAI,GAAK,EAAO,CAAI,EAAI,EAAO,OAAO,CAAI,CAAC,OAE5F,EAAG,OAAO,EAAM,OAAO,CAAK,CAAC,EAIjC,OAAO,CACT"}
1
+ {"version":3,"file":"form-data.cjs","names":[],"sources":["../src/form-data.ts"],"sourcesContent":["const unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction flatten(obj: Record<string, unknown>, prefix: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (unsafeKeys.has(key)) continue;\n\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (isPlainObject(value)) {\n Object.assign(result, flatten(value, fullKey));\n } else {\n result[fullKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Converts a form values object into a `FormData` instance.\n * Nested objects are flattened to dot-notation keys (e.g. `user.name`).\n * `File`, `Blob`, and `FileList` values are appended as-is; all others are coerced to strings.\n * `null` and `undefined` values are omitted.\n */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const fd = new FormData();\n\n const isBlob = (value: unknown): value is Blob => typeof Blob !== 'undefined' && value instanceof Blob;\n const isFile = (value: unknown): value is File => typeof File !== 'undefined' && value instanceof File;\n const isFileList = (value: unknown): value is FileList =>\n typeof FileList !== 'undefined' && value instanceof FileList;\n\n for (const [name, value] of Object.entries(flatten(values, ''))) {\n if (value === null || value === undefined) continue;\n\n if (isFile(value) || isBlob(value)) {\n fd.append(name, value);\n } else if (isFileList(value)) {\n for (let i = 0; i < value.length; i++) fd.append(name, value[i]);\n } else if (Array.isArray(value)) {\n for (const item of value) fd.append(name, isFile(item) || isBlob(item) ? item : String(item));\n } else {\n fd.append(name, String(value));\n }\n }\n\n return fd;\n}\n"],"mappings":"mEAAA,IAAM,EAAa,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAEpE,SAAS,EAAc,EAAkD,CACvE,GAAsB,OAAO,GAAU,WAAnC,GAA+C,MAAM,QAAQ,CAAK,EAAG,MAAO,GAEhF,IAAM,EAAY,OAAO,eAAe,CAAK,EAE7C,OAAO,IAAc,OAAO,WAAa,IAAc,IACzD,CAEA,SAAS,EAAQ,EAA8B,EAAyC,CACtF,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAG,EAAG,CAC9C,GAAI,EAAW,IAAI,CAAG,EAAG,SAEzB,IAAM,EAAU,EAAS,GAAG,EAAO,GAAG,IAAQ,EAE1C,EAAc,CAAK,EACrB,OAAO,OAAO,EAAQ,EAAQ,EAAO,CAAO,CAAC,EAE7C,EAAO,GAAW,CAEtB,CAEA,OAAO,CACT,CAQA,SAAgB,EAAW,EAA2C,CACpE,IAAM,EAAK,IAAI,SAET,EAAU,GAAkC,OAAO,KAAS,KAAe,aAAiB,KAC5F,EAAU,GAAkC,OAAO,KAAS,KAAe,aAAiB,KAC5F,EAAc,GAClB,OAAO,SAAa,KAAe,aAAiB,SAEtD,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAQ,EAAQ,EAAE,CAAC,EACxD,MAAU,KAEd,IAAI,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,CAAA,CAIjC,OAAO,CACT"}
package/dist/form-data.js CHANGED
@@ -20,10 +20,12 @@ function n(r, i) {
20
20
  }
21
21
  function r(e) {
22
22
  let t = new FormData(), r = (e) => typeof Blob < "u" && e instanceof Blob, i = (e) => typeof File < "u" && e instanceof File, a = (e) => typeof FileList < "u" && e instanceof FileList;
23
- for (let [o, s] of Object.entries(n(e, ""))) if (s != null) if (i(s) || r(s)) t.append(o, s);
24
- else if (a(s)) for (let e = 0; e < s.length; e++) t.append(o, s[e]);
25
- else if (Array.isArray(s)) for (let e of s) t.append(o, i(e) || r(e) ? e : String(e));
26
- else t.append(o, String(s));
23
+ for (let [o, s] of Object.entries(n(e, ""))) if (s != null) {
24
+ if (i(s) || r(s)) t.append(o, s);
25
+ else if (a(s)) for (let e = 0; e < s.length; e++) t.append(o, s[e]);
26
+ else if (Array.isArray(s)) for (let e of s) t.append(o, i(e) || r(e) ? e : String(e));
27
+ else t.append(o, String(s));
28
+ }
27
29
  return t;
28
30
  }
29
31
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"form-data.js","names":[],"sources":["../src/form-data.ts"],"sourcesContent":["const unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction flatten(obj: Record<string, unknown>, prefix: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (unsafeKeys.has(key)) continue;\n\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (isPlainObject(value)) {\n Object.assign(result, flatten(value, fullKey));\n } else {\n result[fullKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Converts a form values object into a `FormData` instance.\n * Nested objects are flattened to dot-notation keys (e.g. `user.name`).\n * `File`, `Blob`, and `FileList` values are appended as-is; all others are coerced to strings.\n * `null` and `undefined` values are omitted.\n */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const fd = new FormData();\n\n const isBlob = (value: unknown): value is Blob => typeof Blob !== 'undefined' && value instanceof Blob;\n const isFile = (value: unknown): value is File => typeof File !== 'undefined' && value instanceof File;\n const isFileList = (value: unknown): value is FileList =>\n typeof FileList !== 'undefined' && value instanceof FileList;\n\n for (const [name, value] of Object.entries(flatten(values, ''))) {\n if (value === null || value === undefined) continue;\n\n if (isFile(value) || isBlob(value)) {\n fd.append(name, value);\n } else if (isFileList(value)) {\n for (let i = 0; i < value.length; i++) fd.append(name, value[i]);\n } else if (Array.isArray(value)) {\n for (const item of value) fd.append(name, isFile(item) || isBlob(item) ? item : String(item));\n } else {\n fd.append(name, String(value));\n }\n }\n\n return fd;\n}\n"],"mappings":";AAAA,IAAM,oBAAa,IAAI,IAAI;CAAC;CAAa;CAAe;AAAW,CAAC;AAEpE,SAAS,EAAc,GAAkD;CACvE,IAAsB,OAAO,KAAU,aAAnC,KAA+C,MAAM,QAAQ,CAAK,GAAG,OAAO;CAEhF,IAAM,IAAY,OAAO,eAAe,CAAK;CAE7C,OAAO,MAAc,OAAO,aAAa,MAAc;AACzD;AAEA,SAAS,EAAQ,GAA8B,GAAyC;CACtF,IAAM,IAAkC,CAAC;CAEzC,KAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAG,GAAG;EAC9C,IAAI,EAAW,IAAI,CAAG,GAAG;EAEzB,IAAM,IAAU,IAAS,GAAG,EAAO,GAAG,MAAQ;EAE9C,AAAI,EAAc,CAAK,IACrB,OAAO,OAAO,GAAQ,EAAQ,GAAO,CAAO,CAAC,IAE7C,EAAO,KAAW;CAEtB;CAEA,OAAO;AACT;AAQA,SAAgB,EAAW,GAA2C;CACpE,IAAM,IAAK,IAAI,SAAS,GAElB,KAAU,MAAkC,OAAO,OAAS,OAAe,aAAiB,MAC5F,KAAU,MAAkC,OAAO,OAAS,OAAe,aAAiB,MAC5F,KAAc,MAClB,OAAO,WAAa,OAAe,aAAiB;CAEtD,KAAK,IAAM,CAAC,GAAM,MAAU,OAAO,QAAQ,EAAQ,GAAQ,EAAE,CAAC,GACxD,SAAU,MAEd,IAAI,EAAO,CAAK,KAAK,EAAO,CAAK,GAC/B,EAAG,OAAO,GAAM,CAAK;MAChB,IAAI,EAAW,CAAK,GACzB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK,EAAG,OAAO,GAAM,EAAM,EAAE;MAC1D,IAAI,MAAM,QAAQ,CAAK,GAC5B,KAAK,IAAM,KAAQ,GAAO,EAAG,OAAO,GAAM,EAAO,CAAI,KAAK,EAAO,CAAI,IAAI,IAAO,OAAO,CAAI,CAAC;MAE5F,EAAG,OAAO,GAAM,OAAO,CAAK,CAAC;CAIjC,OAAO;AACT"}
1
+ {"version":3,"file":"form-data.js","names":[],"sources":["../src/form-data.ts"],"sourcesContent":["const unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction flatten(obj: Record<string, unknown>, prefix: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (unsafeKeys.has(key)) continue;\n\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (isPlainObject(value)) {\n Object.assign(result, flatten(value, fullKey));\n } else {\n result[fullKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Converts a form values object into a `FormData` instance.\n * Nested objects are flattened to dot-notation keys (e.g. `user.name`).\n * `File`, `Blob`, and `FileList` values are appended as-is; all others are coerced to strings.\n * `null` and `undefined` values are omitted.\n */\nexport function toFormData(values: Record<string, unknown>): FormData {\n const fd = new FormData();\n\n const isBlob = (value: unknown): value is Blob => typeof Blob !== 'undefined' && value instanceof Blob;\n const isFile = (value: unknown): value is File => typeof File !== 'undefined' && value instanceof File;\n const isFileList = (value: unknown): value is FileList =>\n typeof FileList !== 'undefined' && value instanceof FileList;\n\n for (const [name, value] of Object.entries(flatten(values, ''))) {\n if (value === null || value === undefined) continue;\n\n if (isFile(value) || isBlob(value)) {\n fd.append(name, value);\n } else if (isFileList(value)) {\n for (let i = 0; i < value.length; i++) fd.append(name, value[i]);\n } else if (Array.isArray(value)) {\n for (const item of value) fd.append(name, isFile(item) || isBlob(item) ? item : String(item));\n } else {\n fd.append(name, String(value));\n }\n }\n\n return fd;\n}\n"],"mappings":";AAAA,IAAM,oBAAa,IAAI,IAAI;CAAC;CAAa;CAAe;AAAW,CAAC;AAEpE,SAAS,EAAc,GAAkD;CACvE,IAAsB,OAAO,KAAU,aAAnC,KAA+C,MAAM,QAAQ,CAAK,GAAG,OAAO;CAEhF,IAAM,IAAY,OAAO,eAAe,CAAK;CAE7C,OAAO,MAAc,OAAO,aAAa,MAAc;AACzD;AAEA,SAAS,EAAQ,GAA8B,GAAyC;CACtF,IAAM,IAAkC,CAAC;CAEzC,KAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAG,GAAG;EAC9C,IAAI,EAAW,IAAI,CAAG,GAAG;EAEzB,IAAM,IAAU,IAAS,GAAG,EAAO,GAAG,MAAQ;EAE9C,AAAI,EAAc,CAAK,IACrB,OAAO,OAAO,GAAQ,EAAQ,GAAO,CAAO,CAAC,IAE7C,EAAO,KAAW;CAEtB;CAEA,OAAO;AACT;AAQA,SAAgB,EAAW,GAA2C;CACpE,IAAM,IAAK,IAAI,SAAS,GAElB,KAAU,MAAkC,OAAO,OAAS,OAAe,aAAiB,MAC5F,KAAU,MAAkC,OAAO,OAAS,OAAe,aAAiB,MAC5F,KAAc,MAClB,OAAO,WAAa,OAAe,aAAiB;CAEtD,KAAK,IAAM,CAAC,GAAM,MAAU,OAAO,QAAQ,EAAQ,GAAQ,EAAE,CAAC,GACxD,SAAU,MAEd;MAAI,EAAO,CAAK,KAAK,EAAO,CAAK,GAC/B,EAAG,OAAO,GAAM,CAAK;OAChB,IAAI,EAAW,CAAK,GACzB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK,EAAG,OAAO,GAAM,EAAM,EAAE;OAC1D,IAAI,MAAM,QAAQ,CAAK,GAC5B,KAAK,IAAM,KAAQ,GAAO,EAAG,OAAO,GAAM,EAAO,CAAI,KAAK,EAAO,CAAI,IAAI,IAAO,OAAO,CAAI,CAAC;OAE5F,EAAG,OAAO,GAAM,OAAO,CAAK,CAAC;CAAA;CAIjC,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"spell.cjs","names":[],"sources":["../src/spell.ts"],"sourcesContent":["import type { Issue, Schema, SchemaMode } from '@vielzeug/spell';\nimport type { ErrorTree } from './core/path';\nimport { writeError } from './core/path';\nimport type { FormErrors, FormValidator, ValidationErrors } from './types';\n\ntype UnionIssue = Extract<Issue, { code: 'invalid_union' }>;\n\nfunction isUnionIssue(issue: Issue): issue is UnionIssue {\n return issue.code === 'invalid_union';\n}\n\nfunction abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T | undefined> {\n if (signal.aborted) return Promise.resolve(undefined);\n\n return new Promise((resolve, reject) => {\n const abort = () => resolve(undefined);\n\n signal.addEventListener('abort', abort, { once: true });\n void promise.then(\n (value) => {\n signal.removeEventListener('abort', abort);\n resolve(value);\n },\n (error: unknown) => {\n signal.removeEventListener('abort', abort);\n reject(error);\n },\n );\n });\n}\n\nfunction prefixIssues(path: readonly (string | number)[], issues: readonly Issue[]): Issue[] {\n return issues.map((issue) => ({ ...issue, path: [...path, ...issue.path] }));\n}\n\n/** Adapts a Spell Schema into Forge's full-form validator without transforming form values. */\nexport function customValidator<TValues extends Record<string, unknown>>(\n schema: Schema<unknown, TValues, SchemaMode>,\n): FormValidator<TValues> {\n return async (values, signal) => {\n const result = await abortable(schema.safeParseAsync(values), signal);\n\n if (!result || result.success) return undefined;\n\n const issues = result.error.issues.flatMap((issue) => {\n if (!isUnionIssue(issue)) return [issue];\n\n const bestMatch = result.error.bestMatch(issue);\n\n return bestMatch ? prefixIssues(issue.path, bestMatch) : [issue];\n });\n let fields: ErrorTree = {};\n let formError: string | undefined;\n\n for (const issue of issues) {\n if (issue.path.length === 0) {\n formError ??= issue.message;\n continue;\n }\n\n fields = writeError(fields, issue.path, issue.message);\n }\n\n const errors: ValidationErrors<TValues> = {\n fields: Object.keys(fields).length === 0 ? undefined : (fields as FormErrors<TValues>),\n formError,\n };\n\n return errors.fields === undefined && errors.formError === undefined ? undefined : errors;\n };\n}\n"],"mappings":"sGAOA,SAAS,EAAa,EAAmC,CACvD,OAAO,EAAM,OAAS,eACxB,CAEA,SAAS,EAAa,EAAqB,EAA6C,CAGtF,OAFI,EAAO,QAAgB,QAAQ,QAAQ,IAAA,EAAS,EAE7C,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,MAAc,EAAQ,IAAA,EAAS,EAErC,EAAO,iBAAiB,QAAS,EAAO,CAAE,KAAM,EAAK,CAAC,EACtD,EAAa,KACV,GAAU,CACT,EAAO,oBAAoB,QAAS,CAAK,EACzC,EAAQ,CAAK,CACf,EACC,GAAmB,CAClB,EAAO,oBAAoB,QAAS,CAAK,EACzC,EAAO,CAAK,CACd,CACF,CACF,CAAC,CACH,CAEA,SAAS,EAAa,EAAoC,EAAmC,CAC3F,OAAO,EAAO,IAAK,IAAW,CAAE,GAAG,EAAO,KAAM,CAAC,GAAG,EAAM,GAAG,EAAM,IAAI,CAAE,EAAE,CAC7E,CAGA,SAAgB,EACd,EACwB,CACxB,OAAO,MAAO,EAAQ,IAAW,CAC/B,IAAM,EAAS,MAAM,EAAU,EAAO,eAAe,CAAM,EAAG,CAAM,EAEpE,GAAI,CAAC,GAAU,EAAO,QAAS,OAE/B,IAAM,EAAS,EAAO,MAAM,OAAO,QAAS,GAAU,CACpD,GAAI,CAAC,EAAa,CAAK,EAAG,MAAO,CAAC,CAAK,EAEvC,IAAM,EAAY,EAAO,MAAM,UAAU,CAAK,EAE9C,OAAO,EAAY,EAAa,EAAM,KAAM,CAAS,EAAI,CAAC,CAAK,CACjE,CAAC,EACG,EAAoB,CAAC,EACrB,EAEJ,IAAK,IAAM,KAAS,EAAQ,CAC1B,GAAI,EAAM,KAAK,SAAW,EAAG,CAC3B,IAAc,EAAM,QACpB,QACF,CAEA,EAAS,EAAA,WAAW,EAAQ,EAAM,KAAM,EAAM,OAAO,CACvD,CAEA,IAAM,EAAoC,CACxC,OAAQ,OAAO,KAAK,CAAM,CAAC,CAAC,SAAW,EAAI,IAAA,GAAa,EACxD,WACF,EAEA,OAAO,EAAO,SAAW,IAAA,IAAa,EAAO,YAAc,IAAA,GAAY,IAAA,GAAY,CACrF,CACF"}
1
+ {"version":3,"file":"spell.cjs","names":[],"sources":["../src/spell.ts"],"sourcesContent":["import type { AnySchema, Issue, SchemaMode } from '@vielzeug/spell';\nimport type { ErrorTree } from './core/path';\nimport { writeError } from './core/path';\nimport type { FormErrors, FormValidator, ValidationErrors } from './types';\n\ntype UnionIssue = Extract<Issue, { code: 'invalid_union' }>;\n\nfunction isUnionIssue(issue: Issue): issue is UnionIssue {\n return issue.code === 'invalid_union';\n}\n\nfunction abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T | undefined> {\n if (signal.aborted) return Promise.resolve(undefined);\n\n return new Promise((resolve, reject) => {\n const abort = () => resolve(undefined);\n\n signal.addEventListener('abort', abort, { once: true });\n void promise.then(\n (value) => {\n signal.removeEventListener('abort', abort);\n resolve(value);\n },\n (error: unknown) => {\n signal.removeEventListener('abort', abort);\n reject(error);\n },\n );\n });\n}\n\nfunction prefixIssues(path: readonly (string | number)[], issues: readonly Issue[]): Issue[] {\n return issues.map((issue) => ({ ...issue, path: [...path, ...issue.path] }));\n}\n\n/** Adapts a Spell Schema into Forge's full-form validator without transforming form values. */\nexport function customValidator<TValues extends Record<string, unknown>>(\n schema: AnySchema<unknown, TValues, SchemaMode>,\n): FormValidator<TValues> {\n return async (values, signal) => {\n const result = await abortable(schema.safeParseAsync(values), signal);\n\n if (!result || result.success) return undefined;\n\n const issues = result.error.issues.flatMap((issue) => {\n if (!isUnionIssue(issue)) return [issue];\n\n const bestMatch = result.error.bestMatch(issue);\n\n return bestMatch ? prefixIssues(issue.path, bestMatch) : [issue];\n });\n let fields: ErrorTree = {};\n let formError: string | undefined;\n\n for (const issue of issues) {\n if (issue.path.length === 0) {\n formError ??= issue.message;\n continue;\n }\n\n fields = writeError(fields, issue.path, issue.message);\n }\n\n const errors: ValidationErrors<TValues> = {\n fields: Object.keys(fields).length === 0 ? undefined : (fields as FormErrors<TValues>),\n formError,\n };\n\n return errors.fields === undefined && errors.formError === undefined ? undefined : errors;\n };\n}\n"],"mappings":"sGAOA,SAAS,EAAa,EAAmC,CACvD,OAAO,EAAM,OAAS,eACxB,CAEA,SAAS,EAAa,EAAqB,EAA6C,CAGtF,OAFI,EAAO,QAAgB,QAAQ,QAAQ,IAAA,EAAS,EAE7C,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,MAAc,EAAQ,IAAA,EAAS,EAErC,EAAO,iBAAiB,QAAS,EAAO,CAAE,KAAM,EAAK,CAAC,EACtD,EAAa,KACV,GAAU,CACT,EAAO,oBAAoB,QAAS,CAAK,EACzC,EAAQ,CAAK,CACf,EACC,GAAmB,CAClB,EAAO,oBAAoB,QAAS,CAAK,EACzC,EAAO,CAAK,CACd,CACF,CACF,CAAC,CACH,CAEA,SAAS,EAAa,EAAoC,EAAmC,CAC3F,OAAO,EAAO,IAAK,IAAW,CAAE,GAAG,EAAO,KAAM,CAAC,GAAG,EAAM,GAAG,EAAM,IAAI,CAAE,EAAE,CAC7E,CAGA,SAAgB,EACd,EACwB,CACxB,OAAO,MAAO,EAAQ,IAAW,CAC/B,IAAM,EAAS,MAAM,EAAU,EAAO,eAAe,CAAM,EAAG,CAAM,EAEpE,GAAI,CAAC,GAAU,EAAO,QAAS,OAE/B,IAAM,EAAS,EAAO,MAAM,OAAO,QAAS,GAAU,CACpD,GAAI,CAAC,EAAa,CAAK,EAAG,MAAO,CAAC,CAAK,EAEvC,IAAM,EAAY,EAAO,MAAM,UAAU,CAAK,EAE9C,OAAO,EAAY,EAAa,EAAM,KAAM,CAAS,EAAI,CAAC,CAAK,CACjE,CAAC,EACG,EAAoB,CAAC,EACrB,EAEJ,IAAK,IAAM,KAAS,EAAQ,CAC1B,GAAI,EAAM,KAAK,SAAW,EAAG,CAC3B,IAAc,EAAM,QACpB,QACF,CAEA,EAAS,EAAA,WAAW,EAAQ,EAAM,KAAM,EAAM,OAAO,CACvD,CAEA,IAAM,EAAoC,CACxC,OAAQ,OAAO,KAAK,CAAM,CAAC,CAAC,SAAW,EAAI,IAAA,GAAa,EACxD,WACF,EAEA,OAAO,EAAO,SAAW,IAAA,IAAa,EAAO,YAAc,IAAA,GAAY,IAAA,GAAY,CACrF,CACF"}
package/dist/spell.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Schema, SchemaMode } from '@vielzeug/spell';
1
+ import type { AnySchema, SchemaMode } from '@vielzeug/spell';
2
2
  import type { FormValidator } from './types';
3
3
  /** Adapts a Spell Schema into Forge's full-form validator without transforming form values. */
4
- export declare function customValidator<TValues extends Record<string, unknown>>(schema: Schema<unknown, TValues, SchemaMode>): FormValidator<TValues>;
4
+ export declare function customValidator<TValues extends Record<string, unknown>>(schema: AnySchema<unknown, TValues, SchemaMode>): FormValidator<TValues>;
5
5
  //# sourceMappingURL=spell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spell.d.ts","sourceRoot":"","sources":["../src/spell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,MAAM,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGjE,OAAO,KAAK,EAAc,aAAa,EAAoB,MAAM,SAAS,CAAC;AAgC3E,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,GAC3C,aAAa,CAAC,OAAO,CAAC,CAgCxB"}
1
+ {"version":3,"file":"spell.d.ts","sourceRoot":"","sources":["../src/spell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAS,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGpE,OAAO,KAAK,EAAc,aAAa,EAAoB,MAAM,SAAS,CAAC;AAgC3E,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,GAC9C,aAAa,CAAC,OAAO,CAAC,CAgCxB"}
package/dist/spell.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"spell.js","names":[],"sources":["../src/spell.ts"],"sourcesContent":["import type { Issue, Schema, SchemaMode } from '@vielzeug/spell';\nimport type { ErrorTree } from './core/path';\nimport { writeError } from './core/path';\nimport type { FormErrors, FormValidator, ValidationErrors } from './types';\n\ntype UnionIssue = Extract<Issue, { code: 'invalid_union' }>;\n\nfunction isUnionIssue(issue: Issue): issue is UnionIssue {\n return issue.code === 'invalid_union';\n}\n\nfunction abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T | undefined> {\n if (signal.aborted) return Promise.resolve(undefined);\n\n return new Promise((resolve, reject) => {\n const abort = () => resolve(undefined);\n\n signal.addEventListener('abort', abort, { once: true });\n void promise.then(\n (value) => {\n signal.removeEventListener('abort', abort);\n resolve(value);\n },\n (error: unknown) => {\n signal.removeEventListener('abort', abort);\n reject(error);\n },\n );\n });\n}\n\nfunction prefixIssues(path: readonly (string | number)[], issues: readonly Issue[]): Issue[] {\n return issues.map((issue) => ({ ...issue, path: [...path, ...issue.path] }));\n}\n\n/** Adapts a Spell Schema into Forge's full-form validator without transforming form values. */\nexport function customValidator<TValues extends Record<string, unknown>>(\n schema: Schema<unknown, TValues, SchemaMode>,\n): FormValidator<TValues> {\n return async (values, signal) => {\n const result = await abortable(schema.safeParseAsync(values), signal);\n\n if (!result || result.success) return undefined;\n\n const issues = result.error.issues.flatMap((issue) => {\n if (!isUnionIssue(issue)) return [issue];\n\n const bestMatch = result.error.bestMatch(issue);\n\n return bestMatch ? prefixIssues(issue.path, bestMatch) : [issue];\n });\n let fields: ErrorTree = {};\n let formError: string | undefined;\n\n for (const issue of issues) {\n if (issue.path.length === 0) {\n formError ??= issue.message;\n continue;\n }\n\n fields = writeError(fields, issue.path, issue.message);\n }\n\n const errors: ValidationErrors<TValues> = {\n fields: Object.keys(fields).length === 0 ? undefined : (fields as FormErrors<TValues>),\n formError,\n };\n\n return errors.fields === undefined && errors.formError === undefined ? undefined : errors;\n };\n}\n"],"mappings":";;AAOA,SAAS,EAAa,GAAmC;CACvD,OAAO,EAAM,SAAS;AACxB;AAEA,SAAS,EAAa,GAAqB,GAA6C;CAGtF,OAFI,EAAO,UAAgB,QAAQ,QAAQ,KAAA,CAAS,IAE7C,IAAI,SAAS,GAAS,MAAW;EACtC,IAAM,UAAc,EAAQ,KAAA,CAAS;EAGrC,AADA,EAAO,iBAAiB,SAAS,GAAO,EAAE,MAAM,GAAK,CAAC,GACtD,EAAa,MACV,MAAU;GAET,AADA,EAAO,oBAAoB,SAAS,CAAK,GACzC,EAAQ,CAAK;EACf,IACC,MAAmB;GAElB,AADA,EAAO,oBAAoB,SAAS,CAAK,GACzC,EAAO,CAAK;EACd,CACF;CACF,CAAC;AACH;AAEA,SAAS,EAAa,GAAoC,GAAmC;CAC3F,OAAO,EAAO,KAAK,OAAW;EAAE,GAAG;EAAO,MAAM,CAAC,GAAG,GAAM,GAAG,EAAM,IAAI;CAAE,EAAE;AAC7E;AAGA,SAAgB,EACd,GACwB;CACxB,OAAO,OAAO,GAAQ,MAAW;EAC/B,IAAM,IAAS,MAAM,EAAU,EAAO,eAAe,CAAM,GAAG,CAAM;EAEpE,IAAI,CAAC,KAAU,EAAO,SAAS;EAE/B,IAAM,IAAS,EAAO,MAAM,OAAO,SAAS,MAAU;GACpD,IAAI,CAAC,EAAa,CAAK,GAAG,OAAO,CAAC,CAAK;GAEvC,IAAM,IAAY,EAAO,MAAM,UAAU,CAAK;GAE9C,OAAO,IAAY,EAAa,EAAM,MAAM,CAAS,IAAI,CAAC,CAAK;EACjE,CAAC,GACG,IAAoB,CAAC,GACrB;EAEJ,KAAK,IAAM,KAAS,GAAQ;GAC1B,IAAI,EAAM,KAAK,WAAW,GAAG;IAC3B,MAAc,EAAM;IACpB;GACF;GAEA,IAAS,EAAW,GAAQ,EAAM,MAAM,EAAM,OAAO;EACvD;EAEA,IAAM,IAAoC;GACxC,QAAQ,OAAO,KAAK,CAAM,CAAC,CAAC,WAAW,IAAI,KAAA,IAAa;GACxD;EACF;EAEA,OAAO,EAAO,WAAW,KAAA,KAAa,EAAO,cAAc,KAAA,IAAY,KAAA,IAAY;CACrF;AACF"}
1
+ {"version":3,"file":"spell.js","names":[],"sources":["../src/spell.ts"],"sourcesContent":["import type { AnySchema, Issue, SchemaMode } from '@vielzeug/spell';\nimport type { ErrorTree } from './core/path';\nimport { writeError } from './core/path';\nimport type { FormErrors, FormValidator, ValidationErrors } from './types';\n\ntype UnionIssue = Extract<Issue, { code: 'invalid_union' }>;\n\nfunction isUnionIssue(issue: Issue): issue is UnionIssue {\n return issue.code === 'invalid_union';\n}\n\nfunction abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T | undefined> {\n if (signal.aborted) return Promise.resolve(undefined);\n\n return new Promise((resolve, reject) => {\n const abort = () => resolve(undefined);\n\n signal.addEventListener('abort', abort, { once: true });\n void promise.then(\n (value) => {\n signal.removeEventListener('abort', abort);\n resolve(value);\n },\n (error: unknown) => {\n signal.removeEventListener('abort', abort);\n reject(error);\n },\n );\n });\n}\n\nfunction prefixIssues(path: readonly (string | number)[], issues: readonly Issue[]): Issue[] {\n return issues.map((issue) => ({ ...issue, path: [...path, ...issue.path] }));\n}\n\n/** Adapts a Spell Schema into Forge's full-form validator without transforming form values. */\nexport function customValidator<TValues extends Record<string, unknown>>(\n schema: AnySchema<unknown, TValues, SchemaMode>,\n): FormValidator<TValues> {\n return async (values, signal) => {\n const result = await abortable(schema.safeParseAsync(values), signal);\n\n if (!result || result.success) return undefined;\n\n const issues = result.error.issues.flatMap((issue) => {\n if (!isUnionIssue(issue)) return [issue];\n\n const bestMatch = result.error.bestMatch(issue);\n\n return bestMatch ? prefixIssues(issue.path, bestMatch) : [issue];\n });\n let fields: ErrorTree = {};\n let formError: string | undefined;\n\n for (const issue of issues) {\n if (issue.path.length === 0) {\n formError ??= issue.message;\n continue;\n }\n\n fields = writeError(fields, issue.path, issue.message);\n }\n\n const errors: ValidationErrors<TValues> = {\n fields: Object.keys(fields).length === 0 ? undefined : (fields as FormErrors<TValues>),\n formError,\n };\n\n return errors.fields === undefined && errors.formError === undefined ? undefined : errors;\n };\n}\n"],"mappings":";;AAOA,SAAS,EAAa,GAAmC;CACvD,OAAO,EAAM,SAAS;AACxB;AAEA,SAAS,EAAa,GAAqB,GAA6C;CAGtF,OAFI,EAAO,UAAgB,QAAQ,QAAQ,KAAA,CAAS,IAE7C,IAAI,SAAS,GAAS,MAAW;EACtC,IAAM,UAAc,EAAQ,KAAA,CAAS;EAGrC,AADA,EAAO,iBAAiB,SAAS,GAAO,EAAE,MAAM,GAAK,CAAC,GACtD,EAAa,MACV,MAAU;GAET,AADA,EAAO,oBAAoB,SAAS,CAAK,GACzC,EAAQ,CAAK;EACf,IACC,MAAmB;GAElB,AADA,EAAO,oBAAoB,SAAS,CAAK,GACzC,EAAO,CAAK;EACd,CACF;CACF,CAAC;AACH;AAEA,SAAS,EAAa,GAAoC,GAAmC;CAC3F,OAAO,EAAO,KAAK,OAAW;EAAE,GAAG;EAAO,MAAM,CAAC,GAAG,GAAM,GAAG,EAAM,IAAI;CAAE,EAAE;AAC7E;AAGA,SAAgB,EACd,GACwB;CACxB,OAAO,OAAO,GAAQ,MAAW;EAC/B,IAAM,IAAS,MAAM,EAAU,EAAO,eAAe,CAAM,GAAG,CAAM;EAEpE,IAAI,CAAC,KAAU,EAAO,SAAS;EAE/B,IAAM,IAAS,EAAO,MAAM,OAAO,SAAS,MAAU;GACpD,IAAI,CAAC,EAAa,CAAK,GAAG,OAAO,CAAC,CAAK;GAEvC,IAAM,IAAY,EAAO,MAAM,UAAU,CAAK;GAE9C,OAAO,IAAY,EAAa,EAAM,MAAM,CAAS,IAAI,CAAC,CAAK;EACjE,CAAC,GACG,IAAoB,CAAC,GACrB;EAEJ,KAAK,IAAM,KAAS,GAAQ;GAC1B,IAAI,EAAM,KAAK,WAAW,GAAG;IAC3B,MAAc,EAAM;IACpB;GACF;GAEA,IAAS,EAAW,GAAQ,EAAM,MAAM,EAAM,OAAO;EACvD;EAEA,IAAM,IAAoC;GACxC,QAAQ,OAAO,KAAK,CAAM,CAAC,CAAC,WAAW,IAAI,KAAA,IAAa;GACxD;EACF;EAEA,OAAO,EAAO,WAAW,KAAA,KAAa,EAAO,cAAc,KAAA,IAAY,KAAA,IAAY;CACrF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/forge",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "Immutable typed form state with focused fields and explicit full-form validation",
5
5
  "repository": {
6
6
  "type": "git",
@@ -76,8 +76,8 @@
76
76
  },
77
77
  "dependencies": {},
78
78
  "peerDependencies": {
79
- "@vielzeug/spell": "2.1.1",
80
- "@vielzeug/vault": "2.3.0"
79
+ "@vielzeug/spell": "2.1.2",
80
+ "@vielzeug/vault": "2.3.1"
81
81
  },
82
82
  "peerDependenciesMeta": {
83
83
  "@vielzeug/spell": {
@@ -89,8 +89,8 @@
89
89
  },
90
90
  "devDependencies": {
91
91
  "@types/node": "^26.2.0",
92
- "@vielzeug/spell": "2.1.1",
93
- "@vielzeug/vault": "2.3.0",
92
+ "@vielzeug/spell": "2.1.2",
93
+ "@vielzeug/vault": "2.3.1",
94
94
  "typescript": "^6.0.3",
95
95
  "vite": "^8.2.1",
96
96
  "vitest": "^4.1.10"