attaform 0.25.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.CN4ZEGo6.mjs → attaform.BceJrhQ7.mjs} +5 -5
  57. package/dist/shared/{attaform.CN4ZEGo6.mjs.map → attaform.BceJrhQ7.mjs.map} +1 -1
  58. package/dist/shared/{attaform.i_LA3X9o.d.cts → attaform.C3WnCDXz.d.cts} +81 -24
  59. package/dist/shared/{attaform.i_LA3X9o.d.ts → attaform.C3WnCDXz.d.mts} +81 -24
  60. package/dist/shared/{attaform.i_LA3X9o.d.mts → attaform.C3WnCDXz.d.ts} +81 -24
  61. package/dist/shared/{attaform.DuzQYscR.d.ts → attaform.C9fPTxjB.d.cts} +5 -5
  62. package/dist/shared/{attaform.DuzQYscR.d.cts → attaform.C9fPTxjB.d.mts} +5 -5
  63. package/dist/shared/{attaform.DuzQYscR.d.mts → attaform.C9fPTxjB.d.ts} +5 -5
  64. package/dist/shared/{attaform.B3cgZE3c.d.ts → attaform.CC_y1_Ej.d.ts} +33 -33
  65. package/dist/shared/{attaform.DS_zBcdr.d.ts → attaform.CEXUlUkc.d.ts} +1588 -1190
  66. package/dist/shared/{attaform.Xe8dATED.cjs → attaform.C__F01CE.cjs} +15 -15
  67. package/dist/shared/{attaform.Xe8dATED.cjs.map → attaform.C__F01CE.cjs.map} +1 -1
  68. package/dist/shared/{attaform.3heDHayA.cjs → attaform.Co5LNRnv.cjs} +186 -129
  69. package/dist/shared/attaform.Co5LNRnv.cjs.map +1 -0
  70. package/dist/shared/{attaform.BJt4ZCkM.d.mts → attaform.CpXHK60W.d.cts} +33 -33
  71. package/dist/shared/{attaform.DmKLa4tL.d.cts → attaform.CvVYOvZF.d.mts} +33 -33
  72. package/dist/shared/{attaform.DK3xUBkj.mjs → attaform.CyQxTOdX.mjs} +162 -79
  73. package/dist/shared/attaform.CyQxTOdX.mjs.map +1 -0
  74. package/dist/shared/{attaform.B5GFS3Su.d.cts → attaform.D99pd7JG.d.cts} +1588 -1190
  75. package/dist/shared/{attaform.CwXXbZIQ.mjs → attaform.DDAmSFnl.mjs} +4 -4
  76. package/dist/shared/{attaform.CwXXbZIQ.mjs.map → attaform.DDAmSFnl.mjs.map} +1 -1
  77. package/dist/shared/{attaform.BkUzunyB.cjs → attaform.DQT7_-FO.cjs} +371 -287
  78. package/dist/shared/attaform.DQT7_-FO.cjs.map +1 -0
  79. package/dist/shared/{attaform.CqwcTExO.mjs → attaform.Da8EdI2t.mjs} +182 -129
  80. package/dist/shared/attaform.Da8EdI2t.mjs.map +1 -0
  81. package/dist/shared/{attaform.sks1MFVO.cjs → attaform.DhVgG2jh.cjs} +16 -16
  82. package/dist/shared/{attaform.sks1MFVO.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.DMNnfQq_.mjs → attaform.DlSu08F5.mjs} +4 -4
  88. package/dist/shared/{attaform.DMNnfQq_.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.B5YcWrKi.cjs → attaform.Drsi43GG.cjs} +19 -19
  92. package/dist/shared/{attaform.B5YcWrKi.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.8vmdOURQ.d.mts → attaform.kBkYlKP_.d.mts} +1588 -1190
  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.3heDHayA.cjs.map +0 -1
  147. package/dist/shared/attaform.BRGIpZo4.cjs.map +0 -1
  148. package/dist/shared/attaform.BkUzunyB.cjs.map +0 -1
  149. package/dist/shared/attaform.C3Doa9Pt.mjs.map +0 -1
  150. package/dist/shared/attaform.CO0e7YVY.d.cts +0 -94
  151. package/dist/shared/attaform.CO0e7YVY.d.mts +0 -94
  152. package/dist/shared/attaform.CO0e7YVY.d.ts +0 -94
  153. package/dist/shared/attaform.CqwcTExO.mjs.map +0 -1
  154. package/dist/shared/attaform.DK3xUBkj.mjs.map +0 -1
  155. package/dist/shared/attaform.LEWUFqUw.cjs.map +0 -1
  156. package/dist/shared/attaform.OLtKd9gM.mjs +0 -35
  157. package/dist/shared/attaform.OLtKd9gM.mjs.map +0 -1
  158. package/dist/shared/attaform.sHkHv_98.mjs.map +0 -1
  159. package/dist/shared/attaform.xBDo0Ko0.cjs +0 -39
  160. package/dist/shared/attaform.xBDo0Ko0.cjs.map +0 -1
  161. package/dist/shared/{attaform.DdjDqTah.d.mts → attaform.DRUT703x.d.cts} +14 -14
  162. package/dist/shared/{attaform.DdjDqTah.d.ts → attaform.DRUT703x.d.mts} +14 -14
  163. package/dist/shared/{attaform.DdjDqTah.d.cts → attaform.DRUT703x.d.ts} +14 -14
package/dist/nuxt.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"nuxt.cjs","sources":["../src/nuxt.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { addImports, addPlugin, addVitePlugin, createResolver, defineNuxtModule } from '@nuxt/kit'\nimport type { AttaformDefaults } from './runtime/types/types-api'\nimport { attaform as attaformVitePlugin } from './vite'\n\n// Read the published version from the package's own package.json so the\n// module's DevTools panel surfaces the live version pill without a\n// build-time string injection. `createRequire` reads sync at module load —\n// run once, free at steady state. Works under unbuild's Rollup output\n// without bundler-specific JSON-import handling.\nconst pkgVersion = (createRequire(import.meta.url)('../package.json') as { version: string })\n .version\n\n/**\n * Options accepted by `attaform/nuxt` under the `attaform`\n * config key.\n *\n * ```ts\n * // nuxt.config.ts\n * export default defineNuxtConfig({\n * modules: ['attaform/nuxt'],\n * attaform: {\n * defaults: { debounceMs: 100 },\n * },\n * })\n * ```\n */\nexport interface AttaformModuleOptions {\n /**\n * App-level defaults applied to every `useForm` call. Per-form\n * options always win. See `AttaformDefaults` for the\n * supported option set and merge rules.\n */\n defaults?: AttaformDefaults\n /**\n * Forwarded to `attaform/vite`'s `resolveZodAlias` option.\n * Default `true` — `attaform/zod` imports are rewritten at build\n * time to either `attaform/zod-v3` or `attaform/zod-v4`, based on\n * the consumer's installed Zod major. Set to `false` to bypass\n * the rewrite and ship the runtime-dispatch unified entry instead.\n */\n resolveZodAlias?: boolean\n}\n\n/**\n * Shape of the Nuxt public runtime-config slot the module populates.\n * Reach it via `useRuntimeConfig().public.attaform` if you need to\n * read the configured defaults outside the form library itself.\n */\nexport type AttaformRuntimeConfig = {\n defaults: AttaformDefaults\n /**\n * Library version, read from the package's own `package.json` at\n * module setup. Surfaced to the runtime plugin so the DevTools\n * overlay panel can render a version pill — single source of truth\n * matches the `meta.version` Nuxt DevTools sees in the Modules panel.\n */\n version: string\n}\n\n/**\n * Whether `specifier` is resolvable using ESM resolution from either the\n * consumer's project root or attaform's own module location. Returning\n * true matches what Vite's resolver would do for `optimizeDeps.include`,\n * so a true here means Vite will pre-bundle the dep without warning.\n *\n * Why two probe locations:\n * - Consumer-rootDir probe finds direct deps + their declared peers\n * (the standard pnpm strict-isolation visibility).\n * - attaform-module probe finds peers attaform itself declares —\n * specifically the optional `@vue/devtools-api`, which lands in\n * attaform's own node_modules tree (or pnpm virtual store) when\n * installed, even if the consumer never references it directly.\n *\n * Why ESM resolution (`import.meta.resolve`) rather than CJS\n * (`createRequire(...).resolve`):\n * - attaform's exports map declares only `import` conditions for\n * non-`/nuxt` entries. CJS resolve hits ERR_PACKAGE_PATH_NOT_EXPORTED\n * for `attaform` and its sub-entries.\n * - pnpm strict isolation hides hoisted transitives behind the\n * virtual store. CJS resolve walks the bare node_modules chain and\n * misses them; ESM resolve follows pnpm's symlinks correctly.\n * - `import.meta.resolve(spec, parentURL)` is sync and stable in\n * Node 20.6+, which attaform already requires (engines.node).\n */\nfunction isResolvableForVite(specifier: string, consumerRootDir: string): boolean {\n const consumerURL = pathToFileURL(join(consumerRootDir, 'package.json')).href\n return canResolve(specifier, consumerURL) || canResolve(specifier, import.meta.url)\n}\n\nfunction canResolve(specifier: string, fromURL: string): boolean {\n try {\n import.meta.resolve(specifier, fromURL)\n return true\n } catch {\n return false\n }\n}\n\nexport default defineNuxtModule<AttaformModuleOptions>({\n meta: {\n name: 'Attaform',\n configKey: 'attaform',\n version: pkgVersion,\n docs: 'https://attaform.dev/docs',\n compatibility: {\n nuxt: '>=3.0.0',\n },\n },\n defaults: {},\n setup(_options, nuxt) {\n // Register `attaform/vite` so the same plugin handles every Vite-\n // surface concern: pushing the compile-time node transforms into\n // `@vitejs/plugin-vue`'s `api.options.template.compilerOptions.\n // nodeTransforms`, AND rewriting `attaform/zod` imports at build\n // time to either `/zod-v3` or `/zod-v4` based on the consumer's\n // installed Zod major. Consolidating both behaviors in one Vite\n // plugin instance keeps the Nuxt-side wiring minimal and ensures\n // the consumer's Nuxt build sees the exact same DX as a bare-Vite\n // consumer.\n addVitePlugin(attaformVitePlugin({ resolveZodAlias: _options.resolveZodAlias !== false }))\n\n // Publish module options to public runtime config so the plugin can\n // read them at install time on both server and client. Frozen-empty\n // by default — the plugin's merge code reads this slot directly\n // without a `?? {}` guard at every call site.\n const runtimePublic = nuxt.options.runtimeConfig.public as Record<string, unknown>\n runtimePublic['attaform'] = {\n defaults: _options.defaults ?? {},\n version: pkgVersion,\n } satisfies AttaformRuntimeConfig\n\n // Force-include attaform's own peers that Vite's startup crawl\n // tends to miss for Nuxt projects. Vite scans `index.html` + the\n // statically-known entry points but doesn't deeply follow into\n // pages that get loaded via Nuxt's dynamic router; deps imported\n // exclusively from page chunks are discovered when the page first\n // requests, the optimizer rebundles, and Vite silently broadcasts\n // `{\"type\":\"full-reload\",\"path\":\"*\"}` over the HMR WebSocket — what\n // consumers see as \"the page loads, then reloads itself a second\n // later.\" Vite's own \"discovered new dependencies at runtime\"\n // warning recommends exactly this remediation.\n //\n // We declare here only deps attaform itself owns the relationship\n // with — `@vue/devtools-api` (attaform's DevTools integration\n // peer) and `zod` (the adapter peer for `/zod`, `/zod-v3`, and\n // `/zod-v4`). Consumer-\n // side deps (vue-query, immer, etc.) are the consumer's\n // responsibility — they declare them in their own\n // `vite.optimizeDeps.include`. Each push is gated on the spec\n // being resolvable from the consumer's project (or attaform's\n // own module context for attaform's optional peers like\n // devtools-api), so consumers without the optional peer don't see\n // a \"failed to resolve\" warning at boot.\n nuxt.options.vite.optimizeDeps ??= {}\n nuxt.options.vite.optimizeDeps.include ??= []\n const include = nuxt.options.vite.optimizeDeps.include\n for (const spec of ['@vue/devtools-api', 'zod']) {\n if (!isResolvableForVite(spec, nuxt.options.rootDir)) continue\n if (!include.includes(spec)) include.push(spec)\n }\n\n const resolver = createResolver(import.meta.url)\n\n // Auto-import `useForm` — the framework-agnostic core composable (same\n // binding as `attaform`'s top-level `useForm` export, which\n // is the abstract form composable). Consumers who want the zod-typed\n // wrapper must import from `attaform/zod` or `/zod-v3`\n // explicitly.\n //\n // We point at the public package entry rather than a relative\n // `./runtime/…` path on purpose: in the published package the\n // `src/runtime/composables/use-abstract-form` path has no matching\n // `dist/runtime/…` file (build.config's entries don't include it),\n // so a `resolver.resolve(...)` would raise ENOENT at Nuxt's auto-\n // import step. Importing from `attaform` resolves through\n // the shared chunk, identical to what `attaform/zod`\n // consumers bundle — single registry instance across both import\n // surfaces.\n addImports([{ name: 'useForm', from: 'attaform' }])\n\n // Plugin that installs `createAttaform()` on the Vue app and\n // wires the payload serialize/hydrate bridge. Uses a physical\n // `src/runtime/plugins/attaform.ts` file (shipped to\n // `dist/runtime/plugins/attaform.mjs` via an explicit entry in\n // build.config.ts) rather than an inline plugin template, because a\n // template's `import { createAttaform } from 'attaform'`\n // resolves through the `attaform` package entry — which in\n // local dev (`unbuild --stub`) is a jiti runtime transpiler whose\n // `node:module`/`createRequire` imports Nitro's Rollup build cannot\n // bundle. A physical file lets Nitro follow its imports directly\n // (TS source in dev, ESM in the published package), avoiding the\n // jiti indirection entirely. Unbuild's shared-chunk splitter keeps\n // `core/plugin` + `core/serialize` deduplicated with `src/zod` /\n // `src/index`, so there's still only one `registry` module at runtime.\n //\n // `addPlugin` defaults to PREPEND so the plugin runs before any\n // user plugin / page; `enforce: 'pre'` inside the plugin body makes\n // that ordering explicit at the Nuxt-plugin layer too. Together\n // they guarantee the registry is installed (and SSR payload staged\n // into `pendingHydration`) before any `useForm` call runs.\n addPlugin({\n src: resolver.resolve('./runtime/plugins/attaform'),\n })\n\n // Dev-only: register a Nuxt DevTools overlay tab pointing at an\n // iframe that mounts the Attaform inspector. The iframe URL\n // (`/_attaform_devtools`) is served by a Vite-layer middleware\n // wired up in `attaform/vite` — by intercepting at the Vite layer\n // rather than via `extendPages`, the route stays invisible to\n // vue-router and works regardless of whether the consumer uses\n // a `pages/` directory or `app.vue`-only mode.\n //\n // `@nuxt/devtools-kit` is NOT a transitive peer of `@nuxt/kit`; it\n // ships alongside `@nuxt/devtools`. Consumers who don't install\n // Nuxt DevTools (rare in real Nuxt projects, common in test\n // fixtures) get a silent no-op instead of an \"unresolved import\"\n // error. Mirrors the same try/import pattern used for\n // `@vue/devtools-api` in the runtime devtools wire-up.\n if (nuxt.options.dev) {\n nuxt.hook('ready', async () => {\n try {\n const { addCustomTab } = await import('@nuxt/devtools-kit')\n addCustomTab({\n name: 'attaform',\n title: 'Attaform',\n // Brand mark — purple square with a white \"A\" silhouette,\n // matching `apps/site/public/favicon.svg`. Served by the\n // `attaform/vite` middleware at the same `/_attaform_devtools`\n // route family (sibling to the panel HTML). A real URL\n // renders reliably across Nuxt DevTools versions where\n // `data:` URIs don't.\n icon: '/_attaform_devtools/icon.svg',\n view: {\n type: 'iframe',\n src: '/_attaform_devtools',\n persistent: true,\n },\n })\n } catch {\n // Nuxt DevTools (and thus @nuxt/devtools-kit) isn't installed\n // in this consumer — silently skip. The library still works;\n // only the overlay tab is missing.\n }\n })\n }\n },\n})\n"],"names":["createRequire","pathToFileURL","join","defineNuxtModule","addVitePlugin","attaformVitePlugin","createResolver","addImports","addPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"nuxt.cjs","sources":["../src/nuxt.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { addImports, addPlugin, addVitePlugin, createResolver, defineNuxtModule } from '@nuxt/kit'\nimport { attaformAutoImports } from './runtime/auto-imports'\nimport type { AttaformDefaults } from './runtime/types/types-api'\nimport { attaform as attaformVitePlugin } from './vite'\n\n// Read the published version from the package's own package.json so the\n// module's DevTools panel surfaces the live version pill without a\n// build-time string injection. `createRequire` reads sync at module load —\n// run once, free at steady state. Works under unbuild's Rollup output\n// without bundler-specific JSON-import handling.\nconst pkgVersion = (createRequire(import.meta.url)('../package.json') as { version: string })\n .version\n\n/**\n * Options accepted by `attaform/nuxt` under the `attaform`\n * config key.\n *\n * ```ts\n * // nuxt.config.ts\n * export default defineNuxtConfig({\n * modules: ['attaform/nuxt'],\n * attaform: {\n * defaults: { debounceMs: 100 },\n * },\n * })\n * ```\n */\nexport interface AttaformModuleOptions {\n /**\n * App-level defaults applied to every `useForm` call. Per-form\n * options always win. See `AttaformDefaults` for the\n * supported option set and merge rules.\n */\n defaults?: AttaformDefaults\n /**\n * Forwarded to `attaform/vite`'s `resolveZodAlias` option.\n * Default `true` — `attaform` and `attaform/zod` imports are rewritten\n * at build time to either `attaform/zod-v3` or `attaform/zod-v4`, based\n * on the consumer's installed Zod major. Set to `false` to bypass\n * the rewrite and ship the runtime-dispatch unified entry instead.\n */\n resolveZodAlias?: boolean\n /**\n * Auto-import Attaform's form composables (`useForm`, `useWizard`,\n * `injectForm`, `injectWizard`, `fieldMeta`, `withMeta`, `lazy`) so\n * components can call them without an explicit `import`. Default\n * `true`. The set is declared in Attaform's auto-import manifest and\n * resolves from `attaform/zod`, so the build-time adapter rewrite\n * still ships a single Zod major. Set to `false` to suppress the\n * names entirely and import the composables yourself. Note a Nuxt\n * auto-import already loses to an explicit or local binding of the\n * same name, so opting out is only needed to keep the names out of\n * global scope altogether.\n */\n autoImports?: boolean\n}\n\n/**\n * Shape of the Nuxt public runtime-config slot the module populates.\n * Reach it via `useRuntimeConfig().public.attaform` if you need to\n * read the configured defaults outside the form library itself.\n */\nexport type AttaformRuntimeConfig = {\n defaults: AttaformDefaults\n /**\n * Library version, read from the package's own `package.json` at\n * module setup. Surfaced to the runtime plugin so the DevTools\n * overlay panel can render a version pill — single source of truth\n * matches the `meta.version` Nuxt DevTools sees in the Modules panel.\n */\n version: string\n}\n\n/**\n * Whether `specifier` is resolvable using ESM resolution from either the\n * consumer's project root or attaform's own module location. Returning\n * true matches what Vite's resolver would do for `optimizeDeps.include`,\n * so a true here means Vite will pre-bundle the dep without warning.\n *\n * Why two probe locations:\n * - Consumer-rootDir probe finds direct deps + their declared peers\n * (the standard pnpm strict-isolation visibility).\n * - attaform-module probe finds peers attaform itself declares —\n * specifically the optional `@vue/devtools-api`, which lands in\n * attaform's own node_modules tree (or pnpm virtual store) when\n * installed, even if the consumer never references it directly.\n *\n * Why ESM resolution (`import.meta.resolve`) rather than CJS\n * (`createRequire(...).resolve`):\n * - attaform's exports map declares only `import` conditions for\n * non-`/nuxt` entries. CJS resolve hits ERR_PACKAGE_PATH_NOT_EXPORTED\n * for `attaform` and its sub-entries.\n * - pnpm strict isolation hides hoisted transitives behind the\n * virtual store. CJS resolve walks the bare node_modules chain and\n * misses them; ESM resolve follows pnpm's symlinks correctly.\n * - `import.meta.resolve(spec, parentURL)` is sync and stable in\n * Node 20.6+, which attaform already requires (engines.node).\n */\nfunction isResolvableForVite(specifier: string, consumerRootDir: string): boolean {\n const consumerURL = pathToFileURL(join(consumerRootDir, 'package.json')).href\n return canResolve(specifier, consumerURL) || canResolve(specifier, import.meta.url)\n}\n\nfunction canResolve(specifier: string, fromURL: string): boolean {\n try {\n import.meta.resolve(specifier, fromURL)\n return true\n } catch {\n return false\n }\n}\n\nexport default defineNuxtModule<AttaformModuleOptions>({\n meta: {\n name: 'Attaform',\n configKey: 'attaform',\n version: pkgVersion,\n docs: 'https://attaform.dev/docs',\n compatibility: {\n nuxt: '>=3.0.0',\n },\n },\n defaults: {},\n setup(_options, nuxt) {\n // Register `attaform/vite` so the same plugin handles every Vite-\n // surface concern: pushing the compile-time node transforms into\n // `@vitejs/plugin-vue`'s `api.options.template.compilerOptions.\n // nodeTransforms`, AND rewriting `attaform/zod` imports at build\n // time to either `/zod-v3` or `/zod-v4` based on the consumer's\n // installed Zod major. Consolidating both behaviors in one Vite\n // plugin instance keeps the Nuxt-side wiring minimal and ensures\n // the consumer's Nuxt build sees the exact same DX as a bare-Vite\n // consumer.\n addVitePlugin(attaformVitePlugin({ resolveZodAlias: _options.resolveZodAlias !== false }))\n\n // Publish module options to public runtime config so the plugin can\n // read them at install time on both server and client. Frozen-empty\n // by default — the plugin's merge code reads this slot directly\n // without a `?? {}` guard at every call site.\n const runtimePublic = nuxt.options.runtimeConfig.public as Record<string, unknown>\n runtimePublic['attaform'] = {\n defaults: _options.defaults ?? {},\n version: pkgVersion,\n } satisfies AttaformRuntimeConfig\n\n // Force-include attaform's own peers that Vite's startup crawl\n // tends to miss for Nuxt projects. Vite scans `index.html` + the\n // statically-known entry points but doesn't deeply follow into\n // pages that get loaded via Nuxt's dynamic router; deps imported\n // exclusively from page chunks are discovered when the page first\n // requests, the optimizer rebundles, and Vite silently broadcasts\n // `{\"type\":\"full-reload\",\"path\":\"*\"}` over the HMR WebSocket — what\n // consumers see as \"the page loads, then reloads itself a second\n // later.\" Vite's own \"discovered new dependencies at runtime\"\n // warning recommends exactly this remediation.\n //\n // We declare here only deps attaform itself owns the relationship\n // with — `@vue/devtools-api` (attaform's DevTools integration\n // peer) and `zod` (the adapter peer for `/zod`, `/zod-v3`, and\n // `/zod-v4`). Consumer-\n // side deps (vue-query, immer, etc.) are the consumer's\n // responsibility — they declare them in their own\n // `vite.optimizeDeps.include`. Each push is gated on the spec\n // being resolvable from the consumer's project (or attaform's\n // own module context for attaform's optional peers like\n // devtools-api), so consumers without the optional peer don't see\n // a \"failed to resolve\" warning at boot.\n nuxt.options.vite.optimizeDeps ??= {}\n nuxt.options.vite.optimizeDeps.include ??= []\n const include = nuxt.options.vite.optimizeDeps.include\n for (const spec of ['@vue/devtools-api', 'zod']) {\n if (!isResolvableForVite(spec, nuxt.options.rootDir)) continue\n if (!include.includes(spec)) include.push(spec)\n }\n\n const resolver = createResolver(import.meta.url)\n\n // Auto-import the Zod-default form composables so a component can\n // reach for `useForm` / `useWizard` / `injectForm` / `injectWizard` /\n // `fieldMeta` / `withMeta` / `lazy` with no import line. The manifest\n // in `./runtime/auto-imports` is the single source of truth, shared\n // with the `attaform/vite` preset re-export.\n //\n // Each entry resolves from `attaform/zod`, not the bare `attaform`\n // barrel: the Vite/bundler plugin rewrites the exact `attaform/zod`\n // specifier to the one installed Zod major at build time, so a Nuxt\n // consumer's bundle ships a single adapter instead of the runtime\n // dispatcher. After the schema-entry re-partition the two surfaces\n // are byte-identical (`attaform` re-exports exactly what\n // `attaform/zod` does), so pointing at `/zod` costs nothing and buys\n // the lean bundle for free. Resolving a public subpath rather than a\n // relative `./runtime/…` path also keeps the published package honest\n // — `attaform/zod` maps to a real `dist/zod.mjs`, so Nuxt's\n // auto-import step never chases a source path with no built artifact.\n //\n // A Nuxt auto-import always loses to an explicit or local binding, so\n // registering these never shadows a consumer's own `useForm`. The\n // `autoImports: false` option suppresses the whole set for consumers\n // who prefer explicit imports everywhere.\n if (_options.autoImports !== false) {\n addImports(attaformAutoImports)\n }\n\n // Plugin that installs `createAttaform()` on the Vue app and\n // wires the payload serialize/hydrate bridge. Uses a physical\n // `src/runtime/plugins/attaform.ts` file (shipped to\n // `dist/runtime/plugins/attaform.mjs` via an explicit entry in\n // build.config.ts) rather than an inline plugin template, because a\n // template's `import { createAttaform } from 'attaform'`\n // resolves through the `attaform` package entry — which in\n // local dev (`unbuild --stub`) is a jiti runtime transpiler whose\n // `node:module`/`createRequire` imports Nitro's Rollup build cannot\n // bundle. A physical file lets Nitro follow its imports directly\n // (TS source in dev, ESM in the published package), avoiding the\n // jiti indirection entirely. Unbuild's shared-chunk splitter keeps\n // `core/plugin` + `core/serialize` deduplicated with `src/zod` /\n // `src/index`, so there's still only one `registry` module at runtime.\n //\n // `addPlugin` defaults to PREPEND so the plugin runs before any\n // user plugin / page; `enforce: 'pre'` inside the plugin body makes\n // that ordering explicit at the Nuxt-plugin layer too. Together\n // they guarantee the registry is installed (and SSR payload staged\n // into `pendingHydration`) before any `useForm` call runs.\n addPlugin({\n src: resolver.resolve('./runtime/plugins/attaform'),\n })\n\n // Dev-only: register a Nuxt DevTools overlay tab pointing at an\n // iframe that mounts the Attaform inspector. The iframe URL\n // (`/_attaform_devtools`) is served by a Vite-layer middleware\n // wired up in `attaform/vite` — by intercepting at the Vite layer\n // rather than via `extendPages`, the route stays invisible to\n // vue-router and works regardless of whether the consumer uses\n // a `pages/` directory or `app.vue`-only mode.\n //\n // `@nuxt/devtools-kit` is NOT a transitive peer of `@nuxt/kit`; it\n // ships alongside `@nuxt/devtools`. Consumers who don't install\n // Nuxt DevTools (rare in real Nuxt projects, common in test\n // fixtures) get a silent no-op instead of an \"unresolved import\"\n // error. Mirrors the same try/import pattern used for\n // `@vue/devtools-api` in the runtime devtools wire-up.\n if (nuxt.options.dev) {\n nuxt.hook('ready', async () => {\n try {\n const { addCustomTab } = await import('@nuxt/devtools-kit')\n addCustomTab({\n name: 'attaform',\n title: 'Attaform',\n // Brand mark — purple square with a white \"A\" silhouette,\n // matching `apps/site/public/favicon.svg`. Served by the\n // `attaform/vite` middleware at the same `/_attaform_devtools`\n // route family (sibling to the panel HTML). A real URL\n // renders reliably across Nuxt DevTools versions where\n // `data:` URIs don't.\n icon: '/_attaform_devtools/icon.svg',\n view: {\n type: 'iframe',\n src: '/_attaform_devtools',\n persistent: true,\n },\n })\n } catch {\n // Nuxt DevTools (and thus @nuxt/devtools-kit) isn't installed\n // in this consumer — silently skip. The library still works;\n // only the overlay tab is missing.\n }\n })\n }\n },\n})\n"],"names":["createRequire","pathToFileURL","join","defineNuxtModule","addVitePlugin","attaformVitePlugin","createResolver","addImports","attaformAutoImports","addPlugin"],"mappings":";;;;;;;;;AAaA,MAAM,aAAcA,yBAAA,CAAc,0PAAe,CAAA,CAAE,iBAAiB,CAAA,CACjE,OAAA;AAuFH,SAAS,mBAAA,CAAoB,WAAmB,eAAA,EAAkC;AAChF,EAAA,MAAM,cAAcC,sBAAA,CAAcC,cAAA,CAAK,eAAA,EAAiB,cAAc,CAAC,CAAA,CAAE,IAAA;AACzE,EAAA,OAAO,WAAW,SAAA,EAAW,WAAW,KAAK,UAAA,CAAW,SAAA,EAAW,0PAAe,CAAA;AACpF;AAEA,SAAS,UAAA,CAAW,WAAmB,OAAA,EAA0B;AAC/D,EAAA,IAAI;AACF,IAAA,SAAY,CAAQ,WAAW,OAAO,CAAA;AACtC,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,IAAO,eAAQC,oBAAA,CAAwC;AAAA,EACrD,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,UAAA;AAAA,IACN,SAAA,EAAW,UAAA;AAAA,IACX,OAAA,EAAS,UAAA;AAAA,IACT,IAAA,EAAM,2BAAA;AAAA,IACN,aAAA,EAAe;AAAA,MACb,IAAA,EAAM;AAAA;AACR,GACF;AAAA,EACA,UAAU,EAAC;AAAA,EACX,KAAA,CAAM,UAAU,IAAA,EAAM;AA9HxB,IAAA,IAAA,EAAA,EAAA,EAAA;AAwII,IAAAC,iBAAA,CAAcC,cAAmB,EAAE,eAAA,EAAiB,SAAS,eAAA,KAAoB,KAAA,EAAO,CAAC,CAAA;AAMzF,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,MAAA;AACjD,IAAA,aAAA,CAAc,UAAU,CAAA,GAAI;AAAA,MAC1B,QAAA,EAAU,QAAA,CAAS,QAAA,IAAY,EAAC;AAAA,MAChC,OAAA,EAAS;AAAA,KACX;AAwBA,IAAA,CAAA,EAAA,GAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAK,YAAA,KAAlB,EAAA,CAAkB,eAAiB,EAAC,CAAA;AACpC,IAAA,CAAA,EAAA,GAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,YAAA,EAAa,OAAA,KAA/B,EAAA,CAA+B,UAAY,EAAC,CAAA;AAC5C,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,YAAA,CAAa,OAAA;AAC/C,IAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,mBAAA,EAAqB,KAAK,CAAA,EAAG;AAC/C,MAAA,IAAI,CAAC,mBAAA,CAAoB,IAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA,EAAG;AACtD,MAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA,EAAG,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,QAAA,GAAWC,kBAAA,CAAe,0PAAe,CAAA;AAwB/C,IAAA,IAAI,QAAA,CAAS,gBAAgB,KAAA,EAAO;AAClC,MAAAC,cAAA,CAAWC,wBAAmB,CAAA;AAAA,IAChC;AAsBA,IAAAC,aAAA,CAAU;AAAA,MACR,GAAA,EAAK,QAAA,CAAS,OAAA,CAAQ,4BAA4B;AAAA,KACnD,CAAA;AAgBD,IAAA,IAAI,IAAA,CAAK,QAAQ,GAAA,EAAK;AACpB,MAAA,IAAA,CAAK,IAAA,CAAK,SAAS,YAAY;AAC7B,QAAA,IAAI;AACF,UAAA,MAAM,EAAE,YAAA,EAAa,GAAI,MAAM,OAAO,oBAAoB,CAAA;AAC1D,UAAA,YAAA,CAAa;AAAA,YACX,IAAA,EAAM,UAAA;AAAA,YACN,KAAA,EAAO,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAOP,IAAA,EAAM,8BAAA;AAAA,YACN,IAAA,EAAM;AAAA,cACJ,IAAA,EAAM,QAAA;AAAA,cACN,GAAA,EAAK,qBAAA;AAAA,cACL,UAAA,EAAY;AAAA;AACd,WACD,CAAA;AAAA,QACH,CAAA,CAAA,MAAQ;AAAA,QAIR;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AACF,CAAC;;;;"}
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.i_LA3X9o.cjs';
2
+ import { d as AttaformDefaults } from './shared/attaform.C3WnCDXz.cjs';
3
3
  import 'vue';
4
4
 
5
5
  /**
@@ -25,12 +25,25 @@ interface AttaformModuleOptions {
25
25
  defaults?: AttaformDefaults;
26
26
  /**
27
27
  * Forwarded to `attaform/vite`'s `resolveZodAlias` option.
28
- * Default `true` — `attaform/zod` imports are rewritten at build
29
- * time to either `attaform/zod-v3` or `attaform/zod-v4`, based on
30
- * the consumer's installed Zod major. Set to `false` to bypass
28
+ * Default `true` — `attaform` and `attaform/zod` imports are rewritten
29
+ * at build time to either `attaform/zod-v3` or `attaform/zod-v4`, based
30
+ * on the consumer's installed Zod major. Set to `false` to bypass
31
31
  * the rewrite and ship the runtime-dispatch unified entry instead.
32
32
  */
33
33
  resolveZodAlias?: boolean;
34
+ /**
35
+ * Auto-import Attaform's form composables (`useForm`, `useWizard`,
36
+ * `injectForm`, `injectWizard`, `fieldMeta`, `withMeta`, `lazy`) so
37
+ * components can call them without an explicit `import`. Default
38
+ * `true`. The set is declared in Attaform's auto-import manifest and
39
+ * resolves from `attaform/zod`, so the build-time adapter rewrite
40
+ * still ships a single Zod major. Set to `false` to suppress the
41
+ * names entirely and import the composables yourself. Note a Nuxt
42
+ * auto-import already loses to an explicit or local binding of the
43
+ * same name, so opting out is only needed to keep the names out of
44
+ * global scope altogether.
45
+ */
46
+ autoImports?: boolean;
34
47
  }
35
48
  /**
36
49
  * Shape of the Nuxt public runtime-config slot the module populates.
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.i_LA3X9o.mjs';
2
+ import { d as AttaformDefaults } from './shared/attaform.C3WnCDXz.mjs';
3
3
  import 'vue';
4
4
 
5
5
  /**
@@ -25,12 +25,25 @@ interface AttaformModuleOptions {
25
25
  defaults?: AttaformDefaults;
26
26
  /**
27
27
  * Forwarded to `attaform/vite`'s `resolveZodAlias` option.
28
- * Default `true` — `attaform/zod` imports are rewritten at build
29
- * time to either `attaform/zod-v3` or `attaform/zod-v4`, based on
30
- * the consumer's installed Zod major. Set to `false` to bypass
28
+ * Default `true` — `attaform` and `attaform/zod` imports are rewritten
29
+ * at build time to either `attaform/zod-v3` or `attaform/zod-v4`, based
30
+ * on the consumer's installed Zod major. Set to `false` to bypass
31
31
  * the rewrite and ship the runtime-dispatch unified entry instead.
32
32
  */
33
33
  resolveZodAlias?: boolean;
34
+ /**
35
+ * Auto-import Attaform's form composables (`useForm`, `useWizard`,
36
+ * `injectForm`, `injectWizard`, `fieldMeta`, `withMeta`, `lazy`) so
37
+ * components can call them without an explicit `import`. Default
38
+ * `true`. The set is declared in Attaform's auto-import manifest and
39
+ * resolves from `attaform/zod`, so the build-time adapter rewrite
40
+ * still ships a single Zod major. Set to `false` to suppress the
41
+ * names entirely and import the composables yourself. Note a Nuxt
42
+ * auto-import already loses to an explicit or local binding of the
43
+ * same name, so opting out is only needed to keep the names out of
44
+ * global scope altogether.
45
+ */
46
+ autoImports?: boolean;
34
47
  }
35
48
  /**
36
49
  * Shape of the Nuxt public runtime-config slot the module populates.
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.i_LA3X9o.js';
2
+ import { d as AttaformDefaults } from './shared/attaform.C3WnCDXz.js';
3
3
  import 'vue';
4
4
 
5
5
  /**
@@ -25,12 +25,25 @@ interface AttaformModuleOptions {
25
25
  defaults?: AttaformDefaults;
26
26
  /**
27
27
  * Forwarded to `attaform/vite`'s `resolveZodAlias` option.
28
- * Default `true` — `attaform/zod` imports are rewritten at build
29
- * time to either `attaform/zod-v3` or `attaform/zod-v4`, based on
30
- * the consumer's installed Zod major. Set to `false` to bypass
28
+ * Default `true` — `attaform` and `attaform/zod` imports are rewritten
29
+ * at build time to either `attaform/zod-v3` or `attaform/zod-v4`, based
30
+ * on the consumer's installed Zod major. Set to `false` to bypass
31
31
  * the rewrite and ship the runtime-dispatch unified entry instead.
32
32
  */
33
33
  resolveZodAlias?: boolean;
34
+ /**
35
+ * Auto-import Attaform's form composables (`useForm`, `useWizard`,
36
+ * `injectForm`, `injectWizard`, `fieldMeta`, `withMeta`, `lazy`) so
37
+ * components can call them without an explicit `import`. Default
38
+ * `true`. The set is declared in Attaform's auto-import manifest and
39
+ * resolves from `attaform/zod`, so the build-time adapter rewrite
40
+ * still ships a single Zod major. Set to `false` to suppress the
41
+ * names entirely and import the composables yourself. Note a Nuxt
42
+ * auto-import already loses to an explicit or local binding of the
43
+ * same name, so opting out is only needed to keep the names out of
44
+ * global scope altogether.
45
+ */
46
+ autoImports?: boolean;
34
47
  }
35
48
  /**
36
49
  * Shape of the Nuxt public runtime-config slot the module populates.
package/dist/nuxt.mjs CHANGED
@@ -2,7 +2,7 @@ import { createRequire } from 'node:module';
2
2
  import { join } from 'node:path';
3
3
  import { pathToFileURL } from 'node:url';
4
4
  import { defineNuxtModule, addVitePlugin, createResolver, addImports, addPlugin } from '@nuxt/kit';
5
- import { attaform } from './vite.mjs';
5
+ import { attaform, attaformAutoImports } from './vite.mjs';
6
6
 
7
7
  const pkgVersion = createRequire(import.meta.url)("../package.json").version;
8
8
  function isResolvableForVite(specifier, consumerRootDir) {
@@ -44,7 +44,9 @@ var nuxt_default = defineNuxtModule({
44
44
  if (!include.includes(spec)) include.push(spec);
45
45
  }
46
46
  const resolver = createResolver(import.meta.url);
47
- addImports([{ name: "useForm", from: "attaform" }]);
47
+ if (_options.autoImports !== false) {
48
+ addImports(attaformAutoImports);
49
+ }
48
50
  addPlugin({
49
51
  src: resolver.resolve("./runtime/plugins/attaform")
50
52
  });
package/dist/nuxt.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"nuxt.mjs","sources":["../src/nuxt.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { addImports, addPlugin, addVitePlugin, createResolver, defineNuxtModule } from '@nuxt/kit'\nimport type { AttaformDefaults } from './runtime/types/types-api'\nimport { attaform as attaformVitePlugin } from './vite'\n\n// Read the published version from the package's own package.json so the\n// module's DevTools panel surfaces the live version pill without a\n// build-time string injection. `createRequire` reads sync at module load —\n// run once, free at steady state. Works under unbuild's Rollup output\n// without bundler-specific JSON-import handling.\nconst pkgVersion = (createRequire(import.meta.url)('../package.json') as { version: string })\n .version\n\n/**\n * Options accepted by `attaform/nuxt` under the `attaform`\n * config key.\n *\n * ```ts\n * // nuxt.config.ts\n * export default defineNuxtConfig({\n * modules: ['attaform/nuxt'],\n * attaform: {\n * defaults: { debounceMs: 100 },\n * },\n * })\n * ```\n */\nexport interface AttaformModuleOptions {\n /**\n * App-level defaults applied to every `useForm` call. Per-form\n * options always win. See `AttaformDefaults` for the\n * supported option set and merge rules.\n */\n defaults?: AttaformDefaults\n /**\n * Forwarded to `attaform/vite`'s `resolveZodAlias` option.\n * Default `true` — `attaform/zod` imports are rewritten at build\n * time to either `attaform/zod-v3` or `attaform/zod-v4`, based on\n * the consumer's installed Zod major. Set to `false` to bypass\n * the rewrite and ship the runtime-dispatch unified entry instead.\n */\n resolveZodAlias?: boolean\n}\n\n/**\n * Shape of the Nuxt public runtime-config slot the module populates.\n * Reach it via `useRuntimeConfig().public.attaform` if you need to\n * read the configured defaults outside the form library itself.\n */\nexport type AttaformRuntimeConfig = {\n defaults: AttaformDefaults\n /**\n * Library version, read from the package's own `package.json` at\n * module setup. Surfaced to the runtime plugin so the DevTools\n * overlay panel can render a version pill — single source of truth\n * matches the `meta.version` Nuxt DevTools sees in the Modules panel.\n */\n version: string\n}\n\n/**\n * Whether `specifier` is resolvable using ESM resolution from either the\n * consumer's project root or attaform's own module location. Returning\n * true matches what Vite's resolver would do for `optimizeDeps.include`,\n * so a true here means Vite will pre-bundle the dep without warning.\n *\n * Why two probe locations:\n * - Consumer-rootDir probe finds direct deps + their declared peers\n * (the standard pnpm strict-isolation visibility).\n * - attaform-module probe finds peers attaform itself declares —\n * specifically the optional `@vue/devtools-api`, which lands in\n * attaform's own node_modules tree (or pnpm virtual store) when\n * installed, even if the consumer never references it directly.\n *\n * Why ESM resolution (`import.meta.resolve`) rather than CJS\n * (`createRequire(...).resolve`):\n * - attaform's exports map declares only `import` conditions for\n * non-`/nuxt` entries. CJS resolve hits ERR_PACKAGE_PATH_NOT_EXPORTED\n * for `attaform` and its sub-entries.\n * - pnpm strict isolation hides hoisted transitives behind the\n * virtual store. CJS resolve walks the bare node_modules chain and\n * misses them; ESM resolve follows pnpm's symlinks correctly.\n * - `import.meta.resolve(spec, parentURL)` is sync and stable in\n * Node 20.6+, which attaform already requires (engines.node).\n */\nfunction isResolvableForVite(specifier: string, consumerRootDir: string): boolean {\n const consumerURL = pathToFileURL(join(consumerRootDir, 'package.json')).href\n return canResolve(specifier, consumerURL) || canResolve(specifier, import.meta.url)\n}\n\nfunction canResolve(specifier: string, fromURL: string): boolean {\n try {\n import.meta.resolve(specifier, fromURL)\n return true\n } catch {\n return false\n }\n}\n\nexport default defineNuxtModule<AttaformModuleOptions>({\n meta: {\n name: 'Attaform',\n configKey: 'attaform',\n version: pkgVersion,\n docs: 'https://attaform.dev/docs',\n compatibility: {\n nuxt: '>=3.0.0',\n },\n },\n defaults: {},\n setup(_options, nuxt) {\n // Register `attaform/vite` so the same plugin handles every Vite-\n // surface concern: pushing the compile-time node transforms into\n // `@vitejs/plugin-vue`'s `api.options.template.compilerOptions.\n // nodeTransforms`, AND rewriting `attaform/zod` imports at build\n // time to either `/zod-v3` or `/zod-v4` based on the consumer's\n // installed Zod major. Consolidating both behaviors in one Vite\n // plugin instance keeps the Nuxt-side wiring minimal and ensures\n // the consumer's Nuxt build sees the exact same DX as a bare-Vite\n // consumer.\n addVitePlugin(attaformVitePlugin({ resolveZodAlias: _options.resolveZodAlias !== false }))\n\n // Publish module options to public runtime config so the plugin can\n // read them at install time on both server and client. Frozen-empty\n // by default — the plugin's merge code reads this slot directly\n // without a `?? {}` guard at every call site.\n const runtimePublic = nuxt.options.runtimeConfig.public as Record<string, unknown>\n runtimePublic['attaform'] = {\n defaults: _options.defaults ?? {},\n version: pkgVersion,\n } satisfies AttaformRuntimeConfig\n\n // Force-include attaform's own peers that Vite's startup crawl\n // tends to miss for Nuxt projects. Vite scans `index.html` + the\n // statically-known entry points but doesn't deeply follow into\n // pages that get loaded via Nuxt's dynamic router; deps imported\n // exclusively from page chunks are discovered when the page first\n // requests, the optimizer rebundles, and Vite silently broadcasts\n // `{\"type\":\"full-reload\",\"path\":\"*\"}` over the HMR WebSocket — what\n // consumers see as \"the page loads, then reloads itself a second\n // later.\" Vite's own \"discovered new dependencies at runtime\"\n // warning recommends exactly this remediation.\n //\n // We declare here only deps attaform itself owns the relationship\n // with — `@vue/devtools-api` (attaform's DevTools integration\n // peer) and `zod` (the adapter peer for `/zod`, `/zod-v3`, and\n // `/zod-v4`). Consumer-\n // side deps (vue-query, immer, etc.) are the consumer's\n // responsibility — they declare them in their own\n // `vite.optimizeDeps.include`. Each push is gated on the spec\n // being resolvable from the consumer's project (or attaform's\n // own module context for attaform's optional peers like\n // devtools-api), so consumers without the optional peer don't see\n // a \"failed to resolve\" warning at boot.\n nuxt.options.vite.optimizeDeps ??= {}\n nuxt.options.vite.optimizeDeps.include ??= []\n const include = nuxt.options.vite.optimizeDeps.include\n for (const spec of ['@vue/devtools-api', 'zod']) {\n if (!isResolvableForVite(spec, nuxt.options.rootDir)) continue\n if (!include.includes(spec)) include.push(spec)\n }\n\n const resolver = createResolver(import.meta.url)\n\n // Auto-import `useForm` — the framework-agnostic core composable (same\n // binding as `attaform`'s top-level `useForm` export, which\n // is the abstract form composable). Consumers who want the zod-typed\n // wrapper must import from `attaform/zod` or `/zod-v3`\n // explicitly.\n //\n // We point at the public package entry rather than a relative\n // `./runtime/…` path on purpose: in the published package the\n // `src/runtime/composables/use-abstract-form` path has no matching\n // `dist/runtime/…` file (build.config's entries don't include it),\n // so a `resolver.resolve(...)` would raise ENOENT at Nuxt's auto-\n // import step. Importing from `attaform` resolves through\n // the shared chunk, identical to what `attaform/zod`\n // consumers bundle — single registry instance across both import\n // surfaces.\n addImports([{ name: 'useForm', from: 'attaform' }])\n\n // Plugin that installs `createAttaform()` on the Vue app and\n // wires the payload serialize/hydrate bridge. Uses a physical\n // `src/runtime/plugins/attaform.ts` file (shipped to\n // `dist/runtime/plugins/attaform.mjs` via an explicit entry in\n // build.config.ts) rather than an inline plugin template, because a\n // template's `import { createAttaform } from 'attaform'`\n // resolves through the `attaform` package entry — which in\n // local dev (`unbuild --stub`) is a jiti runtime transpiler whose\n // `node:module`/`createRequire` imports Nitro's Rollup build cannot\n // bundle. A physical file lets Nitro follow its imports directly\n // (TS source in dev, ESM in the published package), avoiding the\n // jiti indirection entirely. Unbuild's shared-chunk splitter keeps\n // `core/plugin` + `core/serialize` deduplicated with `src/zod` /\n // `src/index`, so there's still only one `registry` module at runtime.\n //\n // `addPlugin` defaults to PREPEND so the plugin runs before any\n // user plugin / page; `enforce: 'pre'` inside the plugin body makes\n // that ordering explicit at the Nuxt-plugin layer too. Together\n // they guarantee the registry is installed (and SSR payload staged\n // into `pendingHydration`) before any `useForm` call runs.\n addPlugin({\n src: resolver.resolve('./runtime/plugins/attaform'),\n })\n\n // Dev-only: register a Nuxt DevTools overlay tab pointing at an\n // iframe that mounts the Attaform inspector. The iframe URL\n // (`/_attaform_devtools`) is served by a Vite-layer middleware\n // wired up in `attaform/vite` — by intercepting at the Vite layer\n // rather than via `extendPages`, the route stays invisible to\n // vue-router and works regardless of whether the consumer uses\n // a `pages/` directory or `app.vue`-only mode.\n //\n // `@nuxt/devtools-kit` is NOT a transitive peer of `@nuxt/kit`; it\n // ships alongside `@nuxt/devtools`. Consumers who don't install\n // Nuxt DevTools (rare in real Nuxt projects, common in test\n // fixtures) get a silent no-op instead of an \"unresolved import\"\n // error. Mirrors the same try/import pattern used for\n // `@vue/devtools-api` in the runtime devtools wire-up.\n if (nuxt.options.dev) {\n nuxt.hook('ready', async () => {\n try {\n const { addCustomTab } = await import('@nuxt/devtools-kit')\n addCustomTab({\n name: 'attaform',\n title: 'Attaform',\n // Brand mark — purple square with a white \"A\" silhouette,\n // matching `apps/site/public/favicon.svg`. Served by the\n // `attaform/vite` middleware at the same `/_attaform_devtools`\n // route family (sibling to the panel HTML). A real URL\n // renders reliably across Nuxt DevTools versions where\n // `data:` URIs don't.\n icon: '/_attaform_devtools/icon.svg',\n view: {\n type: 'iframe',\n src: '/_attaform_devtools',\n persistent: true,\n },\n })\n } catch {\n // Nuxt DevTools (and thus @nuxt/devtools-kit) isn't installed\n // in this consumer — silently skip. The library still works;\n // only the overlay tab is missing.\n }\n })\n }\n },\n})\n"],"names":["attaformVitePlugin"],"mappings":"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"}
1
+ {"version":3,"file":"nuxt.mjs","sources":["../src/nuxt.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { addImports, addPlugin, addVitePlugin, createResolver, defineNuxtModule } from '@nuxt/kit'\nimport { attaformAutoImports } from './runtime/auto-imports'\nimport type { AttaformDefaults } from './runtime/types/types-api'\nimport { attaform as attaformVitePlugin } from './vite'\n\n// Read the published version from the package's own package.json so the\n// module's DevTools panel surfaces the live version pill without a\n// build-time string injection. `createRequire` reads sync at module load —\n// run once, free at steady state. Works under unbuild's Rollup output\n// without bundler-specific JSON-import handling.\nconst pkgVersion = (createRequire(import.meta.url)('../package.json') as { version: string })\n .version\n\n/**\n * Options accepted by `attaform/nuxt` under the `attaform`\n * config key.\n *\n * ```ts\n * // nuxt.config.ts\n * export default defineNuxtConfig({\n * modules: ['attaform/nuxt'],\n * attaform: {\n * defaults: { debounceMs: 100 },\n * },\n * })\n * ```\n */\nexport interface AttaformModuleOptions {\n /**\n * App-level defaults applied to every `useForm` call. Per-form\n * options always win. See `AttaformDefaults` for the\n * supported option set and merge rules.\n */\n defaults?: AttaformDefaults\n /**\n * Forwarded to `attaform/vite`'s `resolveZodAlias` option.\n * Default `true` — `attaform` and `attaform/zod` imports are rewritten\n * at build time to either `attaform/zod-v3` or `attaform/zod-v4`, based\n * on the consumer's installed Zod major. Set to `false` to bypass\n * the rewrite and ship the runtime-dispatch unified entry instead.\n */\n resolveZodAlias?: boolean\n /**\n * Auto-import Attaform's form composables (`useForm`, `useWizard`,\n * `injectForm`, `injectWizard`, `fieldMeta`, `withMeta`, `lazy`) so\n * components can call them without an explicit `import`. Default\n * `true`. The set is declared in Attaform's auto-import manifest and\n * resolves from `attaform/zod`, so the build-time adapter rewrite\n * still ships a single Zod major. Set to `false` to suppress the\n * names entirely and import the composables yourself. Note a Nuxt\n * auto-import already loses to an explicit or local binding of the\n * same name, so opting out is only needed to keep the names out of\n * global scope altogether.\n */\n autoImports?: boolean\n}\n\n/**\n * Shape of the Nuxt public runtime-config slot the module populates.\n * Reach it via `useRuntimeConfig().public.attaform` if you need to\n * read the configured defaults outside the form library itself.\n */\nexport type AttaformRuntimeConfig = {\n defaults: AttaformDefaults\n /**\n * Library version, read from the package's own `package.json` at\n * module setup. Surfaced to the runtime plugin so the DevTools\n * overlay panel can render a version pill — single source of truth\n * matches the `meta.version` Nuxt DevTools sees in the Modules panel.\n */\n version: string\n}\n\n/**\n * Whether `specifier` is resolvable using ESM resolution from either the\n * consumer's project root or attaform's own module location. Returning\n * true matches what Vite's resolver would do for `optimizeDeps.include`,\n * so a true here means Vite will pre-bundle the dep without warning.\n *\n * Why two probe locations:\n * - Consumer-rootDir probe finds direct deps + their declared peers\n * (the standard pnpm strict-isolation visibility).\n * - attaform-module probe finds peers attaform itself declares —\n * specifically the optional `@vue/devtools-api`, which lands in\n * attaform's own node_modules tree (or pnpm virtual store) when\n * installed, even if the consumer never references it directly.\n *\n * Why ESM resolution (`import.meta.resolve`) rather than CJS\n * (`createRequire(...).resolve`):\n * - attaform's exports map declares only `import` conditions for\n * non-`/nuxt` entries. CJS resolve hits ERR_PACKAGE_PATH_NOT_EXPORTED\n * for `attaform` and its sub-entries.\n * - pnpm strict isolation hides hoisted transitives behind the\n * virtual store. CJS resolve walks the bare node_modules chain and\n * misses them; ESM resolve follows pnpm's symlinks correctly.\n * - `import.meta.resolve(spec, parentURL)` is sync and stable in\n * Node 20.6+, which attaform already requires (engines.node).\n */\nfunction isResolvableForVite(specifier: string, consumerRootDir: string): boolean {\n const consumerURL = pathToFileURL(join(consumerRootDir, 'package.json')).href\n return canResolve(specifier, consumerURL) || canResolve(specifier, import.meta.url)\n}\n\nfunction canResolve(specifier: string, fromURL: string): boolean {\n try {\n import.meta.resolve(specifier, fromURL)\n return true\n } catch {\n return false\n }\n}\n\nexport default defineNuxtModule<AttaformModuleOptions>({\n meta: {\n name: 'Attaform',\n configKey: 'attaform',\n version: pkgVersion,\n docs: 'https://attaform.dev/docs',\n compatibility: {\n nuxt: '>=3.0.0',\n },\n },\n defaults: {},\n setup(_options, nuxt) {\n // Register `attaform/vite` so the same plugin handles every Vite-\n // surface concern: pushing the compile-time node transforms into\n // `@vitejs/plugin-vue`'s `api.options.template.compilerOptions.\n // nodeTransforms`, AND rewriting `attaform/zod` imports at build\n // time to either `/zod-v3` or `/zod-v4` based on the consumer's\n // installed Zod major. Consolidating both behaviors in one Vite\n // plugin instance keeps the Nuxt-side wiring minimal and ensures\n // the consumer's Nuxt build sees the exact same DX as a bare-Vite\n // consumer.\n addVitePlugin(attaformVitePlugin({ resolveZodAlias: _options.resolveZodAlias !== false }))\n\n // Publish module options to public runtime config so the plugin can\n // read them at install time on both server and client. Frozen-empty\n // by default — the plugin's merge code reads this slot directly\n // without a `?? {}` guard at every call site.\n const runtimePublic = nuxt.options.runtimeConfig.public as Record<string, unknown>\n runtimePublic['attaform'] = {\n defaults: _options.defaults ?? {},\n version: pkgVersion,\n } satisfies AttaformRuntimeConfig\n\n // Force-include attaform's own peers that Vite's startup crawl\n // tends to miss for Nuxt projects. Vite scans `index.html` + the\n // statically-known entry points but doesn't deeply follow into\n // pages that get loaded via Nuxt's dynamic router; deps imported\n // exclusively from page chunks are discovered when the page first\n // requests, the optimizer rebundles, and Vite silently broadcasts\n // `{\"type\":\"full-reload\",\"path\":\"*\"}` over the HMR WebSocket — what\n // consumers see as \"the page loads, then reloads itself a second\n // later.\" Vite's own \"discovered new dependencies at runtime\"\n // warning recommends exactly this remediation.\n //\n // We declare here only deps attaform itself owns the relationship\n // with — `@vue/devtools-api` (attaform's DevTools integration\n // peer) and `zod` (the adapter peer for `/zod`, `/zod-v3`, and\n // `/zod-v4`). Consumer-\n // side deps (vue-query, immer, etc.) are the consumer's\n // responsibility — they declare them in their own\n // `vite.optimizeDeps.include`. Each push is gated on the spec\n // being resolvable from the consumer's project (or attaform's\n // own module context for attaform's optional peers like\n // devtools-api), so consumers without the optional peer don't see\n // a \"failed to resolve\" warning at boot.\n nuxt.options.vite.optimizeDeps ??= {}\n nuxt.options.vite.optimizeDeps.include ??= []\n const include = nuxt.options.vite.optimizeDeps.include\n for (const spec of ['@vue/devtools-api', 'zod']) {\n if (!isResolvableForVite(spec, nuxt.options.rootDir)) continue\n if (!include.includes(spec)) include.push(spec)\n }\n\n const resolver = createResolver(import.meta.url)\n\n // Auto-import the Zod-default form composables so a component can\n // reach for `useForm` / `useWizard` / `injectForm` / `injectWizard` /\n // `fieldMeta` / `withMeta` / `lazy` with no import line. The manifest\n // in `./runtime/auto-imports` is the single source of truth, shared\n // with the `attaform/vite` preset re-export.\n //\n // Each entry resolves from `attaform/zod`, not the bare `attaform`\n // barrel: the Vite/bundler plugin rewrites the exact `attaform/zod`\n // specifier to the one installed Zod major at build time, so a Nuxt\n // consumer's bundle ships a single adapter instead of the runtime\n // dispatcher. After the schema-entry re-partition the two surfaces\n // are byte-identical (`attaform` re-exports exactly what\n // `attaform/zod` does), so pointing at `/zod` costs nothing and buys\n // the lean bundle for free. Resolving a public subpath rather than a\n // relative `./runtime/…` path also keeps the published package honest\n // — `attaform/zod` maps to a real `dist/zod.mjs`, so Nuxt's\n // auto-import step never chases a source path with no built artifact.\n //\n // A Nuxt auto-import always loses to an explicit or local binding, so\n // registering these never shadows a consumer's own `useForm`. The\n // `autoImports: false` option suppresses the whole set for consumers\n // who prefer explicit imports everywhere.\n if (_options.autoImports !== false) {\n addImports(attaformAutoImports)\n }\n\n // Plugin that installs `createAttaform()` on the Vue app and\n // wires the payload serialize/hydrate bridge. Uses a physical\n // `src/runtime/plugins/attaform.ts` file (shipped to\n // `dist/runtime/plugins/attaform.mjs` via an explicit entry in\n // build.config.ts) rather than an inline plugin template, because a\n // template's `import { createAttaform } from 'attaform'`\n // resolves through the `attaform` package entry — which in\n // local dev (`unbuild --stub`) is a jiti runtime transpiler whose\n // `node:module`/`createRequire` imports Nitro's Rollup build cannot\n // bundle. A physical file lets Nitro follow its imports directly\n // (TS source in dev, ESM in the published package), avoiding the\n // jiti indirection entirely. Unbuild's shared-chunk splitter keeps\n // `core/plugin` + `core/serialize` deduplicated with `src/zod` /\n // `src/index`, so there's still only one `registry` module at runtime.\n //\n // `addPlugin` defaults to PREPEND so the plugin runs before any\n // user plugin / page; `enforce: 'pre'` inside the plugin body makes\n // that ordering explicit at the Nuxt-plugin layer too. Together\n // they guarantee the registry is installed (and SSR payload staged\n // into `pendingHydration`) before any `useForm` call runs.\n addPlugin({\n src: resolver.resolve('./runtime/plugins/attaform'),\n })\n\n // Dev-only: register a Nuxt DevTools overlay tab pointing at an\n // iframe that mounts the Attaform inspector. The iframe URL\n // (`/_attaform_devtools`) is served by a Vite-layer middleware\n // wired up in `attaform/vite` — by intercepting at the Vite layer\n // rather than via `extendPages`, the route stays invisible to\n // vue-router and works regardless of whether the consumer uses\n // a `pages/` directory or `app.vue`-only mode.\n //\n // `@nuxt/devtools-kit` is NOT a transitive peer of `@nuxt/kit`; it\n // ships alongside `@nuxt/devtools`. Consumers who don't install\n // Nuxt DevTools (rare in real Nuxt projects, common in test\n // fixtures) get a silent no-op instead of an \"unresolved import\"\n // error. Mirrors the same try/import pattern used for\n // `@vue/devtools-api` in the runtime devtools wire-up.\n if (nuxt.options.dev) {\n nuxt.hook('ready', async () => {\n try {\n const { addCustomTab } = await import('@nuxt/devtools-kit')\n addCustomTab({\n name: 'attaform',\n title: 'Attaform',\n // Brand mark — purple square with a white \"A\" silhouette,\n // matching `apps/site/public/favicon.svg`. Served by the\n // `attaform/vite` middleware at the same `/_attaform_devtools`\n // route family (sibling to the panel HTML). A real URL\n // renders reliably across Nuxt DevTools versions where\n // `data:` URIs don't.\n icon: '/_attaform_devtools/icon.svg',\n view: {\n type: 'iframe',\n src: '/_attaform_devtools',\n persistent: true,\n },\n })\n } catch {\n // Nuxt DevTools (and thus @nuxt/devtools-kit) isn't installed\n // in this consumer — silently skip. The library still works;\n // only the overlay tab is missing.\n }\n })\n }\n },\n})\n"],"names":["attaformVitePlugin"],"mappings":"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"}
package/dist/rollup.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;
@@ -14,7 +14,7 @@ function attaform(options = {}) {
14
14
  },
15
15
  resolveId(source, importer) {
16
16
  if (aliasTarget === null) return null;
17
- if (source !== detectZodMajor.ZOD_UNIFIED_SPECIFIER) return null;
17
+ if (!detectZodMajor.isRewritableZodSpecifier(source)) return null;
18
18
  return this.resolve(aliasTarget, importer, { skipSelf: true });
19
19
  }
20
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"rollup.cjs","sources":["../src/rollup.ts"],"sourcesContent":["/**\n * `attaform/rollup` — Rollup plugin that rewrites `attaform/zod` imports\n * 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, Rollup ships both adapters because the unified\n * `attaform/zod` entry imports both for runtime dispatch.\n *\n * Usage:\n *\n * // rollup.config.js\n * import { attaform } from 'attaform/rollup'\n *\n * export default {\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 `rollup` (the bundler injects\n * its plugin context at the consumer's build); the structural types below\n * are all it needs to compile.\n */\nimport { resolveZodAliasTarget, ZOD_UNIFIED_SPECIFIER } from './core/detect-zod-major'\n\n/** Options for the Rollup `attaform()` plugin. */\nexport interface AttaformRollupPluginOptions {\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\n * `process.cwd()`. Set this when the build runs from a directory other\n * than the project that owns the Zod dependency.\n */\n root?: string\n}\n\ninterface RollupResolveContext {\n resolve(\n source: string,\n importer: string | undefined,\n options: { skipSelf: boolean }\n ): Promise<{ id: string; external: boolean | 'absolute' | 'relative' } | null>\n}\n\n/** The structural shape Rollup requires of the plugin. */\nexport interface AttaformRollupPlugin {\n name: string\n buildStart(): void\n resolveId(\n this: RollupResolveContext,\n source: string,\n importer: string | undefined\n ): Promise<{ id: string } | null> | null\n}\n\nexport function attaform(options: AttaformRollupPluginOptions = {}): AttaformRollupPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const root = options.root ?? process.cwd()\n const warnState = { warned: false }\n let aliasTarget: string | null = null\n\n return {\n name: 'attaform',\n buildStart() {\n // Detect once at build start (fail fast on missing zod). `buildStart`\n // is guaranteed to run before any `resolveId`, so the target is set\n // before the rewrite hook fires.\n aliasTarget = resolveZodAliasTarget(root, 'attaform/rollup', resolveZodAlias, warnState)\n },\n resolveId(source, importer) {\n if (aliasTarget === null) return null\n if (source !== ZOD_UNIFIED_SPECIFIER) return null\n // Re-run the rewritten specifier through the resolver chain so the\n // matching subpath export lands as a real module. `skipSelf` keeps\n // the hook reentrant (our source check rejects the rewritten target\n // anyway, since it is no longer the bare unified specifier).\n return this.resolve(aliasTarget, importer, { skipSelf: true })\n },\n }\n}\n"],"names":["resolveZodAliasTarget","ZOD_UNIFIED_SPECIFIER"],"mappings":";;;;AA+DO,SAAS,QAAA,CAAS,OAAA,GAAuC,EAAC,EAAyB;AACxF,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,GAAA,EAAI;AACzC,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,IAAI,WAAA,GAA6B,IAAA;AAEjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,UAAA,GAAa;AAIX,MAAA,WAAA,GAAcA,oCAAA,CAAsB,IAAA,EAAM,iBAAA,EAAmB,eAAA,EAAiB,SAAS,CAAA;AAAA,IACzF,CAAA;AAAA,IACA,SAAA,CAAU,QAAQ,QAAA,EAAU;AAC1B,MAAA,IAAI,WAAA,KAAgB,MAAM,OAAO,IAAA;AACjC,MAAA,IAAI,MAAA,KAAWC,sCAAuB,OAAO,IAAA;AAK7C,MAAA,OAAO,KAAK,OAAA,CAAQ,WAAA,EAAa,UAAU,EAAE,QAAA,EAAU,MAAM,CAAA;AAAA,IAC/D;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"rollup.cjs","sources":["../src/rollup.ts"],"sourcesContent":["/**\n * `attaform/rollup` — Rollup 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, Rollup ships both adapters\n * because those entries import both for runtime dispatch.\n *\n * Usage:\n *\n * // rollup.config.js\n * import { attaform } from 'attaform/rollup'\n *\n * export default {\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 `rollup` (the bundler injects\n * its plugin context at the consumer's build); the structural types below\n * are all it needs to compile.\n */\nimport { isRewritableZodSpecifier, resolveZodAliasTarget } from './core/detect-zod-major'\n\n/** Options for the Rollup `attaform()` plugin. */\nexport interface AttaformRollupPluginOptions {\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\n * `process.cwd()`. Set this when the build runs from a directory other\n * than the project that owns the Zod dependency.\n */\n root?: string\n}\n\ninterface RollupResolveContext {\n resolve(\n source: string,\n importer: string | undefined,\n options: { skipSelf: boolean }\n ): Promise<{ id: string; external: boolean | 'absolute' | 'relative' } | null>\n}\n\n/** The structural shape Rollup requires of the plugin. */\nexport interface AttaformRollupPlugin {\n name: string\n buildStart(): void\n resolveId(\n this: RollupResolveContext,\n source: string,\n importer: string | undefined\n ): Promise<{ id: string } | null> | null\n}\n\nexport function attaform(options: AttaformRollupPluginOptions = {}): AttaformRollupPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const root = options.root ?? process.cwd()\n const warnState = { warned: false }\n let aliasTarget: string | null = null\n\n return {\n name: 'attaform',\n buildStart() {\n // Detect once at build start (fail fast on missing zod). `buildStart`\n // is guaranteed to run before any `resolveId`, so the target is set\n // before the rewrite hook fires.\n aliasTarget = resolveZodAliasTarget(root, 'attaform/rollup', resolveZodAlias, warnState)\n },\n resolveId(source, importer) {\n if (aliasTarget === null) return null\n // Both the bare `attaform` barrel and the explicit `attaform/zod`\n // carry the runtime dispatcher, so both collapse to the one detected\n // adapter; the pinned subpaths pass through untouched.\n if (!isRewritableZodSpecifier(source)) return null\n // Re-run the rewritten specifier through the resolver chain so the\n // matching subpath export lands as a real module. `skipSelf` keeps\n // the hook reentrant (our source check rejects the rewritten target\n // anyway, since it is no longer a rewritable specifier).\n return this.resolve(aliasTarget, importer, { skipSelf: true })\n },\n }\n}\n"],"names":["resolveZodAliasTarget","isRewritableZodSpecifier"],"mappings":";;;;AA+DO,SAAS,QAAA,CAAS,OAAA,GAAuC,EAAC,EAAyB;AACxF,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,GAAA,EAAI;AACzC,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,IAAI,WAAA,GAA6B,IAAA;AAEjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,UAAA,GAAa;AAIX,MAAA,WAAA,GAAcA,oCAAA,CAAsB,IAAA,EAAM,iBAAA,EAAmB,eAAA,EAAiB,SAAS,CAAA;AAAA,IACzF,CAAA;AAAA,IACA,SAAA,CAAU,QAAQ,QAAA,EAAU;AAC1B,MAAA,IAAI,WAAA,KAAgB,MAAM,OAAO,IAAA;AAIjC,MAAA,IAAI,CAACC,uCAAA,CAAyB,MAAM,CAAA,EAAG,OAAO,IAAA;AAK9C,MAAA,OAAO,KAAK,OAAA,CAAQ,WAAA,EAAa,UAAU,EAAE,QAAA,EAAU,MAAM,CAAA;AAAA,IAC/D;AAAA,GACF;AACF;;;;"}
package/dist/rollup.d.cts CHANGED
@@ -1,9 +1,9 @@
1
1
  /** Options for the Rollup `attaform()` plugin. */
2
2
  interface AttaformRollupPluginOptions {
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/rollup.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  /** Options for the Rollup `attaform()` plugin. */
2
2
  interface AttaformRollupPluginOptions {
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/rollup.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /** Options for the Rollup `attaform()` plugin. */
2
2
  interface AttaformRollupPluginOptions {
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/rollup.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { r as resolveZodAliasTarget, Z as ZOD_UNIFIED_SPECIFIER } from './shared/attaform.sHkHv_98.mjs';
1
+ import { r as resolveZodAliasTarget, i as isRewritableZodSpecifier } from './shared/attaform.DhnPb6nK.mjs';
2
2
 
3
3
  function attaform(options = {}) {
4
4
  const resolveZodAlias = options.resolveZodAlias !== false;
@@ -12,7 +12,7 @@ function attaform(options = {}) {
12
12
  },
13
13
  resolveId(source, importer) {
14
14
  if (aliasTarget === null) return null;
15
- if (source !== ZOD_UNIFIED_SPECIFIER) return null;
15
+ if (!isRewritableZodSpecifier(source)) return null;
16
16
  return this.resolve(aliasTarget, importer, { skipSelf: true });
17
17
  }
18
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"rollup.mjs","sources":["../src/rollup.ts"],"sourcesContent":["/**\n * `attaform/rollup` — Rollup plugin that rewrites `attaform/zod` imports\n * 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, Rollup ships both adapters because the unified\n * `attaform/zod` entry imports both for runtime dispatch.\n *\n * Usage:\n *\n * // rollup.config.js\n * import { attaform } from 'attaform/rollup'\n *\n * export default {\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 `rollup` (the bundler injects\n * its plugin context at the consumer's build); the structural types below\n * are all it needs to compile.\n */\nimport { resolveZodAliasTarget, ZOD_UNIFIED_SPECIFIER } from './core/detect-zod-major'\n\n/** Options for the Rollup `attaform()` plugin. */\nexport interface AttaformRollupPluginOptions {\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\n * `process.cwd()`. Set this when the build runs from a directory other\n * than the project that owns the Zod dependency.\n */\n root?: string\n}\n\ninterface RollupResolveContext {\n resolve(\n source: string,\n importer: string | undefined,\n options: { skipSelf: boolean }\n ): Promise<{ id: string; external: boolean | 'absolute' | 'relative' } | null>\n}\n\n/** The structural shape Rollup requires of the plugin. */\nexport interface AttaformRollupPlugin {\n name: string\n buildStart(): void\n resolveId(\n this: RollupResolveContext,\n source: string,\n importer: string | undefined\n ): Promise<{ id: string } | null> | null\n}\n\nexport function attaform(options: AttaformRollupPluginOptions = {}): AttaformRollupPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const root = options.root ?? process.cwd()\n const warnState = { warned: false }\n let aliasTarget: string | null = null\n\n return {\n name: 'attaform',\n buildStart() {\n // Detect once at build start (fail fast on missing zod). `buildStart`\n // is guaranteed to run before any `resolveId`, so the target is set\n // before the rewrite hook fires.\n aliasTarget = resolveZodAliasTarget(root, 'attaform/rollup', resolveZodAlias, warnState)\n },\n resolveId(source, importer) {\n if (aliasTarget === null) return null\n if (source !== ZOD_UNIFIED_SPECIFIER) return null\n // Re-run the rewritten specifier through the resolver chain so the\n // matching subpath export lands as a real module. `skipSelf` keeps\n // the hook reentrant (our source check rejects the rewritten target\n // anyway, since it is no longer the bare unified specifier).\n return this.resolve(aliasTarget, importer, { skipSelf: true })\n },\n }\n}\n"],"names":[],"mappings":";;AA+DO,SAAS,QAAA,CAAS,OAAA,GAAuC,EAAC,EAAyB;AACxF,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,GAAA,EAAI;AACzC,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,IAAI,WAAA,GAA6B,IAAA;AAEjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,UAAA,GAAa;AAIX,MAAA,WAAA,GAAc,qBAAA,CAAsB,IAAA,EAAM,iBAAA,EAAmB,eAAA,EAAiB,SAAS,CAAA;AAAA,IACzF,CAAA;AAAA,IACA,SAAA,CAAU,QAAQ,QAAA,EAAU;AAC1B,MAAA,IAAI,WAAA,KAAgB,MAAM,OAAO,IAAA;AACjC,MAAA,IAAI,MAAA,KAAW,uBAAuB,OAAO,IAAA;AAK7C,MAAA,OAAO,KAAK,OAAA,CAAQ,WAAA,EAAa,UAAU,EAAE,QAAA,EAAU,MAAM,CAAA;AAAA,IAC/D;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"rollup.mjs","sources":["../src/rollup.ts"],"sourcesContent":["/**\n * `attaform/rollup` — Rollup 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, Rollup ships both adapters\n * because those entries import both for runtime dispatch.\n *\n * Usage:\n *\n * // rollup.config.js\n * import { attaform } from 'attaform/rollup'\n *\n * export default {\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 `rollup` (the bundler injects\n * its plugin context at the consumer's build); the structural types below\n * are all it needs to compile.\n */\nimport { isRewritableZodSpecifier, resolveZodAliasTarget } from './core/detect-zod-major'\n\n/** Options for the Rollup `attaform()` plugin. */\nexport interface AttaformRollupPluginOptions {\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\n * `process.cwd()`. Set this when the build runs from a directory other\n * than the project that owns the Zod dependency.\n */\n root?: string\n}\n\ninterface RollupResolveContext {\n resolve(\n source: string,\n importer: string | undefined,\n options: { skipSelf: boolean }\n ): Promise<{ id: string; external: boolean | 'absolute' | 'relative' } | null>\n}\n\n/** The structural shape Rollup requires of the plugin. */\nexport interface AttaformRollupPlugin {\n name: string\n buildStart(): void\n resolveId(\n this: RollupResolveContext,\n source: string,\n importer: string | undefined\n ): Promise<{ id: string } | null> | null\n}\n\nexport function attaform(options: AttaformRollupPluginOptions = {}): AttaformRollupPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const root = options.root ?? process.cwd()\n const warnState = { warned: false }\n let aliasTarget: string | null = null\n\n return {\n name: 'attaform',\n buildStart() {\n // Detect once at build start (fail fast on missing zod). `buildStart`\n // is guaranteed to run before any `resolveId`, so the target is set\n // before the rewrite hook fires.\n aliasTarget = resolveZodAliasTarget(root, 'attaform/rollup', resolveZodAlias, warnState)\n },\n resolveId(source, importer) {\n if (aliasTarget === null) return null\n // Both the bare `attaform` barrel and the explicit `attaform/zod`\n // carry the runtime dispatcher, so both collapse to the one detected\n // adapter; the pinned subpaths pass through untouched.\n if (!isRewritableZodSpecifier(source)) return null\n // Re-run the rewritten specifier through the resolver chain so the\n // matching subpath export lands as a real module. `skipSelf` keeps\n // the hook reentrant (our source check rejects the rewritten target\n // anyway, since it is no longer a rewritable specifier).\n return this.resolve(aliasTarget, importer, { skipSelf: true })\n },\n }\n}\n"],"names":[],"mappings":";;AA+DO,SAAS,QAAA,CAAS,OAAA,GAAuC,EAAC,EAAyB;AACxF,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,GAAA,EAAI;AACzC,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,IAAI,WAAA,GAA6B,IAAA;AAEjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,UAAA,GAAa;AAIX,MAAA,WAAA,GAAc,qBAAA,CAAsB,IAAA,EAAM,iBAAA,EAAmB,eAAA,EAAiB,SAAS,CAAA;AAAA,IACzF,CAAA;AAAA,IACA,SAAA,CAAU,QAAQ,QAAA,EAAU;AAC1B,MAAA,IAAI,WAAA,KAAgB,MAAM,OAAO,IAAA;AAIjC,MAAA,IAAI,CAAC,wBAAA,CAAyB,MAAM,CAAA,EAAG,OAAO,IAAA;AAK9C,MAAA,OAAO,KAAK,OAAA,CAAQ,WAAA,EAAa,UAAU,EAAE,QAAA,EAAU,MAAM,CAAA;AAAA,IAC/D;AAAA,GACF;AACF;;;;"}
package/dist/rspack.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const webpackFamilyPlugin = require('./shared/attaform.BRGIpZo4.cjs');
3
+ const webpackFamilyPlugin = require('./shared/attaform.RaTzp1WF.cjs');
4
4
 
5
5
  function attaform(options = {}) {
6
6
  return webpackFamilyPlugin.createWebpackFamilyPlugin("attaform/rspack", options);
package/dist/rspack.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { W as WebpackFamilyPlugin, a as WebpackFamilyPluginOptions } from './shared/attaform.DuzQYscR.cjs';
1
+ import { W as WebpackFamilyPlugin, a as WebpackFamilyPluginOptions } from './shared/attaform.C9fPTxjB.cjs';
2
2
 
3
3
  /**
4
4
  * `attaform/rspack` — Rspack plugin that rewrites `attaform/zod` imports
package/dist/rspack.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { W as WebpackFamilyPlugin, a as WebpackFamilyPluginOptions } from './shared/attaform.DuzQYscR.mjs';
1
+ import { W as WebpackFamilyPlugin, a as WebpackFamilyPluginOptions } from './shared/attaform.C9fPTxjB.mjs';
2
2
 
3
3
  /**
4
4
  * `attaform/rspack` — Rspack plugin that rewrites `attaform/zod` imports
package/dist/rspack.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { W as WebpackFamilyPlugin, a as WebpackFamilyPluginOptions } from './shared/attaform.DuzQYscR.js';
1
+ import { W as WebpackFamilyPlugin, a as WebpackFamilyPluginOptions } from './shared/attaform.C9fPTxjB.js';
2
2
 
3
3
  /**
4
4
  * `attaform/rspack` — Rspack plugin that rewrites `attaform/zod` imports
package/dist/rspack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { c as createWebpackFamilyPlugin } from './shared/attaform.C3Doa9Pt.mjs';
1
+ import { c as createWebpackFamilyPlugin } from './shared/attaform.v0fQtWyA.mjs';
2
2
 
3
3
  function attaform(options = {}) {
4
4
  return createWebpackFamilyPlugin("attaform/rspack", options);
@@ -1,8 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const app = require('nuxt/app');
4
- const devtoolsShared = require('../../shared/attaform.xBDo0Ko0.cjs');
5
- const paths = require('../../shared/attaform.3heDHayA.cjs');
4
+ const devtoolsShared = require('../../shared/attaform.Co5LNRnv.cjs');
6
5
 
7
6
  var attaform_default = app.defineNuxtPlugin({
8
7
  // `enforce: 'pre'` makes the "we run before any component's setup" claim
@@ -15,8 +14,8 @@ var attaform_default = app.defineNuxtPlugin({
15
14
  const isServer = undefined;
16
15
  const config = app.useRuntimeConfig().public;
17
16
  const { defaults, version } = config.attaform;
18
- nuxtApp.vueApp.use(paths.createAttaform({ ssr: isServer, defaults }));
19
- nuxtApp.vueApp.provide(paths.kAttaformWizardActiveStepResolver, (param) => {
17
+ nuxtApp.vueApp.use(devtoolsShared.createAttaform({ ssr: isServer, defaults }));
18
+ nuxtApp.vueApp.provide(devtoolsShared.kAttaformWizardActiveStepResolver, (param) => {
20
19
  const value = app.useRoute().query[param];
21
20
  if (typeof value === "string") return value;
22
21
  if (Array.isArray(value) && typeof value[0] === "string") return value[0];
@@ -33,7 +32,7 @@ var attaform_default = app.defineNuxtPlugin({
33
32
  devtoolsShared.hydrateAttaformState(nuxtApp.vueApp, serialized);
34
33
  }
35
34
  if (undefined) {
36
- const registry = paths.getRegistryFromApp(nuxtApp.vueApp);
35
+ const registry = devtoolsShared.getRegistryFromApp(nuxtApp.vueApp);
37
36
  window[devtoolsShared.DEVTOOLS_WINDOW_KEY] = { registry, version };
38
37
  }
39
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"attaform.cjs","sources":["../../../src/runtime/plugins/attaform.ts"],"sourcesContent":["/**\n * Nuxt plugin: installs the framework-agnostic createAttaform Vue\n * plugin on nuxtApp.vueApp and wires the Nuxt payload mechanism to the\n * registry's SSR serialization helpers. Replaces the old split of\n * register.ts (client-only) + register-stub.ts (server-only).\n *\n * Runs on BOTH server and client — Vue's SSR renderer is a natural no-op\n * for directive lifecycle hooks, so the same plugin works on both sides\n * without a stub.\n */\nimport { defineNuxtPlugin, useRoute, useRuntimeConfig } from 'nuxt/app'\nimport { DEVTOOLS_WINDOW_KEY } from '../core/devtools-shared'\nimport { createAttaform } from '../core/plugin'\nimport { getRegistryFromApp, kAttaformWizardActiveStepResolver } from '../core/registry'\nimport { hydrateAttaformState, renderAttaformState } from '../core/serialize'\nimport type { SerializedAttaformState } from '../core/serialize'\nimport type { AttaformDefaults } from '../types/types-api'\n\nexport default defineNuxtPlugin({\n // `enforce: 'pre'` makes the \"we run before any component's setup\" claim\n // explicit. Combined with `prepend: true` on the addPlugin call in\n // src/nuxt.ts, this guarantees hydration is staged into pendingHydration\n // before any user plugin or page can call `useForm`. Without it, a user\n // plugin running first would observe an empty registry and skip hydration.\n enforce: 'pre',\n setup(nuxtApp) {\n const isServer = import.meta.server\n\n // Read app-level defaults from the Nuxt module's runtime-config slot\n // (populated in src/nuxt.ts). The module ships in the same package\n // as this plugin, so the slot is always present and well-typed.\n const config = useRuntimeConfig().public as {\n attaform: { defaults: AttaformDefaults; version: string }\n }\n const { defaults, version } = config.attaform\n\n nuxtApp.vueApp.use(createAttaform({ ssr: isServer, defaults }))\n\n // Bridge `useWizard`'s active-step resolution to the Nuxt route so\n // deep-links hydrate without flicker. On the server, `useRoute()`\n // reads the incoming request URL; on the client, it reads the live\n // route — so server and client compute the same initial step and\n // Vue's hydration walks a matching tree. Without this bridge, the\n // wizard would fall back to its first step on the server while the\n // client reads the URL, producing the deep-link mismatch cascade.\n // Consumers can still pass `options.restore` explicitly to override;\n // this just removes the boilerplate for the common case.\n nuxtApp.vueApp.provide(kAttaformWizardActiveStepResolver, (param) => {\n const value = useRoute().query[param]\n if (typeof value === 'string') return value\n if (Array.isArray(value) && typeof value[0] === 'string') return value[0]\n return undefined\n })\n\n if (isServer) {\n // After the app renders, capture every FormStore into the Nuxt payload\n // so the client can hydrate with matching form values and errors.\n nuxtApp.hook('app:rendered', () => {\n const state = renderAttaformState(nuxtApp.vueApp)\n ;(nuxtApp.payload as unknown as { attaform?: SerializedAttaformState }).attaform = state\n })\n } else {\n // Stage the payload into pendingHydration so `useForm` finds it. The\n // `enforce: 'pre'` + `prepend: true` pair above is what makes it safe\n // to assume this runs before any user setup.\n const serialized = (nuxtApp.payload as unknown as { attaform?: SerializedAttaformState })\n .attaform\n if (serialized !== undefined) {\n hydrateAttaformState(nuxtApp.vueApp, serialized)\n }\n\n // Dev-only: attach the registry to window so the Nuxt DevTools overlay\n // panel (which runs in an iframe at /_attaform_devtools) can reach it\n // via `window.parent.__attaform_devtools__`. The bridge holds a live\n // reference to the registry — Vue's reactivity flows across the\n // same-origin iframe boundary, so the panel re-renders on every form\n // mutation without an explicit push channel. `import.meta.dev` is\n // statically replaced by Nuxt at build time, so this whole branch is\n // tree-shaken from production builds.\n if (import.meta.dev) {\n const registry = getRegistryFromApp(nuxtApp.vueApp)\n window[DEVTOOLS_WINDOW_KEY] = { registry, version }\n }\n }\n },\n})\n"],"names":["defineNuxtPlugin","useRuntimeConfig","createAttaform","kAttaformWizardActiveStepResolver","useRoute","renderAttaformState","hydrateAttaformState","getRegistryFromApp","DEVTOOLS_WINDOW_KEY"],"mappings":";;;;;;AAkBA,IAAO,mBAAQA,oBAAA,CAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,OAAA,EAAS,KAAA;AAAA,EACT,MAAM,OAAA,EAAS;AACb,IAAA,MAAM,WAAW,SAAY;AAK7B,IAAA,MAAM,MAAA,GAASC,sBAAiB,CAAE,MAAA;AAGlC,IAAA,MAAM,EAAE,QAAA,EAAU,OAAA,EAAQ,GAAI,MAAA,CAAO,QAAA;AAErC,IAAA,OAAA,CAAQ,MAAA,CAAO,IAAIC,oBAAA,CAAe,EAAE,KAAK,QAAA,EAAU,QAAA,EAAU,CAAC,CAAA;AAW9D,IAAA,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQC,uCAAA,EAAmC,CAAC,KAAA,KAAU;AACnE,MAAA,MAAM,KAAA,GAAQC,YAAA,EAAS,CAAE,KAAA,CAAM,KAAK,CAAA;AACpC,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,OAAO,KAAA,CAAM,CAAC,CAAA,KAAM,QAAA,EAAU,OAAO,KAAA,CAAM,CAAC,CAAA;AACxE,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,IAAI,QAAA,EAAU;AAGZ,MAAA,OAAA,CAAQ,IAAA,CAAK,gBAAgB,MAAM;AACjC,QAAA,MAAM,KAAA,GAAQC,kCAAA,CAAoB,OAAA,CAAQ,MAAM,CAAA;AAC/C,QAAC,OAAA,CAAQ,QAA8D,QAAA,GAAW,KAAA;AAAA,MACrF,CAAC,CAAA;AAAA,IACH,CAAA,MAAO;AAIL,MAAA,MAAM,UAAA,GAAc,QAAQ,OAAA,CACzB,QAAA;AACH,MAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,QAAAC,mCAAA,CAAqB,OAAA,CAAQ,QAAQ,UAAU,CAAA;AAAA,MACjD;AAUA,MAAA,IAAI,SAAY,EAAK;AACnB,QAAA,MAAM,QAAA,GAAWC,wBAAA,CAAmB,OAAA,CAAQ,MAAM,CAAA;AAClD,QAAA,MAAA,CAAOC,kCAAmB,CAAA,GAAI,EAAE,QAAA,EAAU,OAAA,EAAQ;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"attaform.cjs","sources":["../../../src/runtime/plugins/attaform.ts"],"sourcesContent":["/**\n * Nuxt plugin: installs the framework-agnostic createAttaform Vue\n * plugin on nuxtApp.vueApp and wires the Nuxt payload mechanism to the\n * registry's SSR serialization helpers. Replaces the old split of\n * register.ts (client-only) + register-stub.ts (server-only).\n *\n * Runs on BOTH server and client — Vue's SSR renderer is a natural no-op\n * for directive lifecycle hooks, so the same plugin works on both sides\n * without a stub.\n */\nimport { defineNuxtPlugin, useRoute, useRuntimeConfig } from 'nuxt/app'\nimport { DEVTOOLS_WINDOW_KEY } from '../core/devtools-shared'\nimport { createAttaform } from '../core/plugin'\nimport { getRegistryFromApp, kAttaformWizardActiveStepResolver } from '../core/registry'\nimport { hydrateAttaformState, renderAttaformState } from '../core/serialize'\nimport type { SerializedAttaformState } from '../core/serialize'\nimport type { AttaformDefaults } from '../types/types-api'\n\nexport default defineNuxtPlugin({\n // `enforce: 'pre'` makes the \"we run before any component's setup\" claim\n // explicit. Combined with `prepend: true` on the addPlugin call in\n // src/nuxt.ts, this guarantees hydration is staged into pendingHydration\n // before any user plugin or page can call `useForm`. Without it, a user\n // plugin running first would observe an empty registry and skip hydration.\n enforce: 'pre',\n setup(nuxtApp) {\n const isServer = import.meta.server\n\n // Read app-level defaults from the Nuxt module's runtime-config slot\n // (populated in src/nuxt.ts). The module ships in the same package\n // as this plugin, so the slot is always present and well-typed.\n const config = useRuntimeConfig().public as {\n attaform: { defaults: AttaformDefaults; version: string }\n }\n const { defaults, version } = config.attaform\n\n nuxtApp.vueApp.use(createAttaform({ ssr: isServer, defaults }))\n\n // Bridge `useWizard`'s active-step resolution to the Nuxt route so\n // deep-links hydrate without flicker. On the server, `useRoute()`\n // reads the incoming request URL; on the client, it reads the live\n // route — so server and client compute the same initial step and\n // Vue's hydration walks a matching tree. Without this bridge, the\n // wizard would fall back to its first step on the server while the\n // client reads the URL, producing the deep-link mismatch cascade.\n // Consumers can still pass `options.restore` explicitly to override;\n // this just removes the boilerplate for the common case.\n nuxtApp.vueApp.provide(kAttaformWizardActiveStepResolver, (param) => {\n const value = useRoute().query[param]\n if (typeof value === 'string') return value\n if (Array.isArray(value) && typeof value[0] === 'string') return value[0]\n return undefined\n })\n\n if (isServer) {\n // After the app renders, capture every FormStore into the Nuxt payload\n // so the client can hydrate with matching form values and errors.\n nuxtApp.hook('app:rendered', () => {\n const state = renderAttaformState(nuxtApp.vueApp)\n ;(nuxtApp.payload as unknown as { attaform?: SerializedAttaformState }).attaform = state\n })\n } else {\n // Stage the payload into pendingHydration so `useForm` finds it. The\n // `enforce: 'pre'` + `prepend: true` pair above is what makes it safe\n // to assume this runs before any user setup.\n const serialized = (nuxtApp.payload as unknown as { attaform?: SerializedAttaformState })\n .attaform\n if (serialized !== undefined) {\n hydrateAttaformState(nuxtApp.vueApp, serialized)\n }\n\n // Dev-only: attach the registry to window so the Nuxt DevTools overlay\n // panel (which runs in an iframe at /_attaform_devtools) can reach it\n // via `window.parent.__attaform_devtools__`. The bridge holds a live\n // reference to the registry — Vue's reactivity flows across the\n // same-origin iframe boundary, so the panel re-renders on every form\n // mutation without an explicit push channel. `import.meta.dev` is\n // statically replaced by Nuxt at build time, so this whole branch is\n // tree-shaken from production builds.\n if (import.meta.dev) {\n const registry = getRegistryFromApp(nuxtApp.vueApp)\n window[DEVTOOLS_WINDOW_KEY] = { registry, version }\n }\n }\n },\n})\n"],"names":["defineNuxtPlugin","useRuntimeConfig","createAttaform","kAttaformWizardActiveStepResolver","useRoute","renderAttaformState","hydrateAttaformState","getRegistryFromApp","DEVTOOLS_WINDOW_KEY"],"mappings":";;;;;AAkBA,IAAO,mBAAQA,oBAAA,CAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,OAAA,EAAS,KAAA;AAAA,EACT,MAAM,OAAA,EAAS;AACb,IAAA,MAAM,WAAW,SAAY;AAK7B,IAAA,MAAM,MAAA,GAASC,sBAAiB,CAAE,MAAA;AAGlC,IAAA,MAAM,EAAE,QAAA,EAAU,OAAA,EAAQ,GAAI,MAAA,CAAO,QAAA;AAErC,IAAA,OAAA,CAAQ,MAAA,CAAO,IAAIC,6BAAA,CAAe,EAAE,KAAK,QAAA,EAAU,QAAA,EAAU,CAAC,CAAA;AAW9D,IAAA,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQC,gDAAA,EAAmC,CAAC,KAAA,KAAU;AACnE,MAAA,MAAM,KAAA,GAAQC,YAAA,EAAS,CAAE,KAAA,CAAM,KAAK,CAAA;AACpC,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,OAAO,KAAA,CAAM,CAAC,CAAA,KAAM,QAAA,EAAU,OAAO,KAAA,CAAM,CAAC,CAAA;AACxE,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,IAAI,QAAA,EAAU;AAGZ,MAAA,OAAA,CAAQ,IAAA,CAAK,gBAAgB,MAAM;AACjC,QAAA,MAAM,KAAA,GAAQC,kCAAA,CAAoB,OAAA,CAAQ,MAAM,CAAA;AAC/C,QAAC,OAAA,CAAQ,QAA8D,QAAA,GAAW,KAAA;AAAA,MACrF,CAAC,CAAA;AAAA,IACH,CAAA,MAAO;AAIL,MAAA,MAAM,UAAA,GAAc,QAAQ,OAAA,CACzB,QAAA;AACH,MAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,QAAAC,mCAAA,CAAqB,OAAA,CAAQ,QAAQ,UAAU,CAAA;AAAA,MACjD;AAUA,MAAA,IAAI,SAAY,EAAK;AACnB,QAAA,MAAM,QAAA,GAAWC,iCAAA,CAAmB,OAAA,CAAQ,MAAM,CAAA;AAClD,QAAA,MAAA,CAAOC,kCAAmB,CAAA,GAAI,EAAE,QAAA,EAAU,OAAA,EAAQ;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF,CAAC;;;;"}
@@ -1,6 +1,5 @@
1
1
  import { defineNuxtPlugin, useRuntimeConfig, useRoute } from 'nuxt/app';
2
- import { r as renderAttaformState, h as hydrateAttaformState, D as DEVTOOLS_WINDOW_KEY } from '../../shared/attaform.OLtKd9gM.mjs';
3
- import { g as createAttaform, l as kAttaformWizardActiveStepResolver, i as getRegistryFromApp } from '../../shared/attaform.CqwcTExO.mjs';
2
+ import { g as createAttaform, m as kAttaformWizardActiveStepResolver, r as renderAttaformState, j as hydrateAttaformState, i as getRegistryFromApp, D as DEVTOOLS_WINDOW_KEY } from '../../shared/attaform.Da8EdI2t.mjs';
4
3
 
5
4
  var attaform_default = defineNuxtPlugin({
6
5
  // `enforce: 'pre'` makes the "we run before any component's setup" claim
@@ -1 +1 @@
1
- {"version":3,"file":"attaform.mjs","sources":["../../../src/runtime/plugins/attaform.ts"],"sourcesContent":["/**\n * Nuxt plugin: installs the framework-agnostic createAttaform Vue\n * plugin on nuxtApp.vueApp and wires the Nuxt payload mechanism to the\n * registry's SSR serialization helpers. Replaces the old split of\n * register.ts (client-only) + register-stub.ts (server-only).\n *\n * Runs on BOTH server and client — Vue's SSR renderer is a natural no-op\n * for directive lifecycle hooks, so the same plugin works on both sides\n * without a stub.\n */\nimport { defineNuxtPlugin, useRoute, useRuntimeConfig } from 'nuxt/app'\nimport { DEVTOOLS_WINDOW_KEY } from '../core/devtools-shared'\nimport { createAttaform } from '../core/plugin'\nimport { getRegistryFromApp, kAttaformWizardActiveStepResolver } from '../core/registry'\nimport { hydrateAttaformState, renderAttaformState } from '../core/serialize'\nimport type { SerializedAttaformState } from '../core/serialize'\nimport type { AttaformDefaults } from '../types/types-api'\n\nexport default defineNuxtPlugin({\n // `enforce: 'pre'` makes the \"we run before any component's setup\" claim\n // explicit. Combined with `prepend: true` on the addPlugin call in\n // src/nuxt.ts, this guarantees hydration is staged into pendingHydration\n // before any user plugin or page can call `useForm`. Without it, a user\n // plugin running first would observe an empty registry and skip hydration.\n enforce: 'pre',\n setup(nuxtApp) {\n const isServer = import.meta.server\n\n // Read app-level defaults from the Nuxt module's runtime-config slot\n // (populated in src/nuxt.ts). The module ships in the same package\n // as this plugin, so the slot is always present and well-typed.\n const config = useRuntimeConfig().public as {\n attaform: { defaults: AttaformDefaults; version: string }\n }\n const { defaults, version } = config.attaform\n\n nuxtApp.vueApp.use(createAttaform({ ssr: isServer, defaults }))\n\n // Bridge `useWizard`'s active-step resolution to the Nuxt route so\n // deep-links hydrate without flicker. On the server, `useRoute()`\n // reads the incoming request URL; on the client, it reads the live\n // route — so server and client compute the same initial step and\n // Vue's hydration walks a matching tree. Without this bridge, the\n // wizard would fall back to its first step on the server while the\n // client reads the URL, producing the deep-link mismatch cascade.\n // Consumers can still pass `options.restore` explicitly to override;\n // this just removes the boilerplate for the common case.\n nuxtApp.vueApp.provide(kAttaformWizardActiveStepResolver, (param) => {\n const value = useRoute().query[param]\n if (typeof value === 'string') return value\n if (Array.isArray(value) && typeof value[0] === 'string') return value[0]\n return undefined\n })\n\n if (isServer) {\n // After the app renders, capture every FormStore into the Nuxt payload\n // so the client can hydrate with matching form values and errors.\n nuxtApp.hook('app:rendered', () => {\n const state = renderAttaformState(nuxtApp.vueApp)\n ;(nuxtApp.payload as unknown as { attaform?: SerializedAttaformState }).attaform = state\n })\n } else {\n // Stage the payload into pendingHydration so `useForm` finds it. The\n // `enforce: 'pre'` + `prepend: true` pair above is what makes it safe\n // to assume this runs before any user setup.\n const serialized = (nuxtApp.payload as unknown as { attaform?: SerializedAttaformState })\n .attaform\n if (serialized !== undefined) {\n hydrateAttaformState(nuxtApp.vueApp, serialized)\n }\n\n // Dev-only: attach the registry to window so the Nuxt DevTools overlay\n // panel (which runs in an iframe at /_attaform_devtools) can reach it\n // via `window.parent.__attaform_devtools__`. The bridge holds a live\n // reference to the registry — Vue's reactivity flows across the\n // same-origin iframe boundary, so the panel re-renders on every form\n // mutation without an explicit push channel. `import.meta.dev` is\n // statically replaced by Nuxt at build time, so this whole branch is\n // tree-shaken from production builds.\n if (import.meta.dev) {\n const registry = getRegistryFromApp(nuxtApp.vueApp)\n window[DEVTOOLS_WINDOW_KEY] = { registry, version }\n }\n }\n },\n})\n"],"names":[],"mappings":";;;;AAkBA,IAAO,mBAAQ,gBAAA,CAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,OAAA,EAAS,KAAA;AAAA,EACT,MAAM,OAAA,EAAS;AACb,IAAA,MAAM,WAAW,MAAA,CAAA,IAAA,CAAY,MAAA;AAK7B,IAAA,MAAM,MAAA,GAAS,kBAAiB,CAAE,MAAA;AAGlC,IAAA,MAAM,EAAE,QAAA,EAAU,OAAA,EAAQ,GAAI,MAAA,CAAO,QAAA;AAErC,IAAA,OAAA,CAAQ,MAAA,CAAO,IAAI,cAAA,CAAe,EAAE,KAAK,QAAA,EAAU,QAAA,EAAU,CAAC,CAAA;AAW9D,IAAA,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,iCAAA,EAAmC,CAAC,KAAA,KAAU;AACnE,MAAA,MAAM,KAAA,GAAQ,QAAA,EAAS,CAAE,KAAA,CAAM,KAAK,CAAA;AACpC,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,OAAO,KAAA,CAAM,CAAC,CAAA,KAAM,QAAA,EAAU,OAAO,KAAA,CAAM,CAAC,CAAA;AACxE,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,IAAI,QAAA,EAAU;AAGZ,MAAA,OAAA,CAAQ,IAAA,CAAK,gBAAgB,MAAM;AACjC,QAAA,MAAM,KAAA,GAAQ,mBAAA,CAAoB,OAAA,CAAQ,MAAM,CAAA;AAC/C,QAAC,OAAA,CAAQ,QAA8D,QAAA,GAAW,KAAA;AAAA,MACrF,CAAC,CAAA;AAAA,IACH,CAAA,MAAO;AAIL,MAAA,MAAM,UAAA,GAAc,QAAQ,OAAA,CACzB,QAAA;AACH,MAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,QAAA,oBAAA,CAAqB,OAAA,CAAQ,QAAQ,UAAU,CAAA;AAAA,MACjD;AAUA,MAAA,IAAI,YAAY,GAAA,EAAK;AACnB,QAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,OAAA,CAAQ,MAAM,CAAA;AAClD,QAAA,MAAA,CAAO,mBAAmB,CAAA,GAAI,EAAE,QAAA,EAAU,OAAA,EAAQ;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"attaform.mjs","sources":["../../../src/runtime/plugins/attaform.ts"],"sourcesContent":["/**\n * Nuxt plugin: installs the framework-agnostic createAttaform Vue\n * plugin on nuxtApp.vueApp and wires the Nuxt payload mechanism to the\n * registry's SSR serialization helpers. Replaces the old split of\n * register.ts (client-only) + register-stub.ts (server-only).\n *\n * Runs on BOTH server and client — Vue's SSR renderer is a natural no-op\n * for directive lifecycle hooks, so the same plugin works on both sides\n * without a stub.\n */\nimport { defineNuxtPlugin, useRoute, useRuntimeConfig } from 'nuxt/app'\nimport { DEVTOOLS_WINDOW_KEY } from '../core/devtools-shared'\nimport { createAttaform } from '../core/plugin'\nimport { getRegistryFromApp, kAttaformWizardActiveStepResolver } from '../core/registry'\nimport { hydrateAttaformState, renderAttaformState } from '../core/serialize'\nimport type { SerializedAttaformState } from '../core/serialize'\nimport type { AttaformDefaults } from '../types/types-api'\n\nexport default defineNuxtPlugin({\n // `enforce: 'pre'` makes the \"we run before any component's setup\" claim\n // explicit. Combined with `prepend: true` on the addPlugin call in\n // src/nuxt.ts, this guarantees hydration is staged into pendingHydration\n // before any user plugin or page can call `useForm`. Without it, a user\n // plugin running first would observe an empty registry and skip hydration.\n enforce: 'pre',\n setup(nuxtApp) {\n const isServer = import.meta.server\n\n // Read app-level defaults from the Nuxt module's runtime-config slot\n // (populated in src/nuxt.ts). The module ships in the same package\n // as this plugin, so the slot is always present and well-typed.\n const config = useRuntimeConfig().public as {\n attaform: { defaults: AttaformDefaults; version: string }\n }\n const { defaults, version } = config.attaform\n\n nuxtApp.vueApp.use(createAttaform({ ssr: isServer, defaults }))\n\n // Bridge `useWizard`'s active-step resolution to the Nuxt route so\n // deep-links hydrate without flicker. On the server, `useRoute()`\n // reads the incoming request URL; on the client, it reads the live\n // route — so server and client compute the same initial step and\n // Vue's hydration walks a matching tree. Without this bridge, the\n // wizard would fall back to its first step on the server while the\n // client reads the URL, producing the deep-link mismatch cascade.\n // Consumers can still pass `options.restore` explicitly to override;\n // this just removes the boilerplate for the common case.\n nuxtApp.vueApp.provide(kAttaformWizardActiveStepResolver, (param) => {\n const value = useRoute().query[param]\n if (typeof value === 'string') return value\n if (Array.isArray(value) && typeof value[0] === 'string') return value[0]\n return undefined\n })\n\n if (isServer) {\n // After the app renders, capture every FormStore into the Nuxt payload\n // so the client can hydrate with matching form values and errors.\n nuxtApp.hook('app:rendered', () => {\n const state = renderAttaformState(nuxtApp.vueApp)\n ;(nuxtApp.payload as unknown as { attaform?: SerializedAttaformState }).attaform = state\n })\n } else {\n // Stage the payload into pendingHydration so `useForm` finds it. The\n // `enforce: 'pre'` + `prepend: true` pair above is what makes it safe\n // to assume this runs before any user setup.\n const serialized = (nuxtApp.payload as unknown as { attaform?: SerializedAttaformState })\n .attaform\n if (serialized !== undefined) {\n hydrateAttaformState(nuxtApp.vueApp, serialized)\n }\n\n // Dev-only: attach the registry to window so the Nuxt DevTools overlay\n // panel (which runs in an iframe at /_attaform_devtools) can reach it\n // via `window.parent.__attaform_devtools__`. The bridge holds a live\n // reference to the registry — Vue's reactivity flows across the\n // same-origin iframe boundary, so the panel re-renders on every form\n // mutation without an explicit push channel. `import.meta.dev` is\n // statically replaced by Nuxt at build time, so this whole branch is\n // tree-shaken from production builds.\n if (import.meta.dev) {\n const registry = getRegistryFromApp(nuxtApp.vueApp)\n window[DEVTOOLS_WINDOW_KEY] = { registry, version }\n }\n }\n },\n})\n"],"names":[],"mappings":";;;AAkBA,IAAO,mBAAQ,gBAAA,CAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,OAAA,EAAS,KAAA;AAAA,EACT,MAAM,OAAA,EAAS;AACb,IAAA,MAAM,WAAW,MAAA,CAAA,IAAA,CAAY,MAAA;AAK7B,IAAA,MAAM,MAAA,GAAS,kBAAiB,CAAE,MAAA;AAGlC,IAAA,MAAM,EAAE,QAAA,EAAU,OAAA,EAAQ,GAAI,MAAA,CAAO,QAAA;AAErC,IAAA,OAAA,CAAQ,MAAA,CAAO,IAAI,cAAA,CAAe,EAAE,KAAK,QAAA,EAAU,QAAA,EAAU,CAAC,CAAA;AAW9D,IAAA,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,iCAAA,EAAmC,CAAC,KAAA,KAAU;AACnE,MAAA,MAAM,KAAA,GAAQ,QAAA,EAAS,CAAE,KAAA,CAAM,KAAK,CAAA;AACpC,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,OAAO,KAAA,CAAM,CAAC,CAAA,KAAM,QAAA,EAAU,OAAO,KAAA,CAAM,CAAC,CAAA;AACxE,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,IAAI,QAAA,EAAU;AAGZ,MAAA,OAAA,CAAQ,IAAA,CAAK,gBAAgB,MAAM;AACjC,QAAA,MAAM,KAAA,GAAQ,mBAAA,CAAoB,OAAA,CAAQ,MAAM,CAAA;AAC/C,QAAC,OAAA,CAAQ,QAA8D,QAAA,GAAW,KAAA;AAAA,MACrF,CAAC,CAAA;AAAA,IACH,CAAA,MAAO;AAIL,MAAA,MAAM,UAAA,GAAc,QAAQ,OAAA,CACzB,QAAA;AACH,MAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,QAAA,oBAAA,CAAqB,OAAA,CAAQ,QAAQ,UAAU,CAAA;AAAA,MACjD;AAUA,MAAA,IAAI,YAAY,GAAA,EAAK;AACnB,QAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,OAAA,CAAQ,MAAM,CAAA;AAClD,QAAA,MAAA,CAAO,mBAAmB,CAAA,GAAI,EAAE,QAAA,EAAU,OAAA,EAAQ;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF,CAAC;;;;"}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const compilerCore = require('@vue/compiler-core');
4
- const registerProtocol = require('./attaform.ZXZ6dH72.cjs');
4
+ const registerProtocol = require('./attaform.yUrz7C2z.cjs');
5
5
 
6
6
  function getSummarizedProps(node) {
7
7
  if (!("props" in node)) return [];
@@ -749,4 +749,4 @@ exports.inputTextAreaNodeTransform = inputTextAreaNodeTransform;
749
749
  exports.redundantBindingWarnTransform = redundantBindingWarnTransform;
750
750
  exports.vRegisterHintTransform = vRegisterHintTransform;
751
751
  exports.vRegisterPreambleTransform = vRegisterPreambleTransform;
752
- //# sourceMappingURL=attaform.BRzKBj2g.cjs.map
752
+ //# sourceMappingURL=attaform.8tFZu1Ub.cjs.map