attaform 0.15.0 → 0.16.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 (98) hide show
  1. package/README.md +21 -11
  2. package/dist/chunks/devtools.cjs +4 -4
  3. package/dist/chunks/devtools.cjs.map +1 -1
  4. package/dist/chunks/devtools.mjs +2 -2
  5. package/dist/chunks/indexeddb.cjs +4 -4
  6. package/dist/chunks/indexeddb.cjs.map +1 -1
  7. package/dist/chunks/indexeddb.mjs +1 -1
  8. package/dist/chunks/local-storage.cjs +2 -2
  9. package/dist/chunks/local-storage.cjs.map +1 -1
  10. package/dist/chunks/local-storage.mjs +1 -1
  11. package/dist/chunks/session-storage.cjs +2 -2
  12. package/dist/chunks/session-storage.cjs.map +1 -1
  13. package/dist/chunks/session-storage.mjs +1 -1
  14. package/dist/index.cjs +23 -22
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +76 -71
  17. package/dist/index.d.mts +76 -71
  18. package/dist/index.d.ts +76 -71
  19. package/dist/index.mjs +6 -6
  20. package/dist/nuxt.cjs +5 -11
  21. package/dist/nuxt.cjs.map +1 -1
  22. package/dist/nuxt.d.cts +8 -0
  23. package/dist/nuxt.d.mts +8 -0
  24. package/dist/nuxt.d.ts +8 -0
  25. package/dist/nuxt.mjs +6 -12
  26. package/dist/nuxt.mjs.map +1 -1
  27. package/dist/runtime/plugins/attaform.cjs +3 -2
  28. package/dist/runtime/plugins/attaform.cjs.map +1 -1
  29. package/dist/runtime/plugins/attaform.mjs +2 -1
  30. package/dist/runtime/plugins/attaform.mjs.map +1 -1
  31. package/dist/shared/{attaform.BwaYWtMs.d.cts → attaform.B7rzpK1U.d.cts} +34 -5
  32. package/dist/shared/{attaform.BwaYWtMs.d.mts → attaform.B7rzpK1U.d.mts} +34 -5
  33. package/dist/shared/{attaform.BwaYWtMs.d.ts → attaform.B7rzpK1U.d.ts} +34 -5
  34. package/dist/shared/attaform.BAuJTWuT.d.mts +84 -0
  35. package/dist/shared/{attaform.CRk8NhlD.mjs → attaform.BfMxsfmE.mjs} +428 -49
  36. package/dist/shared/attaform.BfMxsfmE.mjs.map +1 -0
  37. package/dist/shared/attaform.Bp1c-uGF.cjs +1561 -0
  38. package/dist/shared/attaform.Bp1c-uGF.cjs.map +1 -0
  39. package/dist/shared/{attaform.CDJVeoJU.cjs → attaform.C9Ph2SMx.cjs} +49 -42
  40. package/dist/shared/{attaform.qxyip_aN.mjs.map → attaform.C9Ph2SMx.cjs.map} +1 -1
  41. package/dist/shared/attaform.CINUMjPq.mjs +29 -0
  42. package/dist/shared/attaform.CINUMjPq.mjs.map +1 -0
  43. package/dist/shared/attaform.CJttVxRj.cjs +32 -0
  44. package/dist/shared/attaform.CJttVxRj.cjs.map +1 -0
  45. package/dist/shared/{attaform.CPx7zTgS.d.mts → attaform.CVv9Oh0a.d.mts} +9 -7
  46. package/dist/shared/{attaform.riAENZQM.d.ts → attaform.CWCx2r0x.d.ts} +9 -7
  47. package/dist/shared/attaform.CvOXSpCb.mjs +1908 -0
  48. package/dist/shared/attaform.CvOXSpCb.mjs.map +1 -0
  49. package/dist/shared/{attaform.qxyip_aN.mjs → attaform.DILbdvfo.mjs} +12 -5
  50. package/dist/shared/{attaform.CDJVeoJU.cjs.map → attaform.DILbdvfo.mjs.map} +1 -1
  51. package/dist/shared/attaform.DdnithOf.mjs +1555 -0
  52. package/dist/shared/attaform.DdnithOf.mjs.map +1 -0
  53. package/dist/shared/attaform.DfrYByDj.cjs +1916 -0
  54. package/dist/shared/attaform.DfrYByDj.cjs.map +1 -0
  55. package/dist/shared/{attaform.D-eHWfVx.d.cts → attaform.Dq5BabH1.d.cts} +9 -7
  56. package/dist/shared/{attaform.BOi138GE.cjs → attaform.c_NzdRyc.cjs} +4 -4
  57. package/dist/shared/{attaform.BOi138GE.cjs.map → attaform.c_NzdRyc.cjs.map} +1 -1
  58. package/dist/shared/{attaform.DXye3JKf.mjs → attaform.jrxE_xZw.mjs} +2 -2
  59. package/dist/shared/{attaform.DXye3JKf.mjs.map → attaform.jrxE_xZw.mjs.map} +1 -1
  60. package/dist/shared/attaform.ls_7jBYc.d.ts +84 -0
  61. package/dist/shared/{attaform.BgYBU8gV.cjs → attaform.rIRYSUI1.cjs} +461 -61
  62. package/dist/shared/attaform.rIRYSUI1.cjs.map +1 -0
  63. package/dist/shared/attaform.xIcmqscx.d.cts +84 -0
  64. package/dist/vite.cjs +62 -9
  65. package/dist/vite.cjs.map +1 -1
  66. package/dist/vite.d.cts +23 -32
  67. package/dist/vite.d.mts +23 -32
  68. package/dist/vite.d.ts +23 -32
  69. package/dist/vite.mjs +62 -9
  70. package/dist/vite.mjs.map +1 -1
  71. package/dist/zod-v3.cjs +9 -1553
  72. package/dist/zod-v3.cjs.map +1 -1
  73. package/dist/zod-v3.d.cts +1 -1
  74. package/dist/zod-v3.d.mts +1 -1
  75. package/dist/zod-v3.d.ts +1 -1
  76. package/dist/zod-v3.mjs +3 -1553
  77. package/dist/zod-v3.mjs.map +1 -1
  78. package/dist/zod-v4.cjs +21 -0
  79. package/dist/zod-v4.cjs.map +1 -0
  80. package/dist/zod-v4.d.cts +104 -0
  81. package/dist/zod-v4.d.mts +104 -0
  82. package/dist/zod-v4.d.ts +104 -0
  83. package/dist/zod-v4.mjs +4 -0
  84. package/dist/zod-v4.mjs.map +1 -0
  85. package/dist/zod.cjs +19 -1900
  86. package/dist/zod.cjs.map +1 -1
  87. package/dist/zod.d.cts +28 -156
  88. package/dist/zod.d.mts +28 -156
  89. package/dist/zod.d.ts +28 -156
  90. package/dist/zod.mjs +19 -1896
  91. package/dist/zod.mjs.map +1 -1
  92. package/package.json +6 -2
  93. package/dist/shared/attaform.BgYBU8gV.cjs.map +0 -1
  94. package/dist/shared/attaform.CRk8NhlD.mjs.map +0 -1
  95. package/dist/shared/attaform.RypIkgVy.cjs +0 -417
  96. package/dist/shared/attaform.RypIkgVy.cjs.map +0 -1
  97. package/dist/shared/attaform.a99dQV7Q.mjs +0 -392
  98. package/dist/shared/attaform.a99dQV7Q.mjs.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,71 +1,8 @@
1
- import { Plugin, App, InjectionKey } from 'vue';
2
- import { A as AttaformDefaults, C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform.0Gxd_OOx.cjs';
1
+ import { App, InjectionKey, Plugin } from 'vue';
2
+ import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform.0Gxd_OOx.cjs';
3
3
  export { h as ApiErrorEntry, i as ArrayItem, j as ArrayPath, k as CoercionResult, l as CustomDirectiveRegisterAssignerFn, m as DefaultValuesResponse, n as FieldMetaPayload, o as FieldState, p as FieldStateMap, q as FieldStateMapEntry, r as FlatPath, s as FormErrorRecord, t as FormErrorsSurface, u as FormMeta, v as FormStorage, w as FormStorageKind, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, z as NestedType, O as OnError, B as OnInvalidSubmitPolicy, E as OnSubmit, P as Path, Q as PathKey, T as PendingValidationStatus, W as PersistConfig, X as PersistConfigOptions, Y as PersistIncludeMode, Z as ROOT_PATH, _ as ROOT_PATH_KEY, $ as ReactiveValidationStatus, a0 as RegisterDirective, a1 as RegisterFlatPath, a2 as RegisterOptions, a3 as RegisterSelectModifier, a4 as RegisterTextModifier, a5 as RegisterTransform, a6 as Segment, a7 as SetValueCallback, a8 as SetValuePayload, a9 as SettledValidationStatus, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationResponse, ag as ValidationResponseWithoutValue, ah as ValueOfUnion, ai as WriteMeta, aj as WriteShape, ak as canonicalizePath, al as isPathPrefix, am as isUnset, an as parseDottedPath, ao as unset } from './shared/attaform.0Gxd_OOx.cjs';
4
- export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.D-eHWfVx.cjs';
5
- export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, O as OutsideSetupError, R as RegistryNotInstalledError, b as ReservedFormKeyError, S as SensitivePersistFieldError, c as SubmitErrorHandlerError } from './shared/attaform.BwaYWtMs.cjs';
6
-
7
- /**
8
- * Portable SSR detection. The plugin captures this value at install time and
9
- * exposes it via the registry so every runtime branch reads a single source
10
- * of truth instead of sniffing `import.meta.*` (bundler-specific) at each
11
- * call site.
12
- *
13
- * Consumers can override explicitly via `createAttaform({ ssr: true })`;
14
- * the default heuristic handles the common Node-vs-browser split without
15
- * relying on any bundler-injected flag.
16
- */
17
- interface SSRDetectOptions {
18
- override?: boolean;
19
- }
20
-
21
- /**
22
- * Options for `createAttaform()`.
23
- */
24
- type AttaformPluginOptions = SSRDetectOptions & {
25
- /**
26
- * Whether to install the Vue DevTools integration. Default `true`.
27
- * The DevTools peer dependency is loaded lazily — in production
28
- * builds where it's absent, the import fails silently and no
29
- * extra bundle is shipped. Pass `false` to skip even attempting
30
- * the import.
31
- */
32
- devtools?: boolean;
33
- /**
34
- * App-level defaults applied to every `useForm` call in this app.
35
- * Per-form options always win. See `AttaformDefaults` for
36
- * the supported option set and the merge rules.
37
- *
38
- * ```ts
39
- * app.use(
40
- * createAttaform({
41
- * defaults: { debounceMs: 100 },
42
- * })
43
- * )
44
- * ```
45
- */
46
- defaults?: AttaformDefaults;
47
- };
48
- /**
49
- * Create the Vue plugin that installs the form library on a Vue
50
- * application. Call once per app, then `app.use(...)` the result.
51
- *
52
- * ```ts
53
- * import { createApp } from 'vue'
54
- * import { createAttaform } from 'attaform'
55
- *
56
- * createApp(App)
57
- * .use(createAttaform())
58
- * .mount('#app')
59
- * ```
60
- *
61
- * Under SSR with bare Vue 3, pass `{ ssr: true }` from your server
62
- * entry. Under Nuxt, install via `attaform/nuxt` instead —
63
- * the Nuxt module wires both server and client automatically.
64
- *
65
- * Installing more than once on the same app is a no-op (the second
66
- * call logs a dev-mode warning).
67
- */
68
- declare function createAttaform(options?: AttaformPluginOptions): Plugin;
4
+ export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.Dq5BabH1.cjs';
5
+ export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, c as ReservedFormKeyError, S as SensitivePersistFieldError, d as SubmitErrorHandlerError } from './shared/attaform.B7rzpK1U.cjs';
69
6
 
70
7
  /**
71
8
  * Schema-driven coercion of user-typed DOM values at the v-register
@@ -110,6 +47,20 @@ declare function defineCoercion<I extends SlimPrimitiveKind, O extends SlimPrimi
110
47
  */
111
48
  declare const defaultCoercionRules: CoercionRegistry;
112
49
 
50
+ /**
51
+ * Portable SSR detection. The plugin captures this value at install time and
52
+ * exposes it via the registry so every runtime branch reads a single source
53
+ * of truth instead of sniffing `import.meta.*` (bundler-specific) at each
54
+ * call site.
55
+ *
56
+ * Consumers can override explicitly via `createAttaform({ ssr: true })`;
57
+ * the default heuristic handles the common Node-vs-browser split without
58
+ * relying on any bundler-injected flag.
59
+ */
60
+ interface SSRDetectOptions {
61
+ override?: boolean;
62
+ }
63
+
113
64
  /**
114
65
  * Per-Vue-app container for all form state instances. Each
115
66
  * `app.use(createAttaform())` call gets its own registry,
@@ -223,6 +174,61 @@ declare function useRegistry(): AttaformRegistry;
223
174
  */
224
175
  declare function getRegistryFromApp(app: App): AttaformRegistry;
225
176
 
177
+ /**
178
+ * Options for `createAttaform()`.
179
+ */
180
+ type AttaformPluginOptions = SSRDetectOptions & {
181
+ /**
182
+ * Whether to install the Vue DevTools integration. Default `true`.
183
+ * The DevTools peer dependency is loaded lazily — in production
184
+ * builds where it's absent, the import fails silently and no
185
+ * extra bundle is shipped. Pass `false` to skip even attempting
186
+ * the import.
187
+ */
188
+ devtools?: boolean;
189
+ /**
190
+ * App-level defaults applied to every `useForm` call in this app.
191
+ * Per-form options always win. See `AttaformDefaults` for
192
+ * the supported option set and the merge rules.
193
+ *
194
+ * ```ts
195
+ * app.use(
196
+ * createAttaform({
197
+ * defaults: { debounceMs: 100 },
198
+ * })
199
+ * )
200
+ * ```
201
+ */
202
+ defaults?: AttaformDefaults;
203
+ };
204
+ /**
205
+ * Create the Vue plugin that installs the form library on a Vue
206
+ * application. Required only when you want app-wide options
207
+ * (`defaults`, `devtools: false`, `ssr: true`) — for the default
208
+ * setup, `useForm` / `injectForm` / `useRegister` lazy-install the
209
+ * registry on first use.
210
+ *
211
+ * ```ts
212
+ * import { createApp } from 'vue'
213
+ * import { createAttaform } from 'attaform'
214
+ *
215
+ * createApp(App)
216
+ * .use(createAttaform({ defaults: { debounceMs: 100 } }))
217
+ * .mount('#app')
218
+ * ```
219
+ *
220
+ * Under SSR with bare Vue 3, install explicitly with `{ ssr: true }`
221
+ * from your server entry — the SSR serialization helpers
222
+ * (`renderAttaformState` / `hydrateAttaformState`) require an
223
+ * already-attached registry and don't trigger lazy install. Under
224
+ * Nuxt, install via `attaform/nuxt` instead — the Nuxt module wires
225
+ * both server and client automatically.
226
+ *
227
+ * Installing more than once on the same app is a no-op (the second
228
+ * call logs a dev-mode warning).
229
+ */
230
+ declare function createAttaform(options?: AttaformPluginOptions): Plugin;
231
+
226
232
  /**
227
233
  * Serialised snapshot of every form in a Vue app, produced by
228
234
  * `renderAttaformState` and consumed by `hydrateAttaformState`.
@@ -305,10 +311,9 @@ declare function escapeForInlineScript(json: string): string;
305
311
  * })
306
312
  * ```
307
313
  *
308
- * Most consumers prefer a typed entry point e.g.
309
- * `attaform/zod` (v4) or `attaform/zod-v3`
310
- * which wrap the underlying library's schema with the matching
311
- * adapter automatically.
314
+ * Most consumers prefer a typed entry point that wraps the underlying
315
+ * library's schema with the matching adapter automatically; see the
316
+ * subpath documentation for the available adapters.
312
317
  *
313
318
  * Returns the same form API as the typed entry points; see
314
319
  * `UseFormReturnType` for the full surface.
package/dist/index.d.mts CHANGED
@@ -1,71 +1,8 @@
1
- import { Plugin, App, InjectionKey } from 'vue';
2
- import { A as AttaformDefaults, C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform.0Gxd_OOx.mjs';
1
+ import { App, InjectionKey, Plugin } from 'vue';
2
+ import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform.0Gxd_OOx.mjs';
3
3
  export { h as ApiErrorEntry, i as ArrayItem, j as ArrayPath, k as CoercionResult, l as CustomDirectiveRegisterAssignerFn, m as DefaultValuesResponse, n as FieldMetaPayload, o as FieldState, p as FieldStateMap, q as FieldStateMapEntry, r as FlatPath, s as FormErrorRecord, t as FormErrorsSurface, u as FormMeta, v as FormStorage, w as FormStorageKind, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, z as NestedType, O as OnError, B as OnInvalidSubmitPolicy, E as OnSubmit, P as Path, Q as PathKey, T as PendingValidationStatus, W as PersistConfig, X as PersistConfigOptions, Y as PersistIncludeMode, Z as ROOT_PATH, _ as ROOT_PATH_KEY, $ as ReactiveValidationStatus, a0 as RegisterDirective, a1 as RegisterFlatPath, a2 as RegisterOptions, a3 as RegisterSelectModifier, a4 as RegisterTextModifier, a5 as RegisterTransform, a6 as Segment, a7 as SetValueCallback, a8 as SetValuePayload, a9 as SettledValidationStatus, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationResponse, ag as ValidationResponseWithoutValue, ah as ValueOfUnion, ai as WriteMeta, aj as WriteShape, ak as canonicalizePath, al as isPathPrefix, am as isUnset, an as parseDottedPath, ao as unset } from './shared/attaform.0Gxd_OOx.mjs';
4
- export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.CPx7zTgS.mjs';
5
- export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, O as OutsideSetupError, R as RegistryNotInstalledError, b as ReservedFormKeyError, S as SensitivePersistFieldError, c as SubmitErrorHandlerError } from './shared/attaform.BwaYWtMs.mjs';
6
-
7
- /**
8
- * Portable SSR detection. The plugin captures this value at install time and
9
- * exposes it via the registry so every runtime branch reads a single source
10
- * of truth instead of sniffing `import.meta.*` (bundler-specific) at each
11
- * call site.
12
- *
13
- * Consumers can override explicitly via `createAttaform({ ssr: true })`;
14
- * the default heuristic handles the common Node-vs-browser split without
15
- * relying on any bundler-injected flag.
16
- */
17
- interface SSRDetectOptions {
18
- override?: boolean;
19
- }
20
-
21
- /**
22
- * Options for `createAttaform()`.
23
- */
24
- type AttaformPluginOptions = SSRDetectOptions & {
25
- /**
26
- * Whether to install the Vue DevTools integration. Default `true`.
27
- * The DevTools peer dependency is loaded lazily — in production
28
- * builds where it's absent, the import fails silently and no
29
- * extra bundle is shipped. Pass `false` to skip even attempting
30
- * the import.
31
- */
32
- devtools?: boolean;
33
- /**
34
- * App-level defaults applied to every `useForm` call in this app.
35
- * Per-form options always win. See `AttaformDefaults` for
36
- * the supported option set and the merge rules.
37
- *
38
- * ```ts
39
- * app.use(
40
- * createAttaform({
41
- * defaults: { debounceMs: 100 },
42
- * })
43
- * )
44
- * ```
45
- */
46
- defaults?: AttaformDefaults;
47
- };
48
- /**
49
- * Create the Vue plugin that installs the form library on a Vue
50
- * application. Call once per app, then `app.use(...)` the result.
51
- *
52
- * ```ts
53
- * import { createApp } from 'vue'
54
- * import { createAttaform } from 'attaform'
55
- *
56
- * createApp(App)
57
- * .use(createAttaform())
58
- * .mount('#app')
59
- * ```
60
- *
61
- * Under SSR with bare Vue 3, pass `{ ssr: true }` from your server
62
- * entry. Under Nuxt, install via `attaform/nuxt` instead —
63
- * the Nuxt module wires both server and client automatically.
64
- *
65
- * Installing more than once on the same app is a no-op (the second
66
- * call logs a dev-mode warning).
67
- */
68
- declare function createAttaform(options?: AttaformPluginOptions): Plugin;
4
+ export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.CVv9Oh0a.mjs';
5
+ export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, c as ReservedFormKeyError, S as SensitivePersistFieldError, d as SubmitErrorHandlerError } from './shared/attaform.B7rzpK1U.mjs';
69
6
 
70
7
  /**
71
8
  * Schema-driven coercion of user-typed DOM values at the v-register
@@ -110,6 +47,20 @@ declare function defineCoercion<I extends SlimPrimitiveKind, O extends SlimPrimi
110
47
  */
111
48
  declare const defaultCoercionRules: CoercionRegistry;
112
49
 
50
+ /**
51
+ * Portable SSR detection. The plugin captures this value at install time and
52
+ * exposes it via the registry so every runtime branch reads a single source
53
+ * of truth instead of sniffing `import.meta.*` (bundler-specific) at each
54
+ * call site.
55
+ *
56
+ * Consumers can override explicitly via `createAttaform({ ssr: true })`;
57
+ * the default heuristic handles the common Node-vs-browser split without
58
+ * relying on any bundler-injected flag.
59
+ */
60
+ interface SSRDetectOptions {
61
+ override?: boolean;
62
+ }
63
+
113
64
  /**
114
65
  * Per-Vue-app container for all form state instances. Each
115
66
  * `app.use(createAttaform())` call gets its own registry,
@@ -223,6 +174,61 @@ declare function useRegistry(): AttaformRegistry;
223
174
  */
224
175
  declare function getRegistryFromApp(app: App): AttaformRegistry;
225
176
 
177
+ /**
178
+ * Options for `createAttaform()`.
179
+ */
180
+ type AttaformPluginOptions = SSRDetectOptions & {
181
+ /**
182
+ * Whether to install the Vue DevTools integration. Default `true`.
183
+ * The DevTools peer dependency is loaded lazily — in production
184
+ * builds where it's absent, the import fails silently and no
185
+ * extra bundle is shipped. Pass `false` to skip even attempting
186
+ * the import.
187
+ */
188
+ devtools?: boolean;
189
+ /**
190
+ * App-level defaults applied to every `useForm` call in this app.
191
+ * Per-form options always win. See `AttaformDefaults` for
192
+ * the supported option set and the merge rules.
193
+ *
194
+ * ```ts
195
+ * app.use(
196
+ * createAttaform({
197
+ * defaults: { debounceMs: 100 },
198
+ * })
199
+ * )
200
+ * ```
201
+ */
202
+ defaults?: AttaformDefaults;
203
+ };
204
+ /**
205
+ * Create the Vue plugin that installs the form library on a Vue
206
+ * application. Required only when you want app-wide options
207
+ * (`defaults`, `devtools: false`, `ssr: true`) — for the default
208
+ * setup, `useForm` / `injectForm` / `useRegister` lazy-install the
209
+ * registry on first use.
210
+ *
211
+ * ```ts
212
+ * import { createApp } from 'vue'
213
+ * import { createAttaform } from 'attaform'
214
+ *
215
+ * createApp(App)
216
+ * .use(createAttaform({ defaults: { debounceMs: 100 } }))
217
+ * .mount('#app')
218
+ * ```
219
+ *
220
+ * Under SSR with bare Vue 3, install explicitly with `{ ssr: true }`
221
+ * from your server entry — the SSR serialization helpers
222
+ * (`renderAttaformState` / `hydrateAttaformState`) require an
223
+ * already-attached registry and don't trigger lazy install. Under
224
+ * Nuxt, install via `attaform/nuxt` instead — the Nuxt module wires
225
+ * both server and client automatically.
226
+ *
227
+ * Installing more than once on the same app is a no-op (the second
228
+ * call logs a dev-mode warning).
229
+ */
230
+ declare function createAttaform(options?: AttaformPluginOptions): Plugin;
231
+
226
232
  /**
227
233
  * Serialised snapshot of every form in a Vue app, produced by
228
234
  * `renderAttaformState` and consumed by `hydrateAttaformState`.
@@ -305,10 +311,9 @@ declare function escapeForInlineScript(json: string): string;
305
311
  * })
306
312
  * ```
307
313
  *
308
- * Most consumers prefer a typed entry point e.g.
309
- * `attaform/zod` (v4) or `attaform/zod-v3`
310
- * which wrap the underlying library's schema with the matching
311
- * adapter automatically.
314
+ * Most consumers prefer a typed entry point that wraps the underlying
315
+ * library's schema with the matching adapter automatically; see the
316
+ * subpath documentation for the available adapters.
312
317
  *
313
318
  * Returns the same form API as the typed entry points; see
314
319
  * `UseFormReturnType` for the full surface.
package/dist/index.d.ts CHANGED
@@ -1,71 +1,8 @@
1
- import { Plugin, App, InjectionKey } from 'vue';
2
- import { A as AttaformDefaults, C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform.0Gxd_OOx.js';
1
+ import { App, InjectionKey, Plugin } from 'vue';
2
+ import { C as CoercionRegistry, S as SlimPrimitiveKind, a as CoercionEntry, A as AttaformDefaults, F as FormKey, G as GenericForm, U as UseFormConfiguration, b as AbstractSchema, D as DeepPartial, c as DefaultValuesShape, d as UseFormReturnType, R as RegisterValue, e as RegisterModelDynamicCustomDirective, V as ValidationError, f as ApiErrorEnvelope, g as ApiErrorDetails } from './shared/attaform.0Gxd_OOx.js';
3
3
  export { h as ApiErrorEntry, i as ArrayItem, j as ArrayPath, k as CoercionResult, l as CustomDirectiveRegisterAssignerFn, m as DefaultValuesResponse, n as FieldMetaPayload, o as FieldState, p as FieldStateMap, q as FieldStateMapEntry, r as FlatPath, s as FormErrorRecord, t as FormErrorsSurface, u as FormMeta, v as FormStorage, w as FormStorageKind, H as HandleSubmit, x as HistoryConfig, I as IsTuple, y as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, z as NestedType, O as OnError, B as OnInvalidSubmitPolicy, E as OnSubmit, P as Path, Q as PathKey, T as PendingValidationStatus, W as PersistConfig, X as PersistConfigOptions, Y as PersistIncludeMode, Z as ROOT_PATH, _ as ROOT_PATH_KEY, $ as ReactiveValidationStatus, a0 as RegisterDirective, a1 as RegisterFlatPath, a2 as RegisterOptions, a3 as RegisterSelectModifier, a4 as RegisterTextModifier, a5 as RegisterTransform, a6 as Segment, a7 as SetValueCallback, a8 as SetValuePayload, a9 as SettledValidationStatus, aa as SlimRuntimeOf, ab as SubmitHandler, ac as Unset, ad as ValidateOn, ae as ValidateOnConfig, af as ValidationResponse, ag as ValidationResponseWithoutValue, ah as ValueOfUnion, ai as WriteMeta, aj as WriteShape, ak as canonicalizePath, al as isPathPrefix, am as isUnset, an as parseDottedPath, ao as unset } from './shared/attaform.0Gxd_OOx.js';
4
- export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.riAENZQM.js';
5
- export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, O as OutsideSetupError, R as RegistryNotInstalledError, b as ReservedFormKeyError, S as SensitivePersistFieldError, c as SubmitErrorHandlerError } from './shared/attaform.BwaYWtMs.js';
6
-
7
- /**
8
- * Portable SSR detection. The plugin captures this value at install time and
9
- * exposes it via the registry so every runtime branch reads a single source
10
- * of truth instead of sniffing `import.meta.*` (bundler-specific) at each
11
- * call site.
12
- *
13
- * Consumers can override explicitly via `createAttaform({ ssr: true })`;
14
- * the default heuristic handles the common Node-vs-browser split without
15
- * relying on any bundler-injected flag.
16
- */
17
- interface SSRDetectOptions {
18
- override?: boolean;
19
- }
20
-
21
- /**
22
- * Options for `createAttaform()`.
23
- */
24
- type AttaformPluginOptions = SSRDetectOptions & {
25
- /**
26
- * Whether to install the Vue DevTools integration. Default `true`.
27
- * The DevTools peer dependency is loaded lazily — in production
28
- * builds where it's absent, the import fails silently and no
29
- * extra bundle is shipped. Pass `false` to skip even attempting
30
- * the import.
31
- */
32
- devtools?: boolean;
33
- /**
34
- * App-level defaults applied to every `useForm` call in this app.
35
- * Per-form options always win. See `AttaformDefaults` for
36
- * the supported option set and the merge rules.
37
- *
38
- * ```ts
39
- * app.use(
40
- * createAttaform({
41
- * defaults: { debounceMs: 100 },
42
- * })
43
- * )
44
- * ```
45
- */
46
- defaults?: AttaformDefaults;
47
- };
48
- /**
49
- * Create the Vue plugin that installs the form library on a Vue
50
- * application. Call once per app, then `app.use(...)` the result.
51
- *
52
- * ```ts
53
- * import { createApp } from 'vue'
54
- * import { createAttaform } from 'attaform'
55
- *
56
- * createApp(App)
57
- * .use(createAttaform())
58
- * .mount('#app')
59
- * ```
60
- *
61
- * Under SSR with bare Vue 3, pass `{ ssr: true }` from your server
62
- * entry. Under Nuxt, install via `attaform/nuxt` instead —
63
- * the Nuxt module wires both server and client automatically.
64
- *
65
- * Installing more than once on the same app is a no-op (the second
66
- * call logs a dev-mode warning).
67
- */
68
- declare function createAttaform(options?: AttaformPluginOptions): Plugin;
4
+ export { A as AttaformErrorCode, i as injectForm, u as useRegister } from './shared/attaform.CWCx2r0x.js';
5
+ export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, c as ReservedFormKeyError, S as SensitivePersistFieldError, d as SubmitErrorHandlerError } from './shared/attaform.B7rzpK1U.js';
69
6
 
70
7
  /**
71
8
  * Schema-driven coercion of user-typed DOM values at the v-register
@@ -110,6 +47,20 @@ declare function defineCoercion<I extends SlimPrimitiveKind, O extends SlimPrimi
110
47
  */
111
48
  declare const defaultCoercionRules: CoercionRegistry;
112
49
 
50
+ /**
51
+ * Portable SSR detection. The plugin captures this value at install time and
52
+ * exposes it via the registry so every runtime branch reads a single source
53
+ * of truth instead of sniffing `import.meta.*` (bundler-specific) at each
54
+ * call site.
55
+ *
56
+ * Consumers can override explicitly via `createAttaform({ ssr: true })`;
57
+ * the default heuristic handles the common Node-vs-browser split without
58
+ * relying on any bundler-injected flag.
59
+ */
60
+ interface SSRDetectOptions {
61
+ override?: boolean;
62
+ }
63
+
113
64
  /**
114
65
  * Per-Vue-app container for all form state instances. Each
115
66
  * `app.use(createAttaform())` call gets its own registry,
@@ -223,6 +174,61 @@ declare function useRegistry(): AttaformRegistry;
223
174
  */
224
175
  declare function getRegistryFromApp(app: App): AttaformRegistry;
225
176
 
177
+ /**
178
+ * Options for `createAttaform()`.
179
+ */
180
+ type AttaformPluginOptions = SSRDetectOptions & {
181
+ /**
182
+ * Whether to install the Vue DevTools integration. Default `true`.
183
+ * The DevTools peer dependency is loaded lazily — in production
184
+ * builds where it's absent, the import fails silently and no
185
+ * extra bundle is shipped. Pass `false` to skip even attempting
186
+ * the import.
187
+ */
188
+ devtools?: boolean;
189
+ /**
190
+ * App-level defaults applied to every `useForm` call in this app.
191
+ * Per-form options always win. See `AttaformDefaults` for
192
+ * the supported option set and the merge rules.
193
+ *
194
+ * ```ts
195
+ * app.use(
196
+ * createAttaform({
197
+ * defaults: { debounceMs: 100 },
198
+ * })
199
+ * )
200
+ * ```
201
+ */
202
+ defaults?: AttaformDefaults;
203
+ };
204
+ /**
205
+ * Create the Vue plugin that installs the form library on a Vue
206
+ * application. Required only when you want app-wide options
207
+ * (`defaults`, `devtools: false`, `ssr: true`) — for the default
208
+ * setup, `useForm` / `injectForm` / `useRegister` lazy-install the
209
+ * registry on first use.
210
+ *
211
+ * ```ts
212
+ * import { createApp } from 'vue'
213
+ * import { createAttaform } from 'attaform'
214
+ *
215
+ * createApp(App)
216
+ * .use(createAttaform({ defaults: { debounceMs: 100 } }))
217
+ * .mount('#app')
218
+ * ```
219
+ *
220
+ * Under SSR with bare Vue 3, install explicitly with `{ ssr: true }`
221
+ * from your server entry — the SSR serialization helpers
222
+ * (`renderAttaformState` / `hydrateAttaformState`) require an
223
+ * already-attached registry and don't trigger lazy install. Under
224
+ * Nuxt, install via `attaform/nuxt` instead — the Nuxt module wires
225
+ * both server and client automatically.
226
+ *
227
+ * Installing more than once on the same app is a no-op (the second
228
+ * call logs a dev-mode warning).
229
+ */
230
+ declare function createAttaform(options?: AttaformPluginOptions): Plugin;
231
+
226
232
  /**
227
233
  * Serialised snapshot of every form in a Vue app, produced by
228
234
  * `renderAttaformState` and consumed by `hydrateAttaformState`.
@@ -305,10 +311,9 @@ declare function escapeForInlineScript(json: string): string;
305
311
  * })
306
312
  * ```
307
313
  *
308
- * Most consumers prefer a typed entry point e.g.
309
- * `attaform/zod` (v4) or `attaform/zod-v3`
310
- * which wrap the underlying library's schema with the matching
311
- * adapter automatically.
314
+ * Most consumers prefer a typed entry point that wraps the underlying
315
+ * library's schema with the matching adapter automatically; see the
316
+ * subpath documentation for the available adapters.
312
317
  *
313
318
  * Returns the same form API as the typed entry points; see
314
319
  * `UseFormReturnType` for the full surface.
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
- export { a as assignKey, c as createAttaform, h as hydrateAttaformState, i as isRegisterValue, r as renderAttaformState, v as vRegister } from './shared/attaform.CRk8NhlD.mjs';
2
- import { I as InvalidPathError } from './shared/attaform.a99dQV7Q.mjs';
3
- export { A as AnonPersistError, a as AttaformError, O as OutsideSetupError, R as RegistryNotInstalledError, b as ReservedFormKeyError, S as SensitivePersistFieldError, c as SubmitErrorHandlerError, d as createRegistry, g as getRegistryFromApp, k as kAttaformRegistry, u as useRegister, e as useRegistry } from './shared/attaform.a99dQV7Q.mjs';
4
- export { A as AttaformErrorCode, d as defaultCoercionRules, a as defineCoercion, i as injectForm, b as isUnset, u as unset, c as useForm } from './shared/attaform.qxyip_aN.mjs';
5
- import { c as canonicalizePath } from './shared/attaform.DXye3JKf.mjs';
6
- export { R as ROOT_PATH, a as ROOT_PATH_KEY, i as isPathPrefix, p as parseDottedPath } from './shared/attaform.DXye3JKf.mjs';
1
+ import { I as InvalidPathError } from './shared/attaform.BfMxsfmE.mjs';
2
+ export { A as AnonPersistError, a as AttaformError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, d as ReservedFormKeyError, S as SensitivePersistFieldError, e as SubmitErrorHandlerError, f as assignKey, c as createAttaform, h as createRegistry, g as getRegistryFromApp, j as isRegisterValue, k as kAttaformRegistry, u as useRegister, l as useRegistry, v as vRegister } from './shared/attaform.BfMxsfmE.mjs';
3
+ export { h as hydrateAttaformState, r as renderAttaformState } from './shared/attaform.CINUMjPq.mjs';
4
+ export { A as AttaformErrorCode, d as defaultCoercionRules, b as defineCoercion, i as injectForm, a as isUnset, u as unset, c as useForm } from './shared/attaform.DILbdvfo.mjs';
5
+ import { c as canonicalizePath } from './shared/attaform.jrxE_xZw.mjs';
6
+ export { R as ROOT_PATH, a as ROOT_PATH_KEY, i as isPathPrefix, p as parseDottedPath } from './shared/attaform.jrxE_xZw.mjs';
7
7
 
8
8
  function escapeForInlineScript(json) {
9
9
  return json.replace(/[<>&\u2028\u2029]/g, (char) => {
package/dist/nuxt.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  const node_path = require('node:path');
4
4
  const node_url = require('node:url');
5
5
  const kit = require('@nuxt/kit');
6
- const vRegisterPreambleTransform = require('./shared/attaform.Bubm_slq.cjs');
6
+ const vite = require('./vite.cjs');
7
7
 
8
8
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
9
9
  function isResolvableForVite(specifier, consumerRootDir) {
@@ -28,20 +28,14 @@ var nuxt_default = kit.defineNuxtModule({
28
28
  },
29
29
  defaults: {},
30
30
  setup(_options, nuxt) {
31
- var _a, _b, _c;
32
- (_a = nuxt.options.vue.compilerOptions).nodeTransforms ?? (_a.nodeTransforms = []);
33
- nuxt.options.vue.compilerOptions.nodeTransforms.push(
34
- vRegisterPreambleTransform.selectNodeTransform,
35
- vRegisterPreambleTransform.inputTextAreaNodeTransform,
36
- vRegisterPreambleTransform.vRegisterPreambleTransform,
37
- vRegisterPreambleTransform.vRegisterHintTransform
38
- );
31
+ var _a, _b;
32
+ kit.addVitePlugin(vite.attaform({ resolveZodAlias: _options.resolveZodAlias !== false }));
39
33
  const runtimePublic = nuxt.options.runtimeConfig.public;
40
34
  runtimePublic["attaform"] = {
41
35
  defaults: _options.defaults ?? {}
42
36
  };
43
- (_b = nuxt.options.vite).optimizeDeps ?? (_b.optimizeDeps = {});
44
- (_c = nuxt.options.vite.optimizeDeps).include ?? (_c.include = []);
37
+ (_a = nuxt.options.vite).optimizeDeps ?? (_a.optimizeDeps = {});
38
+ (_b = nuxt.options.vite.optimizeDeps).include ?? (_b.include = []);
45
39
  const include = nuxt.options.vite.optimizeDeps.include;
46
40
  for (const spec of ["@vue/devtools-api", "zod"]) {
47
41
  if (!isResolvableForVite(spec, nuxt.options.rootDir)) continue;
package/dist/nuxt.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"nuxt.cjs","sources":["../src/nuxt.ts"],"sourcesContent":["import { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { addImports, addPlugin, addTypeTemplate, createResolver, defineNuxtModule } from '@nuxt/kit'\nimport { inputTextAreaNodeTransform } from './runtime/lib/core/transforms/input-text-area-transform'\nimport { selectNodeTransform } from './runtime/lib/core/transforms/select-transform'\nimport { vRegisterHintTransform } from './runtime/lib/core/transforms/v-register-hint-transform'\nimport { vRegisterPreambleTransform } from './runtime/lib/core/transforms/v-register-preamble-transform'\nimport type { AttaformDefaults } from './runtime/types/types-api'\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\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\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 compatibility: {\n nuxt: '>=3.0.0',\n },\n },\n defaults: {},\n setup(_options, nuxt) {\n // vRegisterPreambleTransform MUST come before vRegisterHintTransform\n // — see src/vite.ts for the ordering rationale.\n nuxt.options.vue.compilerOptions.nodeTransforms ??= []\n nuxt.options.vue.compilerOptions.nodeTransforms.push(\n selectNodeTransform,\n inputTextAreaNodeTransform,\n vRegisterPreambleTransform,\n vRegisterHintTransform\n )\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 } 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 `/zod` and `/zod-v3` adapter peer). 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 // v-register directive type. The directive itself is globally\n // registered by `createAttaform().install(app)` in the plugin\n // above; this template only publishes the type so that\n // `<input v-register=\"…\">` type-checks in consumer SFCs.\n addTypeTemplate({\n filename: 'types/v-register.d.ts',\n getContents: () => `// Generated by attaform\nimport type { ObjectDirective } from \"vue\"\nimport type { RegisterDirective } from \"attaform/types\"\n\ndeclare module \"vue\" {\n interface GlobalDirectives {\n /**\n * The \\`v-register\\` directive. Binds a form field to a native\n * input, select, textarea, checkbox, or radio:\n *\n * \\`\\`\\`vue\n * <input v-register=\"form.register('email')\" />\n * \\`\\`\\`\n *\n * Also works on custom components whose root is NOT a native\n * input — call \\`useRegister()\\` in the child's setup to read\n * the parent's binding, then re-bind \\`v-register\\` onto an\n * inner native element. (When the wrapper's root IS the input\n * itself, attribute fallthrough handles it; \\`useRegister\\` is\n * unnecessary.) See \\`RegisterDirective\\` for the full\n * non-input-root example.\n *\n * Modifier support varies by element:\n * - text / number / textarea: \\`.lazy\\`, \\`.trim\\`, \\`.number\\`\n * - select: \\`.number\\`\n * - checkbox / radio: none\n *\n * See \\`RegisterDirective\\` for full usage and per-modifier\n * semantics.\n */\n vRegister: RegisterDirective\n }\n}\n\nexport { }`,\n })\n },\n})\n"],"names":["pathToFileURL","join","defineNuxtModule","selectNodeTransform","inputTextAreaNodeTransform","vRegisterPreambleTransform","vRegisterHintTransform","createResolver","addImports","addPlugin","addTypeTemplate"],"mappings":";;;;;;;;AAkEA,SAAS,mBAAA,CAAoB,WAAmB,eAAA,EAAkC;AAChF,EAAA,MAAM,cAAcA,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,aAAA,EAAe;AAAA,MACb,IAAA,EAAM;AAAA;AACR,GACF;AAAA,EACA,UAAU,EAAC;AAAA,EACX,KAAA,CAAM,UAAU,IAAA,EAAM;AAzFxB,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AA4FI,IAAA,CAAA,EAAA,GAAA,IAAA,CAAK,QAAQ,GAAA,CAAI,eAAA,EAAgB,cAAA,KAAjC,EAAA,CAAiC,iBAAmB,EAAC,CAAA;AACrD,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,IAAA;AAAA,MAC9CC,8CAAA;AAAA,MACAC,qDAAA;AAAA,MACAC,qDAAA;AAAA,MACAC;AAAA,KACF;AAMA,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;AAAC,KAClC;AAuBA,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;AAiB/C,IAAAC,cAAA,CAAW,CAAC,EAAE,IAAA,EAAM,WAAW,IAAA,EAAM,UAAA,EAAY,CAAC,CAAA;AAsBlD,IAAAC,aAAA,CAAU;AAAA,MACR,GAAA,EAAK,QAAA,CAAS,OAAA,CAAQ,4BAA4B;AAAA,KACnD,CAAA;AAMD,IAAAC,mBAAA,CAAgB;AAAA,MACd,QAAA,EAAU,uBAAA;AAAA,MACV,aAAa,MAAM,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,UAAA;AAAA,KAmCpB,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"nuxt.cjs","sources":["../src/nuxt.ts"],"sourcesContent":["import { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport {\n addImports,\n addPlugin,\n addTypeTemplate,\n addVitePlugin,\n createResolver,\n defineNuxtModule,\n} from '@nuxt/kit'\nimport type { AttaformDefaults } from './runtime/types/types-api'\nimport { attaform as attaformVitePlugin } from './vite'\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\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 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 } 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 // v-register directive type. The directive itself is globally\n // registered by `createAttaform().install(app)` in the plugin\n // above; this template only publishes the type so that\n // `<input v-register=\"…\">` type-checks in consumer SFCs.\n addTypeTemplate({\n filename: 'types/v-register.d.ts',\n getContents: () => `// Generated by attaform\nimport type { ObjectDirective } from \"vue\"\nimport type { RegisterDirective } from \"attaform/types\"\n\ndeclare module \"vue\" {\n interface GlobalDirectives {\n /**\n * The \\`v-register\\` directive. Binds a form field to a native\n * input, select, textarea, checkbox, or radio:\n *\n * \\`\\`\\`vue\n * <input v-register=\"form.register('email')\" />\n * \\`\\`\\`\n *\n * Also works on custom components whose root is NOT a native\n * input — call \\`useRegister()\\` in the child's setup to read\n * the parent's binding, then re-bind \\`v-register\\` onto an\n * inner native element. (When the wrapper's root IS the input\n * itself, attribute fallthrough handles it; \\`useRegister\\` is\n * unnecessary.) See \\`RegisterDirective\\` for the full\n * non-input-root example.\n *\n * Modifier support varies by element:\n * - text / number / textarea: \\`.lazy\\`, \\`.trim\\`, \\`.number\\`\n * - select: \\`.number\\`\n * - checkbox / radio: none\n *\n * See \\`RegisterDirective\\` for full usage and per-modifier\n * semantics.\n */\n vRegister: RegisterDirective\n }\n}\n\nexport { }`,\n })\n },\n})\n"],"names":["pathToFileURL","join","defineNuxtModule","addVitePlugin","attaformVitePlugin","createResolver","addImports","addPlugin","addTypeTemplate"],"mappings":";;;;;;;;AA8EA,SAAS,mBAAA,CAAoB,WAAmB,eAAA,EAAkC;AAChF,EAAA,MAAM,cAAcA,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,aAAA,EAAe;AAAA,MACb,IAAA,EAAM;AAAA;AACR,GACF;AAAA,EACA,UAAU,EAAC;AAAA,EACX,KAAA,CAAM,UAAU,IAAA,EAAM;AArGxB,IAAA,IAAA,EAAA,EAAA,EAAA;AA+GI,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;AAAC,KAClC;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;AAiB/C,IAAAC,cAAA,CAAW,CAAC,EAAE,IAAA,EAAM,WAAW,IAAA,EAAM,UAAA,EAAY,CAAC,CAAA;AAsBlD,IAAAC,aAAA,CAAU;AAAA,MACR,GAAA,EAAK,QAAA,CAAS,OAAA,CAAQ,4BAA4B;AAAA,KACnD,CAAA;AAMD,IAAAC,mBAAA,CAAgB;AAAA,MACd,QAAA,EAAU,uBAAA;AAAA,MACV,aAAa,MAAM,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,UAAA;AAAA,KAmCpB,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
package/dist/nuxt.d.cts CHANGED
@@ -23,6 +23,14 @@ interface AttaformModuleOptions {
23
23
  * supported option set and merge rules.
24
24
  */
25
25
  defaults?: AttaformDefaults;
26
+ /**
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
31
+ * the rewrite and ship the runtime-dispatch unified entry instead.
32
+ */
33
+ resolveZodAlias?: boolean;
26
34
  }
27
35
  /**
28
36
  * Shape of the Nuxt public runtime-config slot the module populates.