attaform 0.26.0 → 0.27.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.
Files changed (163) hide show
  1. package/README.md +21 -11
  2. package/bin/attaform.mjs +78 -0
  3. package/dist/abstract.cjs +47 -0
  4. package/dist/abstract.cjs.map +1 -0
  5. package/dist/abstract.d.cts +42 -0
  6. package/dist/abstract.d.mts +42 -0
  7. package/dist/abstract.d.ts +42 -0
  8. package/dist/abstract.mjs +4 -0
  9. package/dist/abstract.mjs.map +1 -0
  10. package/dist/chunks/devtools.cjs +2 -2
  11. package/dist/chunks/devtools.cjs.map +1 -1
  12. package/dist/chunks/devtools.mjs +1 -1
  13. package/dist/chunks/fingerprint2.cjs +1 -1
  14. package/dist/chunks/fingerprint2.mjs +1 -1
  15. package/dist/esbuild.cjs +2 -2
  16. package/dist/esbuild.cjs.map +1 -1
  17. package/dist/esbuild.d.cts +3 -3
  18. package/dist/esbuild.d.mts +3 -3
  19. package/dist/esbuild.d.ts +3 -3
  20. package/dist/esbuild.mjs +2 -2
  21. package/dist/esbuild.mjs.map +1 -1
  22. package/dist/index.cjs +41 -56
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +194 -282
  25. package/dist/index.d.mts +194 -282
  26. package/dist/index.d.ts +194 -282
  27. package/dist/index.mjs +4 -25
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/nuxt.cjs +3 -1
  30. package/dist/nuxt.cjs.map +1 -1
  31. package/dist/nuxt.d.cts +17 -4
  32. package/dist/nuxt.d.mts +17 -4
  33. package/dist/nuxt.d.ts +17 -4
  34. package/dist/nuxt.mjs +4 -2
  35. package/dist/nuxt.mjs.map +1 -1
  36. package/dist/rollup.cjs +2 -2
  37. package/dist/rollup.cjs.map +1 -1
  38. package/dist/rollup.d.cts +3 -3
  39. package/dist/rollup.d.mts +3 -3
  40. package/dist/rollup.d.ts +3 -3
  41. package/dist/rollup.mjs +2 -2
  42. package/dist/rollup.mjs.map +1 -1
  43. package/dist/rspack.cjs +1 -1
  44. package/dist/rspack.d.cts +1 -1
  45. package/dist/rspack.d.mts +1 -1
  46. package/dist/rspack.d.ts +1 -1
  47. package/dist/rspack.mjs +1 -1
  48. package/dist/runtime/plugins/attaform.cjs +4 -5
  49. package/dist/runtime/plugins/attaform.cjs.map +1 -1
  50. package/dist/runtime/plugins/attaform.mjs +1 -2
  51. package/dist/runtime/plugins/attaform.mjs.map +1 -1
  52. package/dist/shared/{attaform.BRzKBj2g.cjs → attaform.8tFZu1Ub.cjs} +2 -2
  53. package/dist/shared/{attaform.BRzKBj2g.cjs.map → attaform.8tFZu1Ub.cjs.map} +1 -1
  54. package/dist/shared/{attaform.k9V0py0s.mjs → attaform.BERt5YMU.mjs} +2 -2
  55. package/dist/shared/{attaform.k9V0py0s.mjs.map → attaform.BERt5YMU.mjs.map} +1 -1
  56. package/dist/shared/{attaform.DSOIz08n.mjs → attaform.BceJrhQ7.mjs} +5 -5
  57. package/dist/shared/{attaform.DSOIz08n.mjs.map → attaform.BceJrhQ7.mjs.map} +1 -1
  58. package/dist/shared/{attaform.DBNjHgNj.d.cts → attaform.C3WnCDXz.d.cts} +11 -9
  59. package/dist/shared/{attaform.DBNjHgNj.d.mts → attaform.C3WnCDXz.d.mts} +11 -9
  60. package/dist/shared/{attaform.DBNjHgNj.d.ts → attaform.C3WnCDXz.d.ts} +11 -9
  61. package/dist/shared/{attaform.DuzQYscR.d.mts → attaform.C9fPTxjB.d.cts} +5 -5
  62. package/dist/shared/{attaform.DuzQYscR.d.ts → attaform.C9fPTxjB.d.mts} +5 -5
  63. package/dist/shared/{attaform.DuzQYscR.d.cts → attaform.C9fPTxjB.d.ts} +5 -5
  64. package/dist/shared/{attaform.Be5otUVw.d.ts → attaform.CC_y1_Ej.d.ts} +33 -33
  65. package/dist/shared/{attaform.ceYeVkjn.d.ts → attaform.CEXUlUkc.d.ts} +1579 -1192
  66. package/dist/shared/{attaform.tZ0YKisf.cjs → attaform.C__F01CE.cjs} +15 -15
  67. package/dist/shared/{attaform.tZ0YKisf.cjs.map → attaform.C__F01CE.cjs.map} +1 -1
  68. package/dist/shared/{attaform.BPl-ECRT.cjs → attaform.Co5LNRnv.cjs} +162 -129
  69. package/dist/shared/attaform.Co5LNRnv.cjs.map +1 -0
  70. package/dist/shared/{attaform.B71rfNL5.d.mts → attaform.CpXHK60W.d.cts} +33 -33
  71. package/dist/shared/{attaform.BFfY7HRI.d.cts → attaform.CvVYOvZF.d.mts} +33 -33
  72. package/dist/shared/{attaform.BoYqnIPI.mjs → attaform.CyQxTOdX.mjs} +55 -36
  73. package/dist/shared/attaform.CyQxTOdX.mjs.map +1 -0
  74. package/dist/shared/{attaform.CEY_WLRJ.d.mts → attaform.D99pd7JG.d.cts} +1579 -1192
  75. package/dist/shared/{attaform.CXVmZtFq.mjs → attaform.DDAmSFnl.mjs} +4 -4
  76. package/dist/shared/{attaform.CXVmZtFq.mjs.map → attaform.DDAmSFnl.mjs.map} +1 -1
  77. package/dist/shared/{attaform.Du9RZp8m.cjs → attaform.DQT7_-FO.cjs} +272 -252
  78. package/dist/shared/attaform.DQT7_-FO.cjs.map +1 -0
  79. package/dist/shared/{attaform.DGhIix5D.mjs → attaform.Da8EdI2t.mjs} +160 -129
  80. package/dist/shared/attaform.Da8EdI2t.mjs.map +1 -0
  81. package/dist/shared/{attaform.Cs0UZ7q6.cjs → attaform.DhVgG2jh.cjs} +16 -16
  82. package/dist/shared/{attaform.Cs0UZ7q6.cjs.map → attaform.DhVgG2jh.cjs.map} +1 -1
  83. package/dist/shared/{attaform.sHkHv_98.mjs → attaform.DhnPb6nK.mjs} +6 -3
  84. package/dist/shared/attaform.DhnPb6nK.mjs.map +1 -0
  85. package/dist/shared/attaform.DkD0DR7R.mjs +42 -0
  86. package/dist/shared/attaform.DkD0DR7R.mjs.map +1 -0
  87. package/dist/shared/{attaform.CSXDW2tO.mjs → attaform.DlSu08F5.mjs} +4 -4
  88. package/dist/shared/{attaform.CSXDW2tO.mjs.map → attaform.DlSu08F5.mjs.map} +1 -1
  89. package/dist/shared/{attaform.LEWUFqUw.cjs → attaform.DoQm_Vkd.cjs} +7 -3
  90. package/dist/shared/attaform.DoQm_Vkd.cjs.map +1 -0
  91. package/dist/shared/{attaform.BQflyVOL.cjs → attaform.Drsi43GG.cjs} +19 -19
  92. package/dist/shared/{attaform.BQflyVOL.cjs.map → attaform.Drsi43GG.cjs.map} +1 -1
  93. package/dist/shared/attaform.K6Thc6By.cjs +46 -0
  94. package/dist/shared/attaform.K6Thc6By.cjs.map +1 -0
  95. package/dist/shared/{attaform.Vp2-CWZB.mjs → attaform.KvlEedlF.mjs} +3 -3
  96. package/dist/shared/{attaform.Vp2-CWZB.mjs.map → attaform.KvlEedlF.mjs.map} +1 -1
  97. package/dist/shared/{attaform.BRGIpZo4.cjs → attaform.RaTzp1WF.cjs} +3 -3
  98. package/dist/shared/attaform.RaTzp1WF.cjs.map +1 -0
  99. package/dist/shared/{attaform.MgaYKlPP.d.cts → attaform.kBkYlKP_.d.mts} +1579 -1192
  100. package/dist/shared/{attaform.C3Doa9Pt.mjs → attaform.v0fQtWyA.mjs} +3 -3
  101. package/dist/shared/attaform.v0fQtWyA.mjs.map +1 -0
  102. package/dist/shared/{attaform.ZXZ6dH72.cjs → attaform.yUrz7C2z.cjs} +3 -3
  103. package/dist/shared/{attaform.ZXZ6dH72.cjs.map → attaform.yUrz7C2z.cjs.map} +1 -1
  104. package/dist/transforms.cjs +1 -1
  105. package/dist/transforms.mjs +1 -1
  106. package/dist/vite.cjs +21 -3
  107. package/dist/vite.cjs.map +1 -1
  108. package/dist/vite.d.cts +70 -17
  109. package/dist/vite.d.mts +70 -17
  110. package/dist/vite.d.ts +70 -17
  111. package/dist/vite.mjs +20 -4
  112. package/dist/vite.mjs.map +1 -1
  113. package/dist/webpack.cjs +1 -1
  114. package/dist/webpack.d.cts +1 -1
  115. package/dist/webpack.d.mts +1 -1
  116. package/dist/webpack.d.ts +1 -1
  117. package/dist/webpack.mjs +1 -1
  118. package/dist/zod-v3.cjs +41 -10
  119. package/dist/zod-v3.cjs.map +1 -1
  120. package/dist/zod-v3.d.cts +5 -5
  121. package/dist/zod-v3.d.mts +5 -5
  122. package/dist/zod-v3.d.ts +5 -5
  123. package/dist/zod-v3.mjs +4 -2
  124. package/dist/zod-v3.mjs.map +1 -1
  125. package/dist/zod-v4.cjs +41 -10
  126. package/dist/zod-v4.cjs.map +1 -1
  127. package/dist/zod-v4.d.cts +7 -7
  128. package/dist/zod-v4.d.mts +7 -7
  129. package/dist/zod-v4.d.ts +7 -7
  130. package/dist/zod-v4.mjs +4 -2
  131. package/dist/zod-v4.mjs.map +1 -1
  132. package/dist/zod.cjs +44 -49
  133. package/dist/zod.cjs.map +1 -1
  134. package/dist/zod.d.cts +6 -248
  135. package/dist/zod.d.mts +6 -248
  136. package/dist/zod.d.ts +6 -248
  137. package/dist/zod.mjs +4 -42
  138. package/dist/zod.mjs.map +1 -1
  139. package/package.json +12 -2
  140. package/skills/attaform/SKILL.md +128 -0
  141. package/skills/attaform/references/custom-components.md +72 -0
  142. package/skills/attaform/references/errors.md +62 -0
  143. package/skills/attaform/references/ssr.md +26 -0
  144. package/skills/attaform/references/validation.md +40 -0
  145. package/skills/attaform/references/wizards.md +104 -0
  146. package/dist/shared/attaform.55hFR_cl.d.ts +0 -97
  147. package/dist/shared/attaform.BPl-ECRT.cjs.map +0 -1
  148. package/dist/shared/attaform.BRGIpZo4.cjs.map +0 -1
  149. package/dist/shared/attaform.BoYqnIPI.mjs.map +0 -1
  150. package/dist/shared/attaform.C3Doa9Pt.mjs.map +0 -1
  151. package/dist/shared/attaform.D51IwDtP.cjs +0 -39
  152. package/dist/shared/attaform.D51IwDtP.cjs.map +0 -1
  153. package/dist/shared/attaform.DGhIix5D.mjs.map +0 -1
  154. package/dist/shared/attaform.DJRz_bzM.d.cts +0 -97
  155. package/dist/shared/attaform.Du9RZp8m.cjs.map +0 -1
  156. package/dist/shared/attaform.JPsaqjLl.d.mts +0 -97
  157. package/dist/shared/attaform.LEWUFqUw.cjs.map +0 -1
  158. package/dist/shared/attaform.NqYEzRcM.mjs +0 -35
  159. package/dist/shared/attaform.NqYEzRcM.mjs.map +0 -1
  160. package/dist/shared/attaform.sHkHv_98.mjs.map +0 -1
  161. package/dist/shared/{attaform.DdjDqTah.d.ts → attaform.DRUT703x.d.cts} +14 -14
  162. package/dist/shared/{attaform.DdjDqTah.d.cts → attaform.DRUT703x.d.mts} +14 -14
  163. package/dist/shared/{attaform.DdjDqTah.d.mts → attaform.DRUT703x.d.ts} +14 -14
package/README.md CHANGED
@@ -24,36 +24,44 @@ A type-safe, schema-driven form library for Vue 3 and Nuxt with first-class Zod
24
24
  npm install attaform zod
25
25
  ```
26
26
 
27
+ <!-- @generated-start:quick-start -->
28
+
27
29
  ```vue
28
30
  <script setup lang="ts">
31
+ import { useForm } from 'attaform'
29
32
  import { z } from 'zod'
30
- import { useForm } from 'attaform/zod' // auto-detects your Zod major
31
33
 
32
34
  const schema = z.object({
33
- username: z.string().min(2, 'At least 2 characters'),
35
+ email: z.email('Enter a valid email'),
34
36
  password: z.string().min(8, 'At least 8 characters'),
35
37
  })
36
38
 
37
39
  const form = useForm({ schema })
38
40
 
39
41
  const onSubmit = form.handleSubmit(async (values) => {
40
- await fetch('/api/signup', { method: 'POST', body: JSON.stringify(values) })
42
+ await fetch('/api/sign-in', { method: 'POST', body: JSON.stringify(values) })
41
43
  })
42
44
  </script>
43
45
 
44
46
  <template>
45
- <form @submit.prevent="onSubmit">
46
- <input v-register="form.register('username')" placeholder="Username" />
47
- <small v-if="form.errors.username?.[0]">{{ form.errors.username[0].message }}</small>
48
-
49
- <input v-register="form.register('password')" type="password" placeholder="Password" />
50
- <small v-if="form.errors.password?.[0]">{{ form.errors.password[0].message }}</small>
51
-
52
- <button :disabled="form.meta.submitting">Sign up</button>
47
+ <form @submit="onSubmit">
48
+ <label>
49
+ Email
50
+ <input v-register="form.register('email')" autocomplete="email" />
51
+ <em v-if="form.fields.email.showErrors">{{ form.fields.email.firstError?.message }}</em>
52
+ </label>
53
+ <label>
54
+ Password
55
+ <input v-register="form.register('password')" type="password" autocomplete="off" />
56
+ <em v-if="form.fields.password.showErrors">{{ form.fields.password.firstError?.message }}</em>
57
+ </label>
58
+ <button :disabled="form.meta.submitting" type="submit">Sign in</button>
53
59
  </form>
54
60
  </template>
55
61
  ```
56
62
 
63
+ <!-- @generated-end:quick-start -->
64
+
57
65
  Hand the schema to `useForm`, bind each input with `v-register`, and Attaform owns the values, the coercion, the live errors, and the typed submit payload. That is the whole loop.
58
66
 
59
67
  **[Full walkthrough →](https://attaform.dev/docs/getting-started/quick-start)** Setting up Nuxt, Vite, or bare Vue? See the [installation guide](https://attaform.dev/docs/getting-started/installation).
@@ -65,6 +73,7 @@ Hand the schema to `useForm`, bind each input with `v-register`, and Attaform ow
65
73
  - **`useWizard` for multistep.** Compose forms into a flow with shared navigation, per-step validation, state retained across steps, and deep-link restore. [useWizard →](https://attaform.dev/docs/multistep/use-wizard)
66
74
  - **SSR-native.** Server-rendered HTML matches the hydrated client with no flash. Auto-wired in Nuxt, one Vite plugin for bare Vue. [SSR in Nuxt →](https://attaform.dev/docs/server-and-ssr/ssr-nuxt)
67
75
  - **DevTools built in.** Inspect every form on the page, walk its history, and edit values live. No probes to install. [DevTools panel →](https://attaform.dev/docs/devtools-and-debugging/devtools-panel)
76
+ - **Built for AI-assisted coding.** Ships an `llms.txt` index, a full-text docs dump, and an installable Agent Skill (`npx attaform skill`), so your coding assistant writes idiomatic Attaform the first time. [AI agents →](https://attaform.dev/docs/reference/ai-agents)
68
77
  - **Secure by construction.** Zero runtime dependencies (no supply-chain surface), prototype-pollution-safe deep writes, and Attaform never throws into your app. [Security policy →](./SECURITY.md)
69
78
 
70
79
  ## Documentation
@@ -76,6 +85,7 @@ Full docs live at **[attaform.dev](https://attaform.dev)**.
76
85
  - [Entry points](https://attaform.dev/docs/reference/entry-points): every public export, grouped by subpath.
77
86
  - [Performance](https://attaform.dev/docs/server-and-ssr/performance): how it scales, when to worry.
78
87
  - [Troubleshooting](https://attaform.dev/docs/devtools-and-debugging/troubleshooting): common gotchas and fixes.
88
+ - [AI agents](https://attaform.dev/docs/reference/ai-agents): `llms.txt`, the full-text docs dump, and an installable skill for coding assistants.
79
89
  - [Changelog](./CHANGELOG.md): full release history.
80
90
 
81
91
  ## Status
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Attaform CLI.
4
+ *
5
+ * `attaform skill [dir]` copies the bundled Agent Skill (which ships in
6
+ * the package under `skills/attaform/`) into a project so an AI
7
+ * assistant loads it while working on a form. The skill moves in
8
+ * lockstep with the installed Attaform version: run through `npx` in a
9
+ * project that already has Attaform and it copies that version's skill.
10
+ *
11
+ * Zero dependencies (Node built-ins only), so it ships verbatim with no
12
+ * build step.
13
+ */
14
+ import { cpSync, existsSync, readdirSync } from 'node:fs'
15
+ import { relative, resolve } from 'node:path'
16
+ import { fileURLToPath } from 'node:url'
17
+
18
+ // The skill directory bundled in the package, resolved relative to this
19
+ // file (`bin/attaform.mjs` -> `skills/attaform/`). It ships via the
20
+ // package.json `files` entry, so it is present in both the git checkout
21
+ // and the installed package.
22
+ const SKILL_SOURCE = fileURLToPath(new URL('../skills/attaform/', import.meta.url))
23
+ const DEFAULT_SKILLS_DIR = '.claude/skills'
24
+
25
+ function usage() {
26
+ console.log(
27
+ [
28
+ 'Usage: attaform skill [dir]',
29
+ '',
30
+ " Copy Attaform's Agent Skill into your project so an AI assistant",
31
+ ' loads it while working on a form.',
32
+ '',
33
+ ` [dir] Skills directory to install into (default: ${DEFAULT_SKILLS_DIR}).`,
34
+ ' Point it at another runtime, e.g. attaform skill .cursor/skills',
35
+ ].join('\n'),
36
+ )
37
+ }
38
+
39
+ function countFiles(dir) {
40
+ let total = 0
41
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
42
+ total += entry.isDirectory() ? countFiles(resolve(dir, entry.name)) : 1
43
+ }
44
+ return total
45
+ }
46
+
47
+ function installSkill(skillsDir) {
48
+ const dest = resolve(skillsDir, 'attaform')
49
+ const existed = existsSync(dest)
50
+ cpSync(SKILL_SOURCE, dest, { recursive: true })
51
+
52
+ const where = relative(process.cwd(), dest) || dest
53
+ const count = countFiles(dest)
54
+ console.log(
55
+ `${existed ? 'Updated' : 'Installed'} the Attaform skill (${count} file${count === 1 ? '' : 's'}) at ${where}/`,
56
+ )
57
+ console.log('Your assistant will load it while it works on a form in this project.')
58
+ }
59
+
60
+ const [command, dirArg] = process.argv.slice(2)
61
+
62
+ if (command === undefined || command === '-h' || command === '--help' || command === 'help') {
63
+ usage()
64
+ process.exit(0)
65
+ }
66
+
67
+ if (command !== 'skill') {
68
+ console.error(`attaform: unknown command "${command}"\n`)
69
+ usage()
70
+ process.exit(1)
71
+ }
72
+
73
+ try {
74
+ installSkill(dirArg ?? DEFAULT_SKILLS_DIR)
75
+ } catch (error) {
76
+ console.error(`attaform: could not install the skill: ${error instanceof Error ? error.message : String(error)}`)
77
+ process.exit(1)
78
+ }
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ const serializeScript = require('./shared/attaform.DQT7_-FO.cjs');
4
+ const devtoolsShared = require('./shared/attaform.Co5LNRnv.cjs');
5
+ const registerProtocol = require('./shared/attaform.yUrz7C2z.cjs');
6
+
7
+
8
+
9
+ exports.AttaformErrorCode = serializeScript.AttaformErrorCode;
10
+ exports.DEFAULT_TIMINGS = serializeScript.DEFAULT_TIMINGS;
11
+ exports.defaultCoercionRules = serializeScript.defaultCoercionRules;
12
+ exports.defaultDisplayState = serializeScript.defaultDisplayState;
13
+ exports.defineCoercion = serializeScript.defineCoercion;
14
+ exports.escapeForInlineScript = serializeScript.escapeForInlineScript;
15
+ exports.injectForm = serializeScript.injectForm;
16
+ exports.injectWizard = serializeScript.injectWizard;
17
+ exports.isUnset = serializeScript.isUnset;
18
+ exports.lazy = serializeScript.lazy;
19
+ exports.makeDefaultDisplayState = serializeScript.makeDefaultDisplayState;
20
+ exports.unset = serializeScript.unset;
21
+ exports.useAbstractForm = serializeScript.useAbstractForm;
22
+ exports.useRegister = serializeScript.useRegister;
23
+ exports.useWizard = serializeScript.useWizard;
24
+ exports.AttaformError = devtoolsShared.AttaformError;
25
+ exports.DEVTOOLS_WINDOW_KEY = devtoolsShared.DEVTOOLS_WINDOW_KEY;
26
+ exports.InvalidPathError = devtoolsShared.InvalidPathError;
27
+ exports.InvalidUseFormConfigError = devtoolsShared.InvalidUseFormConfigError;
28
+ exports.OutsideSetupError = devtoolsShared.OutsideSetupError;
29
+ exports.ROOT_PATH = devtoolsShared.ROOT_PATH;
30
+ exports.ROOT_PATH_KEY = devtoolsShared.ROOT_PATH_KEY;
31
+ exports.RegistryNotInstalledError = devtoolsShared.RegistryNotInstalledError;
32
+ exports.ReservedFormKeyError = devtoolsShared.ReservedFormKeyError;
33
+ exports.SubmitErrorHandlerError = devtoolsShared.SubmitErrorHandlerError;
34
+ exports.assignKey = devtoolsShared.assignKey;
35
+ exports.canonicalizePath = devtoolsShared.canonicalizePath;
36
+ exports.createAttaform = devtoolsShared.createAttaform;
37
+ exports.createRegistry = devtoolsShared.createRegistry;
38
+ exports.getRegistryFromApp = devtoolsShared.getRegistryFromApp;
39
+ exports.hydrateAttaformState = devtoolsShared.hydrateAttaformState;
40
+ exports.isPathPrefix = devtoolsShared.isPathPrefix;
41
+ exports.kAttaformRegistry = devtoolsShared.kAttaformRegistry;
42
+ exports.parseDottedPath = devtoolsShared.parseDottedPath;
43
+ exports.renderAttaformState = devtoolsShared.renderAttaformState;
44
+ exports.useRegistry = devtoolsShared.useRegistry;
45
+ exports.vRegister = devtoolsShared.vRegister;
46
+ exports.isRegisterValue = registerProtocol.isRegisterValue;
47
+ //# sourceMappingURL=abstract.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,42 @@
1
+ import { A as AttaformRegistry } from './shared/attaform.D99pd7JG.cjs';
2
+ export { a as AnyForm, b as AttaformDevtoolsBridge, c as AttaformError, d as AttaformErrorCode, e as AttaformPluginOptions, C as CompiledStep, D as DEFAULT_TIMINGS, f as DEVTOOLS_WINDOW_KEY, g as DisplayTimings, F as FormStatus, I as InjectWizardInput, h as InvalidPathError, i as InvalidUseFormConfigError, L as LazyMarker, O as OutsideSetupError, R as RegistryNotInstalledError, j as ReservedFormKeyError, S as SerializedAttaformState, k as SerializedFormData, l as StepSlot, m as SubmitErrorHandlerError, U as UseRegisterReturn, n as UseWizardReturnType, W as WizardAggregateError, o as WizardCtx, p as WizardCtxForm, q as WizardOnError, r as WizardOnSubmit, s as WizardOptions, t as WizardPersistFn, u as WizardRestoreFn, v as WizardRestoreState, w as WizardStatusesProxy, x as WizardSubmitContext, y as assignKey, z as createAttaform, B as createRegistry, E as defaultCoercionRules, G as defaultDisplayState, H as defineCoercion, J as escapeForInlineScript, K as getRegistryFromApp, M as hydrateAttaformState, N as injectForm, P as injectWizard, Q as isRegisterValue, T as kAttaformRegistry, V as lazy, X as makeDefaultDisplayState, Y as renderAttaformState, Z as useRegister, _ as useRegistry, $ as useWizard, a0 as vRegister } from './shared/attaform.D99pd7JG.cjs';
3
+ import { G as GenericForm, F as FormKey, U as UseFormConfiguration, A as AbstractSchema, D as DefaultValuesInput, a as UseFormReturnType } from './shared/attaform.C3WnCDXz.cjs';
4
+ export { b as ArrayItem, c as ArrayPath, d as AttaformDefaults, C as CoercionEntry, e as CoercionRegistry, f as CoercionResult, g as CustomDirectiveRegisterAssignerFn, h as DeepPartial, i as DefaultValuesResponse, j as DefaultValuesShape, k as DisplayCtx, l as DisplayMachine, m as DisplayState, E as ErrorInput, n as ErrorsProxyShape, 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 GetDisplayState, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, z as Json, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, B as NestedType, O as OnError, P as OnInvalidSubmitPolicy, Q as OnSubmit, R as PartialFlatPath, S as Path, T as PathKey, V as PendingValidationStatus, W as Primitive, X as ROOT_PATH, Y as ROOT_PATH_KEY, Z as ReactiveValidationStatus, _ as RegisterDirective, $ as RegisterFlatPath, a0 as RegisterOptions, a1 as RegisterSelectModifier, a2 as RegisterTextModifier, a3 as RegisterTransform, a4 as RegisterValue, a5 as Segment, a6 as SetValueCallback, a7 as SetValuePayload, a8 as SettledValidationStatus, a9 as SlimPrimitiveKind, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationError, ag as ValidationResponse, ah as ValidationResponseWithoutValue, ai as ValueOfUnion, aj as WriteMeta, ak as WriteShape, al as canonicalizePath, am as isPathPrefix, an as isUnset, ao as parseDottedPath, ap as unset } from './shared/attaform.C3WnCDXz.cjs';
5
+ import 'vue';
6
+
7
+ /**
8
+ * Schema-agnostic `useForm`. Accepts any object that implements
9
+ * `AbstractSchema` — useful when integrating a custom schema
10
+ * adapter or a third-party validation library.
11
+ *
12
+ * ```ts
13
+ * import { useForm } from 'attaform'
14
+ *
15
+ * const form = useForm({
16
+ * schema: myCustomAdapter,
17
+ * defaultValues: { name: '' },
18
+ * })
19
+ * ```
20
+ *
21
+ * Most consumers prefer a typed entry point that wraps the underlying
22
+ * library's schema with the matching adapter automatically; see the
23
+ * subpath documentation for the available adapters.
24
+ *
25
+ * Returns the same form API as the typed entry points; see
26
+ * `UseFormReturnType` for the full surface.
27
+ */
28
+ declare function useAbstractForm<Form extends GenericForm, GetValueFormType extends GenericForm = Form, ReadForm extends GenericForm = Form, K extends FormKey = FormKey>(configuration: UseFormConfiguration<Form, GetValueFormType, AbstractSchema<Form, GetValueFormType>, DefaultValuesInput<Form>, K>,
29
+ /**
30
+ * Internal escape hatch for callers that already hold a registry
31
+ * reference and need to construct a form outside Vue's setup context
32
+ * (e.g. the wizard's lazy noop builder, which runs inside a
33
+ * `computed` re-eval). Passing this skips the strict `useRegistry()`
34
+ * call; everything else (FormStore allocation, registry presence,
35
+ * consumer ref-counting via `onScopeDispose`) goes through the same
36
+ * path eager calls follow. Not part of the public surface.
37
+ */
38
+ options?: {
39
+ readonly registry?: AttaformRegistry;
40
+ }): UseFormReturnType<Form, GetValueFormType, ReadForm, K>;
41
+
42
+ export { AbstractSchema, AttaformRegistry, DefaultValuesInput, FormKey, GenericForm, UseFormConfiguration, UseFormReturnType, useAbstractForm };
@@ -0,0 +1,42 @@
1
+ import { A as AttaformRegistry } from './shared/attaform.kBkYlKP_.mjs';
2
+ export { a as AnyForm, b as AttaformDevtoolsBridge, c as AttaformError, d as AttaformErrorCode, e as AttaformPluginOptions, C as CompiledStep, D as DEFAULT_TIMINGS, f as DEVTOOLS_WINDOW_KEY, g as DisplayTimings, F as FormStatus, I as InjectWizardInput, h as InvalidPathError, i as InvalidUseFormConfigError, L as LazyMarker, O as OutsideSetupError, R as RegistryNotInstalledError, j as ReservedFormKeyError, S as SerializedAttaformState, k as SerializedFormData, l as StepSlot, m as SubmitErrorHandlerError, U as UseRegisterReturn, n as UseWizardReturnType, W as WizardAggregateError, o as WizardCtx, p as WizardCtxForm, q as WizardOnError, r as WizardOnSubmit, s as WizardOptions, t as WizardPersistFn, u as WizardRestoreFn, v as WizardRestoreState, w as WizardStatusesProxy, x as WizardSubmitContext, y as assignKey, z as createAttaform, B as createRegistry, E as defaultCoercionRules, G as defaultDisplayState, H as defineCoercion, J as escapeForInlineScript, K as getRegistryFromApp, M as hydrateAttaformState, N as injectForm, P as injectWizard, Q as isRegisterValue, T as kAttaformRegistry, V as lazy, X as makeDefaultDisplayState, Y as renderAttaformState, Z as useRegister, _ as useRegistry, $ as useWizard, a0 as vRegister } from './shared/attaform.kBkYlKP_.mjs';
3
+ import { G as GenericForm, F as FormKey, U as UseFormConfiguration, A as AbstractSchema, D as DefaultValuesInput, a as UseFormReturnType } from './shared/attaform.C3WnCDXz.mjs';
4
+ export { b as ArrayItem, c as ArrayPath, d as AttaformDefaults, C as CoercionEntry, e as CoercionRegistry, f as CoercionResult, g as CustomDirectiveRegisterAssignerFn, h as DeepPartial, i as DefaultValuesResponse, j as DefaultValuesShape, k as DisplayCtx, l as DisplayMachine, m as DisplayState, E as ErrorInput, n as ErrorsProxyShape, 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 GetDisplayState, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, z as Json, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, B as NestedType, O as OnError, P as OnInvalidSubmitPolicy, Q as OnSubmit, R as PartialFlatPath, S as Path, T as PathKey, V as PendingValidationStatus, W as Primitive, X as ROOT_PATH, Y as ROOT_PATH_KEY, Z as ReactiveValidationStatus, _ as RegisterDirective, $ as RegisterFlatPath, a0 as RegisterOptions, a1 as RegisterSelectModifier, a2 as RegisterTextModifier, a3 as RegisterTransform, a4 as RegisterValue, a5 as Segment, a6 as SetValueCallback, a7 as SetValuePayload, a8 as SettledValidationStatus, a9 as SlimPrimitiveKind, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationError, ag as ValidationResponse, ah as ValidationResponseWithoutValue, ai as ValueOfUnion, aj as WriteMeta, ak as WriteShape, al as canonicalizePath, am as isPathPrefix, an as isUnset, ao as parseDottedPath, ap as unset } from './shared/attaform.C3WnCDXz.mjs';
5
+ import 'vue';
6
+
7
+ /**
8
+ * Schema-agnostic `useForm`. Accepts any object that implements
9
+ * `AbstractSchema` — useful when integrating a custom schema
10
+ * adapter or a third-party validation library.
11
+ *
12
+ * ```ts
13
+ * import { useForm } from 'attaform'
14
+ *
15
+ * const form = useForm({
16
+ * schema: myCustomAdapter,
17
+ * defaultValues: { name: '' },
18
+ * })
19
+ * ```
20
+ *
21
+ * Most consumers prefer a typed entry point that wraps the underlying
22
+ * library's schema with the matching adapter automatically; see the
23
+ * subpath documentation for the available adapters.
24
+ *
25
+ * Returns the same form API as the typed entry points; see
26
+ * `UseFormReturnType` for the full surface.
27
+ */
28
+ declare function useAbstractForm<Form extends GenericForm, GetValueFormType extends GenericForm = Form, ReadForm extends GenericForm = Form, K extends FormKey = FormKey>(configuration: UseFormConfiguration<Form, GetValueFormType, AbstractSchema<Form, GetValueFormType>, DefaultValuesInput<Form>, K>,
29
+ /**
30
+ * Internal escape hatch for callers that already hold a registry
31
+ * reference and need to construct a form outside Vue's setup context
32
+ * (e.g. the wizard's lazy noop builder, which runs inside a
33
+ * `computed` re-eval). Passing this skips the strict `useRegistry()`
34
+ * call; everything else (FormStore allocation, registry presence,
35
+ * consumer ref-counting via `onScopeDispose`) goes through the same
36
+ * path eager calls follow. Not part of the public surface.
37
+ */
38
+ options?: {
39
+ readonly registry?: AttaformRegistry;
40
+ }): UseFormReturnType<Form, GetValueFormType, ReadForm, K>;
41
+
42
+ export { AbstractSchema, AttaformRegistry, DefaultValuesInput, FormKey, GenericForm, UseFormConfiguration, UseFormReturnType, useAbstractForm };
@@ -0,0 +1,42 @@
1
+ import { A as AttaformRegistry } from './shared/attaform.CEXUlUkc.js';
2
+ export { a as AnyForm, b as AttaformDevtoolsBridge, c as AttaformError, d as AttaformErrorCode, e as AttaformPluginOptions, C as CompiledStep, D as DEFAULT_TIMINGS, f as DEVTOOLS_WINDOW_KEY, g as DisplayTimings, F as FormStatus, I as InjectWizardInput, h as InvalidPathError, i as InvalidUseFormConfigError, L as LazyMarker, O as OutsideSetupError, R as RegistryNotInstalledError, j as ReservedFormKeyError, S as SerializedAttaformState, k as SerializedFormData, l as StepSlot, m as SubmitErrorHandlerError, U as UseRegisterReturn, n as UseWizardReturnType, W as WizardAggregateError, o as WizardCtx, p as WizardCtxForm, q as WizardOnError, r as WizardOnSubmit, s as WizardOptions, t as WizardPersistFn, u as WizardRestoreFn, v as WizardRestoreState, w as WizardStatusesProxy, x as WizardSubmitContext, y as assignKey, z as createAttaform, B as createRegistry, E as defaultCoercionRules, G as defaultDisplayState, H as defineCoercion, J as escapeForInlineScript, K as getRegistryFromApp, M as hydrateAttaformState, N as injectForm, P as injectWizard, Q as isRegisterValue, T as kAttaformRegistry, V as lazy, X as makeDefaultDisplayState, Y as renderAttaformState, Z as useRegister, _ as useRegistry, $ as useWizard, a0 as vRegister } from './shared/attaform.CEXUlUkc.js';
3
+ import { G as GenericForm, F as FormKey, U as UseFormConfiguration, A as AbstractSchema, D as DefaultValuesInput, a as UseFormReturnType } from './shared/attaform.C3WnCDXz.js';
4
+ export { b as ArrayItem, c as ArrayPath, d as AttaformDefaults, C as CoercionEntry, e as CoercionRegistry, f as CoercionResult, g as CustomDirectiveRegisterAssignerFn, h as DeepPartial, i as DefaultValuesResponse, j as DefaultValuesShape, k as DisplayCtx, l as DisplayMachine, m as DisplayState, E as ErrorInput, n as ErrorsProxyShape, 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 GetDisplayState, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, z as Json, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, B as NestedType, O as OnError, P as OnInvalidSubmitPolicy, Q as OnSubmit, R as PartialFlatPath, S as Path, T as PathKey, V as PendingValidationStatus, W as Primitive, X as ROOT_PATH, Y as ROOT_PATH_KEY, Z as ReactiveValidationStatus, _ as RegisterDirective, $ as RegisterFlatPath, a0 as RegisterOptions, a1 as RegisterSelectModifier, a2 as RegisterTextModifier, a3 as RegisterTransform, a4 as RegisterValue, a5 as Segment, a6 as SetValueCallback, a7 as SetValuePayload, a8 as SettledValidationStatus, a9 as SlimPrimitiveKind, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationError, ag as ValidationResponse, ah as ValidationResponseWithoutValue, ai as ValueOfUnion, aj as WriteMeta, ak as WriteShape, al as canonicalizePath, am as isPathPrefix, an as isUnset, ao as parseDottedPath, ap as unset } from './shared/attaform.C3WnCDXz.js';
5
+ import 'vue';
6
+
7
+ /**
8
+ * Schema-agnostic `useForm`. Accepts any object that implements
9
+ * `AbstractSchema` — useful when integrating a custom schema
10
+ * adapter or a third-party validation library.
11
+ *
12
+ * ```ts
13
+ * import { useForm } from 'attaform'
14
+ *
15
+ * const form = useForm({
16
+ * schema: myCustomAdapter,
17
+ * defaultValues: { name: '' },
18
+ * })
19
+ * ```
20
+ *
21
+ * Most consumers prefer a typed entry point that wraps the underlying
22
+ * library's schema with the matching adapter automatically; see the
23
+ * subpath documentation for the available adapters.
24
+ *
25
+ * Returns the same form API as the typed entry points; see
26
+ * `UseFormReturnType` for the full surface.
27
+ */
28
+ declare function useAbstractForm<Form extends GenericForm, GetValueFormType extends GenericForm = Form, ReadForm extends GenericForm = Form, K extends FormKey = FormKey>(configuration: UseFormConfiguration<Form, GetValueFormType, AbstractSchema<Form, GetValueFormType>, DefaultValuesInput<Form>, K>,
29
+ /**
30
+ * Internal escape hatch for callers that already hold a registry
31
+ * reference and need to construct a form outside Vue's setup context
32
+ * (e.g. the wizard's lazy noop builder, which runs inside a
33
+ * `computed` re-eval). Passing this skips the strict `useRegistry()`
34
+ * call; everything else (FormStore allocation, registry presence,
35
+ * consumer ref-counting via `onScopeDispose`) goes through the same
36
+ * path eager calls follow. Not part of the public surface.
37
+ */
38
+ options?: {
39
+ readonly registry?: AttaformRegistry;
40
+ }): UseFormReturnType<Form, GetValueFormType, ReadForm, K>;
41
+
42
+ export { AbstractSchema, AttaformRegistry, DefaultValuesInput, FormKey, GenericForm, UseFormConfiguration, UseFormReturnType, useAbstractForm };
@@ -0,0 +1,4 @@
1
+ export { A as AttaformErrorCode, D as DEFAULT_TIMINGS, d as defaultCoercionRules, a as defaultDisplayState, b as defineCoercion, e as escapeForInlineScript, i as injectForm, c as injectWizard, f as isUnset, l as lazy, m as makeDefaultDisplayState, u as unset, g as useAbstractForm, h as useRegister, j as useWizard } from './shared/attaform.CyQxTOdX.mjs';
2
+ export { A as AttaformError, D as DEVTOOLS_WINDOW_KEY, I as InvalidPathError, a as InvalidUseFormConfigError, O as OutsideSetupError, R as ROOT_PATH, b as ROOT_PATH_KEY, c as RegistryNotInstalledError, d as ReservedFormKeyError, S as SubmitErrorHandlerError, e as assignKey, f as canonicalizePath, g as createAttaform, h as createRegistry, i as getRegistryFromApp, j as hydrateAttaformState, k as isPathPrefix, l as kAttaformRegistry, p as parseDottedPath, r as renderAttaformState, u as useRegistry, v as vRegister } from './shared/attaform.Da8EdI2t.mjs';
3
+ export { i as isRegisterValue } from './shared/attaform.KvlEedlF.mjs';
4
+ //# sourceMappingURL=abstract.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const paths = require('../shared/attaform.BPl-ECRT.cjs');
3
+ const devtoolsShared = require('../shared/attaform.Co5LNRnv.cjs');
4
4
 
5
5
  const INSPECTOR_ID = "attaform";
6
6
  const TIMELINE_LAYER_ID = "attaform:events";
@@ -145,7 +145,7 @@ function wire(api, app, registry) {
145
145
  const section = payload.path[0];
146
146
  if (section !== "Form value") return;
147
147
  const segments = payload.path.slice(2);
148
- const { segments: canonicalPath } = paths.canonicalizePath(segments);
148
+ const { segments: canonicalPath } = devtoolsShared.canonicalizePath(segments);
149
149
  state.setValueAtPath(canonicalPath, payload.state.value);
150
150
  refreshState();
151
151
  });
@@ -1 +1 @@
1
- {"version":3,"file":"devtools.cjs","sources":["../../src/runtime/core/devtools.ts"],"sourcesContent":["import type { App } from 'vue'\nimport type { FormStore } from './create-form-store'\nimport type { AttaformRegistry } from './registry'\nimport type { GenericForm } from '../types/types-core'\nimport type { FormKey } from '../types/types-api'\nimport { canonicalizePath } from './paths'\n\n/**\n * Vue DevTools plugin wiring for attaform. Lazy-imported by\n * `createAttaform` under dev-mode guards so the production\n * bundle tree-shakes it out entirely.\n *\n * Registers:\n * - An inspector (per-app) that lists every registered form, with\n * nodes for form value / errors / aggregates / history.\n * - A timeline layer that emits events on submit start/success/\n * failure, reset, undo, redo, and form mutations.\n * - State editing — modifying a leaf inside the inspector tree\n * pushes through `state.setValueAtPath`, mutating the form.\n *\n * Tolerant of missing `@vue/devtools-api` — the peer dep is marked\n * optional. If the import fails, `setupAttaformDevtools` silently\n * no-ops so production builds / users without DevTools installed\n * don't see errors.\n */\n\nconst INSPECTOR_ID = 'attaform'\nconst TIMELINE_LAYER_ID = 'attaform:events'\n\ntype UnsafeDevtoolsApi = {\n addInspector(opts: { id: string; label: string; icon?: string; app: App }): void\n addTimelineLayer(opts: { id: string; label: string; color: number }): void\n sendInspectorTree(inspectorId: string): void\n sendInspectorState(inspectorId: string): void\n addTimelineEvent(payload: {\n layerId: string\n event: {\n time: number\n title: string\n subtitle?: string\n data?: Record<string, unknown>\n groupId?: string | number\n }\n }): void\n on: {\n getInspectorTree(\n handler: (payload: {\n inspectorId: string\n filter: string\n rootNodes: Array<{ id: string; label: string; tags?: unknown[] }>\n }) => void\n ): void\n getInspectorState(\n handler: (payload: {\n inspectorId: string\n nodeId: string\n state: Record<string, Array<{ key: string; value: unknown; editable?: boolean }>>\n }) => void\n ): void\n editInspectorState(\n handler: (payload: {\n inspectorId: string\n nodeId: string\n path: string[]\n state: { value: unknown; newKey?: string | null; remove?: boolean }\n }) => void\n ): void\n }\n}\n\ntype SetupDevtoolsPluginFn = (\n descriptor: {\n id: string\n label: string\n packageName?: string\n homepage?: string\n componentStateTypes?: string[]\n app: App\n },\n setup: (api: UnsafeDevtoolsApi) => void\n) => void\n\n/**\n * Install the DevTools plugin for the given Vue app + registry. Safe\n * to call in production — if `@vue/devtools-api` isn't installed, the\n * dynamic import fails and we log nothing. Returns `true` when\n * DevTools was wired successfully, `false` otherwise — useful for\n * tests.\n */\nexport async function setupAttaformDevtools(\n app: App,\n registry: AttaformRegistry\n): Promise<boolean> {\n let mod: { setupDevtoolsPlugin?: SetupDevtoolsPluginFn }\n try {\n mod = (await import('@vue/devtools-api')) as {\n setupDevtoolsPlugin?: SetupDevtoolsPluginFn\n }\n } catch {\n // Peer dep not installed — silently skip. Production builds pass\n // `{ devtools: false }` explicitly, but this catch covers the\n // \"dev without the peer dep\" case without a noisy warning.\n return false\n }\n const setupDevtoolsPlugin = mod.setupDevtoolsPlugin\n if (typeof setupDevtoolsPlugin !== 'function') return false\n\n setupDevtoolsPlugin(\n {\n id: INSPECTOR_ID,\n label: 'Attaform',\n packageName: 'attaform',\n homepage: 'https://github.com/attaform/Attaform',\n app,\n componentStateTypes: ['Attaform form'],\n },\n (api) => wire(api, app, registry)\n )\n return true\n}\n\nfunction wire(api: UnsafeDevtoolsApi, app: App, registry: AttaformRegistry): void {\n // Per-form subscriber bookkeeping — we keep the unsubscribers so\n // the registry's eviction path can detach them when a form is\n // disposed. Using a Map keyed by FormKey mirrors the registry.\n const subscriberUnsubs = new Map<FormKey, () => void>()\n\n api.addInspector({ id: INSPECTOR_ID, label: 'Attaform', app })\n api.addTimelineLayer({ id: TIMELINE_LAYER_ID, label: 'Attaform', color: 0x5b8def })\n\n function refreshTree(): void {\n api.sendInspectorTree(INSPECTOR_ID)\n }\n\n function refreshState(): void {\n api.sendInspectorState(INSPECTOR_ID)\n }\n\n function subscribeForm(state: FormStore<GenericForm>): void {\n if (subscriberUnsubs.has(state.formKey)) return\n const unsubChange = state.onFormChange(() => {\n refreshState()\n api.addTimelineEvent({\n layerId: TIMELINE_LAYER_ID,\n event: {\n time: Date.now(),\n title: 'form.change',\n subtitle: state.formKey,\n // Devtools is dev-only — emit raw values. Consumers worried\n // about screen-share leaks should close the panel before\n // sharing, same as they would for the browser DevTools\n // console.\n data: { form: state.form.value as Record<string, unknown> },\n },\n })\n })\n const unsubSubmit = state.onSubmitSuccess(() => {\n api.addTimelineEvent({\n layerId: TIMELINE_LAYER_ID,\n event: {\n time: Date.now(),\n title: 'submit.success',\n subtitle: state.formKey,\n data: { form: state.form.value as Record<string, unknown> },\n },\n })\n })\n const unsubReset = state.onReset(() => {\n refreshState()\n api.addTimelineEvent({\n layerId: TIMELINE_LAYER_ID,\n event: {\n time: Date.now(),\n title: 'reset',\n subtitle: state.formKey,\n },\n })\n })\n subscriberUnsubs.set(state.formKey, () => {\n unsubChange()\n unsubSubmit()\n unsubReset()\n })\n }\n\n // Subscribe all currently-registered forms + register as they're\n // added. The registry's `forms` Map is shallowReactive — we poll\n // once per render on refresh; for live change detection, each\n // useForm call that adds a new form triggers a tree/state refresh\n // via the form's own onFormChange emission on the first\n // applyFormReplacement.\n function syncForms(): void {\n for (const [, state] of registry.forms) {\n subscribeForm(state)\n }\n // Drop subscribers for forms that were evicted.\n for (const [formKey, unsub] of subscriberUnsubs) {\n if (!registry.forms.has(formKey)) {\n unsub()\n subscriberUnsubs.delete(formKey)\n }\n }\n }\n\n api.on.getInspectorTree((payload) => {\n if (payload.inspectorId !== INSPECTOR_ID) return\n syncForms()\n payload.rootNodes = [...registry.forms.keys()].map((key) => ({\n id: `form:${key}`,\n label: key,\n tags: [],\n }))\n })\n\n api.on.getInspectorState((payload) => {\n if (payload.inspectorId !== INSPECTOR_ID) return\n if (!payload.nodeId.startsWith('form:')) return\n const formKey = payload.nodeId.slice('form:'.length)\n const state = registry.forms.get(formKey)\n if (state === undefined) return\n // Devtools is dev-only — render raw values for everything,\n // including sensitive-named paths. Consumers concerned about\n // screen-share leaks should close the panel before sharing.\n payload.state['Form value'] = [\n {\n key: 'form',\n value: state.form.value,\n editable: true,\n },\n ]\n // Schema-driven and user-injected errors land in separate inspector\n // sections so devs can see the source distinction at a glance — a\n // user-injected entry surviving a successful submit, or a schema\n // entry that should have cleared after a value fix, are immediately\n // visible without cross-referencing call sites.\n payload.state['Schema Errors'] = [\n ...[...state.schemaErrors.entries()].map(([k, v]) => ({\n key: String(k),\n value: v as unknown,\n })),\n ]\n payload.state['User Errors'] = [\n ...[...state.userErrors.entries()].map(([k, v]) => ({\n key: String(k),\n value: v as unknown,\n })),\n ]\n payload.state['Aggregates'] = [\n { key: 'submitting', value: state.submitting.value },\n { key: 'submissionAttempts', value: state.submissionAttempts.value },\n { key: 'departAttempts', value: state.departAttempts.value },\n { key: 'submitError', value: state.submitError.value },\n { key: 'activeValidations', value: state.activeValidations.value },\n ]\n })\n\n api.on.editInspectorState((payload) => {\n if (payload.inspectorId !== INSPECTOR_ID) return\n if (!payload.nodeId.startsWith('form:')) return\n const formKey = payload.nodeId.slice('form:'.length)\n const state = registry.forms.get(formKey)\n if (state === undefined) return\n // payload.path is `['Form value', 'form', ...pathSegments]` — the\n // first two segments are the inspector section + key, the rest is\n // the target form path the user edited. Pass the segment array\n // directly to `canonicalizePath`: join('.') would collapse a\n // literal-dot field key (`{\"user.email\": ...}`) into two segments,\n // writing to the wrong leaf.\n if (payload.path.length < 3) return\n const section = payload.path[0]\n if (section !== 'Form value') return\n const segments = payload.path.slice(2)\n const { segments: canonicalPath } = canonicalizePath(segments)\n state.setValueAtPath(canonicalPath, payload.state.value)\n refreshState()\n })\n\n // Initial sync so existing forms show up.\n syncForms()\n refreshTree()\n}\n"],"names":["canonicalizePath"],"mappings":"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"}
1
+ {"version":3,"file":"devtools.cjs","sources":["../../src/runtime/core/devtools.ts"],"sourcesContent":["import type { App } from 'vue'\nimport type { FormStore } from './create-form-store'\nimport type { AttaformRegistry } from './registry'\nimport type { GenericForm } from '../types/types-core'\nimport type { FormKey } from '../types/types-api'\nimport { canonicalizePath } from './paths'\n\n/**\n * Vue DevTools plugin wiring for attaform. Lazy-imported by\n * `createAttaform` under dev-mode guards so the production\n * bundle tree-shakes it out entirely.\n *\n * Registers:\n * - An inspector (per-app) that lists every registered form, with\n * nodes for form value / errors / aggregates / history.\n * - A timeline layer that emits events on submit start/success/\n * failure, reset, undo, redo, and form mutations.\n * - State editing — modifying a leaf inside the inspector tree\n * pushes through `state.setValueAtPath`, mutating the form.\n *\n * Tolerant of missing `@vue/devtools-api` — the peer dep is marked\n * optional. If the import fails, `setupAttaformDevtools` silently\n * no-ops so production builds / users without DevTools installed\n * don't see errors.\n */\n\nconst INSPECTOR_ID = 'attaform'\nconst TIMELINE_LAYER_ID = 'attaform:events'\n\ntype UnsafeDevtoolsApi = {\n addInspector(opts: { id: string; label: string; icon?: string; app: App }): void\n addTimelineLayer(opts: { id: string; label: string; color: number }): void\n sendInspectorTree(inspectorId: string): void\n sendInspectorState(inspectorId: string): void\n addTimelineEvent(payload: {\n layerId: string\n event: {\n time: number\n title: string\n subtitle?: string\n data?: Record<string, unknown>\n groupId?: string | number\n }\n }): void\n on: {\n getInspectorTree(\n handler: (payload: {\n inspectorId: string\n filter: string\n rootNodes: Array<{ id: string; label: string; tags?: unknown[] }>\n }) => void\n ): void\n getInspectorState(\n handler: (payload: {\n inspectorId: string\n nodeId: string\n state: Record<string, Array<{ key: string; value: unknown; editable?: boolean }>>\n }) => void\n ): void\n editInspectorState(\n handler: (payload: {\n inspectorId: string\n nodeId: string\n path: string[]\n state: { value: unknown; newKey?: string | null; remove?: boolean }\n }) => void\n ): void\n }\n}\n\ntype SetupDevtoolsPluginFn = (\n descriptor: {\n id: string\n label: string\n packageName?: string\n homepage?: string\n componentStateTypes?: string[]\n app: App\n },\n setup: (api: UnsafeDevtoolsApi) => void\n) => void\n\n/**\n * Install the DevTools plugin for the given Vue app + registry. Safe\n * to call in production — if `@vue/devtools-api` isn't installed, the\n * dynamic import fails and we log nothing. Returns `true` when\n * DevTools was wired successfully, `false` otherwise — useful for\n * tests.\n */\nexport async function setupAttaformDevtools(\n app: App,\n registry: AttaformRegistry\n): Promise<boolean> {\n let mod: { setupDevtoolsPlugin?: SetupDevtoolsPluginFn }\n try {\n mod = (await import('@vue/devtools-api')) as {\n setupDevtoolsPlugin?: SetupDevtoolsPluginFn\n }\n } catch {\n // Peer dep not installed — silently skip. Production builds pass\n // `{ devtools: false }` explicitly, but this catch covers the\n // \"dev without the peer dep\" case without a noisy warning.\n return false\n }\n const setupDevtoolsPlugin = mod.setupDevtoolsPlugin\n if (typeof setupDevtoolsPlugin !== 'function') return false\n\n setupDevtoolsPlugin(\n {\n id: INSPECTOR_ID,\n label: 'Attaform',\n packageName: 'attaform',\n homepage: 'https://github.com/attaform/Attaform',\n app,\n componentStateTypes: ['Attaform form'],\n },\n (api) => wire(api, app, registry)\n )\n return true\n}\n\nfunction wire(api: UnsafeDevtoolsApi, app: App, registry: AttaformRegistry): void {\n // Per-form subscriber bookkeeping — we keep the unsubscribers so\n // the registry's eviction path can detach them when a form is\n // disposed. Using a Map keyed by FormKey mirrors the registry.\n const subscriberUnsubs = new Map<FormKey, () => void>()\n\n api.addInspector({ id: INSPECTOR_ID, label: 'Attaform', app })\n api.addTimelineLayer({ id: TIMELINE_LAYER_ID, label: 'Attaform', color: 0x5b8def })\n\n function refreshTree(): void {\n api.sendInspectorTree(INSPECTOR_ID)\n }\n\n function refreshState(): void {\n api.sendInspectorState(INSPECTOR_ID)\n }\n\n function subscribeForm(state: FormStore<GenericForm>): void {\n if (subscriberUnsubs.has(state.formKey)) return\n const unsubChange = state.onFormChange(() => {\n refreshState()\n api.addTimelineEvent({\n layerId: TIMELINE_LAYER_ID,\n event: {\n time: Date.now(),\n title: 'form.change',\n subtitle: state.formKey,\n // Devtools is dev-only — emit raw values. Consumers worried\n // about screen-share leaks should close the panel before\n // sharing, same as they would for the browser DevTools\n // console.\n data: { form: state.form.value as Record<string, unknown> },\n },\n })\n })\n const unsubSubmit = state.onSubmitSuccess(() => {\n api.addTimelineEvent({\n layerId: TIMELINE_LAYER_ID,\n event: {\n time: Date.now(),\n title: 'submit.success',\n subtitle: state.formKey,\n data: { form: state.form.value as Record<string, unknown> },\n },\n })\n })\n const unsubReset = state.onReset(() => {\n refreshState()\n api.addTimelineEvent({\n layerId: TIMELINE_LAYER_ID,\n event: {\n time: Date.now(),\n title: 'reset',\n subtitle: state.formKey,\n },\n })\n })\n subscriberUnsubs.set(state.formKey, () => {\n unsubChange()\n unsubSubmit()\n unsubReset()\n })\n }\n\n // Subscribe all currently-registered forms + register as they're\n // added. The registry's `forms` Map is shallowReactive — we poll\n // once per render on refresh; for live change detection, each\n // useForm call that adds a new form triggers a tree/state refresh\n // via the form's own onFormChange emission on the first\n // applyFormReplacement.\n function syncForms(): void {\n for (const [, state] of registry.forms) {\n subscribeForm(state)\n }\n // Drop subscribers for forms that were evicted.\n for (const [formKey, unsub] of subscriberUnsubs) {\n if (!registry.forms.has(formKey)) {\n unsub()\n subscriberUnsubs.delete(formKey)\n }\n }\n }\n\n api.on.getInspectorTree((payload) => {\n if (payload.inspectorId !== INSPECTOR_ID) return\n syncForms()\n payload.rootNodes = [...registry.forms.keys()].map((key) => ({\n id: `form:${key}`,\n label: key,\n tags: [],\n }))\n })\n\n api.on.getInspectorState((payload) => {\n if (payload.inspectorId !== INSPECTOR_ID) return\n if (!payload.nodeId.startsWith('form:')) return\n const formKey = payload.nodeId.slice('form:'.length)\n const state = registry.forms.get(formKey)\n if (state === undefined) return\n // Devtools is dev-only — render raw values for everything,\n // including sensitive-named paths. Consumers concerned about\n // screen-share leaks should close the panel before sharing.\n payload.state['Form value'] = [\n {\n key: 'form',\n value: state.form.value,\n editable: true,\n },\n ]\n // Schema-driven and user-injected errors land in separate inspector\n // sections so devs can see the source distinction at a glance — a\n // user-injected entry surviving a successful submit, or a schema\n // entry that should have cleared after a value fix, are immediately\n // visible without cross-referencing call sites.\n payload.state['Schema Errors'] = [\n ...[...state.schemaErrors.entries()].map(([k, v]) => ({\n key: String(k),\n value: v as unknown,\n })),\n ]\n payload.state['User Errors'] = [\n ...[...state.userErrors.entries()].map(([k, v]) => ({\n key: String(k),\n value: v as unknown,\n })),\n ]\n payload.state['Aggregates'] = [\n { key: 'submitting', value: state.submitting.value },\n { key: 'submissionAttempts', value: state.submissionAttempts.value },\n { key: 'departAttempts', value: state.departAttempts.value },\n { key: 'submitError', value: state.submitError.value },\n { key: 'activeValidations', value: state.activeValidations.value },\n ]\n })\n\n api.on.editInspectorState((payload) => {\n if (payload.inspectorId !== INSPECTOR_ID) return\n if (!payload.nodeId.startsWith('form:')) return\n const formKey = payload.nodeId.slice('form:'.length)\n const state = registry.forms.get(formKey)\n if (state === undefined) return\n // payload.path is `['Form value', 'form', ...pathSegments]` — the\n // first two segments are the inspector section + key, the rest is\n // the target form path the user edited. Pass the segment array\n // directly to `canonicalizePath`: join('.') would collapse a\n // literal-dot field key (`{\"user.email\": ...}`) into two segments,\n // writing to the wrong leaf.\n if (payload.path.length < 3) return\n const section = payload.path[0]\n if (section !== 'Form value') return\n const segments = payload.path.slice(2)\n const { segments: canonicalPath } = canonicalizePath(segments)\n state.setValueAtPath(canonicalPath, payload.state.value)\n refreshState()\n })\n\n // Initial sync so existing forms show up.\n syncForms()\n refreshTree()\n}\n"],"names":["canonicalizePath"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { f as canonicalizePath } from '../shared/attaform.DGhIix5D.mjs';
1
+ import { f as canonicalizePath } from '../shared/attaform.Da8EdI2t.mjs';
2
2
 
3
3
  const INSPECTOR_ID = "attaform";
4
4
  const TIMELINE_LAYER_ID = "attaform:events";
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const canonicalStringify = require('../shared/attaform.CQN9R62B.cjs');
4
- const index = require('../shared/attaform.tZ0YKisf.cjs');
4
+ const index = require('../shared/attaform.C__F01CE.cjs');
5
5
 
6
6
  const cyclicSentinel = "<cyclic>";
7
7
  function fingerprintZodSchema(schema) {
@@ -1,5 +1,5 @@
1
1
  import { c as canonicalStringify } from '../shared/attaform.BJGA_UOS.mjs';
2
- import { k as kindOf, g as getIntersectionLeft, b as getIntersectionRight, c as unwrapLazy, d as unwrapInner, e as unwrapPipe, h as getDiscriminator, i as getDiscriminatedOptions, j as getUnionOptions, l as getRecordKeyType, m as getRecordValueType, n as getTupleItems, o as getSetValueType, p as getArrayElement, q as getObjectShape, r as getEnumValues, s as getLiteralValues, t as getChecks, v as getCatchDefault, x as getDefaultValue } from '../shared/attaform.DSOIz08n.mjs';
2
+ import { k as kindOf, g as getIntersectionLeft, b as getIntersectionRight, c as unwrapLazy, d as unwrapInner, e as unwrapPipe, h as getDiscriminator, i as getDiscriminatedOptions, j as getUnionOptions, l as getRecordKeyType, m as getRecordValueType, n as getTupleItems, o as getSetValueType, p as getArrayElement, q as getObjectShape, r as getEnumValues, s as getLiteralValues, t as getChecks, v as getCatchDefault, x as getDefaultValue } from '../shared/attaform.BceJrhQ7.mjs';
3
3
 
4
4
  const cyclicSentinel = "<cyclic>";
5
5
  function fingerprintZodSchema(schema) {
package/dist/esbuild.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const detectZodMajor = require('./shared/attaform.LEWUFqUw.cjs');
3
+ const detectZodMajor = require('./shared/attaform.DoQm_Vkd.cjs');
4
4
 
5
5
  function attaform(options = {}) {
6
6
  const resolveZodAlias = options.resolveZodAlias !== false;
@@ -11,7 +11,7 @@ function attaform(options = {}) {
11
11
  const root = build.initialOptions.absWorkingDir ?? options.root ?? process.cwd();
12
12
  const target = detectZodMajor.resolveZodAliasTarget(root, "attaform/esbuild", resolveZodAlias, warnState);
13
13
  if (target === null) return;
14
- build.onResolve({ filter: /^attaform\/zod$/ }, async (args) => {
14
+ build.onResolve({ filter: detectZodMajor.REWRITABLE_ZOD_SPECIFIER_FILTER }, async (args) => {
15
15
  const result = await build.resolve(target, {
16
16
  kind: args.kind,
17
17
  importer: args.importer,
@@ -1 +1 @@
1
- {"version":3,"file":"esbuild.cjs","sources":["../src/esbuild.ts"],"sourcesContent":["/**\n * `attaform/esbuild` — esbuild plugin that rewrites `attaform/zod`\n * imports to the single matching adapter subpath (`attaform/zod-v3` or\n * `attaform/zod-v4`) at build time, based on the consumer's installed Zod\n * major. Without it, esbuild ships both adapters because the unified\n * `attaform/zod` entry imports both for runtime dispatch.\n *\n * Usage:\n *\n * // build.mjs\n * import { build } from 'esbuild'\n * import { attaform } from 'attaform/esbuild'\n *\n * await build({\n * entryPoints: ['src/main.ts'],\n * bundle: true,\n * plugins: [attaform()],\n * })\n *\n * This plugin only does the adapter rewrite. The Vue SFC `v-register`\n * transforms that `attaform/vite` wires (load-bearing for SSR initial\n * render) are `@vitejs/plugin-vue`-specific and do not transfer; a\n * non-Vite consumer that needs them wires `attaform/transforms` into\n * their Vue compiler separately.\n *\n * Zero-dep: the plugin imports nothing from `esbuild` (the bundler injects\n * its plugin API at the consumer's build); the structural types below are\n * all it needs to compile.\n */\nimport { resolveZodAliasTarget } from './core/detect-zod-major'\n\n/** Options for the esbuild `attaform()` plugin. */\nexport interface AttaformEsbuildPluginOptions {\n /**\n * Rewrite `attaform/zod` imports at build time to the matching adapter\n * subpath. Default `true`. Set to `false` to keep the runtime-dispatch\n * unified entry (ships both adapters).\n */\n resolveZodAlias?: boolean\n /**\n * Project root to resolve the installed Zod from. Defaults to the\n * build's `absWorkingDir`, falling back to `process.cwd()`. Set this\n * when the build runs from a directory other than the project that owns\n * the Zod dependency.\n */\n root?: string\n}\n\ninterface EsbuildOnResolveArgs {\n path: string\n importer: string\n resolveDir: string\n kind: string\n}\ninterface EsbuildResolveResult {\n path: string\n external: boolean\n namespace: string\n errors: unknown[]\n}\ninterface EsbuildOnResolveResult {\n path?: string\n external?: boolean\n namespace?: string\n errors?: unknown[]\n}\ninterface EsbuildPluginBuild {\n initialOptions: { absWorkingDir?: string }\n onResolve(\n options: { filter: RegExp },\n callback: (args: EsbuildOnResolveArgs) => Promise<EsbuildOnResolveResult>\n ): void\n resolve(\n path: string,\n options: { kind: string; importer?: string; resolveDir?: string }\n ): Promise<EsbuildResolveResult>\n}\n\n/** The structural shape esbuild requires of the plugin. */\nexport interface AttaformEsbuildPlugin {\n name: string\n setup(build: EsbuildPluginBuild): void\n}\n\nexport function attaform(options: AttaformEsbuildPluginOptions = {}): AttaformEsbuildPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const warnState = { warned: false }\n return {\n name: 'attaform',\n setup(build) {\n const root = build.initialOptions.absWorkingDir ?? options.root ?? process.cwd()\n const target = resolveZodAliasTarget(root, 'attaform/esbuild', resolveZodAlias, warnState)\n // Nothing to rewrite (opt-out, or unclassifiable version): leave the\n // unified entry in place and register no hook.\n if (target === null) return\n build.onResolve({ filter: /^attaform\\/zod$/ }, async (args) => {\n // Re-resolve the rewritten specifier so esbuild returns a real\n // path. The filter is anchored to the bare unified specifier, so\n // resolving `attaform/zod-v4` does not re-enter this callback.\n const result = await build.resolve(target, {\n kind: args.kind,\n importer: args.importer,\n resolveDir: args.resolveDir,\n })\n if (result.errors.length > 0) return { errors: result.errors }\n return { path: result.path, external: result.external, namespace: result.namespace }\n })\n },\n }\n}\n"],"names":["resolveZodAliasTarget"],"mappings":";;;;AAoFO,SAAS,QAAA,CAAS,OAAA,GAAwC,EAAC,EAA0B;AAC1F,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,MAAM,KAAA,EAAO;AACX,MAAA,MAAM,OAAO,KAAA,CAAM,cAAA,CAAe,iBAAiB,OAAA,CAAQ,IAAA,IAAQ,QAAQ,GAAA,EAAI;AAC/E,MAAA,MAAM,MAAA,GAASA,oCAAA,CAAsB,IAAA,EAAM,kBAAA,EAAoB,iBAAiB,SAAS,CAAA;AAGzF,MAAA,IAAI,WAAW,IAAA,EAAM;AACrB,MAAA,KAAA,CAAM,UAAU,EAAE,MAAA,EAAQ,iBAAA,EAAkB,EAAG,OAAO,IAAA,KAAS;AAI7D,QAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ;AAAA,UACzC,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,UAAU,IAAA,CAAK,QAAA;AAAA,UACf,YAAY,IAAA,CAAK;AAAA,SAClB,CAAA;AACD,QAAA,IAAI,MAAA,CAAO,OAAO,MAAA,GAAS,CAAA,SAAU,EAAE,MAAA,EAAQ,OAAO,MAAA,EAAO;AAC7D,QAAA,OAAO,EAAE,MAAM,MAAA,CAAO,IAAA,EAAM,UAAU,MAAA,CAAO,QAAA,EAAU,SAAA,EAAW,MAAA,CAAO,SAAA,EAAU;AAAA,MACrF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"esbuild.cjs","sources":["../src/esbuild.ts"],"sourcesContent":["/**\n * `attaform/esbuild` — esbuild plugin that rewrites `attaform` and\n * `attaform/zod` imports to the single matching adapter subpath\n * (`attaform/zod-v3` or `attaform/zod-v4`) at build time, based on the\n * consumer's installed Zod major. Without it, esbuild ships both adapters\n * because those entries import both for runtime dispatch.\n *\n * Usage:\n *\n * // build.mjs\n * import { build } from 'esbuild'\n * import { attaform } from 'attaform/esbuild'\n *\n * await build({\n * entryPoints: ['src/main.ts'],\n * bundle: true,\n * plugins: [attaform()],\n * })\n *\n * This plugin only does the adapter rewrite. The Vue SFC `v-register`\n * transforms that `attaform/vite` wires (load-bearing for SSR initial\n * render) are `@vitejs/plugin-vue`-specific and do not transfer; a\n * non-Vite consumer that needs them wires `attaform/transforms` into\n * their Vue compiler separately.\n *\n * Zero-dep: the plugin imports nothing from `esbuild` (the bundler injects\n * its plugin API at the consumer's build); the structural types below are\n * all it needs to compile.\n */\nimport { resolveZodAliasTarget, REWRITABLE_ZOD_SPECIFIER_FILTER } from './core/detect-zod-major'\n\n/** Options for the esbuild `attaform()` plugin. */\nexport interface AttaformEsbuildPluginOptions {\n /**\n * Rewrite `attaform` and `attaform/zod` imports at build time to the\n * matching adapter subpath. Default `true`. Set to `false` to keep the\n * runtime-dispatch unified entry (ships both adapters).\n */\n resolveZodAlias?: boolean\n /**\n * Project root to resolve the installed Zod from. Defaults to the\n * build's `absWorkingDir`, falling back to `process.cwd()`. Set this\n * when the build runs from a directory other than the project that owns\n * the Zod dependency.\n */\n root?: string\n}\n\ninterface EsbuildOnResolveArgs {\n path: string\n importer: string\n resolveDir: string\n kind: string\n}\ninterface EsbuildResolveResult {\n path: string\n external: boolean\n namespace: string\n errors: unknown[]\n}\ninterface EsbuildOnResolveResult {\n path?: string\n external?: boolean\n namespace?: string\n errors?: unknown[]\n}\ninterface EsbuildPluginBuild {\n initialOptions: { absWorkingDir?: string }\n onResolve(\n options: { filter: RegExp },\n callback: (args: EsbuildOnResolveArgs) => Promise<EsbuildOnResolveResult>\n ): void\n resolve(\n path: string,\n options: { kind: string; importer?: string; resolveDir?: string }\n ): Promise<EsbuildResolveResult>\n}\n\n/** The structural shape esbuild requires of the plugin. */\nexport interface AttaformEsbuildPlugin {\n name: string\n setup(build: EsbuildPluginBuild): void\n}\n\nexport function attaform(options: AttaformEsbuildPluginOptions = {}): AttaformEsbuildPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const warnState = { warned: false }\n return {\n name: 'attaform',\n setup(build) {\n const root = build.initialOptions.absWorkingDir ?? options.root ?? process.cwd()\n const target = resolveZodAliasTarget(root, 'attaform/esbuild', resolveZodAlias, warnState)\n // Nothing to rewrite (opt-out, or unclassifiable version): leave the\n // unified entry in place and register no hook.\n if (target === null) return\n build.onResolve({ filter: REWRITABLE_ZOD_SPECIFIER_FILTER }, async (args) => {\n // Re-resolve the rewritten specifier so esbuild returns a real\n // path. Both matched specifiers (bare `attaform` and\n // `attaform/zod`) rewrite to the same detected adapter; the filter\n // is anchored so resolving `attaform/zod-v4` does not re-enter\n // this callback.\n const result = await build.resolve(target, {\n kind: args.kind,\n importer: args.importer,\n resolveDir: args.resolveDir,\n })\n if (result.errors.length > 0) return { errors: result.errors }\n return { path: result.path, external: result.external, namespace: result.namespace }\n })\n },\n }\n}\n"],"names":["resolveZodAliasTarget","REWRITABLE_ZOD_SPECIFIER_FILTER"],"mappings":";;;;AAoFO,SAAS,QAAA,CAAS,OAAA,GAAwC,EAAC,EAA0B;AAC1F,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,MAAM,KAAA,EAAO;AACX,MAAA,MAAM,OAAO,KAAA,CAAM,cAAA,CAAe,iBAAiB,OAAA,CAAQ,IAAA,IAAQ,QAAQ,GAAA,EAAI;AAC/E,MAAA,MAAM,MAAA,GAASA,oCAAA,CAAsB,IAAA,EAAM,kBAAA,EAAoB,iBAAiB,SAAS,CAAA;AAGzF,MAAA,IAAI,WAAW,IAAA,EAAM;AACrB,MAAA,KAAA,CAAM,UAAU,EAAE,MAAA,EAAQC,8CAAA,EAAgC,EAAG,OAAO,IAAA,KAAS;AAM3E,QAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ;AAAA,UACzC,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,UAAU,IAAA,CAAK,QAAA;AAAA,UACf,YAAY,IAAA,CAAK;AAAA,SAClB,CAAA;AACD,QAAA,IAAI,MAAA,CAAO,OAAO,MAAA,GAAS,CAAA,SAAU,EAAE,MAAA,EAAQ,OAAO,MAAA,EAAO;AAC7D,QAAA,OAAO,EAAE,MAAM,MAAA,CAAO,IAAA,EAAM,UAAU,MAAA,CAAO,QAAA,EAAU,SAAA,EAAW,MAAA,CAAO,SAAA,EAAU;AAAA,MACrF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;;"}
@@ -1,9 +1,9 @@
1
1
  /** Options for the esbuild `attaform()` plugin. */
2
2
  interface AttaformEsbuildPluginOptions {
3
3
  /**
4
- * Rewrite `attaform/zod` imports at build time to the matching adapter
5
- * subpath. Default `true`. Set to `false` to keep the runtime-dispatch
6
- * unified entry (ships both adapters).
4
+ * Rewrite `attaform` and `attaform/zod` imports at build time to the
5
+ * matching adapter subpath. Default `true`. Set to `false` to keep the
6
+ * runtime-dispatch unified entry (ships both adapters).
7
7
  */
8
8
  resolveZodAlias?: boolean;
9
9
  /**
@@ -1,9 +1,9 @@
1
1
  /** Options for the esbuild `attaform()` plugin. */
2
2
  interface AttaformEsbuildPluginOptions {
3
3
  /**
4
- * Rewrite `attaform/zod` imports at build time to the matching adapter
5
- * subpath. Default `true`. Set to `false` to keep the runtime-dispatch
6
- * unified entry (ships both adapters).
4
+ * Rewrite `attaform` and `attaform/zod` imports at build time to the
5
+ * matching adapter subpath. Default `true`. Set to `false` to keep the
6
+ * runtime-dispatch unified entry (ships both adapters).
7
7
  */
8
8
  resolveZodAlias?: boolean;
9
9
  /**
package/dist/esbuild.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /** Options for the esbuild `attaform()` plugin. */
2
2
  interface AttaformEsbuildPluginOptions {
3
3
  /**
4
- * Rewrite `attaform/zod` imports at build time to the matching adapter
5
- * subpath. Default `true`. Set to `false` to keep the runtime-dispatch
6
- * unified entry (ships both adapters).
4
+ * Rewrite `attaform` and `attaform/zod` imports at build time to the
5
+ * matching adapter subpath. Default `true`. Set to `false` to keep the
6
+ * runtime-dispatch unified entry (ships both adapters).
7
7
  */
8
8
  resolveZodAlias?: boolean;
9
9
  /**
package/dist/esbuild.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { r as resolveZodAliasTarget } from './shared/attaform.sHkHv_98.mjs';
1
+ import { r as resolveZodAliasTarget, R as REWRITABLE_ZOD_SPECIFIER_FILTER } from './shared/attaform.DhnPb6nK.mjs';
2
2
 
3
3
  function attaform(options = {}) {
4
4
  const resolveZodAlias = options.resolveZodAlias !== false;
@@ -9,7 +9,7 @@ function attaform(options = {}) {
9
9
  const root = build.initialOptions.absWorkingDir ?? options.root ?? process.cwd();
10
10
  const target = resolveZodAliasTarget(root, "attaform/esbuild", resolveZodAlias, warnState);
11
11
  if (target === null) return;
12
- build.onResolve({ filter: /^attaform\/zod$/ }, async (args) => {
12
+ build.onResolve({ filter: REWRITABLE_ZOD_SPECIFIER_FILTER }, async (args) => {
13
13
  const result = await build.resolve(target, {
14
14
  kind: args.kind,
15
15
  importer: args.importer,
@@ -1 +1 @@
1
- {"version":3,"file":"esbuild.mjs","sources":["../src/esbuild.ts"],"sourcesContent":["/**\n * `attaform/esbuild` — esbuild plugin that rewrites `attaform/zod`\n * imports to the single matching adapter subpath (`attaform/zod-v3` or\n * `attaform/zod-v4`) at build time, based on the consumer's installed Zod\n * major. Without it, esbuild ships both adapters because the unified\n * `attaform/zod` entry imports both for runtime dispatch.\n *\n * Usage:\n *\n * // build.mjs\n * import { build } from 'esbuild'\n * import { attaform } from 'attaform/esbuild'\n *\n * await build({\n * entryPoints: ['src/main.ts'],\n * bundle: true,\n * plugins: [attaform()],\n * })\n *\n * This plugin only does the adapter rewrite. The Vue SFC `v-register`\n * transforms that `attaform/vite` wires (load-bearing for SSR initial\n * render) are `@vitejs/plugin-vue`-specific and do not transfer; a\n * non-Vite consumer that needs them wires `attaform/transforms` into\n * their Vue compiler separately.\n *\n * Zero-dep: the plugin imports nothing from `esbuild` (the bundler injects\n * its plugin API at the consumer's build); the structural types below are\n * all it needs to compile.\n */\nimport { resolveZodAliasTarget } from './core/detect-zod-major'\n\n/** Options for the esbuild `attaform()` plugin. */\nexport interface AttaformEsbuildPluginOptions {\n /**\n * Rewrite `attaform/zod` imports at build time to the matching adapter\n * subpath. Default `true`. Set to `false` to keep the runtime-dispatch\n * unified entry (ships both adapters).\n */\n resolveZodAlias?: boolean\n /**\n * Project root to resolve the installed Zod from. Defaults to the\n * build's `absWorkingDir`, falling back to `process.cwd()`. Set this\n * when the build runs from a directory other than the project that owns\n * the Zod dependency.\n */\n root?: string\n}\n\ninterface EsbuildOnResolveArgs {\n path: string\n importer: string\n resolveDir: string\n kind: string\n}\ninterface EsbuildResolveResult {\n path: string\n external: boolean\n namespace: string\n errors: unknown[]\n}\ninterface EsbuildOnResolveResult {\n path?: string\n external?: boolean\n namespace?: string\n errors?: unknown[]\n}\ninterface EsbuildPluginBuild {\n initialOptions: { absWorkingDir?: string }\n onResolve(\n options: { filter: RegExp },\n callback: (args: EsbuildOnResolveArgs) => Promise<EsbuildOnResolveResult>\n ): void\n resolve(\n path: string,\n options: { kind: string; importer?: string; resolveDir?: string }\n ): Promise<EsbuildResolveResult>\n}\n\n/** The structural shape esbuild requires of the plugin. */\nexport interface AttaformEsbuildPlugin {\n name: string\n setup(build: EsbuildPluginBuild): void\n}\n\nexport function attaform(options: AttaformEsbuildPluginOptions = {}): AttaformEsbuildPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const warnState = { warned: false }\n return {\n name: 'attaform',\n setup(build) {\n const root = build.initialOptions.absWorkingDir ?? options.root ?? process.cwd()\n const target = resolveZodAliasTarget(root, 'attaform/esbuild', resolveZodAlias, warnState)\n // Nothing to rewrite (opt-out, or unclassifiable version): leave the\n // unified entry in place and register no hook.\n if (target === null) return\n build.onResolve({ filter: /^attaform\\/zod$/ }, async (args) => {\n // Re-resolve the rewritten specifier so esbuild returns a real\n // path. The filter is anchored to the bare unified specifier, so\n // resolving `attaform/zod-v4` does not re-enter this callback.\n const result = await build.resolve(target, {\n kind: args.kind,\n importer: args.importer,\n resolveDir: args.resolveDir,\n })\n if (result.errors.length > 0) return { errors: result.errors }\n return { path: result.path, external: result.external, namespace: result.namespace }\n })\n },\n }\n}\n"],"names":[],"mappings":";;AAoFO,SAAS,QAAA,CAAS,OAAA,GAAwC,EAAC,EAA0B;AAC1F,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,MAAM,KAAA,EAAO;AACX,MAAA,MAAM,OAAO,KAAA,CAAM,cAAA,CAAe,iBAAiB,OAAA,CAAQ,IAAA,IAAQ,QAAQ,GAAA,EAAI;AAC/E,MAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,IAAA,EAAM,kBAAA,EAAoB,iBAAiB,SAAS,CAAA;AAGzF,MAAA,IAAI,WAAW,IAAA,EAAM;AACrB,MAAA,KAAA,CAAM,UAAU,EAAE,MAAA,EAAQ,iBAAA,EAAkB,EAAG,OAAO,IAAA,KAAS;AAI7D,QAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ;AAAA,UACzC,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,UAAU,IAAA,CAAK,QAAA;AAAA,UACf,YAAY,IAAA,CAAK;AAAA,SAClB,CAAA;AACD,QAAA,IAAI,MAAA,CAAO,OAAO,MAAA,GAAS,CAAA,SAAU,EAAE,MAAA,EAAQ,OAAO,MAAA,EAAO;AAC7D,QAAA,OAAO,EAAE,MAAM,MAAA,CAAO,IAAA,EAAM,UAAU,MAAA,CAAO,QAAA,EAAU,SAAA,EAAW,MAAA,CAAO,SAAA,EAAU;AAAA,MACrF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"esbuild.mjs","sources":["../src/esbuild.ts"],"sourcesContent":["/**\n * `attaform/esbuild` — esbuild plugin that rewrites `attaform` and\n * `attaform/zod` imports to the single matching adapter subpath\n * (`attaform/zod-v3` or `attaform/zod-v4`) at build time, based on the\n * consumer's installed Zod major. Without it, esbuild ships both adapters\n * because those entries import both for runtime dispatch.\n *\n * Usage:\n *\n * // build.mjs\n * import { build } from 'esbuild'\n * import { attaform } from 'attaform/esbuild'\n *\n * await build({\n * entryPoints: ['src/main.ts'],\n * bundle: true,\n * plugins: [attaform()],\n * })\n *\n * This plugin only does the adapter rewrite. The Vue SFC `v-register`\n * transforms that `attaform/vite` wires (load-bearing for SSR initial\n * render) are `@vitejs/plugin-vue`-specific and do not transfer; a\n * non-Vite consumer that needs them wires `attaform/transforms` into\n * their Vue compiler separately.\n *\n * Zero-dep: the plugin imports nothing from `esbuild` (the bundler injects\n * its plugin API at the consumer's build); the structural types below are\n * all it needs to compile.\n */\nimport { resolveZodAliasTarget, REWRITABLE_ZOD_SPECIFIER_FILTER } from './core/detect-zod-major'\n\n/** Options for the esbuild `attaform()` plugin. */\nexport interface AttaformEsbuildPluginOptions {\n /**\n * Rewrite `attaform` and `attaform/zod` imports at build time to the\n * matching adapter subpath. Default `true`. Set to `false` to keep the\n * runtime-dispatch unified entry (ships both adapters).\n */\n resolveZodAlias?: boolean\n /**\n * Project root to resolve the installed Zod from. Defaults to the\n * build's `absWorkingDir`, falling back to `process.cwd()`. Set this\n * when the build runs from a directory other than the project that owns\n * the Zod dependency.\n */\n root?: string\n}\n\ninterface EsbuildOnResolveArgs {\n path: string\n importer: string\n resolveDir: string\n kind: string\n}\ninterface EsbuildResolveResult {\n path: string\n external: boolean\n namespace: string\n errors: unknown[]\n}\ninterface EsbuildOnResolveResult {\n path?: string\n external?: boolean\n namespace?: string\n errors?: unknown[]\n}\ninterface EsbuildPluginBuild {\n initialOptions: { absWorkingDir?: string }\n onResolve(\n options: { filter: RegExp },\n callback: (args: EsbuildOnResolveArgs) => Promise<EsbuildOnResolveResult>\n ): void\n resolve(\n path: string,\n options: { kind: string; importer?: string; resolveDir?: string }\n ): Promise<EsbuildResolveResult>\n}\n\n/** The structural shape esbuild requires of the plugin. */\nexport interface AttaformEsbuildPlugin {\n name: string\n setup(build: EsbuildPluginBuild): void\n}\n\nexport function attaform(options: AttaformEsbuildPluginOptions = {}): AttaformEsbuildPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const warnState = { warned: false }\n return {\n name: 'attaform',\n setup(build) {\n const root = build.initialOptions.absWorkingDir ?? options.root ?? process.cwd()\n const target = resolveZodAliasTarget(root, 'attaform/esbuild', resolveZodAlias, warnState)\n // Nothing to rewrite (opt-out, or unclassifiable version): leave the\n // unified entry in place and register no hook.\n if (target === null) return\n build.onResolve({ filter: REWRITABLE_ZOD_SPECIFIER_FILTER }, async (args) => {\n // Re-resolve the rewritten specifier so esbuild returns a real\n // path. Both matched specifiers (bare `attaform` and\n // `attaform/zod`) rewrite to the same detected adapter; the filter\n // is anchored so resolving `attaform/zod-v4` does not re-enter\n // this callback.\n const result = await build.resolve(target, {\n kind: args.kind,\n importer: args.importer,\n resolveDir: args.resolveDir,\n })\n if (result.errors.length > 0) return { errors: result.errors }\n return { path: result.path, external: result.external, namespace: result.namespace }\n })\n },\n }\n}\n"],"names":[],"mappings":";;AAoFO,SAAS,QAAA,CAAS,OAAA,GAAwC,EAAC,EAA0B;AAC1F,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,MAAM,KAAA,EAAO;AACX,MAAA,MAAM,OAAO,KAAA,CAAM,cAAA,CAAe,iBAAiB,OAAA,CAAQ,IAAA,IAAQ,QAAQ,GAAA,EAAI;AAC/E,MAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,IAAA,EAAM,kBAAA,EAAoB,iBAAiB,SAAS,CAAA;AAGzF,MAAA,IAAI,WAAW,IAAA,EAAM;AACrB,MAAA,KAAA,CAAM,UAAU,EAAE,MAAA,EAAQ,+BAAA,EAAgC,EAAG,OAAO,IAAA,KAAS;AAM3E,QAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ;AAAA,UACzC,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,UAAU,IAAA,CAAK,QAAA;AAAA,UACf,YAAY,IAAA,CAAK;AAAA,SAClB,CAAA;AACD,QAAA,IAAI,MAAA,CAAO,OAAO,MAAA,GAAS,CAAA,SAAU,EAAE,MAAA,EAAQ,OAAO,MAAA,EAAO;AAC7D,QAAA,OAAO,EAAE,MAAM,MAAA,CAAO,IAAA,EAAM,UAAU,MAAA,CAAO,QAAA,EAAU,SAAA,EAAW,MAAA,CAAO,SAAA,EAAU;AAAA,MACrF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;;"}