attaform 0.16.3 → 0.16.4

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.
Files changed (57) hide show
  1. package/dist/chunks/devtools.cjs +1 -1
  2. package/dist/chunks/devtools.mjs +1 -1
  3. package/dist/index.cjs +3 -2
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +33 -4
  6. package/dist/index.d.mts +33 -4
  7. package/dist/index.d.ts +33 -4
  8. package/dist/index.mjs +3 -3
  9. package/dist/nuxt.d.cts +1 -1
  10. package/dist/nuxt.d.mts +1 -1
  11. package/dist/nuxt.d.ts +1 -1
  12. package/dist/shared/{attaform.lFNwBcA3.d.ts → attaform.CCQkY4Ta.d.ts} +1 -1
  13. package/dist/shared/{attaform.c_NzdRyc.cjs → attaform.CIwZtbGV.cjs} +6 -2
  14. package/dist/shared/attaform.CIwZtbGV.cjs.map +1 -0
  15. package/dist/shared/{attaform.Bls_kFR6.d.mts → attaform.CMRmwGDt.d.cts} +1 -1
  16. package/dist/shared/{attaform._EqYNPYF.d.ts → attaform.CU3JperC.d.cts} +172 -14
  17. package/dist/shared/{attaform._EqYNPYF.d.cts → attaform.CU3JperC.d.mts} +172 -14
  18. package/dist/shared/{attaform._EqYNPYF.d.mts → attaform.CU3JperC.d.ts} +172 -14
  19. package/dist/shared/{attaform.DLnKT7wk.d.cts → attaform.CXMOheyZ.d.mts} +1 -1
  20. package/dist/shared/{attaform.jrxE_xZw.mjs → attaform.DZRj9s0s.mjs} +5 -3
  21. package/dist/shared/attaform.DZRj9s0s.mjs.map +1 -0
  22. package/dist/shared/{attaform.KrNw10aW.cjs → attaform.Dd_pWnmn.cjs} +12 -13
  23. package/dist/shared/attaform.Dd_pWnmn.cjs.map +1 -0
  24. package/dist/shared/{attaform.DILbdvfo.mjs → attaform.DyV1O4tI.mjs} +111 -22
  25. package/dist/shared/attaform.DyV1O4tI.mjs.map +1 -0
  26. package/dist/shared/{attaform.CFA6y0KF.mjs → attaform.UA19EF3J.mjs} +12 -13
  27. package/dist/shared/attaform.UA19EF3J.mjs.map +1 -0
  28. package/dist/shared/{attaform.C9Ph2SMx.cjs → attaform.fegmBJaq.cjs} +111 -21
  29. package/dist/shared/attaform.fegmBJaq.cjs.map +1 -0
  30. package/dist/shared/{attaform.XYOMTvuO.mjs → attaform.g7rfuXdz.mjs} +7 -3
  31. package/dist/shared/attaform.g7rfuXdz.mjs.map +1 -0
  32. package/dist/shared/{attaform.DGuGGNg9.cjs → attaform.keLBaHB6.cjs} +7 -3
  33. package/dist/shared/attaform.keLBaHB6.cjs.map +1 -0
  34. package/dist/zod-v3.cjs +2 -2
  35. package/dist/zod-v3.d.cts +3 -3
  36. package/dist/zod-v3.d.mts +3 -3
  37. package/dist/zod-v3.d.ts +3 -3
  38. package/dist/zod-v3.mjs +2 -2
  39. package/dist/zod-v4.cjs +2 -2
  40. package/dist/zod-v4.d.cts +3 -3
  41. package/dist/zod-v4.d.mts +3 -3
  42. package/dist/zod-v4.d.ts +3 -3
  43. package/dist/zod-v4.mjs +2 -2
  44. package/dist/zod.cjs +3 -3
  45. package/dist/zod.d.cts +3 -3
  46. package/dist/zod.d.mts +3 -3
  47. package/dist/zod.d.ts +3 -3
  48. package/dist/zod.mjs +3 -3
  49. package/package.json +1 -1
  50. package/dist/shared/attaform.C9Ph2SMx.cjs.map +0 -1
  51. package/dist/shared/attaform.CFA6y0KF.mjs.map +0 -1
  52. package/dist/shared/attaform.DGuGGNg9.cjs.map +0 -1
  53. package/dist/shared/attaform.DILbdvfo.mjs.map +0 -1
  54. package/dist/shared/attaform.KrNw10aW.cjs.map +0 -1
  55. package/dist/shared/attaform.XYOMTvuO.mjs.map +0 -1
  56. package/dist/shared/attaform.c_NzdRyc.cjs.map +0 -1
  57. package/dist/shared/attaform.jrxE_xZw.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const paths = require('../shared/attaform.c_NzdRyc.cjs');
3
+ const paths = require('../shared/attaform.CIwZtbGV.cjs');
4
4
  const plugin = require('../shared/attaform.rIRYSUI1.cjs');
5
5
 
6
6
  const INSPECTOR_ID = "attaform";
@@ -1,4 +1,4 @@
1
- import { c as canonicalizePath } from '../shared/attaform.jrxE_xZw.mjs';
1
+ import { c as canonicalizePath } from '../shared/attaform.DZRj9s0s.mjs';
2
2
  import { i as isSensitivePath, s as segmentMatchesSensitive } from '../shared/attaform.BfMxsfmE.mjs';
3
3
 
4
4
  const INSPECTOR_ID = "attaform";
package/dist/index.cjs CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  const plugin = require('./shared/attaform.rIRYSUI1.cjs');
4
4
  const serialize = require('./shared/attaform.CJttVxRj.cjs');
5
- const useFormContext = require('./shared/attaform.C9Ph2SMx.cjs');
6
- const paths = require('./shared/attaform.c_NzdRyc.cjs');
5
+ const useFormContext = require('./shared/attaform.fegmBJaq.cjs');
6
+ const paths = require('./shared/attaform.CIwZtbGV.cjs');
7
7
 
8
8
  function escapeForInlineScript(json) {
9
9
  return json.replace(/[<>&\u2028\u2029]/g, (char) => {
@@ -159,6 +159,7 @@ exports.hydrateAttaformState = serialize.hydrateAttaformState;
159
159
  exports.renderAttaformState = serialize.renderAttaformState;
160
160
  exports.AttaformErrorCode = useFormContext.AttaformErrorCode;
161
161
  exports.defaultCoercionRules = useFormContext.defaultCoercionRules;
162
+ exports.defaultShouldShowErrors = useFormContext.defaultShouldShowErrors;
162
163
  exports.defineCoercion = useFormContext.defineCoercion;
163
164
  exports.injectForm = useFormContext.injectForm;
164
165
  exports.isUnset = useFormContext.isUnset;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/runtime/core/serialize-script.ts","../src/runtime/core/parse-api-errors.ts"],"sourcesContent":["/**\n * Escape a JSON string so it's safe to embed inside an inline\n * `<script>` tag during SSR. Plain `JSON.stringify` is not safe — a\n * form value containing the literal substring `</script>` would\n * break out of the script tag.\n *\n * ```ts\n * const payload = escapeForInlineScript(JSON.stringify(renderAttaformState(app)))\n * // `<script>window.__ATTAFORM_STATE__ = ${payload}</script>` is safe.\n * ```\n *\n * Output remains valid JSON — `JSON.parse` round-trips back to the\n * original value on the client.\n */\nexport function escapeForInlineScript(json: string): string {\n return json.replace(/[<>&\\u2028\\u2029]/g, (char) => {\n switch (char) {\n case '<':\n return '\\\\u003c'\n case '>':\n return '\\\\u003e'\n case '&':\n return '\\\\u0026'\n case '\\u2028':\n return '\\\\u2028'\n case '\\u2029':\n return '\\\\u2029'\n default:\n return char\n }\n })\n}\n","import type {\n ApiErrorDetails,\n ApiErrorEntry,\n ApiErrorEnvelope,\n FormKey,\n ValidationError,\n} from '../types/types-api'\nimport { InvalidPathError } from './errors'\nimport { canonicalizePath } from './paths'\n\n/**\n * Result of `parseApiErrors`. Branch on `ok` to handle the two cases:\n *\n * ```ts\n * const result = parseApiErrors(payload, { formKey: form.key })\n * if (result.ok) {\n * form.setFieldErrors(result.errors)\n * } else {\n * console.warn('Bad error payload:', result.rejected)\n * }\n * ```\n *\n * `ok: true` means the payload was recognised — `errors` may still be\n * empty if the payload was valid but had no actual errors.\n * `ok: false` means the payload didn't match a known shape; `rejected`\n * carries a one-line description of why.\n */\nexport type ParseApiErrorsResult = {\n /** `true` when the payload was recognised; `false` when the shape was unfamiliar. */\n readonly ok: boolean\n /** Errors extracted from the payload. May be empty even when `ok: true`. */\n readonly errors: ValidationError[]\n /** When `ok: false`, a one-line description of why the payload was rejected. */\n readonly rejected?: string\n}\n\n/**\n * Options for `parseApiErrors`. The size caps protect against\n * misbehaving or hostile servers — exceeding any cap causes the\n * parser to reject the payload wholesale rather than partially apply.\n */\nexport type ParseApiErrorsOptions = {\n /**\n * The form's identifier — pass `form.key`. Stamped on every\n * produced `ValidationError` so errors route to the right form.\n */\n readonly formKey: FormKey\n /**\n * Code stamped on `ValidationError`s synthesized from bare-string\n * entries (the Rails / DRF / Laravel `{ field: [\"msg\"] }` shape).\n * Default `'api:unknown'`. Pick something more specific\n * (`'api:server-validation'`, `'myapp:legacy'`, …) when you know\n * the source.\n *\n * Structured `{ message, code }` entries forward their `code`\n * verbatim and ignore this option.\n */\n readonly defaultCode?: string\n /**\n * Maximum number of distinct keys to accept. Default `1000`.\n * Raise for trusted backends that legitimately produce more.\n */\n readonly maxEntries?: number\n /**\n * Maximum number of path segments per key. Default `32`. Keys\n * deeper than this are dropped (the rest of the payload still\n * applies if it stays under the other caps).\n */\n readonly maxPathDepth?: number\n /**\n * Maximum total path segments summed across every accepted key.\n * Default `10000`. Bounds the worst-case traversal cost.\n */\n readonly maxTotalSegments?: number\n}\n\n/**\n * Default size caps + default fallback code used by `parseApiErrors`.\n * Conservative; pass larger values (or a more specific code) via the\n * options bag for trusted-backend integrations.\n */\nexport const PARSE_API_ERRORS_DEFAULTS = {\n maxEntries: 1000,\n maxPathDepth: 32,\n maxTotalSegments: 10000,\n defaultCode: 'api:unknown',\n} as const\n\n/**\n * Normalise a server-side validation error payload into\n * `ValidationError[]`. Pair with `form.setFieldErrors` /\n * `form.addFieldErrors` to surface server errors on the form:\n *\n * ```ts\n * const response = await fetch('/api/signup', { … })\n * if (!response.ok) {\n * const payload = await response.json()\n * const result = parseApiErrors(payload, { formKey: form.key })\n * if (result.ok) form.setFieldErrors(result.errors)\n * }\n * ```\n *\n * Recognised payload shapes:\n *\n * - Wrapped envelope:\n * `{ error: { details: { email: { message: 'taken', code: 'api:duplicate-email' } } } }`\n * - Unwrapped envelope:\n * `{ details: { email: { message: 'taken', code: 'api:duplicate-email' } } }`\n * - Raw details record:\n * `{ email: { message: 'taken', code: 'api:duplicate-email' } }`\n * - **Bare-string Rails / DRF / Laravel shape:**\n * `{ email: ['Email already taken.'], username: 'too short' }`\n * - `null` / `undefined` — returns `{ ok: true, errors: [] }`\n *\n * Two entry shapes are accepted:\n *\n * 1. **Structured** — `{ message: string, code: string }`. The `code`\n * is forwarded verbatim onto the produced `ValidationError`.\n * 2. **Bare-string** — a plain string. Synthesized into\n * `{ message: <string>, code: <defaultCode> }` where `defaultCode`\n * comes from `options.defaultCode` (default `'api:unknown'`).\n * Useful for the Rails / Django REST Framework / FastAPI / Laravel\n * JSON shape that doesn't carry a per-field code.\n *\n * Each detail key's value can be a single entry, an array, or a mix\n * of structured and bare-string entries; arrays expand into one\n * `ValidationError` per entry. Pick a prefix on the server (`api:`,\n * `auth:`, etc.) and stay consistent so error renderers can branch\n * on `code` — or rely on `defaultCode` when the wire shape is\n * message-only.\n *\n * Dotted keys (`\"address.line1\"`) are split into structured paths\n * automatically. Use a custom server response shape outside these\n * patterns? Build the `ValidationError[]` array yourself and pass\n * it to `setFieldErrors` directly — `parseApiErrors` is just a\n * convenience for the common shapes.\n */\nexport function parseApiErrors(\n payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown,\n options: ParseApiErrorsOptions\n): ParseApiErrorsResult {\n const maxEntries = options.maxEntries ?? PARSE_API_ERRORS_DEFAULTS.maxEntries\n const maxPathDepth = options.maxPathDepth ?? PARSE_API_ERRORS_DEFAULTS.maxPathDepth\n const maxTotalSegments = options.maxTotalSegments ?? PARSE_API_ERRORS_DEFAULTS.maxTotalSegments\n const defaultCode = options.defaultCode ?? PARSE_API_ERRORS_DEFAULTS.defaultCode\n\n if (payload === null || payload === undefined) {\n return { ok: true, errors: [] }\n }\n if (typeof payload !== 'object') {\n return { ok: false, errors: [], rejected: `payload was ${typeof payload}, expected object` }\n }\n\n const extraction = extractDetails(payload as Record<string, unknown>)\n if (!extraction.ok) {\n return { ok: false, errors: [], rejected: extraction.reason }\n }\n\n const { details } = extraction\n const entryCount = Object.keys(details).length\n // Enforce the guardrails before we spend time walking the payload.\n // Rejecting wholesale (not partial-applying) keeps the failure visible\n // so consumers can tune the caps or investigate the server payload.\n if (entryCount > maxEntries) {\n return {\n ok: false,\n errors: [],\n rejected: `payload has ${entryCount} entries, exceeds maxEntries=${maxEntries}`,\n }\n }\n\n const errors: ValidationError[] = []\n let totalSegments = 0\n for (const [key, value] of Object.entries(details)) {\n const entryList: ReadonlyArray<string | ApiErrorEntry> = Array.isArray(value) ? value : [value]\n // `canonicalizePath` throws `InvalidPathError` for dotted strings with\n // empty segments (e.g. `'. '`, `'a..b'`). A misbehaving server can\n // genuinely emit such a key; the hydrator is a normaliser, not a\n // validator, so we drop offending keys rather than let the exception\n // escape. Well-formed keys continue as normal.\n let segments: readonly (string | number)[]\n try {\n segments = canonicalizePath(key).segments\n } catch (err) {\n if (err instanceof InvalidPathError) continue\n throw err\n }\n // Per-path depth cap. We drop the offending key (rather than\n // rejecting the whole payload) because a single stray deep path\n // in an otherwise legitimate error set is still worth surfacing\n // the rest. Consumers who want strict rejection can post-filter\n // on `result.errors.length < details entryCount`.\n if (segments.length > maxPathDepth) continue\n // Total-segment cap. Enforced wholesale (not per-key) so a payload\n // that passes the per-key gate but stacks into a pathological\n // total still fails visibly. Mirrors `maxEntries` strictness.\n totalSegments += segments.length\n if (totalSegments > maxTotalSegments) {\n return {\n ok: false,\n errors: [],\n rejected: `payload total path segments exceeds maxTotalSegments=${maxTotalSegments}`,\n }\n }\n for (const entry of entryList) {\n // Bare-string entries (Rails / DRF / Laravel shape) synthesize a\n // `code` from `options.defaultCode`; structured `{ message, code }`\n // entries forward `code` verbatim. Empty messages drop silently\n // (`{ message: '' }` or `''`) — same recoverable-malformed-server\n // policy as before.\n const message = typeof entry === 'string' ? entry : entry.message\n const code = typeof entry === 'string' ? defaultCode : entry.code\n if (message.length === 0) continue\n errors.push({\n message,\n path: Array.from(segments),\n formKey: options.formKey,\n code,\n })\n }\n }\n return { ok: true, errors }\n}\n\ntype ExtractResult = { ok: true; details: ApiErrorDetails } | { ok: false; reason: string }\n\nfunction extractDetails(payload: Record<string, unknown>): ExtractResult {\n const wrappedError = payload['error']\n if (wrappedError !== null && wrappedError !== undefined && typeof wrappedError === 'object') {\n const inner = (wrappedError as { details?: unknown }).details\n if (inner === undefined) {\n // A wrapped envelope without details is considered \"no errors\" — valid shape.\n return { ok: true, details: {} }\n }\n if (isDetailsRecord(inner)) return { ok: true, details: inner }\n return {\n ok: false,\n reason: 'error.details entries must be strings or { message, code } objects',\n }\n }\n\n // `{ error: 'oops' }` / `{ error: 42 }` is a malformed wrapped envelope —\n // the server meant an error object but sent a scalar. Without this guard\n // the payload would fall through to the raw-details branch below, where\n // `{ error: 'oops' }` satisfies `isDetailsRecord` and silently produces\n // a phantom `ValidationError` at path `['error']`.\n if (wrappedError !== null && wrappedError !== undefined && typeof wrappedError !== 'object') {\n return {\n ok: false,\n reason: `payload.error was ${typeof wrappedError}, expected an object with { details }`,\n }\n }\n\n if ('details' in payload) {\n const inner = payload['details']\n if (inner === undefined) return { ok: true, details: {} }\n if (isDetailsRecord(inner)) return { ok: true, details: inner }\n return { ok: false, reason: 'details entries must be strings or { message, code } objects' }\n }\n\n if (isDetailsRecord(payload)) return { ok: true, details: payload }\n\n // Heuristic: if the payload has keys but none of them look like details,\n // it's probably a completely different shape. Reject.\n if (Object.keys(payload).length === 0) return { ok: true, details: {} }\n return { ok: false, reason: 'unrecognised payload shape' }\n}\n\nfunction isStructuredEntry(value: unknown): value is ApiErrorEntry {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false\n const obj = value as { message?: unknown; code?: unknown }\n return typeof obj.message === 'string' && typeof obj.code === 'string'\n}\n\n/**\n * Accepts either a structured `{ message, code }` entry OR a bare\n * string. Bare strings synthesize a `code` at parse time\n * (`options.defaultCode`) and are useful for the Rails / Django REST\n * Framework / Laravel JSON shape that doesn't carry a per-field code.\n */\nfunction isAcceptedEntry(value: unknown): value is string | ApiErrorEntry {\n return typeof value === 'string' || isStructuredEntry(value)\n}\n\n/**\n * A record is a \"details\" record when every value is either an\n * accepted entry or an array of accepted entries (mixing structured +\n * bare-string in the same array is fine; the parser normalises per\n * entry). Half-structured objects (e.g. `{ message: 'x' }` missing\n * `code`) are still rejected so the bug surfaces — see the\n * `'rejects entries that are objects but missing required fields'`\n * test for the rationale.\n */\nfunction isDetailsRecord(value: unknown): value is ApiErrorDetails {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false\n // Reject prototype-polluted keys — we don't use them here, but downstream\n // spreads shouldn't have to worry about this input.\n const record = value as Record<string, unknown>\n for (const k of Object.keys(record)) {\n const v = record[k]\n if (isAcceptedEntry(v)) continue\n if (Array.isArray(v) && v.every((entry) => isAcceptedEntry(entry))) continue\n return false\n }\n return true\n}\n"],"names":["canonicalizePath","InvalidPathError"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/runtime/core/serialize-script.ts","../src/runtime/core/parse-api-errors.ts"],"sourcesContent":["/**\n * Escape a JSON string so it's safe to embed inside an inline\n * `<script>` tag during SSR. Plain `JSON.stringify` is not safe — a\n * form value containing the literal substring `</script>` would\n * break out of the script tag.\n *\n * ```ts\n * const payload = escapeForInlineScript(JSON.stringify(renderAttaformState(app)))\n * // `<script>window.__ATTAFORM_STATE__ = ${payload}</script>` is safe.\n * ```\n *\n * Output remains valid JSON — `JSON.parse` round-trips back to the\n * original value on the client.\n */\nexport function escapeForInlineScript(json: string): string {\n return json.replace(/[<>&\\u2028\\u2029]/g, (char) => {\n switch (char) {\n case '<':\n return '\\\\u003c'\n case '>':\n return '\\\\u003e'\n case '&':\n return '\\\\u0026'\n case '\\u2028':\n return '\\\\u2028'\n case '\\u2029':\n return '\\\\u2029'\n default:\n return char\n }\n })\n}\n","import type {\n ApiErrorDetails,\n ApiErrorEntry,\n ApiErrorEnvelope,\n FormKey,\n ValidationError,\n} from '../types/types-api'\nimport { InvalidPathError } from './errors'\nimport { canonicalizePath } from './paths'\n\n/**\n * Result of `parseApiErrors`. Branch on `ok` to handle the two cases:\n *\n * ```ts\n * const result = parseApiErrors(payload, { formKey: form.key })\n * if (result.ok) {\n * form.setFieldErrors(result.errors)\n * } else {\n * console.warn('Bad error payload:', result.rejected)\n * }\n * ```\n *\n * `ok: true` means the payload was recognised — `errors` may still be\n * empty if the payload was valid but had no actual errors.\n * `ok: false` means the payload didn't match a known shape; `rejected`\n * carries a one-line description of why.\n */\nexport type ParseApiErrorsResult = {\n /** `true` when the payload was recognised; `false` when the shape was unfamiliar. */\n readonly ok: boolean\n /** Errors extracted from the payload. May be empty even when `ok: true`. */\n readonly errors: ValidationError[]\n /** When `ok: false`, a one-line description of why the payload was rejected. */\n readonly rejected?: string\n}\n\n/**\n * Options for `parseApiErrors`. The size caps protect against\n * misbehaving or hostile servers — exceeding any cap causes the\n * parser to reject the payload wholesale rather than partially apply.\n */\nexport type ParseApiErrorsOptions = {\n /**\n * The form's identifier — pass `form.key`. Stamped on every\n * produced `ValidationError` so errors route to the right form.\n */\n readonly formKey: FormKey\n /**\n * Code stamped on `ValidationError`s synthesized from bare-string\n * entries (the Rails / DRF / Laravel `{ field: [\"msg\"] }` shape).\n * Default `'api:unknown'`. Pick something more specific\n * (`'api:server-validation'`, `'myapp:legacy'`, …) when you know\n * the source.\n *\n * Structured `{ message, code }` entries forward their `code`\n * verbatim and ignore this option.\n */\n readonly defaultCode?: string\n /**\n * Maximum number of distinct keys to accept. Default `1000`.\n * Raise for trusted backends that legitimately produce more.\n */\n readonly maxEntries?: number\n /**\n * Maximum number of path segments per key. Default `32`. Keys\n * deeper than this are dropped (the rest of the payload still\n * applies if it stays under the other caps).\n */\n readonly maxPathDepth?: number\n /**\n * Maximum total path segments summed across every accepted key.\n * Default `10000`. Bounds the worst-case traversal cost.\n */\n readonly maxTotalSegments?: number\n}\n\n/**\n * Default size caps + default fallback code used by `parseApiErrors`.\n * Conservative; pass larger values (or a more specific code) via the\n * options bag for trusted-backend integrations.\n */\nexport const PARSE_API_ERRORS_DEFAULTS = {\n maxEntries: 1000,\n maxPathDepth: 32,\n maxTotalSegments: 10000,\n defaultCode: 'api:unknown',\n} as const\n\n/**\n * Normalise a server-side validation error payload into\n * `ValidationError[]`. Pair with `form.setFieldErrors` /\n * `form.addFieldErrors` to surface server errors on the form:\n *\n * ```ts\n * const response = await fetch('/api/signup', { … })\n * if (!response.ok) {\n * const payload = await response.json()\n * const result = parseApiErrors(payload, { formKey: form.key })\n * if (result.ok) form.setFieldErrors(result.errors)\n * }\n * ```\n *\n * Recognised payload shapes:\n *\n * - Wrapped envelope:\n * `{ error: { details: { email: { message: 'taken', code: 'api:duplicate-email' } } } }`\n * - Unwrapped envelope:\n * `{ details: { email: { message: 'taken', code: 'api:duplicate-email' } } }`\n * - Raw details record:\n * `{ email: { message: 'taken', code: 'api:duplicate-email' } }`\n * - **Bare-string Rails / DRF / Laravel shape:**\n * `{ email: ['Email already taken.'], username: 'too short' }`\n * - `null` / `undefined` — returns `{ ok: true, errors: [] }`\n *\n * Two entry shapes are accepted:\n *\n * 1. **Structured** — `{ message: string, code: string }`. The `code`\n * is forwarded verbatim onto the produced `ValidationError`.\n * 2. **Bare-string** — a plain string. Synthesized into\n * `{ message: <string>, code: <defaultCode> }` where `defaultCode`\n * comes from `options.defaultCode` (default `'api:unknown'`).\n * Useful for the Rails / Django REST Framework / FastAPI / Laravel\n * JSON shape that doesn't carry a per-field code.\n *\n * Each detail key's value can be a single entry, an array, or a mix\n * of structured and bare-string entries; arrays expand into one\n * `ValidationError` per entry. Pick a prefix on the server (`api:`,\n * `auth:`, etc.) and stay consistent so error renderers can branch\n * on `code` — or rely on `defaultCode` when the wire shape is\n * message-only.\n *\n * Dotted keys (`\"address.line1\"`) are split into structured paths\n * automatically. Use a custom server response shape outside these\n * patterns? Build the `ValidationError[]` array yourself and pass\n * it to `setFieldErrors` directly — `parseApiErrors` is just a\n * convenience for the common shapes.\n */\nexport function parseApiErrors(\n payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown,\n options: ParseApiErrorsOptions\n): ParseApiErrorsResult {\n const maxEntries = options.maxEntries ?? PARSE_API_ERRORS_DEFAULTS.maxEntries\n const maxPathDepth = options.maxPathDepth ?? PARSE_API_ERRORS_DEFAULTS.maxPathDepth\n const maxTotalSegments = options.maxTotalSegments ?? PARSE_API_ERRORS_DEFAULTS.maxTotalSegments\n const defaultCode = options.defaultCode ?? PARSE_API_ERRORS_DEFAULTS.defaultCode\n\n if (payload === null || payload === undefined) {\n return { ok: true, errors: [] }\n }\n if (typeof payload !== 'object') {\n return { ok: false, errors: [], rejected: `payload was ${typeof payload}, expected object` }\n }\n\n const extraction = extractDetails(payload as Record<string, unknown>)\n if (!extraction.ok) {\n return { ok: false, errors: [], rejected: extraction.reason }\n }\n\n const { details } = extraction\n const entryCount = Object.keys(details).length\n // Enforce the guardrails before we spend time walking the payload.\n // Rejecting wholesale (not partial-applying) keeps the failure visible\n // so consumers can tune the caps or investigate the server payload.\n if (entryCount > maxEntries) {\n return {\n ok: false,\n errors: [],\n rejected: `payload has ${entryCount} entries, exceeds maxEntries=${maxEntries}`,\n }\n }\n\n const errors: ValidationError[] = []\n let totalSegments = 0\n for (const [key, value] of Object.entries(details)) {\n const entryList: ReadonlyArray<string | ApiErrorEntry> = Array.isArray(value) ? value : [value]\n // `canonicalizePath` throws `InvalidPathError` for dotted strings with\n // empty segments (e.g. `'. '`, `'a..b'`). A misbehaving server can\n // genuinely emit such a key; the hydrator is a normaliser, not a\n // validator, so we drop offending keys rather than let the exception\n // escape. Well-formed keys continue as normal.\n let segments: readonly (string | number)[]\n try {\n segments = canonicalizePath(key).segments\n } catch (err) {\n if (err instanceof InvalidPathError) continue\n throw err\n }\n // Per-path depth cap. We drop the offending key (rather than\n // rejecting the whole payload) because a single stray deep path\n // in an otherwise legitimate error set is still worth surfacing\n // the rest. Consumers who want strict rejection can post-filter\n // on `result.errors.length < details entryCount`.\n if (segments.length > maxPathDepth) continue\n // Total-segment cap. Enforced wholesale (not per-key) so a payload\n // that passes the per-key gate but stacks into a pathological\n // total still fails visibly. Mirrors `maxEntries` strictness.\n totalSegments += segments.length\n if (totalSegments > maxTotalSegments) {\n return {\n ok: false,\n errors: [],\n rejected: `payload total path segments exceeds maxTotalSegments=${maxTotalSegments}`,\n }\n }\n for (const entry of entryList) {\n // Bare-string entries (Rails / DRF / Laravel shape) synthesize a\n // `code` from `options.defaultCode`; structured `{ message, code }`\n // entries forward `code` verbatim. Empty messages drop silently\n // (`{ message: '' }` or `''`) — same recoverable-malformed-server\n // policy as before.\n const message = typeof entry === 'string' ? entry : entry.message\n const code = typeof entry === 'string' ? defaultCode : entry.code\n if (message.length === 0) continue\n errors.push({\n message,\n path: Array.from(segments),\n formKey: options.formKey,\n code,\n })\n }\n }\n return { ok: true, errors }\n}\n\ntype ExtractResult = { ok: true; details: ApiErrorDetails } | { ok: false; reason: string }\n\nfunction extractDetails(payload: Record<string, unknown>): ExtractResult {\n const wrappedError = payload['error']\n if (wrappedError !== null && wrappedError !== undefined && typeof wrappedError === 'object') {\n const inner = (wrappedError as { details?: unknown }).details\n if (inner === undefined) {\n // A wrapped envelope without details is considered \"no errors\" — valid shape.\n return { ok: true, details: {} }\n }\n if (isDetailsRecord(inner)) return { ok: true, details: inner }\n return {\n ok: false,\n reason: 'error.details entries must be strings or { message, code } objects',\n }\n }\n\n // `{ error: 'oops' }` / `{ error: 42 }` is a malformed wrapped envelope —\n // the server meant an error object but sent a scalar. Without this guard\n // the payload would fall through to the raw-details branch below, where\n // `{ error: 'oops' }` satisfies `isDetailsRecord` and silently produces\n // a phantom `ValidationError` at path `['error']`.\n if (wrappedError !== null && wrappedError !== undefined && typeof wrappedError !== 'object') {\n return {\n ok: false,\n reason: `payload.error was ${typeof wrappedError}, expected an object with { details }`,\n }\n }\n\n if ('details' in payload) {\n const inner = payload['details']\n if (inner === undefined) return { ok: true, details: {} }\n if (isDetailsRecord(inner)) return { ok: true, details: inner }\n return { ok: false, reason: 'details entries must be strings or { message, code } objects' }\n }\n\n if (isDetailsRecord(payload)) return { ok: true, details: payload }\n\n // Heuristic: if the payload has keys but none of them look like details,\n // it's probably a completely different shape. Reject.\n if (Object.keys(payload).length === 0) return { ok: true, details: {} }\n return { ok: false, reason: 'unrecognised payload shape' }\n}\n\nfunction isStructuredEntry(value: unknown): value is ApiErrorEntry {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false\n const obj = value as { message?: unknown; code?: unknown }\n return typeof obj.message === 'string' && typeof obj.code === 'string'\n}\n\n/**\n * Accepts either a structured `{ message, code }` entry OR a bare\n * string. Bare strings synthesize a `code` at parse time\n * (`options.defaultCode`) and are useful for the Rails / Django REST\n * Framework / Laravel JSON shape that doesn't carry a per-field code.\n */\nfunction isAcceptedEntry(value: unknown): value is string | ApiErrorEntry {\n return typeof value === 'string' || isStructuredEntry(value)\n}\n\n/**\n * A record is a \"details\" record when every value is either an\n * accepted entry or an array of accepted entries (mixing structured +\n * bare-string in the same array is fine; the parser normalises per\n * entry). Half-structured objects (e.g. `{ message: 'x' }` missing\n * `code`) are still rejected so the bug surfaces — see the\n * `'rejects entries that are objects but missing required fields'`\n * test for the rationale.\n */\nfunction isDetailsRecord(value: unknown): value is ApiErrorDetails {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false\n // Reject prototype-polluted keys — we don't use them here, but downstream\n // spreads shouldn't have to worry about this input.\n const record = value as Record<string, unknown>\n for (const k of Object.keys(record)) {\n const v = record[k]\n if (isAcceptedEntry(v)) continue\n if (Array.isArray(v) && v.every((entry) => isAcceptedEntry(entry))) continue\n return false\n }\n return true\n}\n"],"names":["canonicalizePath","InvalidPathError"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { App, InjectionKey, Plugin } from 'vue';
2
- import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform._EqYNPYF.cjs';
3
- export { h as ApiErrorEntry, i as ArrayItem, j as ArrayPath, k as CoercionResult, l as CustomDirectiveRegisterAssignerFn, m as DefaultValuesResponse, n as FieldMetaPayload, o as FieldState, p as FieldStateMap, q as FieldStateMapEntry, r as FlatPath, s as FormErrorRecord, t as FormErrorsSurface, u as FormMeta, v as FormStorage, w as FormStorageKind, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, z as NestedType, O as OnError, B as OnInvalidSubmitPolicy, E as OnSubmit, P as Path, Q as PathKey, T as PendingValidationStatus, W as PersistConfig, X as PersistConfigOptions, Y as PersistIncludeMode, Z as ROOT_PATH, _ as ROOT_PATH_KEY, $ as ReactiveValidationStatus, a0 as RegisterDirective, a1 as RegisterFlatPath, a2 as RegisterOptions, a3 as RegisterSelectModifier, a4 as RegisterTextModifier, a5 as RegisterTransform, a6 as Segment, a7 as SetValueCallback, a8 as SetValuePayload, a9 as SettledValidationStatus, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationResponse, ag as ValidationResponseWithoutValue, ah as ValueOfUnion, ai as WriteMeta, aj as WriteShape, ak as canonicalizePath, al as isPathPrefix, am as isUnset, an as parseDottedPath, ao as unset } from './shared/attaform._EqYNPYF.cjs';
4
- export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.DLnKT7wk.cjs';
2
+ import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, f as ShouldShowErrors, V as ValidationError, g as ApiErrorEnvelope, h as ApiErrorDetails } from './shared/attaform.CU3JperC.cjs';
3
+ export { i as ApiErrorEntry, j as ArrayItem, k as ArrayPath, l as CoercionResult, m as CustomDirectiveRegisterAssignerFn, n as DefaultValuesResponse, o as FieldMetaPayload, p as FieldState, q as FieldStateMap, r as FieldStateMapEntry, s as FlatPath, t as FormErrorRecord, u as FormErrorsSurface, v as FormMeta, w as FormStorage, x as FormStorageKind, H as HandleSubmit, y as HistoryConfig, I as IsTuple, z as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, B as NestedType, O as OnError, E as OnInvalidSubmitPolicy, P as OnSubmit, Q as Path, T as PathKey, W as PendingValidationStatus, X as PersistConfig, Y as PersistConfigOptions, Z as PersistIncludeMode, _ as ROOT_PATH, $ as ROOT_PATH_KEY, a0 as ReactiveValidationStatus, a1 as RegisterDirective, a2 as RegisterFlatPath, a3 as RegisterOptions, a4 as RegisterSelectModifier, a5 as RegisterTextModifier, a6 as RegisterTransform, a7 as Segment, a8 as SetValueCallback, a9 as SetValuePayload, aa as SettledValidationStatus, ab as ShouldShowErrorsConfig, ac as SlimRuntimeOf, ad as SubmitHandler, ae as Unset, af as ValidateOn, ag as ValidateOnConfig, ah as ValidationResponse, ai as ValidationResponseWithoutValue, aj as ValueOfUnion, ak as WriteMeta, al as WriteShape, am as canonicalizePath, an as isPathPrefix, ao as isUnset, ap as parseDottedPath, aq as unset } from './shared/attaform.CU3JperC.cjs';
4
+ export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.CMRmwGDt.cjs';
5
5
  export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, c as ReservedFormKeyError, S as SensitivePersistFieldError, d as SubmitErrorHandlerError } from './shared/attaform.B7rzpK1U.cjs';
6
6
 
7
7
  /**
@@ -368,6 +368,35 @@ declare function isRegisterValue<Value = unknown>(val: unknown): val is Register
368
368
  */
369
369
  declare const vRegister: RegisterModelDynamicCustomDirective;
370
370
 
371
+ /**
372
+ * Library-default heuristic for `shouldShowErrors`. Drives
373
+ * `field.showErrors` and `form.meta.showErrors` whenever the consumer
374
+ * has not configured an override at either the plugin or per-form
375
+ * level.
376
+ *
377
+ * Reads "show errors after the first submit attempt, OR after the
378
+ * user has interacted (`touched`) and made a change (`dirty`)." The
379
+ * framework already gates on `errors.length > 0` before invoking the
380
+ * predicate, so the body only decides *when* to surface existing
381
+ * errors — not whether errors exist.
382
+ *
383
+ * Public re-export so adopters can compose with this without
384
+ * copy-pasting the rule body. A layered predicate that adds a
385
+ * special case but otherwise defers to the library default picks up
386
+ * future heuristic refinements automatically:
387
+ *
388
+ * ```ts
389
+ * import { defaultShouldShowErrors } from 'attaform'
390
+ *
391
+ * useForm({
392
+ * schema,
393
+ * shouldShowErrors: (field, formMeta) =>
394
+ * field.path[0] === 'urgent' || defaultShouldShowErrors(field, formMeta),
395
+ * })
396
+ * ```
397
+ */
398
+ declare const defaultShouldShowErrors: ShouldShowErrors;
399
+
371
400
  /**
372
401
  * Result of `parseApiErrors`. Branch on `ok` to handle the two cases:
373
402
  *
@@ -494,5 +523,5 @@ declare const PARSE_API_ERRORS_DEFAULTS: {
494
523
  */
495
524
  declare function parseApiErrors(payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown, options: ParseApiErrorsOptions): ParseApiErrorsResult;
496
525
 
497
- export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, CoercionEntry, CoercionRegistry, DeepPartial, DefaultValuesShape, FormKey, GenericForm, PARSE_API_ERRORS_DEFAULTS, RegisterValue, SlimPrimitiveKind, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, createRegistry, defaultCoercionRules, defineCoercion, escapeForInlineScript, getRegistryFromApp, hydrateAttaformState, isRegisterValue, kAttaformRegistry, parseApiErrors, renderAttaformState, useAbstractForm as useForm, useRegistry, vRegister };
526
+ export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, CoercionEntry, CoercionRegistry, DeepPartial, DefaultValuesShape, FormKey, GenericForm, PARSE_API_ERRORS_DEFAULTS, RegisterValue, ShouldShowErrors, SlimPrimitiveKind, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, createRegistry, defaultCoercionRules, defaultShouldShowErrors, defineCoercion, escapeForInlineScript, getRegistryFromApp, hydrateAttaformState, isRegisterValue, kAttaformRegistry, parseApiErrors, renderAttaformState, useAbstractForm as useForm, useRegistry, vRegister };
498
527
  export type { AttaformPluginOptions, AttaformRegistry, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState, SerializedFormData };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { App, InjectionKey, Plugin } from 'vue';
2
- import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform._EqYNPYF.mjs';
3
- export { h as ApiErrorEntry, i as ArrayItem, j as ArrayPath, k as CoercionResult, l as CustomDirectiveRegisterAssignerFn, m as DefaultValuesResponse, n as FieldMetaPayload, o as FieldState, p as FieldStateMap, q as FieldStateMapEntry, r as FlatPath, s as FormErrorRecord, t as FormErrorsSurface, u as FormMeta, v as FormStorage, w as FormStorageKind, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, z as NestedType, O as OnError, B as OnInvalidSubmitPolicy, E as OnSubmit, P as Path, Q as PathKey, T as PendingValidationStatus, W as PersistConfig, X as PersistConfigOptions, Y as PersistIncludeMode, Z as ROOT_PATH, _ as ROOT_PATH_KEY, $ as ReactiveValidationStatus, a0 as RegisterDirective, a1 as RegisterFlatPath, a2 as RegisterOptions, a3 as RegisterSelectModifier, a4 as RegisterTextModifier, a5 as RegisterTransform, a6 as Segment, a7 as SetValueCallback, a8 as SetValuePayload, a9 as SettledValidationStatus, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationResponse, ag as ValidationResponseWithoutValue, ah as ValueOfUnion, ai as WriteMeta, aj as WriteShape, ak as canonicalizePath, al as isPathPrefix, am as isUnset, an as parseDottedPath, ao as unset } from './shared/attaform._EqYNPYF.mjs';
4
- export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.Bls_kFR6.mjs';
2
+ import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, f as ShouldShowErrors, V as ValidationError, g as ApiErrorEnvelope, h as ApiErrorDetails } from './shared/attaform.CU3JperC.mjs';
3
+ export { i as ApiErrorEntry, j as ArrayItem, k as ArrayPath, l as CoercionResult, m as CustomDirectiveRegisterAssignerFn, n as DefaultValuesResponse, o as FieldMetaPayload, p as FieldState, q as FieldStateMap, r as FieldStateMapEntry, s as FlatPath, t as FormErrorRecord, u as FormErrorsSurface, v as FormMeta, w as FormStorage, x as FormStorageKind, H as HandleSubmit, y as HistoryConfig, I as IsTuple, z as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, B as NestedType, O as OnError, E as OnInvalidSubmitPolicy, P as OnSubmit, Q as Path, T as PathKey, W as PendingValidationStatus, X as PersistConfig, Y as PersistConfigOptions, Z as PersistIncludeMode, _ as ROOT_PATH, $ as ROOT_PATH_KEY, a0 as ReactiveValidationStatus, a1 as RegisterDirective, a2 as RegisterFlatPath, a3 as RegisterOptions, a4 as RegisterSelectModifier, a5 as RegisterTextModifier, a6 as RegisterTransform, a7 as Segment, a8 as SetValueCallback, a9 as SetValuePayload, aa as SettledValidationStatus, ab as ShouldShowErrorsConfig, ac as SlimRuntimeOf, ad as SubmitHandler, ae as Unset, af as ValidateOn, ag as ValidateOnConfig, ah as ValidationResponse, ai as ValidationResponseWithoutValue, aj as ValueOfUnion, ak as WriteMeta, al as WriteShape, am as canonicalizePath, an as isPathPrefix, ao as isUnset, ap as parseDottedPath, aq as unset } from './shared/attaform.CU3JperC.mjs';
4
+ export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.CXMOheyZ.mjs';
5
5
  export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, c as ReservedFormKeyError, S as SensitivePersistFieldError, d as SubmitErrorHandlerError } from './shared/attaform.B7rzpK1U.mjs';
6
6
 
7
7
  /**
@@ -368,6 +368,35 @@ declare function isRegisterValue<Value = unknown>(val: unknown): val is Register
368
368
  */
369
369
  declare const vRegister: RegisterModelDynamicCustomDirective;
370
370
 
371
+ /**
372
+ * Library-default heuristic for `shouldShowErrors`. Drives
373
+ * `field.showErrors` and `form.meta.showErrors` whenever the consumer
374
+ * has not configured an override at either the plugin or per-form
375
+ * level.
376
+ *
377
+ * Reads "show errors after the first submit attempt, OR after the
378
+ * user has interacted (`touched`) and made a change (`dirty`)." The
379
+ * framework already gates on `errors.length > 0` before invoking the
380
+ * predicate, so the body only decides *when* to surface existing
381
+ * errors — not whether errors exist.
382
+ *
383
+ * Public re-export so adopters can compose with this without
384
+ * copy-pasting the rule body. A layered predicate that adds a
385
+ * special case but otherwise defers to the library default picks up
386
+ * future heuristic refinements automatically:
387
+ *
388
+ * ```ts
389
+ * import { defaultShouldShowErrors } from 'attaform'
390
+ *
391
+ * useForm({
392
+ * schema,
393
+ * shouldShowErrors: (field, formMeta) =>
394
+ * field.path[0] === 'urgent' || defaultShouldShowErrors(field, formMeta),
395
+ * })
396
+ * ```
397
+ */
398
+ declare const defaultShouldShowErrors: ShouldShowErrors;
399
+
371
400
  /**
372
401
  * Result of `parseApiErrors`. Branch on `ok` to handle the two cases:
373
402
  *
@@ -494,5 +523,5 @@ declare const PARSE_API_ERRORS_DEFAULTS: {
494
523
  */
495
524
  declare function parseApiErrors(payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown, options: ParseApiErrorsOptions): ParseApiErrorsResult;
496
525
 
497
- export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, CoercionEntry, CoercionRegistry, DeepPartial, DefaultValuesShape, FormKey, GenericForm, PARSE_API_ERRORS_DEFAULTS, RegisterValue, SlimPrimitiveKind, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, createRegistry, defaultCoercionRules, defineCoercion, escapeForInlineScript, getRegistryFromApp, hydrateAttaformState, isRegisterValue, kAttaformRegistry, parseApiErrors, renderAttaformState, useAbstractForm as useForm, useRegistry, vRegister };
526
+ export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, CoercionEntry, CoercionRegistry, DeepPartial, DefaultValuesShape, FormKey, GenericForm, PARSE_API_ERRORS_DEFAULTS, RegisterValue, ShouldShowErrors, SlimPrimitiveKind, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, createRegistry, defaultCoercionRules, defaultShouldShowErrors, defineCoercion, escapeForInlineScript, getRegistryFromApp, hydrateAttaformState, isRegisterValue, kAttaformRegistry, parseApiErrors, renderAttaformState, useAbstractForm as useForm, useRegistry, vRegister };
498
527
  export type { AttaformPluginOptions, AttaformRegistry, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState, SerializedFormData };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { App, InjectionKey, Plugin } from 'vue';
2
- import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform._EqYNPYF.js';
3
- export { h as ApiErrorEntry, i as ArrayItem, j as ArrayPath, k as CoercionResult, l as CustomDirectiveRegisterAssignerFn, m as DefaultValuesResponse, n as FieldMetaPayload, o as FieldState, p as FieldStateMap, q as FieldStateMapEntry, r as FlatPath, s as FormErrorRecord, t as FormErrorsSurface, u as FormMeta, v as FormStorage, w as FormStorageKind, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, z as NestedType, O as OnError, B as OnInvalidSubmitPolicy, E as OnSubmit, P as Path, Q as PathKey, T as PendingValidationStatus, W as PersistConfig, X as PersistConfigOptions, Y as PersistIncludeMode, Z as ROOT_PATH, _ as ROOT_PATH_KEY, $ as ReactiveValidationStatus, a0 as RegisterDirective, a1 as RegisterFlatPath, a2 as RegisterOptions, a3 as RegisterSelectModifier, a4 as RegisterTextModifier, a5 as RegisterTransform, a6 as Segment, a7 as SetValueCallback, a8 as SetValuePayload, a9 as SettledValidationStatus, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationResponse, ag as ValidationResponseWithoutValue, ah as ValueOfUnion, ai as WriteMeta, aj as WriteShape, ak as canonicalizePath, al as isPathPrefix, am as isUnset, an as parseDottedPath, ao as unset } from './shared/attaform._EqYNPYF.js';
4
- export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.lFNwBcA3.js';
2
+ import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, f as ShouldShowErrors, V as ValidationError, g as ApiErrorEnvelope, h as ApiErrorDetails } from './shared/attaform.CU3JperC.js';
3
+ export { i as ApiErrorEntry, j as ArrayItem, k as ArrayPath, l as CoercionResult, m as CustomDirectiveRegisterAssignerFn, n as DefaultValuesResponse, o as FieldMetaPayload, p as FieldState, q as FieldStateMap, r as FieldStateMapEntry, s as FlatPath, t as FormErrorRecord, u as FormErrorsSurface, v as FormMeta, w as FormStorage, x as FormStorageKind, H as HandleSubmit, y as HistoryConfig, I as IsTuple, z as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, B as NestedType, O as OnError, E as OnInvalidSubmitPolicy, P as OnSubmit, Q as Path, T as PathKey, W as PendingValidationStatus, X as PersistConfig, Y as PersistConfigOptions, Z as PersistIncludeMode, _ as ROOT_PATH, $ as ROOT_PATH_KEY, a0 as ReactiveValidationStatus, a1 as RegisterDirective, a2 as RegisterFlatPath, a3 as RegisterOptions, a4 as RegisterSelectModifier, a5 as RegisterTextModifier, a6 as RegisterTransform, a7 as Segment, a8 as SetValueCallback, a9 as SetValuePayload, aa as SettledValidationStatus, ab as ShouldShowErrorsConfig, ac as SlimRuntimeOf, ad as SubmitHandler, ae as Unset, af as ValidateOn, ag as ValidateOnConfig, ah as ValidationResponse, ai as ValidationResponseWithoutValue, aj as ValueOfUnion, ak as WriteMeta, al as WriteShape, am as canonicalizePath, an as isPathPrefix, ao as isUnset, ap as parseDottedPath, aq as unset } from './shared/attaform.CU3JperC.js';
4
+ export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.CCQkY4Ta.js';
5
5
  export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, c as ReservedFormKeyError, S as SensitivePersistFieldError, d as SubmitErrorHandlerError } from './shared/attaform.B7rzpK1U.js';
6
6
 
7
7
  /**
@@ -368,6 +368,35 @@ declare function isRegisterValue<Value = unknown>(val: unknown): val is Register
368
368
  */
369
369
  declare const vRegister: RegisterModelDynamicCustomDirective;
370
370
 
371
+ /**
372
+ * Library-default heuristic for `shouldShowErrors`. Drives
373
+ * `field.showErrors` and `form.meta.showErrors` whenever the consumer
374
+ * has not configured an override at either the plugin or per-form
375
+ * level.
376
+ *
377
+ * Reads "show errors after the first submit attempt, OR after the
378
+ * user has interacted (`touched`) and made a change (`dirty`)." The
379
+ * framework already gates on `errors.length > 0` before invoking the
380
+ * predicate, so the body only decides *when* to surface existing
381
+ * errors — not whether errors exist.
382
+ *
383
+ * Public re-export so adopters can compose with this without
384
+ * copy-pasting the rule body. A layered predicate that adds a
385
+ * special case but otherwise defers to the library default picks up
386
+ * future heuristic refinements automatically:
387
+ *
388
+ * ```ts
389
+ * import { defaultShouldShowErrors } from 'attaform'
390
+ *
391
+ * useForm({
392
+ * schema,
393
+ * shouldShowErrors: (field, formMeta) =>
394
+ * field.path[0] === 'urgent' || defaultShouldShowErrors(field, formMeta),
395
+ * })
396
+ * ```
397
+ */
398
+ declare const defaultShouldShowErrors: ShouldShowErrors;
399
+
371
400
  /**
372
401
  * Result of `parseApiErrors`. Branch on `ok` to handle the two cases:
373
402
  *
@@ -494,5 +523,5 @@ declare const PARSE_API_ERRORS_DEFAULTS: {
494
523
  */
495
524
  declare function parseApiErrors(payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown, options: ParseApiErrorsOptions): ParseApiErrorsResult;
496
525
 
497
- export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, CoercionEntry, CoercionRegistry, DeepPartial, DefaultValuesShape, FormKey, GenericForm, PARSE_API_ERRORS_DEFAULTS, RegisterValue, SlimPrimitiveKind, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, createRegistry, defaultCoercionRules, defineCoercion, escapeForInlineScript, getRegistryFromApp, hydrateAttaformState, isRegisterValue, kAttaformRegistry, parseApiErrors, renderAttaformState, useAbstractForm as useForm, useRegistry, vRegister };
526
+ export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, CoercionEntry, CoercionRegistry, DeepPartial, DefaultValuesShape, FormKey, GenericForm, PARSE_API_ERRORS_DEFAULTS, RegisterValue, ShouldShowErrors, SlimPrimitiveKind, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, createRegistry, defaultCoercionRules, defaultShouldShowErrors, defineCoercion, escapeForInlineScript, getRegistryFromApp, hydrateAttaformState, isRegisterValue, kAttaformRegistry, parseApiErrors, renderAttaformState, useAbstractForm as useForm, useRegistry, vRegister };
498
527
  export type { AttaformPluginOptions, AttaformRegistry, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState, SerializedFormData };
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import { I as InvalidPathError } from './shared/attaform.BfMxsfmE.mjs';
2
2
  export { A as AnonPersistError, a as AttaformError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, d as ReservedFormKeyError, S as SensitivePersistFieldError, e as SubmitErrorHandlerError, f as assignKey, c as createAttaform, h as createRegistry, g as getRegistryFromApp, j as isRegisterValue, k as kAttaformRegistry, u as useRegister, l as useRegistry, v as vRegister } from './shared/attaform.BfMxsfmE.mjs';
3
3
  export { h as hydrateAttaformState, r as renderAttaformState } from './shared/attaform.CINUMjPq.mjs';
4
- export { A as AttaformErrorCode, d as defaultCoercionRules, b as defineCoercion, i as injectForm, a as isUnset, u as unset, c as useForm } from './shared/attaform.DILbdvfo.mjs';
5
- import { c as canonicalizePath } from './shared/attaform.jrxE_xZw.mjs';
6
- export { R as ROOT_PATH, a as ROOT_PATH_KEY, i as isPathPrefix, p as parseDottedPath } from './shared/attaform.jrxE_xZw.mjs';
4
+ export { A as AttaformErrorCode, d as defaultCoercionRules, b as defaultShouldShowErrors, c as defineCoercion, i as injectForm, a as isUnset, u as unset, e as useForm } from './shared/attaform.DyV1O4tI.mjs';
5
+ import { c as canonicalizePath } from './shared/attaform.DZRj9s0s.mjs';
6
+ export { R as ROOT_PATH, a as ROOT_PATH_KEY, i as isPathPrefix, p as parseDottedPath } from './shared/attaform.DZRj9s0s.mjs';
7
7
 
8
8
  function escapeForInlineScript(json) {
9
9
  return json.replace(/[<>&\u2028\u2029]/g, (char) => {
package/dist/nuxt.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { A as AttaformDefaults } from './shared/attaform._EqYNPYF.cjs';
2
+ import { A as AttaformDefaults } from './shared/attaform.CU3JperC.cjs';
3
3
  import 'vue';
4
4
 
5
5
  /**
package/dist/nuxt.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { A as AttaformDefaults } from './shared/attaform._EqYNPYF.mjs';
2
+ import { A as AttaformDefaults } from './shared/attaform.CU3JperC.mjs';
3
3
  import 'vue';
4
4
 
5
5
  /**
package/dist/nuxt.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { A as AttaformDefaults } from './shared/attaform._EqYNPYF.js';
2
+ import { A as AttaformDefaults } from './shared/attaform.CU3JperC.js';
3
3
  import 'vue';
4
4
 
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { G as GenericForm, F as FormKey, d as UseFormReturnType, R as RegisterValue } from './attaform._EqYNPYF.js';
1
+ import { G as GenericForm, F as FormKey, d as UseFormReturnType, R as RegisterValue } from './attaform.CU3JperC.js';
2
2
  import { Ref } from 'vue';
3
3
 
4
4
  /**
@@ -16,7 +16,7 @@ function normalizeSegment(raw) {
16
16
  return raw;
17
17
  }
18
18
  function parseDottedPath(path) {
19
- if (path.length === 0) return [];
19
+ if (path.length === 0) return [""];
20
20
  const rawSegments = path.split(".");
21
21
  const segments = [];
22
22
  for (const raw of rawSegments) {
@@ -80,6 +80,8 @@ function canonicalizePath(input) {
80
80
  }
81
81
  const ROOT_PATH = Object.freeze([]);
82
82
  const ROOT_PATH_KEY = "[]";
83
+ const FORM_ERRORS_PATH = Object.freeze([""]);
84
+ const FORM_ERRORS_PATH_KEY = '[""]';
83
85
  function isPathPrefix(prefix, path) {
84
86
  if (path.length < prefix.length) return false;
85
87
  for (let i = 0; i < prefix.length; i++) {
@@ -88,10 +90,12 @@ function isPathPrefix(prefix, path) {
88
90
  return true;
89
91
  }
90
92
 
93
+ exports.FORM_ERRORS_PATH = FORM_ERRORS_PATH;
94
+ exports.FORM_ERRORS_PATH_KEY = FORM_ERRORS_PATH_KEY;
91
95
  exports.ROOT_PATH = ROOT_PATH;
92
96
  exports.ROOT_PATH_KEY = ROOT_PATH_KEY;
93
97
  exports.canonicalizePath = canonicalizePath;
94
98
  exports.isPathPrefix = isPathPrefix;
95
99
  exports.parseDottedPath = parseDottedPath;
96
100
  exports.segmentsForPathKey = segmentsForPathKey;
97
- //# sourceMappingURL=attaform.c_NzdRyc.cjs.map
101
+ //# sourceMappingURL=attaform.CIwZtbGV.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attaform.CIwZtbGV.cjs","sources":["../../src/runtime/core/paths.ts"],"sourcesContent":["import { InvalidPathError } from './errors'\n\n/**\n * Path primitives for advanced integrations. The form library accepts\n * paths in dotted-string form (`'user.email'`) at every public API.\n * These primitives are exposed for adapter authors who need to\n * canonicalise user-provided paths.\n */\n\ndeclare const pathKeyBrand: unique symbol\n\n/**\n * Branded string identifier for a canonicalised path. Useful as a\n * `Map` key — two paths that resolve to the same canonical form\n * produce the same `PathKey`. Treat as opaque; don't try to parse.\n */\nexport type PathKey = string & { readonly [pathKeyBrand]: 'PathKey' }\n\n/** A single path segment — a property name or array index. */\nexport type Segment = string | number\n/** A structured path as a read-only sequence of segments. */\nexport type Path = readonly Segment[]\n\n/** Tests an integer-like string without leading zeros. `'0'` | `'1'` | `'42'` pass; `'01'`, `'-1'`, `'1.5'` do not. */\nconst INTEGER_SEGMENT = /^(?:0|[1-9]\\d*)$/\n\nfunction normalizeSegment(raw: Segment): Segment {\n if (typeof raw === 'number') {\n if (!Number.isInteger(raw) || raw < 0) {\n throw new InvalidPathError(\n `Path segments must be non-negative integers when numeric; got ${String(raw)}`\n )\n }\n return raw\n }\n // Integer-looking strings normalise to numbers so that dotted-form\n // `'items.0.name'` and array-form `['items', 0, 'name']` yield the same\n // canonical path (and PathKey).\n if (INTEGER_SEGMENT.test(raw)) return Number(raw)\n return raw\n}\n\n/**\n * Parse a dotted-string path into structured segments.\n *\n * ```ts\n * parseDottedPath('user.address.line1') // ['user', 'address', 'line1']\n * parseDottedPath('items.0.name') // ['items', 0, 'name']\n * parseDottedPath('') // [''] (the empty-string key)\n * ```\n *\n * The empty-string input `''` is the **literal empty-key path**, not\n * the root. Use the array form `[]` for root. Form-level errors\n * (root `.refine()`) live at the empty-string path bucket so\n * `errors('')` returns them without sweeping every field error too.\n *\n * Throws `InvalidPathError` for paths with empty INTERNAL segments\n * (`'a..b'`, leading or trailing dots). For keys containing literal\n * dots, pass an array form (`['user.name']`) instead.\n */\nexport function parseDottedPath(path: string): Segment[] {\n if (path.length === 0) return ['']\n const rawSegments = path.split('.')\n const segments: Segment[] = []\n for (const raw of rawSegments) {\n if (raw.length === 0) {\n throw new InvalidPathError(\n `Path '${path}' has an empty segment; use the array form for empty keys.`\n )\n }\n segments.push(normalizeSegment(raw))\n }\n return segments\n}\n\n/**\n * Bounded FIFO cache for canonicalizePath on dotted-string inputs.\n * Real forms re-canonicalise a small working-set of paths thousands\n * of times per session (every keystroke on a registered field, every\n * validate, every getValue), so a small cache amortises the parse +\n * stringify cost across repeat calls without pinning memory as apps\n * accumulate fields.\n *\n * Eviction is FIFO (oldest insertion wins), not LRU. The 128-entry\n * cap is generous relative to a typical form's working set\n * (playground: ~15 paths; the entire test suite: 45 unique register\n * patterns) — overflow doesn't fire in practice. On the rare overflow\n * a re-canonicalisation hit is still O(segments) and lands back in\n * the cache. Bumping recency on every hit (`delete` + `set`) costs\n * two Map operations per cache hit, in the hottest read-side loop in\n * the library, with no observable benefit at this cap — so we don't.\n *\n * Array inputs are not cached: callers in the runtime (unset-walker's\n * recursive `[...segments, i]`, devtools' inspector `payload.path.slice(...)`)\n * overwhelmingly pass freshly-allocated arrays per call, so a\n * WeakMap-keyed cache would miss on every call and pay the\n * lookup-then-set cost without benefit.\n */\nconst CANONICAL_STRING_CACHE_MAX = 128\nconst canonicalStringCache = new Map<string, { segments: readonly Segment[]; key: PathKey }>()\n\n/**\n * Inverse cache: PathKey → segments. Populated by `canonicalizePath`\n * (string and array branches) so any consumer holding a PathKey\n * produced through the canonical pipeline can recover its structured\n * segments without `JSON.parse`. Callers reach this through\n * `segmentsForPathKey` below.\n *\n * The store-side data structures keyed by PathKey (form-store error\n * maps, blank-paths set, variant-memory map, persistence opt-in\n * registry) all source their keys from `canonicalizePath`, so reads\n * are dominantly cache hits. Cold paths (PathKeys round-tripped from\n * a persisted payload that came from disk) still hit a single\n * `JSON.parse` on first lookup, then warm the cache.\n *\n * Bounded FIFO at 4096 entries — generous relative to a typical form's\n * working set (~tens to ~hundreds of paths per form) but small enough\n * that long-running multi-form apps don't accumulate unbounded\n * references. Eviction only fires on net-new entries; idempotent\n * overwrites (same key, same segments) don't count toward the cap.\n */\nconst PATHKEY_TO_SEGMENTS_MAX = 4096\nconst pathKeyToSegments = new Map<PathKey, readonly Segment[]>()\n\nfunction rememberSegmentsForPathKey(key: PathKey, segments: readonly Segment[]): void {\n if (!pathKeyToSegments.has(key) && pathKeyToSegments.size >= PATHKEY_TO_SEGMENTS_MAX) {\n const oldest = pathKeyToSegments.keys().next().value\n if (oldest !== undefined) pathKeyToSegments.delete(oldest)\n }\n pathKeyToSegments.set(key, segments)\n}\n\n/**\n * Recover the structured `Segment[]` for a `PathKey` produced by\n * `canonicalizePath`. O(1) on the hot path (cache hit); cold keys\n * fall back to `JSON.parse(key)` plus segment normalization, then\n * warm the cache so subsequent lookups hit.\n *\n * Returns `null` for malformed PathKeys (non-JSON, non-array, or\n * containing values that aren't strings/numbers). Keys produced by\n * `canonicalizePath` never trip this — corrupt persistence payloads\n * (or test fixtures crafting raw strings) are the only realistic\n * sources.\n */\nexport function segmentsForPathKey(key: PathKey): readonly Segment[] | null {\n const cached = pathKeyToSegments.get(key)\n if (cached !== undefined) return cached\n let parsed: unknown\n try {\n parsed = JSON.parse(key)\n } catch {\n return null\n }\n if (!Array.isArray(parsed)) return null\n const segments: Segment[] = []\n for (const raw of parsed) {\n if (typeof raw !== 'string' && typeof raw !== 'number') return null\n segments.push(normalizeSegment(raw))\n }\n rememberSegmentsForPathKey(key, segments)\n return segments\n}\n\n/**\n * Canonicalise a path into structured segments plus a stable string\n * key. Accepts either dotted-string or array form; integer-looking\n * segments normalise to numbers.\n *\n * ```ts\n * canonicalizePath('items.0.name')\n * // { segments: ['items', 0, 'name'], key: '[\"items\",0,\"name\"]' as PathKey }\n *\n * canonicalizePath(['items', 0, 'name'])\n * // → same result\n * ```\n *\n * The returned `key` is suitable as a `Map`/`Set` key — equal paths\n * produce equal keys regardless of input form.\n */\nexport function canonicalizePath(input: string | Path): {\n segments: readonly Segment[]\n key: PathKey\n} {\n if (typeof input === 'string') {\n const cached = canonicalStringCache.get(input)\n if (cached !== undefined) return cached\n // `parseDottedPath` already normalises each segment; the previous\n // `.map(normalizeSegment)` second pass was a no-op. We drop it here.\n const segments: readonly Segment[] = parseDottedPath(input)\n const key = JSON.stringify(segments) as PathKey\n const entry = { segments, key }\n if (canonicalStringCache.size >= CANONICAL_STRING_CACHE_MAX) {\n const oldest = canonicalStringCache.keys().next().value\n if (oldest !== undefined) canonicalStringCache.delete(oldest)\n }\n canonicalStringCache.set(input, entry)\n rememberSegmentsForPathKey(key, segments)\n return entry\n }\n const segments = Array.from(input).map(normalizeSegment)\n const key = JSON.stringify(segments) as PathKey\n rememberSegmentsForPathKey(key, segments)\n return { segments, key }\n}\n\n/**\n * The root path — an empty segment tuple. Pass to APIs that accept\n * a `Path` to address the form value as a whole.\n */\nexport const ROOT_PATH: Path = Object.freeze([])\n/** Stable string key for the root path. */\nexport const ROOT_PATH_KEY = '[]' as PathKey\n\n/**\n * The form-level path — a one-segment path with the empty-string\n * key. Conventionally home for errors that don't belong to any\n * specific field: root `.refine()` messages, server-emitted form\n * errors, capacity / availability / cross-field-summary banners.\n *\n * Distinct from `ROOT_PATH` (`[]`): the root is the whole-form\n * subtree address (e.g. `errors([])` returns every error). The\n * form-level path is a sibling-of-no-field path that aggregation\n * walks DON'T sweep into per-field reads — `errors('field')`\n * returns only the field's errors, never the form-level bucket,\n * and `errors('')` returns only the form-level bucket, never the\n * field errors.\n */\nexport const FORM_ERRORS_PATH: Path = Object.freeze([''])\n/** Stable string key for the form-level errors path. */\nexport const FORM_ERRORS_PATH_KEY = '[\"\"]' as PathKey\n\n/**\n * `true` when `path` starts with every segment of `prefix` (in order).\n * The empty `prefix` matches every path — ROOT prefix is universal.\n *\n * Walks segments rather than `PathKey` strings because the data this\n * helper operates on (e.g. `meta.errors[].path`) carries segment\n * arrays directly.\n *\n * ```ts\n * isPathPrefix(['cargo'], ['cargo', 'items', 0, 'sku']) // true\n * isPathPrefix(['cargo', 'items'], ['cargo']) // false (path shorter)\n * isPathPrefix([], ['anything']) // true (root prefix)\n * ```\n */\nexport function isPathPrefix(prefix: readonly Segment[], path: readonly Segment[]): boolean {\n if (path.length < prefix.length) return false\n for (let i = 0; i < prefix.length; i++) {\n if (path[i] !== prefix[i]) return false\n }\n return true\n}\n"],"names":["InvalidPathError","segments","key"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { G as GenericForm, F as FormKey, d as UseFormReturnType, R as RegisterValue } from './attaform._EqYNPYF.mjs';
1
+ import { G as GenericForm, F as FormKey, d as UseFormReturnType, R as RegisterValue } from './attaform.CU3JperC.cjs';
2
2
  import { Ref } from 'vue';
3
3
 
4
4
  /**