attaform 0.22.0 → 0.24.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.
- package/README.md +8 -11
- package/dist/chunks/dev-key-collision-warnings.cjs +0 -33
- package/dist/chunks/dev-key-collision-warnings.cjs.map +1 -1
- package/dist/chunks/dev-key-collision-warnings.mjs +1 -33
- package/dist/chunks/dev-key-collision-warnings.mjs.map +1 -1
- package/dist/chunks/devtools.cjs +3 -5
- package/dist/chunks/devtools.cjs.map +1 -1
- package/dist/chunks/devtools.mjs +3 -5
- package/dist/chunks/devtools.mjs.map +1 -1
- package/dist/chunks/fingerprint2.cjs +1 -1
- package/dist/chunks/fingerprint2.mjs +1 -1
- package/dist/index.cjs +3 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -168
- package/dist/index.d.mts +7 -168
- package/dist/index.d.ts +7 -168
- package/dist/index.mjs +4 -150
- package/dist/index.mjs.map +1 -1
- package/dist/nuxt.d.cts +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/runtime/components/AttaformDevtoolsPanel.vue +5 -13
- package/dist/runtime/plugins/attaform.cjs +2 -2
- package/dist/runtime/plugins/attaform.mjs +2 -2
- package/dist/shared/{attaform.DgCfLqay.mjs → attaform.BJ_W7q3U.mjs} +8 -6
- package/dist/shared/attaform.BJ_W7q3U.mjs.map +1 -0
- package/dist/shared/{attaform.aekT7mMx.d.cts → attaform.BNmkKz0q.d.mts} +38 -6
- package/dist/shared/{attaform.Q3eAD2wD.cjs → attaform.BV_HyaMO.cjs} +6 -4
- package/dist/shared/attaform.BV_HyaMO.cjs.map +1 -0
- package/dist/shared/{attaform.AyujQoHp.cjs → attaform.BnUXV01g.cjs} +4 -4
- package/dist/shared/attaform.BnUXV01g.cjs.map +1 -0
- package/dist/shared/{attaform.DNuiFCXG.mjs → attaform.C-dAB90u.mjs} +4 -4
- package/dist/shared/attaform.C-dAB90u.mjs.map +1 -0
- package/dist/shared/{attaform.CjMcwV7W.cjs → attaform.C42wL7EJ.cjs} +272 -776
- package/dist/shared/attaform.C42wL7EJ.cjs.map +1 -0
- package/dist/shared/{attaform.D4XYaasQ.d.ts → attaform.C6eE50re.d.ts} +27 -87
- package/dist/shared/{attaform.6xE0Lcfd.mjs → attaform.CAWKNCzc.mjs} +2 -2
- package/dist/shared/{attaform.6xE0Lcfd.mjs.map → attaform.CAWKNCzc.mjs.map} +1 -1
- package/dist/shared/{attaform.DkA5J8NW.d.cts → attaform.CO0e7YVY.d.cts} +1 -46
- package/dist/shared/{attaform.DkA5J8NW.d.ts → attaform.CO0e7YVY.d.mts} +1 -46
- package/dist/shared/{attaform.DkA5J8NW.d.mts → attaform.CO0e7YVY.d.ts} +1 -46
- package/dist/shared/{attaform.CsB-iKbU.mjs → attaform.CuBdtfbe.mjs} +274 -767
- package/dist/shared/attaform.CuBdtfbe.mjs.map +1 -0
- package/dist/shared/{attaform.FN0vaQAg.d.mts → attaform.CwFZGv5-.d.ts} +38 -6
- package/dist/shared/{attaform.BGwNZ9GV.d.cts → attaform.DdUYEhkV.d.cts} +27 -87
- package/dist/shared/attaform.DdjDqTah.d.cts +56 -0
- package/dist/shared/attaform.DdjDqTah.d.mts +56 -0
- package/dist/shared/attaform.DdjDqTah.d.ts +56 -0
- package/dist/shared/{attaform.BKFwekY2.mjs → attaform.Df-s8j1X.mjs} +3 -289
- package/dist/shared/attaform.Df-s8j1X.mjs.map +1 -0
- package/dist/shared/{attaform.CCCeEPwa.d.mts → attaform.DiWNbKWa.d.mts} +27 -87
- package/dist/shared/{attaform.01iKS_lz.cjs → attaform.DwkU0oY9.cjs} +2 -298
- package/dist/shared/attaform.DwkU0oY9.cjs.map +1 -0
- package/dist/shared/{attaform.DvUH4a3o.d.ts → attaform.GJbSmwLB.d.cts} +224 -824
- package/dist/shared/{attaform.DvUH4a3o.d.cts → attaform.GJbSmwLB.d.mts} +224 -824
- package/dist/shared/{attaform.DvUH4a3o.d.mts → attaform.GJbSmwLB.d.ts} +224 -824
- package/dist/shared/{attaform.DUMWQefY.d.ts → attaform.K-3glmiT.d.cts} +38 -6
- package/dist/shared/{attaform.C-RtnCJM.cjs → attaform.Z1qTwOYE.cjs} +8 -6
- package/dist/shared/attaform.Z1qTwOYE.cjs.map +1 -0
- package/dist/shared/{attaform.CRzpFCjV.cjs → attaform.nycEksJn.cjs} +2 -2
- package/dist/shared/{attaform.CRzpFCjV.cjs.map → attaform.nycEksJn.cjs.map} +1 -1
- package/dist/shared/{attaform.DCjgGir_.mjs → attaform.o95Kjd3U.mjs} +6 -4
- package/dist/shared/attaform.o95Kjd3U.mjs.map +1 -0
- package/dist/zod-v3.cjs +2 -2
- package/dist/zod-v3.d.cts +12 -11
- package/dist/zod-v3.d.mts +12 -11
- package/dist/zod-v3.d.ts +12 -11
- package/dist/zod-v3.mjs +2 -2
- package/dist/zod-v4.cjs +2 -2
- package/dist/zod-v4.d.cts +7 -6
- package/dist/zod-v4.d.mts +7 -6
- package/dist/zod-v4.d.ts +7 -6
- package/dist/zod-v4.mjs +2 -2
- package/dist/zod.cjs +5 -5
- package/dist/zod.cjs.map +1 -1
- package/dist/zod.d.cts +21 -52
- package/dist/zod.d.mts +21 -52
- package/dist/zod.d.ts +21 -52
- package/dist/zod.mjs +5 -5
- package/dist/zod.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/indexeddb.cjs +0 -119
- package/dist/chunks/indexeddb.cjs.map +0 -1
- package/dist/chunks/indexeddb.mjs +0 -117
- package/dist/chunks/indexeddb.mjs.map +0 -1
- package/dist/chunks/local-storage.cjs +0 -58
- package/dist/chunks/local-storage.cjs.map +0 -1
- package/dist/chunks/local-storage.mjs +0 -56
- package/dist/chunks/local-storage.mjs.map +0 -1
- package/dist/chunks/multi-tab-sync.cjs +0 -367
- package/dist/chunks/multi-tab-sync.cjs.map +0 -1
- package/dist/chunks/multi-tab-sync.mjs +0 -364
- package/dist/chunks/multi-tab-sync.mjs.map +0 -1
- package/dist/chunks/session-storage.cjs +0 -58
- package/dist/chunks/session-storage.cjs.map +0 -1
- package/dist/chunks/session-storage.mjs +0 -56
- package/dist/chunks/session-storage.mjs.map +0 -1
- package/dist/chunks/wire-persistence.cjs +0 -396
- package/dist/chunks/wire-persistence.cjs.map +0 -1
- package/dist/chunks/wire-persistence.mjs +0 -394
- package/dist/chunks/wire-persistence.mjs.map +0 -1
- package/dist/shared/attaform.01iKS_lz.cjs.map +0 -1
- package/dist/shared/attaform.AyujQoHp.cjs.map +0 -1
- package/dist/shared/attaform.BKFwekY2.mjs.map +0 -1
- package/dist/shared/attaform.C-RtnCJM.cjs.map +0 -1
- package/dist/shared/attaform.CjMcwV7W.cjs.map +0 -1
- package/dist/shared/attaform.CsB-iKbU.mjs.map +0 -1
- package/dist/shared/attaform.DCjgGir_.mjs.map +0 -1
- package/dist/shared/attaform.DNuiFCXG.mjs.map +0 -1
- package/dist/shared/attaform.DgCfLqay.mjs.map +0 -1
- package/dist/shared/attaform.Q3eAD2wD.cjs.map +0 -1
- package/dist/shared/attaform.nf83TIR5.d.cts +0 -35
- package/dist/shared/attaform.nf83TIR5.d.mts +0 -35
- package/dist/shared/attaform.nf83TIR5.d.ts +0 -35
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FormKey,
|
|
1
|
+
import { F as FormKey, W as PathKey, m as DisplayCtx, d as GetDisplayState, n as DisplayMachine, V as Path, aa as SlimPrimitiveKind, C as CoercionEntry, g as CoercionRegistry, G as GenericForm, ag as ValidationError, a as AbstractSchema, ak as WriteMeta, j as DeepPartial, al as WriteShape, as as TransformAbortHolder, ae as ValidateOn, A as AttaformDefaults, b as UseFormReturnType, c as RegisterValue } from './attaform.GJbSmwLB.js';
|
|
2
2
|
import { Ref, ComputedRef, App, InjectionKey } from 'vue';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -643,12 +643,12 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
643
643
|
* Schema-driven errors. Written ONLY by the schema validation pipeline:
|
|
644
644
|
* `scheduleFieldValidation`, `handleSubmit`, the construction-time seed,
|
|
645
645
|
* history restore, and hydration. Cleared by `reset` / `resetField` and by
|
|
646
|
-
* a successful submit. `
|
|
646
|
+
* a successful submit. `setErrors` / `clearErrors` do NOT touch this Map.
|
|
647
647
|
*/
|
|
648
648
|
readonly schemaErrors: Map<PathKey, ValidationError[]>;
|
|
649
649
|
/**
|
|
650
|
-
* User-injected errors. Written ONLY by the `
|
|
651
|
-
* (and history / hydration replay). Survives schema revalidation and
|
|
650
|
+
* User-injected errors. Written ONLY by the `setErrors` / `clearErrors`
|
|
651
|
+
* API surface (and history / hydration replay). Survives schema revalidation and
|
|
652
652
|
* successful submits — the consumer owns its lifetime explicitly.
|
|
653
653
|
*/
|
|
654
654
|
readonly userErrors: Map<PathKey, ValidationError[]>;
|
|
@@ -967,17 +967,13 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
967
967
|
/**
|
|
968
968
|
* Replace the form value wholesale. Optional `meta` is forwarded to
|
|
969
969
|
* every `onFormChange` listener so they can decide whether THIS write
|
|
970
|
-
* is one they care about
|
|
971
|
-
* only writes when `meta?.persist === true`. Internal callers that
|
|
972
|
-
* don't pass meta default to no-persist.
|
|
970
|
+
* is one they care about (e.g. history tagging a hydration replay).
|
|
973
971
|
*/
|
|
974
972
|
applyFormReplacement(next: F, meta?: WriteMeta): void;
|
|
975
973
|
/**
|
|
976
974
|
* Set a single path's value. `meta` is forwarded to listeners via
|
|
977
|
-
* `applyFormReplacement` (see above).
|
|
978
|
-
*
|
|
979
|
-
* internal call sites pass `meta.persist = hasAnyOptInForPath(path)`.
|
|
980
|
-
* Public `form.setValue` passes no meta.
|
|
975
|
+
* `applyFormReplacement` (see above). Public `form.setValue` passes no
|
|
976
|
+
* meta.
|
|
981
977
|
*
|
|
982
978
|
* Returns `false` when the slim-primitive gate rejects the write
|
|
983
979
|
* (the value's primitive shape doesn't match the schema's slim
|
|
@@ -1009,7 +1005,7 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
1009
1005
|
*/
|
|
1010
1006
|
applySchemaErrorsForSubtree(path: Path, errors: ValidationError[]): void;
|
|
1011
1007
|
setAllUserErrors(errors: readonly ValidationError[]): void;
|
|
1012
|
-
|
|
1008
|
+
setUserErrorsForPath(path: Path, errors: readonly ValidationError[]): void;
|
|
1013
1009
|
clearUserErrors(path?: Path): void;
|
|
1014
1010
|
/**
|
|
1015
1011
|
* Merged read — returns `[...schemaErrors[path], ...userErrors[path]]`.
|
|
@@ -1191,28 +1187,17 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
1191
1187
|
/**
|
|
1192
1188
|
* Subscribe to every `applyFormReplacement`. Fires synchronously
|
|
1193
1189
|
* after `form.value` has been swapped to `next` and all field /
|
|
1194
|
-
* originals bookkeeping has run. Used by
|
|
1195
|
-
*
|
|
1196
|
-
*
|
|
1197
|
-
*
|
|
1198
|
-
* about meta can ignore the parameter. Returns an unsubscribe
|
|
1199
|
-
* function.
|
|
1190
|
+
* originals bookkeeping has run. Used by undo/redo to hook the single
|
|
1191
|
+
* mutation funnel. The optional `meta` carries the originating call
|
|
1192
|
+
* site's intent; subscribers that don't care about meta can ignore the
|
|
1193
|
+
* parameter. Returns an unsubscribe function.
|
|
1200
1194
|
*/
|
|
1201
1195
|
onFormChange(listener: (next: F, meta?: WriteMeta) => void): () => void;
|
|
1202
|
-
/**
|
|
1203
|
-
* Register a `form.onChange` side-channel handler. `source === undefined`
|
|
1204
|
-
* is the whole form (root); `getForm` lazily resolves the public form
|
|
1205
|
-
* handle for `ctx.form`. Returns an idempotent `stop()`. A no-op on SSR.
|
|
1206
|
-
* The public `form.onChange` overloads and `useForm({ onChange })` wire
|
|
1207
|
-
* through here; dispatch happens in `commitWritePatches`.
|
|
1208
|
-
*/
|
|
1209
|
-
registerOnChange(source: OnChangeSource | undefined, handler: OnChangeHandler, options: OnChangeOptions | undefined, getForm: () => unknown): () => void;
|
|
1210
1196
|
/**
|
|
1211
1197
|
* Subscribe to successful submissions. Fires after the consumer's
|
|
1212
1198
|
* `onSubmit` callback has resolved — not on validation failure,
|
|
1213
|
-
* not on callback throw.
|
|
1214
|
-
*
|
|
1215
|
-
* server round-trip. Returns an unsubscribe function.
|
|
1199
|
+
* not on callback throw. The DevTools panel rides this to surface a
|
|
1200
|
+
* submit event. Returns an unsubscribe function.
|
|
1216
1201
|
*/
|
|
1217
1202
|
onSubmitSuccess(listener: () => void): () => void;
|
|
1218
1203
|
/**
|
|
@@ -1258,58 +1243,6 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
1258
1243
|
* owned by the caller (e.g. `'history'`).
|
|
1259
1244
|
*/
|
|
1260
1245
|
readonly modules: Map<string, unknown>;
|
|
1261
|
-
/**
|
|
1262
|
-
* Per-element persistence opt-in tracker. Empty by default; the
|
|
1263
|
-
* `v-register` directive populates entries on `mount` for each binding
|
|
1264
|
-
* that passed `register('foo', { persist: true })` and clears them on
|
|
1265
|
-
* `beforeUnmount`. Two SFCs sharing a key share this registry — opt-ins
|
|
1266
|
-
* are per-DOM-element, not per-component. Internal to the persistence
|
|
1267
|
-
* subsystem; not part of the consumer API surface.
|
|
1268
|
-
*/
|
|
1269
|
-
readonly persistOptIns: PersistOptInRegistry;
|
|
1270
|
-
/**
|
|
1271
|
-
* Resolved sensitive-path predicate for THIS form. Honors the
|
|
1272
|
-
* cascade (`useForm({ sensitiveNames })` > global default >
|
|
1273
|
-
* library `DEFAULT_SENSITIVE_NAMES`). Used by:
|
|
1274
|
-
* - the persistence opt-in gate (`allowSensitivePersist`);
|
|
1275
|
-
* - the multi-tab sync module (outbound strip + inbound reject);
|
|
1276
|
-
* - DevTools edit rejection;
|
|
1277
|
-
* - any future surface that needs to flag "this path holds
|
|
1278
|
-
* sensitive data."
|
|
1279
|
-
*
|
|
1280
|
-
* Frozen at FormStore construction. Two callsites sharing a key
|
|
1281
|
-
* share the predicate — consistent with the rest of the per-form
|
|
1282
|
-
* resolved-config surface.
|
|
1283
|
-
*/
|
|
1284
|
-
readonly isSensitivePath: (path: Path | PathKey | string) => boolean;
|
|
1285
|
-
/**
|
|
1286
|
-
* Canonical path keys explicitly opted OUT of multi-tab sync by
|
|
1287
|
-
* `register(path, { multiTab: false })`. The sync module's outbound
|
|
1288
|
-
* broadcaster strips patches at these paths AND the inbound listener
|
|
1289
|
-
* rejects them — symmetric tab-local behaviour for selected fields.
|
|
1290
|
-
*
|
|
1291
|
-
* Read-only Set view; mutate via `incrementNoSyncOptOut` /
|
|
1292
|
-
* `decrementNoSyncOptOut` which maintain a per-path ref count so
|
|
1293
|
-
* multiple bindings on the same path balance correctly across
|
|
1294
|
-
* dynamic conditional renders. Empty by default.
|
|
1295
|
-
*/
|
|
1296
|
-
readonly noSyncPaths: ReadonlySet<PathKey>;
|
|
1297
|
-
/**
|
|
1298
|
-
* Ref-counted "this path is tab-local" registration. Called by
|
|
1299
|
-
* `v-register`'s `created` hook for any binding that declared
|
|
1300
|
-
* `register('x', { multiTab: false })`. The first call for a given
|
|
1301
|
-
* path adds it to `noSyncPaths`; subsequent calls just bump the
|
|
1302
|
-
* ref count. Pair with `decrementNoSyncOptOut`.
|
|
1303
|
-
*/
|
|
1304
|
-
incrementNoSyncOptOut(path: PathKey): void;
|
|
1305
|
-
/**
|
|
1306
|
-
* Symmetric companion to `incrementNoSyncOptOut`. Called by
|
|
1307
|
-
* `v-register`'s `beforeUnmount` hook. When the ref count for a
|
|
1308
|
-
* path drops to zero, the path is removed from `noSyncPaths` —
|
|
1309
|
-
* dynamic toggling (the binding rendered conditionally) restores
|
|
1310
|
-
* full sync to the path when the last opt-out unmounts.
|
|
1311
|
-
*/
|
|
1312
|
-
decrementNoSyncOptOut(path: PathKey): void;
|
|
1313
1246
|
/**
|
|
1314
1247
|
* Resolved schema-coercion index — the merged config from
|
|
1315
1248
|
* `createAttaform({ defaults: { coerce } })` ∪ `useForm({ coerce })`,
|
|
@@ -1378,9 +1311,8 @@ type SerializedFormData = {
|
|
|
1378
1311
|
*/
|
|
1379
1312
|
readonly schemaErrors: ReadonlyArray<readonly [string, unknown]>;
|
|
1380
1313
|
/**
|
|
1381
|
-
* Errors set explicitly via `
|
|
1382
|
-
*
|
|
1383
|
-
* at snapshot time. Replayed at hydration; persists across
|
|
1314
|
+
* Errors set explicitly via `setErrors` (typically a server
|
|
1315
|
+
* response) at snapshot time. Replayed at hydration; persists across
|
|
1384
1316
|
* client-side re-validation.
|
|
1385
1317
|
*/
|
|
1386
1318
|
readonly userErrors: ReadonlyArray<readonly [string, unknown]>;
|
|
@@ -1808,9 +1740,9 @@ declare function lazy<Ctx = WizardCtx>(resolve: (ctx: Ctx) => AnyForm | string |
|
|
|
1808
1740
|
* `issue.code` (e.g. `zod:too_small`). No enum here because
|
|
1809
1741
|
* Zod's code list evolves.
|
|
1810
1742
|
* - consumer-defined — anything the consumer's backend / app stamps
|
|
1811
|
-
* onto a `ValidationError` (
|
|
1812
|
-
* or
|
|
1813
|
-
*
|
|
1743
|
+
* onto a `ValidationError` (a server response handed to `setErrors`,
|
|
1744
|
+
* or a code passed inline). Pick a scope (`api:`, `auth:`, etc.) and
|
|
1745
|
+
* stay consistent.
|
|
1814
1746
|
*
|
|
1815
1747
|
* Use these constants in tests and error-routing UI:
|
|
1816
1748
|
*
|
|
@@ -1854,6 +1786,14 @@ declare const AttaformErrorCode: {
|
|
|
1854
1786
|
* `form.hydrateError` for retry UX.
|
|
1855
1787
|
*/
|
|
1856
1788
|
readonly ActivationFailed: "atta:activation-failed";
|
|
1789
|
+
/**
|
|
1790
|
+
* Default code stamped on a manual error set through `form.setErrors`
|
|
1791
|
+
* when the caller omits an explicit `code`. The `setErrors` input is
|
|
1792
|
+
* lenient (`code` optional), so this is the fallback that keeps every
|
|
1793
|
+
* produced `ValidationError` carrying a stable, branchable identifier.
|
|
1794
|
+
* Override it per error by passing your own `code` (`api:…`, `auth:…`).
|
|
1795
|
+
*/
|
|
1796
|
+
readonly UserError: "atta:user-error";
|
|
1857
1797
|
};
|
|
1858
1798
|
type AttaformErrorCode = (typeof AttaformErrorCode)[keyof typeof AttaformErrorCode];
|
|
1859
1799
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as getRegistryFromApp, n as pathKeyToDotted } from './attaform.Df-s8j1X.mjs';
|
|
2
2
|
|
|
3
3
|
function renderAttaformState(app) {
|
|
4
4
|
const registry = getRegistryFromApp(app);
|
|
@@ -32,4 +32,4 @@ function hydrateAttaformState(app, payload) {
|
|
|
32
32
|
const DEVTOOLS_WINDOW_KEY = "__attaform_devtools__";
|
|
33
33
|
|
|
34
34
|
export { DEVTOOLS_WINDOW_KEY as D, hydrateAttaformState as h, renderAttaformState as r };
|
|
35
|
-
//# sourceMappingURL=attaform.
|
|
35
|
+
//# sourceMappingURL=attaform.CAWKNCzc.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attaform.
|
|
1
|
+
{"version":3,"file":"attaform.CAWKNCzc.mjs","sources":["../../src/runtime/core/serialize.ts","../../src/runtime/core/devtools-shared.ts"],"sourcesContent":["import type { App } from 'vue'\nimport type { FormKey } from '../types/types-api'\nimport { pathKeyToDotted, type PathKey } from './paths'\nimport { getRegistryFromApp, type SerializedFormData } from './registry'\n\n/**\n * Serialised snapshot of every form in a Vue app, produced by\n * `renderAttaformState` and consumed by `hydrateAttaformState`.\n *\n * JSON-safe — pass to `JSON.stringify`, `devalue`, or any other\n * serialiser before embedding in your SSR payload.\n */\nexport type SerializedAttaformState = {\n /** Tuples of `[formKey, snapshot]` for every form in the app. */\n readonly forms: ReadonlyArray<readonly [FormKey, SerializedFormData]>\n}\n\n/**\n * Snapshot every form on a Vue app for SSR. Call from your server\n * entry after rendering the app:\n *\n * ```ts\n * import { renderToString } from '@vue/server-renderer'\n * import { renderAttaformState, escapeForInlineScript } from 'attaform'\n *\n * const html = await renderToString(app)\n * const state = renderAttaformState(app)\n * const payload = escapeForInlineScript(JSON.stringify(state))\n *\n * return `\n * ${html}\n * <script>window.__ATTAFORM_STATE__ = ${payload}</script>\n * `\n * ```\n *\n * Pair with `hydrateAttaformState` on the client to restore the\n * forms in their server-rendered state. Nuxt users don't need this —\n * `attaform/nuxt` wires SSR automatically.\n */\nexport function renderAttaformState(app: App): SerializedAttaformState {\n const registry = getRegistryFromApp(app)\n const forms: Array<readonly [FormKey, SerializedFormData]> = []\n for (const [key, state] of registry.forms) {\n // Skip the blank field when the set is empty so the\n // wire payload stays minimal for forms that don't use it. The\n // optional shape on the consuming side handles the absence\n // cleanly (defaults to \"no blank paths\"). PathKey → dotted at\n // the boundary so the wire shape matches the rest of the\n // public path notation.\n const transientList: string[] = []\n for (const pk of state.blankPaths) {\n const d = pathKeyToDotted(pk as PathKey)\n if (d !== null) transientList.push(d)\n }\n forms.push([\n key,\n {\n form: state.form.value,\n schemaErrors: Array.from(state.schemaErrors.entries()),\n userErrors: Array.from(state.userErrors.entries()),\n fields: Array.from(state.fields.entries()),\n ...(transientList.length > 0 ? { blankPaths: transientList } : {}),\n },\n ])\n }\n return { forms }\n}\n\n/**\n * Restore forms from a server-rendered snapshot on the client. Call\n * from your client entry before mounting:\n *\n * ```ts\n * import { createApp } from 'vue'\n * import { createAttaform, hydrateAttaformState } from 'attaform'\n *\n * const app = createApp(App).use(createAttaform())\n * hydrateAttaformState(app, window.__ATTAFORM_STATE__)\n * app.mount('#app')\n * ```\n *\n * The next `useForm({ key })` call for each serialised form picks up\n * the snapshot transparently — no further action is required.\n */\nexport function hydrateAttaformState(app: App, payload: SerializedAttaformState): void {\n const registry = getRegistryFromApp(app)\n for (const [key, data] of payload.forms) {\n registry.pendingHydration.set(key, data)\n }\n}\n","/**\n * Shared building blocks for Attaform's two devtools surfaces — the Vue\n * DevTools (Chrome-extension) inspector wired up in `./devtools.ts`, and\n * the Nuxt DevTools (overlay) panel wired up via `../../nuxt.ts` +\n * `../pages/_attaform_devtools.vue`.\n *\n * Houses the window-bridge contract both surfaces consume so a new\n * bridge field lands in one file. Both surfaces render RAW form values\n * by design — DevTools is a dev-only surface, and redaction across every\n * place a value surfaces is impractical security theater rather than a\n * real safeguard.\n */\nimport type { AttaformRegistry } from './registry'\n\n/**\n * Property key on `window` that the Nuxt-side dev plugin attaches the\n * bridge object to. The iframe-mounted overlay panel reads\n * `window.parent[DEVTOOLS_WINDOW_KEY]` to reach the host app's registry.\n *\n * Underscored + namespaced to make accidental collision with consumer\n * globals vanishingly unlikely. Stable across versions — bumping it\n * would silently disconnect older library builds from newer overlay\n * panels in the same browser tab during a library upgrade.\n */\nexport const DEVTOOLS_WINDOW_KEY = '__attaform_devtools__'\n\n/**\n * Shape of the object the host plugin attaches to `window` in dev mode.\n * The iframe overlay panel reads this to discover the live registry and\n * render its forms.\n *\n * Single-registry assumption: the latest `createAttaform()` install\n * wins. Multi-app pages (rare; typically only seen in micro-frontend\n * setups) will only see one app's forms in the panel. Documented but\n * not actively supported — the alternative (a Set of registries with\n * union-rendering) is a future call if a real consumer hits it.\n */\nexport interface AttaformDevtoolsBridge {\n registry: AttaformRegistry\n /**\n * The library version, surfaced in the panel's footer for support /\n * bug-report context. Read from `package.json` at host-plugin init.\n */\n version: string\n}\n\ndeclare global {\n interface Window {\n [DEVTOOLS_WINDOW_KEY]?: AttaformDevtoolsBridge\n }\n}\n"],"names":[],"mappings":";;AAuCO,SAAS,oBAAoB,GAAA,EAAmC;AACrE,EAAA,MAAM,QAAA,GAAW,mBAAmB,GAAG,CAAA;AACvC,EAAA,MAAM,QAAuD,EAAC;AAC9D,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,SAAS,KAAA,EAAO;AAOzC,IAAA,MAAM,gBAA0B,EAAC;AACjC,IAAA,KAAA,MAAW,EAAA,IAAM,MAAM,UAAA,EAAY;AACjC,MAAA,MAAM,CAAA,GAAI,gBAAgB,EAAa,CAAA;AACvC,MAAA,IAAI,CAAA,KAAM,IAAA,EAAM,aAAA,CAAc,IAAA,CAAK,CAAC,CAAA;AAAA,IACtC;AACA,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,GAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,MAAM,IAAA,CAAK,KAAA;AAAA,QACjB,cAAc,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,SAAS,CAAA;AAAA,QACrD,YAAY,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,SAAS,CAAA;AAAA,QACjD,QAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,SAAS,CAAA;AAAA,QACzC,GAAI,cAAc,MAAA,GAAS,CAAA,GAAI,EAAE,UAAA,EAAY,aAAA,KAAkB;AAAC;AAClE,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAkBO,SAAS,oBAAA,CAAqB,KAAU,OAAA,EAAwC;AACrF,EAAA,MAAM,QAAA,GAAW,mBAAmB,GAAG,CAAA;AACvC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,QAAQ,KAAA,EAAO;AACvC,IAAA,QAAA,CAAS,gBAAA,CAAiB,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAAA,EACzC;AACF;;ACjEO,MAAM,mBAAA,GAAsB;;;;"}
|
|
@@ -90,50 +90,5 @@ declare class OutsideSetupError extends AttaformError {
|
|
|
90
90
|
declare class ReservedFormKeyError extends AttaformError {
|
|
91
91
|
constructor(key: string);
|
|
92
92
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Thrown (in dev) when `useForm({ persist: ... })` is configured on
|
|
95
|
-
* an anonymous form (no `key:` provided). The synthetic `__atta:anon:`
|
|
96
|
-
* identity isn't stable across remounts (Vue's `useId()` allocator
|
|
97
|
-
* drifts under HMR, and any sibling `useId()` call shifts subsequent
|
|
98
|
-
* IDs), so the persistence layer can't reliably find the previous
|
|
99
|
-
* mount's draft. Result: stale entries pile up in storage and the
|
|
100
|
-
* user's most recent edit doesn't always come back.
|
|
101
|
-
*
|
|
102
|
-
* Fix: pass an explicit `key` to `useForm()`.
|
|
103
|
-
*
|
|
104
|
-
* In production builds the runtime downgrades this to a one-shot
|
|
105
|
-
* `console.warn` so a deployed third-party app shipping the
|
|
106
|
-
* anti-pattern doesn't hard-crash.
|
|
107
|
-
*/
|
|
108
|
-
/**
|
|
109
|
-
* Thrown when persistence is misconfigured in a way that would either
|
|
110
|
-
* (a) silently drop writes, or (b) namespace storage under a
|
|
111
|
-
* non-deterministic synthetic key — both of which become security bugs
|
|
112
|
-
* the moment encrypted persistence backends are added (the same key
|
|
113
|
-
* may be derived for two unrelated forms).
|
|
114
|
-
*
|
|
115
|
-
* Two `cause` values, one error shape:
|
|
116
|
-
*
|
|
117
|
-
* - `'no-key'` — `useForm({ persist: ... })` called without `key:`.
|
|
118
|
-
* Anonymous keys (`__atta:anon:*`) drift across mounts; persisting
|
|
119
|
-
* to a non-deterministic location is refused outright.
|
|
120
|
-
*
|
|
121
|
-
* - `'register-without-config'` — `register(_, { persist: true })`
|
|
122
|
-
* declared on a form whose `useForm()` options omit `persist:`.
|
|
123
|
-
* The opt-in is recorded but nothing would ever land in storage.
|
|
124
|
-
*
|
|
125
|
-
* Fix: align the two layers — set `persist:` + `key:` on `useForm()`,
|
|
126
|
-
* or remove `{ persist: true }` from the offending `register()` call.
|
|
127
|
-
*/
|
|
128
|
-
declare class AnonPersistError extends AttaformError {
|
|
129
|
-
readonly schemaFields: readonly string[] | undefined;
|
|
130
|
-
readonly callSite: string | undefined;
|
|
131
|
-
readonly cause: 'no-key' | 'register-without-config';
|
|
132
|
-
constructor(opts: {
|
|
133
|
-
schemaFields?: readonly string[] | undefined;
|
|
134
|
-
callSite?: string | undefined;
|
|
135
|
-
cause: 'no-key' | 'register-without-config';
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
93
|
|
|
139
|
-
export {
|
|
94
|
+
export { AttaformError as A, InvalidPathError as I, OutsideSetupError as O, RegistryNotInstalledError as R, SubmitErrorHandlerError as S, InvalidUseFormConfigError as a, ReservedFormKeyError as b };
|
|
@@ -90,50 +90,5 @@ declare class OutsideSetupError extends AttaformError {
|
|
|
90
90
|
declare class ReservedFormKeyError extends AttaformError {
|
|
91
91
|
constructor(key: string);
|
|
92
92
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Thrown (in dev) when `useForm({ persist: ... })` is configured on
|
|
95
|
-
* an anonymous form (no `key:` provided). The synthetic `__atta:anon:`
|
|
96
|
-
* identity isn't stable across remounts (Vue's `useId()` allocator
|
|
97
|
-
* drifts under HMR, and any sibling `useId()` call shifts subsequent
|
|
98
|
-
* IDs), so the persistence layer can't reliably find the previous
|
|
99
|
-
* mount's draft. Result: stale entries pile up in storage and the
|
|
100
|
-
* user's most recent edit doesn't always come back.
|
|
101
|
-
*
|
|
102
|
-
* Fix: pass an explicit `key` to `useForm()`.
|
|
103
|
-
*
|
|
104
|
-
* In production builds the runtime downgrades this to a one-shot
|
|
105
|
-
* `console.warn` so a deployed third-party app shipping the
|
|
106
|
-
* anti-pattern doesn't hard-crash.
|
|
107
|
-
*/
|
|
108
|
-
/**
|
|
109
|
-
* Thrown when persistence is misconfigured in a way that would either
|
|
110
|
-
* (a) silently drop writes, or (b) namespace storage under a
|
|
111
|
-
* non-deterministic synthetic key — both of which become security bugs
|
|
112
|
-
* the moment encrypted persistence backends are added (the same key
|
|
113
|
-
* may be derived for two unrelated forms).
|
|
114
|
-
*
|
|
115
|
-
* Two `cause` values, one error shape:
|
|
116
|
-
*
|
|
117
|
-
* - `'no-key'` — `useForm({ persist: ... })` called without `key:`.
|
|
118
|
-
* Anonymous keys (`__atta:anon:*`) drift across mounts; persisting
|
|
119
|
-
* to a non-deterministic location is refused outright.
|
|
120
|
-
*
|
|
121
|
-
* - `'register-without-config'` — `register(_, { persist: true })`
|
|
122
|
-
* declared on a form whose `useForm()` options omit `persist:`.
|
|
123
|
-
* The opt-in is recorded but nothing would ever land in storage.
|
|
124
|
-
*
|
|
125
|
-
* Fix: align the two layers — set `persist:` + `key:` on `useForm()`,
|
|
126
|
-
* or remove `{ persist: true }` from the offending `register()` call.
|
|
127
|
-
*/
|
|
128
|
-
declare class AnonPersistError extends AttaformError {
|
|
129
|
-
readonly schemaFields: readonly string[] | undefined;
|
|
130
|
-
readonly callSite: string | undefined;
|
|
131
|
-
readonly cause: 'no-key' | 'register-without-config';
|
|
132
|
-
constructor(opts: {
|
|
133
|
-
schemaFields?: readonly string[] | undefined;
|
|
134
|
-
callSite?: string | undefined;
|
|
135
|
-
cause: 'no-key' | 'register-without-config';
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
93
|
|
|
139
|
-
export {
|
|
94
|
+
export { AttaformError as A, InvalidPathError as I, OutsideSetupError as O, RegistryNotInstalledError as R, SubmitErrorHandlerError as S, InvalidUseFormConfigError as a, ReservedFormKeyError as b };
|
|
@@ -90,50 +90,5 @@ declare class OutsideSetupError extends AttaformError {
|
|
|
90
90
|
declare class ReservedFormKeyError extends AttaformError {
|
|
91
91
|
constructor(key: string);
|
|
92
92
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Thrown (in dev) when `useForm({ persist: ... })` is configured on
|
|
95
|
-
* an anonymous form (no `key:` provided). The synthetic `__atta:anon:`
|
|
96
|
-
* identity isn't stable across remounts (Vue's `useId()` allocator
|
|
97
|
-
* drifts under HMR, and any sibling `useId()` call shifts subsequent
|
|
98
|
-
* IDs), so the persistence layer can't reliably find the previous
|
|
99
|
-
* mount's draft. Result: stale entries pile up in storage and the
|
|
100
|
-
* user's most recent edit doesn't always come back.
|
|
101
|
-
*
|
|
102
|
-
* Fix: pass an explicit `key` to `useForm()`.
|
|
103
|
-
*
|
|
104
|
-
* In production builds the runtime downgrades this to a one-shot
|
|
105
|
-
* `console.warn` so a deployed third-party app shipping the
|
|
106
|
-
* anti-pattern doesn't hard-crash.
|
|
107
|
-
*/
|
|
108
|
-
/**
|
|
109
|
-
* Thrown when persistence is misconfigured in a way that would either
|
|
110
|
-
* (a) silently drop writes, or (b) namespace storage under a
|
|
111
|
-
* non-deterministic synthetic key — both of which become security bugs
|
|
112
|
-
* the moment encrypted persistence backends are added (the same key
|
|
113
|
-
* may be derived for two unrelated forms).
|
|
114
|
-
*
|
|
115
|
-
* Two `cause` values, one error shape:
|
|
116
|
-
*
|
|
117
|
-
* - `'no-key'` — `useForm({ persist: ... })` called without `key:`.
|
|
118
|
-
* Anonymous keys (`__atta:anon:*`) drift across mounts; persisting
|
|
119
|
-
* to a non-deterministic location is refused outright.
|
|
120
|
-
*
|
|
121
|
-
* - `'register-without-config'` — `register(_, { persist: true })`
|
|
122
|
-
* declared on a form whose `useForm()` options omit `persist:`.
|
|
123
|
-
* The opt-in is recorded but nothing would ever land in storage.
|
|
124
|
-
*
|
|
125
|
-
* Fix: align the two layers — set `persist:` + `key:` on `useForm()`,
|
|
126
|
-
* or remove `{ persist: true }` from the offending `register()` call.
|
|
127
|
-
*/
|
|
128
|
-
declare class AnonPersistError extends AttaformError {
|
|
129
|
-
readonly schemaFields: readonly string[] | undefined;
|
|
130
|
-
readonly callSite: string | undefined;
|
|
131
|
-
readonly cause: 'no-key' | 'register-without-config';
|
|
132
|
-
constructor(opts: {
|
|
133
|
-
schemaFields?: readonly string[] | undefined;
|
|
134
|
-
callSite?: string | undefined;
|
|
135
|
-
cause: 'no-key' | 'register-without-config';
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
93
|
|
|
139
|
-
export {
|
|
94
|
+
export { AttaformError as A, InvalidPathError as I, OutsideSetupError as O, RegistryNotInstalledError as R, SubmitErrorHandlerError as S, InvalidUseFormConfigError as a, ReservedFormKeyError as b };
|