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
@@ -1,5 +1,141 @@
1
- import { f as getOrAssignElementId, _ as __DEV__, h as REGISTER_OWNER_MARKER, j as enforceSensitiveCheck, d as createRegistry, l as attachRegistryToApp, g as getRegistryFromApp } from './attaform.a99dQV7Q.mjs';
2
- import { nextTick, warn, isRef } from 'vue';
1
+ import { shallowReactive, getCurrentInstance, inject, shallowRef, onBeforeMount, onBeforeUpdate, onMounted, nextTick, warn, isRef } from 'vue';
2
+
3
+ const __DEV__ = typeof process !== "undefined" && process.env["NODE_ENV"] !== "production";
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
+ class AttaformError extends Error {
9
+ constructor(message, options) {
10
+ super(message, options);
11
+ this.name = new.target.name;
12
+ }
13
+ }
14
+ class InvalidPathError extends AttaformError {
15
+ }
16
+ class InvalidUseFormConfigError extends AttaformError {
17
+ constructor() {
18
+ super(
19
+ "[attaform] useForm received an invalid configuration (a schema directly, no argument, or no `schema` field). Pass it as `useForm({ schema })` \u2014 the schema is one of several configuration options. See https://attaform.com/docs/api/use-form-return for the full configuration shape."
20
+ );
21
+ }
22
+ }
23
+ class SubmitErrorHandlerError extends AttaformError {
24
+ }
25
+ class RegistryNotInstalledError extends AttaformError {
26
+ constructor() {
27
+ super(
28
+ "[attaform] No registry attached to this Vue app. Component-level useForm / injectForm / useRegister auto-install the registry, but SSR helpers (renderAttaformState, hydrateAttaformState) run outside setup and require an explicit `app.use(createAttaform())` at server-render time. Add it to your SSR entry, before `renderToString`."
29
+ );
30
+ }
31
+ }
32
+ class OutsideSetupError extends AttaformError {
33
+ constructor() {
34
+ super(
35
+ "[attaform] useForm / injectForm called outside Vue setup(). Move into setup or mount a child component to trigger from an event."
36
+ );
37
+ }
38
+ }
39
+ class ReservedFormKeyError extends AttaformError {
40
+ constructor(key) {
41
+ super(
42
+ `[attaform] Form key "${key}" uses the reserved "__atta:" namespace. Use a different prefix \u2014 "__atta:" is for library-internal synthetic keys (anonymous useForm() calls without an explicit key).`
43
+ );
44
+ }
45
+ }
46
+ class SensitivePersistFieldError extends AttaformError {
47
+ constructor(path) {
48
+ const display = Array.isArray(path) ? path.join(".") : String(path);
49
+ super(
50
+ `[attaform] Refusing to persist "${display}" \u2014 this path matches a sensitive-name pattern (password / cvv / ssn / token / etc.). Storing sensitive data in client-side storage is a compliance risk (HIPAA / PII / PCI-DSS / SOC2). Fix: persist this server-side, OR pass \`acknowledgeSensitive: true\` to register() (or form.persist()) if the client-side persistence is intentional.`
51
+ );
52
+ }
53
+ }
54
+ class AnonPersistError extends AttaformError {
55
+ constructor(opts) {
56
+ super(formatAnonPersistMessage(opts));
57
+ __publicField(this, "schemaFields");
58
+ __publicField(this, "callSite");
59
+ __publicField(this, "cause");
60
+ this.schemaFields = opts.schemaFields;
61
+ this.callSite = opts.callSite;
62
+ this.cause = opts.cause;
63
+ }
64
+ }
65
+ function formatAnonPersistMessage(opts) {
66
+ const head = opts.cause === "no-key" ? `useForm({ persist: ... }) requires an explicit \`key:\`. Anonymous synthetic keys (\`__atta:anon:*\`) drift across mounts and can collide between unrelated forms \u2014 refusing to persist to a non-deterministic location.` : `register(_, { persist: true }) declared on a form whose useForm() options have no \`persist:\` configured. The opt-in is recorded but nothing would ever land in storage.`;
67
+ const fields = opts.schemaFields !== void 0 && opts.schemaFields.length > 0 ? ` Form fields: { ${opts.schemaFields.join(", ")} }.` : "";
68
+ const fix = opts.cause === "no-key" ? ` Fix: add \`key: '<stable-id>'\` to useForm().` : ` Fix: add \`persist: 'session'\` (or 'local') and \`key:\` to useForm(), or remove \`{ persist: true }\` from this register() call.`;
69
+ const where = opts.callSite !== void 0 ? ` ${opts.callSite}` : "";
70
+ return `[attaform] ${head}${fields}${fix}${where}`;
71
+ }
72
+
73
+ function detectSSR(options = {}) {
74
+ if (options.override !== void 0) return options.override;
75
+ return typeof window === "undefined" && typeof document === "undefined";
76
+ }
77
+
78
+ const kAttaformRegistry = Symbol.for("attaform:registry");
79
+ const kFormContext = Symbol.for("attaform:form-context");
80
+ const kFormInstanceId = Symbol.for("attaform:form-instance-id");
81
+ function createRegistry(options = {}) {
82
+ const ssr = detectSSR(options);
83
+ const defaults = Object.freeze({ ...options.defaults ?? {} });
84
+ const forms = shallowReactive(/* @__PURE__ */ new Map());
85
+ const pendingHydration = shallowReactive(/* @__PURE__ */ new Map());
86
+ const consumers = /* @__PURE__ */ new Map();
87
+ const evicting = /* @__PURE__ */ new Set();
88
+ function trackConsumer(key) {
89
+ consumers.set(key, (consumers.get(key) ?? 0) + 1);
90
+ let disposed = false;
91
+ return () => {
92
+ if (disposed) return;
93
+ disposed = true;
94
+ const remaining = (consumers.get(key) ?? 1) - 1;
95
+ if (remaining <= 0) {
96
+ const state = forms.get(key);
97
+ consumers.delete(key);
98
+ forms.delete(key);
99
+ if (state !== void 0) {
100
+ evicting.add(state);
101
+ void state.awaitPendingWrites().catch(() => void 0).finally(() => {
102
+ evicting.delete(state);
103
+ state.dispose();
104
+ });
105
+ }
106
+ } else {
107
+ consumers.set(key, remaining);
108
+ }
109
+ };
110
+ }
111
+ async function shutdown() {
112
+ const states = [...forms.values(), ...evicting];
113
+ await Promise.allSettled(states.map((state) => state.awaitPendingWrites()));
114
+ }
115
+ return { forms, pendingHydration, ssr, defaults, trackConsumer, shutdown };
116
+ }
117
+ function useRegistry() {
118
+ const instance = getCurrentInstance();
119
+ if (instance === null) {
120
+ throw new OutsideSetupError();
121
+ }
122
+ const registry = inject(kAttaformRegistry, null);
123
+ if (registry === null) {
124
+ throw new RegistryNotInstalledError();
125
+ }
126
+ return registry;
127
+ }
128
+ function getRegistryFromApp(app) {
129
+ const registry = app._attaform;
130
+ if (registry === void 0) {
131
+ throw new RegistryNotInstalledError();
132
+ }
133
+ return registry;
134
+ }
135
+ function attachRegistryToApp(app, registry) {
136
+ app.provide(kAttaformRegistry, registry);
137
+ app._attaform = registry;
138
+ }
3
139
 
4
140
  const isArray = Array.isArray;
5
141
  function isFunction(value) {
@@ -72,6 +208,267 @@ function invokeArrayFns(fns, ...args) {
72
208
  }
73
209
  }
74
210
 
211
+ function captureUserCallSite() {
212
+ const raw = new Error().stack;
213
+ if (typeof raw !== "string") return void 0;
214
+ const lines = raw.split("\n");
215
+ for (let i = 1; i < lines.length; i++) {
216
+ const frame = lines[i];
217
+ if (frame === void 0) continue;
218
+ if (/attaform[/-]forms?/i.test(frame)) continue;
219
+ if (/\bforms\.[A-Za-z0-9_-]+\.m?js\b/.test(frame)) continue;
220
+ const trimmed = frame.trim();
221
+ if (trimmed.length === 0) continue;
222
+ return shortenSourceFrame(trimmed);
223
+ }
224
+ return void 0;
225
+ }
226
+ function shortenSourceFrame(frame) {
227
+ const match = /(?:^|\s|\()([^\s()]+):(\d+):\d+\)?$/.exec(frame);
228
+ if (match === null) return frame;
229
+ const [, urlOrPath, line] = match;
230
+ if (urlOrPath === void 0 || line === void 0) return frame;
231
+ let path = urlOrPath;
232
+ path = path.replace(/^[a-z]+:\/\/[^/]+\//i, "");
233
+ path = path.replace(/^_nuxt\//, "");
234
+ path = path.replace(/^\//, "");
235
+ return `(${path}:${line})`;
236
+ }
237
+
238
+ const REGISTER_OWNER_MARKER = Symbol.for("attaform:register-owner-marker");
239
+ const warnedNoParentRV = __DEV__ ? /* @__PURE__ */ new WeakSet() : null;
240
+ let warnedOutsideSetup = false;
241
+ function makeRegisterValueProxy(capturedRegisterValue) {
242
+ return new Proxy({}, {
243
+ get(_target, prop) {
244
+ if (prop === "__v_isRef") return true;
245
+ if (prop === "value") return capturedRegisterValue.value;
246
+ const v = capturedRegisterValue.value;
247
+ if (v === void 0) return void 0;
248
+ return Reflect.get(v, prop);
249
+ },
250
+ has(_target, prop) {
251
+ if (prop === "__v_isRef" || prop === "value") return true;
252
+ const v = capturedRegisterValue.value;
253
+ if (v === void 0) return false;
254
+ return Reflect.has(v, prop);
255
+ },
256
+ ownKeys(_target) {
257
+ const v = capturedRegisterValue.value;
258
+ if (v === void 0) return [];
259
+ return Reflect.ownKeys(v);
260
+ },
261
+ getOwnPropertyDescriptor(_target, prop) {
262
+ const v = capturedRegisterValue.value;
263
+ if (v === void 0) return void 0;
264
+ const desc = Reflect.getOwnPropertyDescriptor(v, prop);
265
+ if (desc !== void 0) {
266
+ desc.configurable = true;
267
+ }
268
+ return desc;
269
+ }
270
+ });
271
+ }
272
+ function useRegister() {
273
+ const instance = getCurrentInstance();
274
+ if (instance === null) {
275
+ warnOutsideSetup();
276
+ return makeRegisterValueProxy(shallowRef(void 0));
277
+ }
278
+ ensureAttaformInstalled(instance.appContext.app);
279
+ const capturedRegisterValue = shallowRef(void 0);
280
+ const refreshAndStripBridgeAttrs = () => {
281
+ const rawAttrs = instance.attrs;
282
+ if ("registerValue" in rawAttrs) {
283
+ capturedRegisterValue.value = rawAttrs["registerValue"];
284
+ delete rawAttrs["registerValue"];
285
+ }
286
+ if ("value" in rawAttrs) delete rawAttrs["value"];
287
+ };
288
+ refreshAndStripBridgeAttrs();
289
+ onBeforeMount(refreshAndStripBridgeAttrs);
290
+ onBeforeUpdate(refreshAndStripBridgeAttrs);
291
+ onMounted(() => {
292
+ const el = instance.vnode.el;
293
+ if (el !== null && el !== void 0 && typeof el === "object") {
294
+ el[REGISTER_OWNER_MARKER] = true;
295
+ }
296
+ if (capturedRegisterValue.value === void 0) {
297
+ warnNoParentRV(instance);
298
+ }
299
+ });
300
+ return makeRegisterValueProxy(capturedRegisterValue);
301
+ }
302
+ function warnOutsideSetup() {
303
+ if (!__DEV__) return;
304
+ if (warnedOutsideSetup) return;
305
+ warnedOutsideSetup = true;
306
+ const frame = captureUserCallSite();
307
+ console.warn(
308
+ `[attaform] useRegister() called outside a component setup; returning an unbound RegisterValue proxy. Fix: call it inside <script setup> or a setup() function \u2014 not from an event handler or async callback.` + (frame !== void 0 ? ` ${frame}` : "")
309
+ );
310
+ }
311
+ function warnNoParentRV(instance) {
312
+ if (!__DEV__ || warnedNoParentRV === null) return;
313
+ if (warnedNoParentRV.has(instance)) return;
314
+ warnedNoParentRV.add(instance);
315
+ const frame = captureUserCallSite();
316
+ console.warn(
317
+ `[attaform] useRegister: no parent registerValue prop; RegisterValue fields will read as undefined. Pass v-register on the parent: \`<YourComponent v-register="form.register('field')" />\`.` + (frame !== void 0 ? ` ${frame}` : "")
318
+ );
319
+ }
320
+
321
+ const idGenerator = /* @__PURE__ */ (() => {
322
+ let counter = 0;
323
+ return () => `el-${++counter}`;
324
+ })();
325
+ const elementIds = /* @__PURE__ */ new WeakMap();
326
+ function getOrAssignElementId(el) {
327
+ let id = elementIds.get(el);
328
+ if (id === void 0) {
329
+ id = idGenerator();
330
+ elementIds.set(el, id);
331
+ }
332
+ return id;
333
+ }
334
+ function createPersistOptInRegistry() {
335
+ const byPath = /* @__PURE__ */ new Map();
336
+ function add(elementId, path) {
337
+ const existing = byPath.get(path);
338
+ if (existing === void 0) {
339
+ byPath.set(path, /* @__PURE__ */ new Set([elementId]));
340
+ return;
341
+ }
342
+ existing.add(elementId);
343
+ }
344
+ function remove(elementId, path) {
345
+ const existing = byPath.get(path);
346
+ if (existing === void 0) return;
347
+ existing.delete(elementId);
348
+ if (existing.size === 0) byPath.delete(path);
349
+ }
350
+ function removeAllFor(elementId) {
351
+ for (const [path, ids] of byPath) {
352
+ if (!ids.delete(elementId)) continue;
353
+ if (ids.size === 0) byPath.delete(path);
354
+ }
355
+ }
356
+ function hasOptIn(elementId, path) {
357
+ return byPath.get(path)?.has(elementId) ?? false;
358
+ }
359
+ function hasAnyOptInForPath(path) {
360
+ const ids = byPath.get(path);
361
+ return ids !== void 0 && ids.size > 0;
362
+ }
363
+ function optedInPaths() {
364
+ return byPath.keys();
365
+ }
366
+ function isEmpty() {
367
+ return byPath.size === 0;
368
+ }
369
+ function clear() {
370
+ byPath.clear();
371
+ }
372
+ return {
373
+ add,
374
+ remove,
375
+ removeAllFor,
376
+ hasOptIn,
377
+ hasAnyOptInForPath,
378
+ optedInPaths,
379
+ isEmpty,
380
+ clear
381
+ };
382
+ }
383
+
384
+ const SENSITIVE_NAME_PATTERNS = [
385
+ // Passwords and PIN-like
386
+ /password/i,
387
+ /passwd/i,
388
+ /passwords/i,
389
+ /\bpwd\b/i,
390
+ /\bpin\b/i,
391
+ // Card / payment
392
+ /\bcvv\b/i,
393
+ /\bcvc\b/i,
394
+ /card[_\s-]?(?:number|num)/i,
395
+ /\bcard\b/i,
396
+ /\biban\b/i,
397
+ /routing[_\s-]?number/i,
398
+ /account[_\s-]?number/i,
399
+ // Government / identity
400
+ /\bssn\b/i,
401
+ /social[_\s-]?security/i,
402
+ /\bdob\b/i,
403
+ /date[_\s-]?of[_\s-]?birth/i,
404
+ /passport/i,
405
+ /driver[_\s-]?license/i,
406
+ // Tax IDs (US + international common variants)
407
+ /\btin\b/i,
408
+ /\bein\b/i,
409
+ /\bitin\b/i,
410
+ /tax[_\s-]?id/i,
411
+ // Tokens, secrets, API/auth credentials
412
+ /\btoken\b/i,
413
+ /\btokens\b/i,
414
+ /secret/i,
415
+ /secrets/i,
416
+ /api[_\s-]?key/i,
417
+ /api[_\s-]?secret/i,
418
+ /api[_\s-]?token/i,
419
+ /private[_\s-]?key/i,
420
+ /\bbearer\b/i,
421
+ /\boauth\b/i,
422
+ /auth[_\s-]?token/i,
423
+ /access[_\s-]?token/i,
424
+ /refresh[_\s-]?token/i,
425
+ /session[_\s-]?(?:id|key|token)/i,
426
+ // MFA / OTP
427
+ /\botp\b/i,
428
+ /one[_\s-]?time[_\s-]?(?:password|code)/i,
429
+ /mfa[_\s-]?(?:secret|seed|code|token)/i,
430
+ /two[_\s-]?factor[_\s-]?(?:code|token)/i,
431
+ /\b2fa[_\s-]?(?:code|token)?\b/i,
432
+ /recovery[_\s-]?code/i,
433
+ /backup[_\s-]?code/i
434
+ ];
435
+ function segmentMatchesSensitive(segment) {
436
+ if (typeof segment !== "string") return false;
437
+ for (const pattern of SENSITIVE_NAME_PATTERNS) {
438
+ if (pattern.test(segment)) return true;
439
+ }
440
+ return false;
441
+ }
442
+ function isSensitivePath(path) {
443
+ if (typeof path !== "string") {
444
+ for (const segment of path) {
445
+ if (segmentMatchesSensitive(segment)) return true;
446
+ }
447
+ return false;
448
+ }
449
+ if (path.startsWith("[")) {
450
+ try {
451
+ const parsed = JSON.parse(path);
452
+ if (Array.isArray(parsed)) {
453
+ for (const segment of parsed) {
454
+ if (segmentMatchesSensitive(segment)) return true;
455
+ }
456
+ return false;
457
+ }
458
+ } catch {
459
+ }
460
+ }
461
+ for (const segment of path.split(".")) {
462
+ if (segmentMatchesSensitive(segment)) return true;
463
+ }
464
+ return false;
465
+ }
466
+ function enforceSensitiveCheck(path, acknowledged) {
467
+ if (acknowledged) return;
468
+ if (!isSensitivePath(path)) return;
469
+ throw new SensitivePersistFieldError(path);
470
+ }
471
+
75
472
  const assignKey = Symbol.for("attaform:assign-key");
76
473
  const listenersKey = Symbol.for("attaform:directive-listeners");
77
474
  function isRegisterValue(val) {
@@ -733,58 +1130,40 @@ function callModelHook(el, binding, vnode, prevVNode, hook) {
733
1130
  }
734
1131
  const vRegister = vRegisterDynamic;
735
1132
 
1133
+ function installAttaformOnApp(app, options, source) {
1134
+ if (app._attaform !== void 0) {
1135
+ if (__DEV__ && source === "explicit") {
1136
+ console.warn(
1137
+ "[attaform] createAttaform() install was called twice on the same app; the second call is a no-op. Likely cause: registering the plugin via both the Nuxt module AND a manual `app.use(...)`."
1138
+ );
1139
+ }
1140
+ return app._attaform;
1141
+ }
1142
+ const registry = createRegistry(options);
1143
+ attachRegistryToApp(app, registry);
1144
+ app.directive("register", vRegister);
1145
+ if (options.devtools !== false && !registry.ssr) {
1146
+ void (async () => {
1147
+ try {
1148
+ const { setupAttaformDevtools } = await import('../chunks/devtools.mjs');
1149
+ await setupAttaformDevtools(app, registry);
1150
+ } catch {
1151
+ }
1152
+ })();
1153
+ }
1154
+ return registry;
1155
+ }
1156
+ function ensureAttaformInstalled(app) {
1157
+ return installAttaformOnApp(app, {}, "lazy");
1158
+ }
736
1159
  function createAttaform(options = {}) {
737
1160
  const plugin = {
738
1161
  install(app) {
739
- if (app._attaform !== void 0) {
740
- if (__DEV__) {
741
- console.warn(
742
- "[attaform] createAttaform() install was called twice on the same app; the second call is a no-op. Likely cause: registering the plugin via both the Nuxt module AND a manual `app.use(...)`."
743
- );
744
- }
745
- return;
746
- }
747
- const registry = createRegistry(options);
748
- attachRegistryToApp(app, registry);
749
- app.directive("register", vRegister);
750
- if (options.devtools !== false && !registry.ssr) {
751
- void (async () => {
752
- try {
753
- const { setupAttaformDevtools } = await import('../chunks/devtools.mjs');
754
- await setupAttaformDevtools(app, registry);
755
- } catch {
756
- }
757
- })();
758
- }
1162
+ installAttaformOnApp(app, options, "explicit");
759
1163
  }
760
1164
  };
761
1165
  return plugin;
762
1166
  }
763
1167
 
764
- function renderAttaformState(app) {
765
- const registry = getRegistryFromApp(app);
766
- const forms = [];
767
- for (const [key, state] of registry.forms) {
768
- const transientList = Array.from(state.blankPaths);
769
- forms.push([
770
- key,
771
- {
772
- form: state.form.value,
773
- schemaErrors: Array.from(state.schemaErrors.entries()),
774
- userErrors: Array.from(state.userErrors.entries()),
775
- fields: Array.from(state.fields.entries()),
776
- ...transientList.length > 0 ? { blankPaths: transientList } : {}
777
- }
778
- ]);
779
- }
780
- return { forms };
781
- }
782
- function hydrateAttaformState(app, payload) {
783
- const registry = getRegistryFromApp(app);
784
- for (const [key, data] of payload.forms) {
785
- registry.pendingHydration.set(key, data);
786
- }
787
- }
788
-
789
- export { assignKey as a, createAttaform as c, hydrateAttaformState as h, isRegisterValue as i, renderAttaformState as r, vRegister as v };
790
- //# sourceMappingURL=attaform.CRk8NhlD.mjs.map
1168
+ export { AnonPersistError as A, InvalidPathError as I, OutsideSetupError as O, RegistryNotInstalledError as R, SensitivePersistFieldError as S, __DEV__ as _, AttaformError as a, InvalidUseFormConfigError as b, createAttaform as c, ReservedFormKeyError as d, SubmitErrorHandlerError as e, assignKey as f, getRegistryFromApp as g, createRegistry as h, isSensitivePath as i, isRegisterValue as j, kAttaformRegistry as k, useRegistry as l, captureUserCallSite as m, enforceSensitiveCheck as n, createPersistOptInRegistry as o, ensureAttaformInstalled as p, kFormContext as q, kFormInstanceId as r, segmentMatchesSensitive as s, useRegister as u, vRegister as v };
1169
+ //# sourceMappingURL=attaform.BfMxsfmE.mjs.map