@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/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./form.cjs"),n=require("./adapters/form-data.cjs");exports.ForgeConfigError=e.ForgeConfigError,exports.ForgeDisposedError=e.ForgeDisposedError,exports.ForgeError=e.ForgeError,exports.ForgeSubmitError=e.ForgeSubmitError,exports.ForgeValidationError=e.ForgeValidationError,exports.createForm=t.createForm,exports.toFormData=n.toFormData;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./adapters/form-data.cjs"),n=require("./form.cjs");exports.ForgeConfigError=e.ForgeConfigError,exports.ForgeDisposedError=e.ForgeDisposedError,exports.ForgeError=e.ForgeError,exports.ForgeSubmitError=e.ForgeSubmitError,exports.ForgeValidationError=e.ForgeValidationError,exports.createForm=n.createForm,exports.toFormData=t.toFormData;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
+ export { toFormData } from './adapters/form-data';
1
2
  export { ForgeConfigError, ForgeDisposedError, ForgeError, ForgeSubmitError, ForgeValidationError } from './errors';
2
- export * from './types';
3
3
  export { createForm } from './form';
4
- export { toFormData } from './adapters/form-data';
4
+ export * from './types';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,UAAU,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACpH,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,UAAU,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACpH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { ForgeConfigError as e, ForgeDisposedError as t, ForgeError as n, ForgeSubmitError as r, ForgeValidationError as i } from "./errors.js";
2
- import { createForm as a } from "./form.js";
3
- import { toFormData as o } from "./adapters/form-data.js";
4
- export { e as ForgeConfigError, t as ForgeDisposedError, n as ForgeError, r as ForgeSubmitError, i as ForgeValidationError, a as createForm, o as toFormData };
2
+ import { toFormData as a } from "./adapters/form-data.js";
3
+ import { createForm as o } from "./form.js";
4
+ export { e as ForgeConfigError, t as ForgeDisposedError, n as ForgeError, r as ForgeSubmitError, i as ForgeValidationError, o as createForm, a as toFormData };
package/dist/spell.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core/path.cjs");require("@vielzeug/spell");function t(e){return e.code===`invalid_union`}function n(e,t){return t.aborted?Promise.resolve(void 0):new Promise((n,r)=>{let i=()=>n(void 0);t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}function r(e){let t=[];for(let n of e){if(typeof n==`number`)break;t.push(n)}return t}function i(e,t){return t.map(t=>({...t,path:[...e,...t.path]}))}function a(a){return async(o,s)=>{let c=await n(a.safeParseAsync(o),s);if(!c||c.success)return;let l=c.error.issues.flatMap(e=>{if(!t(e))return[e];let n=c.error.bestMatch(e);return n?i(e.path,n):[e]}),u={},d;for(let t of l){if(t.path.length===0){d??=t.message;continue}u=e.writeError(u,r(t.path),t.message)}let f={fields:Object.keys(u).length===0?void 0:u,formError:d};return f.fields===void 0&&f.formError===void 0?void 0:f}}exports.customValidator=a;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core/path.cjs");function t(e){return e.code===`invalid_union`}function n(e,t){return t.aborted?Promise.resolve(void 0):new Promise((n,r)=>{let i=()=>n(void 0);t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}function r(e){let t=[];for(let n of e){if(typeof n==`number`)break;t.push(n)}return t}function i(e,t){return t.map(t=>({...t,path:[...e,...t.path]}))}function a(a){return async(o,s)=>{let c=await n(a.safeParseAsync(o),s);if(!c||c.success)return;let l=c.error.issues.flatMap(e=>{if(!t(e))return[e];let n=c.error.bestMatch(e);return n?i(e.path,n):[e]}),u={},d;for(let t of l){if(t.path.length===0){d??=t.message;continue}u=e.writeError(u,r(t.path),t.message)}let f={fields:Object.keys(u).length===0?void 0:u,formError:d};return f.fields===void 0&&f.formError===void 0?void 0:f}}exports.customValidator=a;
2
2
  //# sourceMappingURL=spell.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"spell.cjs","names":[],"sources":["../src/spell.ts"],"sourcesContent":["import { Schema, type Issue, type SchemaMode } from '@vielzeug/spell';\n\nimport type { FormErrors, FormValidator, ValidationErrors } from './types';\n\nimport { writeError } from './core/path';\n\ntype ErrorTree = Record<string, unknown>;\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 fieldPath(path: readonly (string | number)[]): string[] {\n const segments: string[] = [];\n\n for (const segment of path) {\n if (typeof segment === 'number') break;\n\n segments.push(segment);\n }\n\n return segments;\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, fieldPath(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":"iIASA,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,EAAU,EAA8C,CAC/D,IAAM,EAAqB,CAAC,EAE5B,IAAK,IAAM,KAAW,EAAM,CAC1B,GAAI,OAAO,GAAY,SAAU,MAEjC,EAAS,KAAK,CAAO,CACvB,CAEA,OAAO,CACT,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,EAAU,EAAM,IAAI,EAAG,EAAM,OAAO,CAClE,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 { Issue, Schema, SchemaMode } from '@vielzeug/spell';\nimport { writeError } from './core/path';\nimport type { FormErrors, FormValidator, ValidationErrors } from './types';\n\ntype ErrorTree = Record<string, unknown>;\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 fieldPath(path: readonly (string | number)[]): string[] {\n const segments: string[] = [];\n\n for (const segment of path) {\n if (typeof segment === 'number') break;\n\n segments.push(segment);\n }\n\n return segments;\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, fieldPath(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,EAAU,EAA8C,CAC/D,IAAM,EAAqB,CAAC,EAE5B,IAAK,IAAM,KAAW,EAAM,CAC1B,GAAI,OAAO,GAAY,SAAU,MAEjC,EAAS,KAAK,CAAO,CACvB,CAEA,OAAO,CACT,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,EAAU,EAAM,IAAI,EAAG,EAAM,OAAO,CAClE,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,4 +1,4 @@
1
- import { Schema, type SchemaMode } from '@vielzeug/spell';
1
+ import type { Schema, 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
4
  export declare function customValidator<TValues extends Record<string, unknown>>(schema: Schema<unknown, TValues, SchemaMode>): FormValidator<TValues>;
@@ -1 +1 @@
1
- {"version":3,"file":"spell.d.ts","sourceRoot":"","sources":["../src/spell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,KAAK,EAAc,aAAa,EAAoB,MAAM,SAAS,CAAC;AA+C3E,+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,EAAS,MAAM,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,KAAK,EAAc,aAAa,EAAoB,MAAM,SAAS,CAAC;AA6C3E,+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"}
package/dist/spell.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { writeError as e } from "./core/path.js";
2
- import "@vielzeug/spell";
3
2
  //#region src/spell.ts
4
3
  function t(e) {
5
4
  return e.code === "invalid_union";
package/dist/spell.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"spell.js","names":[],"sources":["../src/spell.ts"],"sourcesContent":["import { Schema, type Issue, type SchemaMode } from '@vielzeug/spell';\n\nimport type { FormErrors, FormValidator, ValidationErrors } from './types';\n\nimport { writeError } from './core/path';\n\ntype ErrorTree = Record<string, unknown>;\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 fieldPath(path: readonly (string | number)[]): string[] {\n const segments: string[] = [];\n\n for (const segment of path) {\n if (typeof segment === 'number') break;\n\n segments.push(segment);\n }\n\n return segments;\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, fieldPath(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":";;;AASA,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,EAAU,GAA8C;CAC/D,IAAM,IAAqB,CAAC;CAE5B,KAAK,IAAM,KAAW,GAAM;EAC1B,IAAI,OAAO,KAAY,UAAU;EAEjC,EAAS,KAAK,CAAO;CACvB;CAEA,OAAO;AACT;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,EAAU,EAAM,IAAI,GAAG,EAAM,OAAO;EAClE;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 { Issue, Schema, SchemaMode } from '@vielzeug/spell';\nimport { writeError } from './core/path';\nimport type { FormErrors, FormValidator, ValidationErrors } from './types';\n\ntype ErrorTree = Record<string, unknown>;\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 fieldPath(path: readonly (string | number)[]): string[] {\n const segments: string[] = [];\n\n for (const segment of path) {\n if (typeof segment === 'number') break;\n\n segments.push(segment);\n }\n\n return segments;\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, fieldPath(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,EAAU,GAA8C;CAC/D,IAAM,IAAqB,CAAC;CAE5B,KAAK,IAAM,KAAW,GAAM;EAC1B,IAAI,OAAO,KAAY,UAAU;EAEjC,EAAS,KAAK,CAAO;CACvB;CAEA,OAAO;AACT;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,EAAU,EAAM,IAAI,GAAG,EAAM,OAAO;EAClE;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,8 +1,11 @@
1
1
  {
2
2
  "name": "@vielzeug/forge",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "Immutable typed form state with focused fields and explicit full-form validation",
5
5
  "type": "module",
6
+ "engines": {
7
+ "node": ">=22"
8
+ },
6
9
  "files": [
7
10
  "dist"
8
11
  ],
@@ -11,62 +14,59 @@
11
14
  "types": "dist/index.d.ts",
12
15
  "exports": {
13
16
  ".": {
14
- "types": "./dist/index.d.ts",
15
17
  "import": "./dist/index.js",
16
- "require": "./dist/index.cjs"
17
- },
18
- "./devtools": {
19
- "types": "./dist/devtools.d.ts",
20
- "import": "./dist/devtools.js",
21
- "require": "./dist/devtools.cjs"
18
+ "require": "./dist/index.cjs",
19
+ "types": "./dist/index.d.ts"
22
20
  },
23
21
  "./dom": {
24
- "types": "./dist/dom.d.ts",
25
22
  "import": "./dist/dom.js",
26
- "require": "./dist/dom.cjs"
23
+ "require": "./dist/dom.cjs",
24
+ "types": "./dist/dom.d.ts"
27
25
  },
28
26
  "./spell": {
29
- "types": "./dist/spell.d.ts",
30
27
  "import": "./dist/spell.js",
31
- "require": "./dist/spell.cjs"
28
+ "require": "./dist/spell.cjs",
29
+ "types": "./dist/spell.d.ts"
32
30
  },
33
31
  "./vault": {
34
- "types": "./dist/vault.d.ts",
35
32
  "import": "./dist/vault.js",
36
- "require": "./dist/vault.cjs"
33
+ "require": "./dist/vault.cjs",
34
+ "types": "./dist/vault.d.ts"
37
35
  }
38
36
  },
39
- "scripts": {
40
- "build": "vite build && pnpm run build:bundle && pnpm run build:types",
41
- "build:types": "tsc -p tsconfig.declarations.json",
42
- "fix": "eslint --fix src",
43
- "lint": "eslint src",
44
- "prepublishOnly": "pnpm run build",
45
- "preview": "vite preview",
46
- "test": "vitest",
47
- "build:bundle": "vite build --config vite.bundle.config.ts"
37
+ "typesVersions": {
38
+ "*": {
39
+ "dom": [
40
+ "dist/dom.d.ts"
41
+ ],
42
+ "spell": [
43
+ "dist/spell.d.ts"
44
+ ],
45
+ "vault": [
46
+ "dist/vault.d.ts"
47
+ ]
48
+ }
48
49
  },
49
50
  "publishConfig": {
50
51
  "access": "public",
51
52
  "registry": "https://registry.npmjs.org/"
52
53
  },
53
- "engines": {
54
- "node": ">=22"
54
+ "scripts": {
55
+ "build": "vite build && pnpm run build:bundle && pnpm run build:types",
56
+ "build:bundle": "vite build --config vite.bundle.config.ts",
57
+ "build:types": "tsc -p tsconfig.declarations.json",
58
+ "fix": "biome check --write src",
59
+ "lint": "biome ci src",
60
+ "prepublishOnly": "pnpm run build",
61
+ "preview": "vite preview",
62
+ "test": "vitest"
55
63
  },
56
64
  "dependencies": {
57
65
  "@vielzeug/arsenal": "2.0.1"
58
66
  },
59
- "devDependencies": {
60
- "@types/node": "^26.1.2",
61
- "@vielzeug/spell": "2.0.1",
62
- "@vielzeug/vault": "2.0.1",
63
- "typescript": "^6.0.3",
64
- "vite": "^8.2.0",
65
- "vitest": "^4.1.10"
66
- },
67
67
  "peerDependencies": {
68
- "@vielzeug/spell": "2.0.1",
69
- "@vielzeug/vault": "2.0.1"
68
+ "@vielzeug/spell": "2.1.0",
69
+ "@vielzeug/vault": "2.1.0"
70
70
  },
71
71
  "peerDependenciesMeta": {
72
72
  "@vielzeug/spell": {
@@ -76,20 +76,12 @@
76
76
  "optional": true
77
77
  }
78
78
  },
79
- "typesVersions": {
80
- "*": {
81
- "devtools": [
82
- "dist/devtools.d.ts"
83
- ],
84
- "dom": [
85
- "dist/dom.d.ts"
86
- ],
87
- "spell": [
88
- "dist/spell.d.ts"
89
- ],
90
- "vault": [
91
- "dist/vault.d.ts"
92
- ]
93
- }
79
+ "devDependencies": {
80
+ "@types/node": "^26.2.0",
81
+ "@vielzeug/spell": "2.1.0",
82
+ "@vielzeug/vault": "2.1.0",
83
+ "typescript": "^6.0.3",
84
+ "vite": "^8.2.1",
85
+ "vitest": "^4.1.10"
94
86
  }
95
87
  }
package/dist/_utils.cjs DELETED
@@ -1 +0,0 @@
1
- require("@vielzeug/arsenal/object");
package/dist/_utils.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export { flattenPaths as flattenValues } from '@vielzeug/arsenal/object';
2
- export declare function sanitizeForLog(text: string, maxLength?: number): string;
3
- //# sourceMappingURL=_utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_utils.d.ts","sourceRoot":"","sources":["../src/_utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAM,GAAG,MAAM,CAEpE"}
package/dist/_utils.js DELETED
@@ -1,2 +0,0 @@
1
- import { flattenPaths as e } from "@vielzeug/arsenal/object";
2
- export { e as flattenValues };
package/dist/devtools.cjs DELETED
@@ -1,2 +0,0 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,t={}){let n=`[forge:devtools:${t.label??`form`}]`,r;return e.subscribe(e=>{r&&(r.submitting!==e.submitting&&console.debug(`${n} submitting:`,e.submitting),r.validating!==e.validating&&console.debug(`${n} validating:`,e.validating),r.valid!==e.valid&&console.debug(`${n} valid:`,e.valid)),r=e},{immediate:!0})}exports.debugForm=e;
2
- //# sourceMappingURL=devtools.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools.cjs","names":[],"sources":["../src/devtools.ts"],"sourcesContent":["import type { Form, FormState, Unsubscribe } from './types';\n\nexport type ForgeDevtoolsOptions = Readonly<{\n label?: string;\n}>;\n\n/** Logs public form-state transitions without coupling diagnostics to form internals. */\nexport function debugForm<TValues extends Record<string, unknown>>(\n form: Form<TValues>,\n options: ForgeDevtoolsOptions = {},\n): Unsubscribe {\n const prefix = `[forge:devtools:${options.label ?? 'form'}]`;\n let previous: FormState<TValues> | undefined;\n\n return form.subscribe(\n (next) => {\n if (previous) {\n if (previous.submitting !== next.submitting) console.debug(`${prefix} submitting:`, next.submitting);\n\n if (previous.validating !== next.validating) console.debug(`${prefix} validating:`, next.validating);\n\n if (previous.valid !== next.valid) console.debug(`${prefix} valid:`, next.valid);\n }\n\n previous = next;\n },\n { immediate: true },\n );\n}\n"],"mappings":"mEAOA,SAAgB,EACd,EACA,EAAgC,CAAC,EACpB,CACb,IAAM,EAAS,mBAAmB,EAAQ,OAAS,OAAO,GACtD,EAEJ,OAAO,EAAK,UACT,GAAS,CACJ,IACE,EAAS,aAAe,EAAK,YAAY,QAAQ,MAAM,GAAG,EAAO,cAAe,EAAK,UAAU,EAE/F,EAAS,aAAe,EAAK,YAAY,QAAQ,MAAM,GAAG,EAAO,cAAe,EAAK,UAAU,EAE/F,EAAS,QAAU,EAAK,OAAO,QAAQ,MAAM,GAAG,EAAO,SAAU,EAAK,KAAK,GAGjF,EAAW,CACb,EACA,CAAE,UAAW,EAAK,CACpB,CACF"}
@@ -1,7 +0,0 @@
1
- import type { Form, Unsubscribe } from './types';
2
- export type ForgeDevtoolsOptions = Readonly<{
3
- label?: string;
4
- }>;
5
- /** Logs public form-state transitions without coupling diagnostics to form internals. */
6
- export declare function debugForm<TValues extends Record<string, unknown>>(form: Form<TValues>, options?: ForgeDevtoolsOptions): Unsubscribe;
7
- //# sourceMappingURL=devtools.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools.d.ts","sourceRoot":"","sources":["../src/devtools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAa,WAAW,EAAE,MAAM,SAAS,CAAC;AAE5D,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,EACnB,OAAO,GAAE,oBAAyB,GACjC,WAAW,CAkBb"}
package/dist/devtools.js DELETED
@@ -1,11 +0,0 @@
1
- //#region src/devtools.ts
2
- function e(e, t = {}) {
3
- let n = `[forge:devtools:${t.label ?? "form"}]`, r;
4
- return e.subscribe((e) => {
5
- r && (r.submitting !== e.submitting && console.debug(`${n} submitting:`, e.submitting), r.validating !== e.validating && console.debug(`${n} validating:`, e.validating), r.valid !== e.valid && console.debug(`${n} valid:`, e.valid)), r = e;
6
- }, { immediate: !0 });
7
- }
8
- //#endregion
9
- export { e as debugForm };
10
-
11
- //# sourceMappingURL=devtools.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools.js","names":[],"sources":["../src/devtools.ts"],"sourcesContent":["import type { Form, FormState, Unsubscribe } from './types';\n\nexport type ForgeDevtoolsOptions = Readonly<{\n label?: string;\n}>;\n\n/** Logs public form-state transitions without coupling diagnostics to form internals. */\nexport function debugForm<TValues extends Record<string, unknown>>(\n form: Form<TValues>,\n options: ForgeDevtoolsOptions = {},\n): Unsubscribe {\n const prefix = `[forge:devtools:${options.label ?? 'form'}]`;\n let previous: FormState<TValues> | undefined;\n\n return form.subscribe(\n (next) => {\n if (previous) {\n if (previous.submitting !== next.submitting) console.debug(`${prefix} submitting:`, next.submitting);\n\n if (previous.validating !== next.validating) console.debug(`${prefix} validating:`, next.validating);\n\n if (previous.valid !== next.valid) console.debug(`${prefix} valid:`, next.valid);\n }\n\n previous = next;\n },\n { immediate: true },\n );\n}\n"],"mappings":";AAOA,SAAgB,EACd,GACA,IAAgC,CAAC,GACpB;CACb,IAAM,IAAS,mBAAmB,EAAQ,SAAS,OAAO,IACtD;CAEJ,OAAO,EAAK,WACT,MAAS;EASR,AARI,MACE,EAAS,eAAe,EAAK,cAAY,QAAQ,MAAM,GAAG,EAAO,eAAe,EAAK,UAAU,GAE/F,EAAS,eAAe,EAAK,cAAY,QAAQ,MAAM,GAAG,EAAO,eAAe,EAAK,UAAU,GAE/F,EAAS,UAAU,EAAK,SAAO,QAAQ,MAAM,GAAG,EAAO,UAAU,EAAK,KAAK,IAGjF,IAAW;CACb,GACA,EAAE,WAAW,GAAK,CACpB;AACF"}