attaform 0.30.0 → 0.30.1
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/dist/abstract.d.mts +15 -21
- package/dist/abstract.mjs +2 -2
- package/dist/dev/abstract.mjs +4 -4
- package/dist/dev/chunks/devtools.mjs +2 -2
- package/dist/dev/directive.mjs +1 -1
- package/dist/dev/history.mjs +1 -1
- package/dist/dev/index.mjs +5 -5
- package/dist/dev/runtime/plugins/attaform.mjs +1 -1
- package/dist/dev/shared/{attaform-dev.BK6Ge2qR.mjs → attaform-dev.BJK1kqHY.mjs} +14 -14
- package/dist/dev/shared/{attaform-dev.D6CLvaQT.mjs → attaform-dev.BMQ3GcgD.mjs} +46 -59
- package/dist/dev/shared/{attaform-dev.BisFstxh.mjs → attaform-dev.BUIFcTYf.mjs} +6 -6
- package/dist/dev/shared/{attaform-dev.DTrHonpc.mjs → attaform-dev.CT7MDjPy.mjs} +27 -36
- package/dist/dev/shared/{attaform-dev.BcYT6tFh.mjs → attaform-dev.CZz4GYZ6.mjs} +21 -9
- package/dist/dev/shared/{attaform-dev.DUZckyV8.mjs → attaform-dev.Chm4D6SJ.mjs} +2 -2
- package/dist/dev/shared/{attaform-dev.BcNtyOmf.mjs → attaform-dev.DuEE4GU1.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.CQ2rJiAX.mjs → attaform-dev.DxHdkkPG.mjs} +126 -115
- package/dist/dev/shared/{attaform-dev.BQc5QV3Y.mjs → attaform-dev.zlvDr0WB.mjs} +2 -2
- package/dist/dev/zod-v3.mjs +6 -6
- package/dist/dev/zod-v4.mjs +6 -6
- package/dist/dev/zod.mjs +5 -5
- package/dist/directive.d.mts +4 -4
- package/dist/directive.mjs +1 -1
- package/dist/esbuild.d.mts +11 -0
- package/dist/esbuild.mjs +1 -1
- package/dist/history.d.mts +3 -32
- package/dist/history.mjs +1 -1
- package/dist/index.d.mts +67 -70
- package/dist/index.mjs +3 -3
- package/dist/nuxt.d.mts +4 -3
- package/dist/nuxt.mjs +3 -6
- package/dist/rollup.d.mts +11 -0
- package/dist/rollup.mjs +1 -1
- package/dist/rspack.d.mts +19 -11
- package/dist/rspack.mjs +1 -1
- package/dist/runtime/components/AttaformDevtoolsPanel.vue +12 -12
- package/dist/runtime/components/DevtoolsValueTree.vue +2 -2
- package/dist/shared/{attaform.Rc9u4Vfw.d.mts → attaform.2FslhB9R.d.mts} +83 -95
- package/dist/shared/{attaform.BRDDQeHV.mjs → attaform.8mfKZCwH.mjs} +2 -2
- package/dist/shared/{attaform.DRUT703x.d.mts → attaform.B-Tb62qV.d.mts} +12 -12
- package/dist/shared/{attaform.v0fQtWyA.mjs → attaform.B1rH9ht6.mjs} +1 -1
- package/dist/shared/{attaform.ByWP6kSx.mjs → attaform.B2iebkPA.mjs} +3 -3
- package/dist/shared/{attaform.DhnPb6nK.mjs → attaform.BAf3UNn4.mjs} +1 -1
- package/dist/shared/{attaform.DNJOWjQw.mjs → attaform.BIWicztt.mjs} +102 -100
- package/dist/shared/attaform.BcQwgWaq.d.mts +2153 -0
- package/dist/shared/attaform.Br8EBn5B.d.mts +4553 -0
- package/dist/shared/{attaform.BXneBxEj.mjs → attaform.CO918TdU.mjs} +13 -13
- package/dist/shared/{attaform.CUfrMK7t.mjs → attaform.DRsANMok.mjs} +5 -5
- package/dist/shared/{attaform.B3resMQ1.mjs → attaform.D_f1WgYf.mjs} +40 -53
- package/dist/shared/{attaform.CJ8DpRGj.mjs → attaform.D_pt1gOj.mjs} +26 -33
- package/dist/shared/attaform.L0kUn3vL.d.mts +42 -0
- package/dist/shared/{attaform.BK0cgu2K.mjs → attaform.ZYn2ahzJ.mjs} +3 -3
- package/dist/transforms.d.mts +153 -26
- package/dist/transforms.mjs +1 -1
- package/dist/vite.d.mts +29 -52
- package/dist/vite.mjs +3 -3
- package/dist/webpack.d.mts +20 -12
- package/dist/webpack.mjs +1 -1
- package/dist/zod-v3.d.mts +90 -96
- package/dist/zod-v3.mjs +4 -4
- package/dist/zod-v4.d.mts +118 -118
- package/dist/zod-v4.mjs +4 -4
- package/dist/zod.d.mts +5 -5
- package/dist/zod.mjs +3 -3
- package/package.json +7 -6
- package/dist/shared/attaform.Clz0ArIi.d.mts +0 -44
- package/dist/shared/attaform.UGyOK83T.d.mts +0 -2366
- package/dist/shared/attaform.bKLzMU0o.d.mts +0 -4761
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { j as humanize, c as useAbstractForm } from './attaform.
|
|
1
|
+
import { j as humanize, c as useAbstractForm } from './attaform.BIWicztt.mjs';
|
|
2
2
|
import { A as AttaformError, e as canonicalizePath, a as InvalidUseFormConfigError } from './attaform.CdZIEf7_.mjs';
|
|
3
|
-
import { s as slimPrimitivesWalk, d as deriveDefaultWalk, m as mergeDeep, f as fixStructuralDefaults, w as walkPathSegments, c as createAbstractSchema, a as createSharedSchemaStore, b as buildFieldMetaPathMap, e as getFieldMetaListForSchema, g as getFieldMetaForSchema } from './attaform.
|
|
4
|
-
import { c as
|
|
3
|
+
import { s as slimPrimitivesWalk, d as deriveDefaultWalk, m as mergeDeep, f as fixStructuralDefaults, w as walkPathSegments, c as createAbstractSchema, a as createSharedSchemaStore, b as buildFieldMetaPathMap, e as getFieldMetaListForSchema, g as getFieldMetaForSchema } from './attaform.DRsANMok.mjs';
|
|
4
|
+
import { c as callConsumerFn } from './attaform.8mfKZCwH.mjs';
|
|
5
5
|
|
|
6
6
|
function readDef(schema) {
|
|
7
7
|
if (schema === null || typeof schema !== "object") return void 0;
|
|
@@ -131,7 +131,7 @@ function unwrapLazy(schema) {
|
|
|
131
131
|
const def = readDef(schema);
|
|
132
132
|
const getter = def?.getter;
|
|
133
133
|
if (typeof getter !== "function") return void 0;
|
|
134
|
-
return
|
|
134
|
+
return callConsumerFn(() => getter(), void 0);
|
|
135
135
|
}
|
|
136
136
|
function getIntersectionLeft(schema) {
|
|
137
137
|
const def = readDef(schema);
|
|
@@ -145,7 +145,7 @@ function getCatchDefault(schema) {
|
|
|
145
145
|
const def = readDef(schema);
|
|
146
146
|
const cv = def?.catchValue;
|
|
147
147
|
if (typeof cv !== "function") return void 0;
|
|
148
|
-
return
|
|
148
|
+
return callConsumerFn(
|
|
149
149
|
() => cv({ error: new Error("atta:default-values"), input: void 0 }),
|
|
150
150
|
void 0);
|
|
151
151
|
}
|
|
@@ -155,7 +155,7 @@ function hasCatchValue(schema) {
|
|
|
155
155
|
}
|
|
156
156
|
function getDefaultValue(schema) {
|
|
157
157
|
const def = readDef(schema);
|
|
158
|
-
return
|
|
158
|
+
return callConsumerFn(() => def?.defaultValue, void 0);
|
|
159
159
|
}
|
|
160
160
|
function getNativeEnumValues(_schema) {
|
|
161
161
|
return void 0;
|
|
@@ -335,10 +335,10 @@ function zodIssuesToValidationErrors(issues) {
|
|
|
335
335
|
}
|
|
336
336
|
return {
|
|
337
337
|
message: issue.message,
|
|
338
|
-
// Adapter-side paths stay schema-
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
//
|
|
338
|
+
// Adapter-side paths stay schema-RELATIVE: the validation pipeline
|
|
339
|
+
// in `core/create-form-store.ts` prepends the parent path to
|
|
340
|
+
// absolutise, then routes form-level entries, those whose absolute
|
|
341
|
+
// path is empty, to the empty-string bucket at storage time.
|
|
342
342
|
path: issue.path.map((seg) => typeof seg === "number" ? seg : String(seg)),
|
|
343
343
|
code
|
|
344
344
|
};
|
|
@@ -533,9 +533,9 @@ const sharedV4Schemas = createSharedSchemaStore();
|
|
|
533
533
|
function buildV4Services() {
|
|
534
534
|
return {
|
|
535
535
|
getNestedSchemasAtPath: (schema, path, maxRecursionDepth) => getNestedZodSchemasAtPath(schema, path, maxRecursionDepth),
|
|
536
|
-
//
|
|
537
|
-
//
|
|
538
|
-
//
|
|
536
|
+
// No pre-strip for the slim-mode walk: the path walker peels every
|
|
537
|
+
// transparent wrapper inline, so the slim and unstripped walks
|
|
538
|
+
// coincide.
|
|
539
539
|
getNestedSchemasInSlimMode: (schema, path, maxRecursionDepth) => getNestedZodSchemasAtPath(schema, path, maxRecursionDepth),
|
|
540
540
|
slimPrimitivesOf: (schema, maxRecursionDepth) => slimPrimitivesOf(schema, maxRecursionDepth),
|
|
541
541
|
deriveDefault: (schema, useDefault, maxRecursionDepth) => deriveDefault(schema, useDefault, maxRecursionDepth),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as AttaformErrorCode, k as isPlainRecord, s as slimKindOf } from './attaform.
|
|
1
|
+
import { A as AttaformErrorCode, k as isPlainRecord, s as slimKindOf } from './attaform.BIWicztt.mjs';
|
|
2
2
|
import { e as canonicalizePath, h as SET_MEMBER_SEGMENT } from './attaform.CdZIEf7_.mjs';
|
|
3
|
-
import { a as safeOwnRead, b as safeAssign } from './attaform.
|
|
3
|
+
import { a as safeOwnRead, b as safeAssign } from './attaform.8mfKZCwH.mjs';
|
|
4
4
|
|
|
5
5
|
const PATH_SEPARATOR = ".";
|
|
6
6
|
function isOpaqueKind(kind) {
|
|
@@ -425,8 +425,8 @@ function walkPathSegments(schema, segments, intro, maxDepth, lazyDepth) {
|
|
|
425
425
|
const rightResults = right === void 0 ? [] : walkPathSegments(right, segments, intro, maxDepth, lazyDepth);
|
|
426
426
|
return [...leftResults, ...rightResults];
|
|
427
427
|
}
|
|
428
|
-
// Leaves
|
|
429
|
-
// `unknown` / `custom`)
|
|
428
|
+
// Leaves, with nothing further to descend. An opaque leaf (`any` /
|
|
429
|
+
// `unknown` / `custom`) lands here too and `[]` is the truthful
|
|
430
430
|
// answer: the schema declares no sub-paths under them, so none are
|
|
431
431
|
// fabricated. `symbol` / `function` / `promise` hold a value
|
|
432
432
|
// without declaring anything inside it and land here for the same
|
|
@@ -1017,7 +1017,7 @@ function slimPrimitivesWalk(schema, intro, maxDepth, lazyDepth = 0) {
|
|
|
1017
1017
|
case "unknown":
|
|
1018
1018
|
case "custom":
|
|
1019
1019
|
return PERMISSIVE_SLIM_KINDS;
|
|
1020
|
-
// A kind this walker has no case for
|
|
1020
|
+
// A kind this walker has no case for, in practice one a newer
|
|
1021
1021
|
// Zod introduced. Be permissive rather than reject: the adapter
|
|
1022
1022
|
// carries the value opaquely and the schema's own parse is what
|
|
1023
1023
|
// decides whether it was legal.
|
|
@@ -931,20 +931,15 @@ const vRegisterCheckbox = {
|
|
|
931
931
|
el._lastAppliedModel = value.innerRef.value;
|
|
932
932
|
});
|
|
933
933
|
},
|
|
934
|
-
// Skip the DOM sync when the model is identity-unchanged
|
|
935
|
-
//
|
|
936
|
-
//
|
|
937
|
-
//
|
|
938
|
-
//
|
|
939
|
-
//
|
|
940
|
-
//
|
|
941
|
-
//
|
|
942
|
-
//
|
|
943
|
-
// the browser fires `change`. Identity comparison on
|
|
944
|
-
// `innerRef.value` is sound for the same reason as multi-select —
|
|
945
|
-
// every form write produces a fresh value at the path (new
|
|
946
|
-
// primitives; new array/Set references along the spine), so
|
|
947
|
-
// reference equality tracks "did the model move" exactly.
|
|
934
|
+
// Skip the DOM sync when the model is identity-unchanged since the last
|
|
935
|
+
// application. Without the guard, a sibling's reactive write triggers
|
|
936
|
+
// `beforeUpdate` mid-click, `setChecked` re-applies the prior model state,
|
|
937
|
+
// and the in-flight toggle is clobbered before the browser fires `change`.
|
|
938
|
+
// Compare `innerRef.value` by identity: every form write produces a fresh
|
|
939
|
+
// value at the path, new primitives and new array or Set references along
|
|
940
|
+
// the spine, so reference equality tracks "did the model move" exactly. The
|
|
941
|
+
// guard must NOT compare against `oldValue`, which is the previous binding's
|
|
942
|
+
// wrapper RegisterValue and never equals a model scalar.
|
|
948
943
|
beforeUpdate(el, binding, vnode) {
|
|
949
944
|
setAssignFunction(el, vnode, binding.value);
|
|
950
945
|
if (!isRegisterValue(binding.value)) return;
|
|
@@ -994,13 +989,11 @@ const vRegisterRadio = {
|
|
|
994
989
|
}
|
|
995
990
|
});
|
|
996
991
|
},
|
|
997
|
-
//
|
|
998
|
-
//
|
|
999
|
-
//
|
|
1000
|
-
//
|
|
1001
|
-
//
|
|
1002
|
-
// model. Checkbox already uses `mounted: setChecked` for the same
|
|
1003
|
-
// reason.
|
|
992
|
+
// The initial checked sync runs in `mounted`, NOT `created`: Vue fires
|
|
993
|
+
// `created` before the element's attributes are patched, so `type`, `value`
|
|
994
|
+
// and `_value` are absent, `getValue(el)` returns undefined, and every radio
|
|
995
|
+
// in a group mounts unchecked whatever the model says. Checkbox uses
|
|
996
|
+
// `mounted` for the same reason.
|
|
1004
997
|
mounted(el, { value }) {
|
|
1005
998
|
if (!isRegisterValue(value)) return;
|
|
1006
999
|
el.checked = looseEqual(value.innerRef.value, applyCoerce(getValue(el), value));
|
|
@@ -1010,15 +1003,12 @@ const vRegisterRadio = {
|
|
|
1010
1003
|
el._lastAppliedModel = value.innerRef.value;
|
|
1011
1004
|
});
|
|
1012
1005
|
},
|
|
1013
|
-
// Skip the DOM sync when the model is identity-unchanged
|
|
1014
|
-
//
|
|
1015
|
-
//
|
|
1016
|
-
//
|
|
1017
|
-
//
|
|
1018
|
-
//
|
|
1019
|
-
// `vRegisterSelect` and `setChecked` bugs: a sibling's reactive
|
|
1020
|
-
// write triggers `beforeUpdate` mid-click and writes back the
|
|
1021
|
-
// prior model state, clobbering the in-flight selection.
|
|
1006
|
+
// Skip the DOM sync when the model is identity-unchanged since the last
|
|
1007
|
+
// application, tracked on `_lastAppliedModel`. Comparing against `oldValue`
|
|
1008
|
+
// instead compares a primitive scalar to the previous binding's wrapper
|
|
1009
|
+
// RegisterValue, never equal, so `el.checked` re-applies on every parent
|
|
1010
|
+
// re-render and a sibling's reactive write clobbers an in-flight selection
|
|
1011
|
+
// mid-click.
|
|
1022
1012
|
beforeUpdate(el, { value }, vnode) {
|
|
1023
1013
|
if (!isRegisterValue(value)) return;
|
|
1024
1014
|
setAssignFunction(el, vnode, value);
|
|
@@ -1077,22 +1067,20 @@ const vRegisterSelect = {
|
|
|
1077
1067
|
beforeUpdate(el, binding, vnode) {
|
|
1078
1068
|
setAssignFunction(el, vnode, binding.value);
|
|
1079
1069
|
},
|
|
1080
|
-
// Skip the DOM sync when the model is identity-unchanged
|
|
1081
|
-
//
|
|
1082
|
-
//
|
|
1083
|
-
//
|
|
1084
|
-
//
|
|
1085
|
-
//
|
|
1086
|
-
//
|
|
1087
|
-
//
|
|
1088
|
-
//
|
|
1089
|
-
//
|
|
1090
|
-
//
|
|
1091
|
-
//
|
|
1092
|
-
//
|
|
1093
|
-
//
|
|
1094
|
-
// — it short-circuits the immediate post-write render where the
|
|
1095
|
-
// DOM is already in sync from the user's click.
|
|
1070
|
+
// Skip the DOM sync when the model is identity-unchanged since the last
|
|
1071
|
+
// application. A parent re-render fires `updated` whether or not the bound
|
|
1072
|
+
// model moved: a typed character in a sibling, an async-validation tick, any
|
|
1073
|
+
// reactive read elsewhere on the page. Re-applying `setSelected` against the
|
|
1074
|
+
// prior model on each of those clobbers an in-progress `<select multiple>`
|
|
1075
|
+
// selection between mousedown and the browser's change decision, after which
|
|
1076
|
+
// the browser sees no net change, never fires `change`, and the model never
|
|
1077
|
+
// updates.
|
|
1078
|
+
//
|
|
1079
|
+
// Identity comparison is sound: every form write produces a new array or Set
|
|
1080
|
+
// reference at the path, the replacement of `form.value` rolling fresh
|
|
1081
|
+
// structures forward along the spine. The `_assigning` gate stays as well,
|
|
1082
|
+
// short-circuiting the immediate post-write render where the DOM is already
|
|
1083
|
+
// in sync from the user's click.
|
|
1096
1084
|
updated(el, { value }) {
|
|
1097
1085
|
if (el._assigning === true) return;
|
|
1098
1086
|
if (!isRegisterValue(value)) return;
|
|
@@ -1306,13 +1294,12 @@ const vRegisterDynamic = {
|
|
|
1306
1294
|
delete el._syncFromStorage;
|
|
1307
1295
|
delete el[assignKey];
|
|
1308
1296
|
},
|
|
1309
|
-
//
|
|
1310
|
-
//
|
|
1311
|
-
//
|
|
1312
|
-
//
|
|
1313
|
-
//
|
|
1314
|
-
//
|
|
1315
|
-
// describedby matches the client after hydration.
|
|
1297
|
+
// Vue skips directive lifecycle during SSR, so the hooks above never run on
|
|
1298
|
+
// the server and the same aria attributes are emitted here from the SSR-time
|
|
1299
|
+
// gated display state. Honours authored attrs through the vnode-level
|
|
1300
|
+
// lockout, touches no DOM, and shares `resolveAriaValue` with the client
|
|
1301
|
+
// path. Ids are SSR-stable, `formInstanceId` deriving from Vue's `useId`, so
|
|
1302
|
+
// a server-rendered describedby matches the client after hydration.
|
|
1316
1303
|
getSSRProps(binding, vnode) {
|
|
1317
1304
|
const rv = binding.value;
|
|
1318
1305
|
if (!isRegisterValue(rv)) return void 0;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { w as walkPathSegments, s as slimPrimitivesWalk, c as createAbstractSchema, a as createSharedSchemaStore, b as buildFieldMetaPathMap, g as getFieldMetaForSchema, f as fixStructuralDefaults, m as mergeDeep, d as deriveDefaultWalk, e as getFieldMetaListForSchema } from './attaform.
|
|
2
|
-
import { h as getAtPath, j as humanize, c as useAbstractForm } from './attaform.
|
|
3
|
-
import { c as
|
|
1
|
+
import { w as walkPathSegments, s as slimPrimitivesWalk, c as createAbstractSchema, a as createSharedSchemaStore, b as buildFieldMetaPathMap, g as getFieldMetaForSchema, f as fixStructuralDefaults, m as mergeDeep, d as deriveDefaultWalk, e as getFieldMetaListForSchema } from './attaform.DRsANMok.mjs';
|
|
2
|
+
import { h as getAtPath, j as humanize, c as useAbstractForm } from './attaform.BIWicztt.mjs';
|
|
3
|
+
import { c as callConsumerFn } from './attaform.8mfKZCwH.mjs';
|
|
4
4
|
import { A as AttaformError, e as canonicalizePath, a as InvalidUseFormConfigError } from './attaform.CdZIEf7_.mjs';
|
|
5
5
|
|
|
6
6
|
function isZodSchemaType(schema, expectedType) {
|
|
@@ -306,7 +306,7 @@ function unwrapLazy(schema) {
|
|
|
306
306
|
const def = readDef(schema);
|
|
307
307
|
const getter = def?.getter;
|
|
308
308
|
if (typeof getter !== "function") return void 0;
|
|
309
|
-
return
|
|
309
|
+
return callConsumerFn(() => getter(), void 0);
|
|
310
310
|
}
|
|
311
311
|
function getLiteralValues(schema) {
|
|
312
312
|
const def = readDef(schema);
|
|
@@ -323,15 +323,13 @@ function getDefaultValue(schema) {
|
|
|
323
323
|
const def = readDef(schema);
|
|
324
324
|
const thunk = def?.defaultValue;
|
|
325
325
|
if (typeof thunk !== "function") return void 0;
|
|
326
|
-
return
|
|
326
|
+
return callConsumerFn(() => thunk(), void 0);
|
|
327
327
|
}
|
|
328
328
|
function getCatchDefault(schema) {
|
|
329
329
|
const def = readDef(schema);
|
|
330
330
|
const cv = def?.catchValue;
|
|
331
331
|
if (typeof cv !== "function") return void 0;
|
|
332
|
-
return
|
|
333
|
-
() => cv({ error: null, input: void 0 }),
|
|
334
|
-
void 0);
|
|
332
|
+
return callConsumerFn(() => cv({ error: null, input: void 0 }), void 0);
|
|
335
333
|
}
|
|
336
334
|
function hasCatchValue(schema) {
|
|
337
335
|
const def = readDef(schema);
|
|
@@ -830,13 +828,9 @@ function buildV3Services(maxRecursionDepth) {
|
|
|
830
828
|
};
|
|
831
829
|
return {
|
|
832
830
|
getNestedSchemasAtPath: (schema, path, maxRecursionDepth2) => getNestedZodSchemasAtPath(schema, path, maxRecursionDepth2),
|
|
833
|
-
//
|
|
834
|
-
// slim
|
|
835
|
-
//
|
|
836
|
-
// candidates reflect the slim shape.
|
|
837
|
-
// The slim-root projection is gone (size-teardown P7): the shared
|
|
838
|
-
// path walker peels wrappers / effects inline, so the slim and
|
|
839
|
-
// unstripped walks coincide — same aliasing v4 always had.
|
|
831
|
+
// The shared path walker peels wrappers and effects inline, so the
|
|
832
|
+
// slim and unstripped walks coincide and the root needs no slim
|
|
833
|
+
// projection of its own. Same aliasing v4 has.
|
|
840
834
|
getNestedSchemasInSlimMode: (schema, path, maxRecursionDepth2) => getNestedZodSchemasAtPath(schema, path, maxRecursionDepth2),
|
|
841
835
|
slimPrimitivesOf: (schema, _maxRecursionDepth) => slimPrimitivesV3(schema),
|
|
842
836
|
deriveDefault: (schema, useDefault) => getDefaultValuesFromZodSchema(schema, useDefault),
|
|
@@ -855,10 +849,10 @@ function buildV3Services(maxRecursionDepth) {
|
|
|
855
849
|
const result = await schema.safeParseAsync(data);
|
|
856
850
|
return result.success ? { success: true, data: result.data } : { success: false, issues: refileIssues(schema, data, result.error.issues) };
|
|
857
851
|
},
|
|
858
|
-
//
|
|
859
|
-
//
|
|
860
|
-
//
|
|
861
|
-
//
|
|
852
|
+
// A `getSchemasAtPath` consumer may probe any method on the result,
|
|
853
|
+
// so a sub-schema comes back as a full recursive AbstractSchema: the
|
|
854
|
+
// factory call rebuilds the whole surface against it, with its own
|
|
855
|
+
// per-form caches.
|
|
862
856
|
makeSubSchema: (sub, maxRecursionDepth2) => createAbstractSchema(
|
|
863
857
|
sub,
|
|
864
858
|
V3_INTROSPECTOR,
|
|
@@ -878,17 +872,16 @@ function zodIssuesToValidationErrors(issues) {
|
|
|
878
872
|
}
|
|
879
873
|
validationErrors.push({
|
|
880
874
|
message: issue.message,
|
|
881
|
-
// `ValidationError.path` is `(string | number)[]`
|
|
882
|
-
//
|
|
883
|
-
//
|
|
884
|
-
//
|
|
885
|
-
//
|
|
886
|
-
// Mirrors v4's behaviour at the same site.
|
|
875
|
+
// `ValidationError.path` is `(string | number)[]` publicly, and
|
|
876
|
+
// v3's `issue.path` matches in the standard case, but a custom
|
|
877
|
+
// check calling `ctx.addIssue({ path: [...] })` can smuggle a
|
|
878
|
+
// Symbol through. Coerce to keep the promise. v4 does the same
|
|
879
|
+
// here.
|
|
887
880
|
//
|
|
888
|
-
// Adapter-side paths stay schema-
|
|
889
|
-
//
|
|
890
|
-
//
|
|
891
|
-
//
|
|
881
|
+
// Adapter-side paths stay schema-RELATIVE: the validation pipeline
|
|
882
|
+
// in `core/create-form-store.ts` prepends the parent path to
|
|
883
|
+
// absolutise, then routes form-level entries, those whose absolute
|
|
884
|
+
// path is empty, to the empty-string bucket at storage time.
|
|
892
885
|
path: coercePathSegments(issue.path),
|
|
893
886
|
code
|
|
894
887
|
});
|
|
@@ -920,10 +913,10 @@ function unwrapStructuralLeafV3(schema) {
|
|
|
920
913
|
return current;
|
|
921
914
|
}
|
|
922
915
|
function isStructuralV3Kind(schema) {
|
|
923
|
-
return isZodSchemaType(schema, "ZodObject") || isZodSchemaType(schema, "ZodArray") || isZodSchemaType(schema, "ZodRecord") || isZodSchemaType(schema, "ZodTuple") || isZodSchemaType(schema, "ZodUnion") || isZodSchemaType(schema, "ZodDiscriminatedUnion") || // Wrappers that themselves resolve to a structural type
|
|
924
|
-
// peeling
|
|
925
|
-
isZodSchemaType(schema, "ZodOptional") || isZodSchemaType(schema, "ZodNullable") || isZodSchemaType(schema, "ZodDefault") || isZodSchemaType(schema, "ZodEffects") || // Newer transparent wrappers (v3.23+)
|
|
926
|
-
// schema with no structural impact
|
|
916
|
+
return isZodSchemaType(schema, "ZodObject") || isZodSchemaType(schema, "ZodArray") || isZodSchemaType(schema, "ZodRecord") || isZodSchemaType(schema, "ZodTuple") || isZodSchemaType(schema, "ZodUnion") || isZodSchemaType(schema, "ZodDiscriminatedUnion") || // Wrappers that themselves resolve to a structural type; keep
|
|
917
|
+
// peeling next iteration.
|
|
918
|
+
isZodSchemaType(schema, "ZodOptional") || isZodSchemaType(schema, "ZodNullable") || isZodSchemaType(schema, "ZodDefault") || isZodSchemaType(schema, "ZodEffects") || // Newer transparent wrappers (v3.23+), each wrapping one inner
|
|
919
|
+
// schema with no structural impact. `peelV3Wrappers` resolves them.
|
|
927
920
|
isZodSchemaType(schema, "ZodPipeline") || isZodSchemaType(schema, "ZodReadonly") || isZodSchemaType(schema, "ZodBranded");
|
|
928
921
|
}
|
|
929
922
|
function peelV3Wrappers(schema) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { App } from 'vue';
|
|
2
|
+
import { ao as RegisterModelDynamicCustomDirective } from './attaform.Br8EBn5B.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `v-register` directive. Bind a form field to a native input, select,
|
|
6
|
+
* textarea, checkbox or radio:
|
|
7
|
+
*
|
|
8
|
+
* ```vue
|
|
9
|
+
* <input v-register="form.register('email')" />
|
|
10
|
+
* <select v-register="form.register('country')">
|
|
11
|
+
* <option value="us">US</option>
|
|
12
|
+
* <option value="uk">UK</option>
|
|
13
|
+
* </select>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* The binding strategy follows the element's `tagName` and `type`. Delivered by
|
|
17
|
+
* the Vite and Nuxt plugins' compile-time binding, or by
|
|
18
|
+
* `installVRegister(app)` everywhere else. Most consumers never import it
|
|
19
|
+
* directly; it is exposed for integrations that wire directives by hand.
|
|
20
|
+
*/
|
|
21
|
+
declare const vRegister: RegisterModelDynamicCustomDirective;
|
|
22
|
+
/**
|
|
23
|
+
* Register the `v-register` directive app-wide. The one-line setup for an app
|
|
24
|
+
* whose templates are compiled without Attaform's Vite or Nuxt plugin: a
|
|
25
|
+
* webpack-family bundler, a no-build page, or runtime-compiled templates.
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { createApp } from 'vue'
|
|
29
|
+
* import { installVRegister } from 'attaform/directive'
|
|
30
|
+
*
|
|
31
|
+
* const app = createApp(App)
|
|
32
|
+
* installVRegister(app)
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Vite and Nuxt consumers do not call this; their build plugin binds each
|
|
36
|
+
* template's `v-register` at compile time. Idempotent: a second call for the
|
|
37
|
+
* same app is a no-op, and a directive the consumer registered under the same
|
|
38
|
+
* name is left in place.
|
|
39
|
+
*/
|
|
40
|
+
declare function installVRegister(app: App): void;
|
|
41
|
+
|
|
42
|
+
export { installVRegister as i, vRegister as v };
|
|
@@ -756,9 +756,9 @@ function injectPreamble(element, captured) {
|
|
|
756
756
|
),
|
|
757
757
|
exp,
|
|
758
758
|
modifiers: [],
|
|
759
|
-
//
|
|
760
|
-
//
|
|
761
|
-
//
|
|
759
|
+
// The host element's source location, so a runtime error in the
|
|
760
|
+
// synthesized expression points at the consumer's template line
|
|
761
|
+
// rather than at line 0.
|
|
762
762
|
loc: element.loc
|
|
763
763
|
};
|
|
764
764
|
element.props.unshift(directive);
|
package/dist/transforms.d.mts
CHANGED
|
@@ -1,50 +1,177 @@
|
|
|
1
1
|
import { NodeTransform } from '@vue/compiler-core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Vue compiler node transform that bridges `v-register` into the binding
|
|
5
|
+
* shapes its consumers expect, on two kinds of host.
|
|
6
|
+
*
|
|
7
|
+
* - `<select v-register>` gets `:value` on a single-select plus a
|
|
8
|
+
* per-`<option>` `:selected`, so the runtime directive can pre-mark
|
|
9
|
+
* selected options at SSR time.
|
|
10
|
+
* - `<MyComponent v-register>`, and a kebab-case custom-element host,
|
|
11
|
+
* gets a `:registerValue` bridge prop, so `useRegister` inside the
|
|
12
|
+
* child sees the parent's RegisterValue. Any parent-authored slotted
|
|
13
|
+
* `<option>` is marked exactly as the native path marks it, so a
|
|
14
|
+
* `<select>` wrapped in a styled component keeps its SSR-selected
|
|
15
|
+
* option (#394).
|
|
16
|
+
*
|
|
17
|
+
* `attaform/vite` and `attaform/nuxt` wire it for you; reach for it
|
|
18
|
+
* directly only when integrating a custom bundler.
|
|
19
|
+
*/
|
|
20
|
+
|
|
3
21
|
declare const componentBridgeTransform: NodeTransform;
|
|
4
22
|
|
|
5
23
|
/**
|
|
6
|
-
* Vue compiler node transform for `<input v-register>` and
|
|
7
|
-
*
|
|
8
|
-
*
|
|
24
|
+
* Vue compiler node transform for `<input v-register>` and `<textarea
|
|
25
|
+
* v-register>`, injecting the `:value` and `:checked` bindings an
|
|
26
|
+
* SSR-correct initial render needs.
|
|
9
27
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* a custom bundler.
|
|
28
|
+
* `attaform/vite` and `attaform/nuxt` wire it for you; reach for it
|
|
29
|
+
* directly only when integrating a custom bundler.
|
|
13
30
|
*/
|
|
14
31
|
declare const inputTextAreaNodeTransform: NodeTransform;
|
|
15
32
|
|
|
16
33
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
34
|
+
* The compile-time half of the redundant-binding guard (#464). On every
|
|
35
|
+
* element carrying `v-register` it does two things.
|
|
36
|
+
*
|
|
37
|
+
* 1. Warns at build time when a `v-model` sits beside `v-register` on
|
|
38
|
+
* a native `<input>`, `<select>` or `<textarea>`, which installs
|
|
39
|
+
* Vue's own model directive next to Attaform's: two writers driving
|
|
40
|
+
* one element with no fallback story between them.
|
|
41
|
+
* `findRedundantStateBinding` below carries the full reasoning for
|
|
42
|
+
* what does and does not count.
|
|
43
|
+
*
|
|
44
|
+
* 2. Stamps `V_REGISTER_COMPILED_MODIFIER` on the directive so the
|
|
45
|
+
* runtime diagnostic in `core/directive.ts` stands down. This
|
|
46
|
+
* transform runs BEFORE `inputTextAreaNodeTransform` and
|
|
47
|
+
* `componentBridgeTransform` strip and inject the value channel, so
|
|
48
|
+
* it sees the author's props verbatim where the runtime, seeing
|
|
49
|
+
* only the post-injection props, cannot. Exactly one layer fires
|
|
50
|
+
* per consumer.
|
|
51
|
+
*
|
|
52
|
+
* The carve-out: a `:value`, or a static `value=`, is the legitimate
|
|
53
|
+
* IDENTITY channel for a radio and an `<option>`, and `v-register` READS
|
|
54
|
+
* it. Those never warn; only the STATE attrs do.
|
|
55
|
+
*
|
|
56
|
+
* A dynamic `:type` cannot be classified at compile time, so that input
|
|
57
|
+
* is skipped for the warn, best-effort as in `inputTextAreaNodeTransform`
|
|
58
|
+
* and the runtime `resolveDynamicModel`. The marker is still stamped, so
|
|
59
|
+
* the runtime layer, which sees the resolved type, does not double-report.
|
|
60
|
+
*
|
|
61
|
+
* It is deliberately NOT `__DEV__`-gated: firing on every compile,
|
|
62
|
+
* production and CI included, is what lets a consumer retire a bespoke
|
|
63
|
+
* SFC-lint gate. Warnings only. A redundant binding never fails the
|
|
64
|
+
* build, the Vue compiler giving transforms no error channel and a
|
|
65
|
+
* library having no business nuking a consumer's build over a
|
|
66
|
+
* lint-level issue.
|
|
67
|
+
*
|
|
68
|
+
* `attaform/vite` and `attaform/nuxt` wire it first in `nodeTransforms`;
|
|
69
|
+
* reach for it directly only when integrating a custom bundler.
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Vue compiler node transform that warns about a redundant state binding
|
|
74
|
+
* sitting beside `v-register`, and stamps the compile-active marker so
|
|
75
|
+
* the runtime diagnostic stands down.
|
|
20
76
|
*
|
|
21
|
-
*
|
|
22
|
-
* `componentBridgeTransform
|
|
23
|
-
* are stripped
|
|
24
|
-
*
|
|
77
|
+
* It MUST run before `inputTextAreaNodeTransform` and
|
|
78
|
+
* `componentBridgeTransform`, so it reads the author's props before they
|
|
79
|
+
* are stripped and injected. `attaform/vite` and `attaform/nuxt` wire it
|
|
80
|
+
* first.
|
|
25
81
|
*/
|
|
26
82
|
declare const redundantBindingWarnTransform: NodeTransform;
|
|
27
83
|
|
|
28
84
|
/**
|
|
29
|
-
*
|
|
30
|
-
* expression in
|
|
31
|
-
*
|
|
32
|
-
*
|
|
85
|
+
* Rewrites every `<element v-register="<expr>">` so the binding
|
|
86
|
+
* expression wraps `<expr>` in an IIFE that calls
|
|
87
|
+
* `markConnectedOptimistically()` on the resulting `RegisterValue` and
|
|
88
|
+
* hands back the same object:
|
|
89
|
+
*
|
|
90
|
+
* ((__attaRv) => (__attaRv?.markConnectedOptimistically?.(), __attaRv))(<expr>)
|
|
91
|
+
*
|
|
92
|
+
* Vue deliberately skips directive lifecycle hooks during SSR (see the
|
|
93
|
+
* header of `core/directive.ts`), so the `v-register` directive's
|
|
94
|
+
* `created` hook, the one that flips `connected: true`, never fires on
|
|
95
|
+
* the server. Every SSR'd FieldState therefore serialises `connected:
|
|
96
|
+
* false`, then flickers to `true` when the directive runs on hydration,
|
|
97
|
+
* and anything reading `getFieldState(path).connected` in a
|
|
98
|
+
* server-rendered template sees the stale value baked into the HTML.
|
|
33
99
|
*
|
|
34
|
-
*
|
|
35
|
-
* by `
|
|
100
|
+
* The IIFE captures the `RegisterValue` `<expr>` produced, fires the
|
|
101
|
+
* optimistic mark, itself guarded by `state.ssr` so it is a free no-op
|
|
102
|
+
* on the client, and returns the same object, so the directive receives
|
|
103
|
+
* exactly what the author wrote.
|
|
104
|
+
*
|
|
105
|
+
* It is agnostic to the shape of `<expr>`, inline, hoisted into a
|
|
106
|
+
* variable, or dynamically built: all three produce a `RegisterValue` at
|
|
107
|
+
* runtime and the wrapper never needs the path string. A setup-time
|
|
108
|
+
* `register()` call NEVER bound to `v-register` gets no wrapper, no
|
|
109
|
+
* mark, and stays `connected: false` after hydration, which is correct:
|
|
110
|
+
* it represents no rendered DOM element.
|
|
111
|
+
*
|
|
112
|
+
* Idempotent. Running twice on one AST, as some bundler configurations
|
|
113
|
+
* do, detects the marker on the second pass and skips re-wrapping.
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Vue compiler node transform that wraps every `v-register` expression
|
|
118
|
+
* in a small IIFE, so the directive can flag a field connected during
|
|
119
|
+
* SSR and `getFieldState(path).connected` does not flicker after
|
|
120
|
+
* hydration.
|
|
121
|
+
*
|
|
122
|
+
* It must run after `vRegisterPreambleTransform`. `attaform/vite` and
|
|
123
|
+
* `attaform/nuxt` wire both.
|
|
36
124
|
*/
|
|
37
125
|
declare const vRegisterHintTransform: NodeTransform;
|
|
38
126
|
|
|
39
127
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
128
|
+
* Closes the render-order edge `vRegisterHintTransform` alone leaves
|
|
129
|
+
* open.
|
|
130
|
+
*
|
|
131
|
+
* The hint transform wraps each `v-register` expression in an IIFE that
|
|
132
|
+
* calls `markConnectedOptimistically()` when the element's vnode is
|
|
133
|
+
* created, which covers any expression evaluated AT or AFTER the input
|
|
134
|
+
* in render order. Vue's SSR is single-pass top to bottom, though, so in
|
|
135
|
+
*
|
|
136
|
+
* <pre>{{ form.fields.password.connected }}</pre>
|
|
137
|
+
* <input v-register="form.register('password')" />
|
|
138
|
+
*
|
|
139
|
+
* the `<pre>` evaluates BEFORE the wrapper has fired. The serialized
|
|
140
|
+
* HTML carries `connected: false`, the post-hydration steady state says
|
|
141
|
+
* `true`, and the user sees a one-tick flicker.
|
|
142
|
+
*
|
|
143
|
+
* So the marks hoist one level up. The walk collects every static
|
|
144
|
+
* `v-register` binding, skipping `v-for` descendants, whose expressions
|
|
145
|
+
* reference loop locals unavailable at root scope, and prepends a
|
|
146
|
+
* synthetic `:data-atta-pre-mark` directive to the first root element.
|
|
147
|
+
* Vue evaluates an element's prop bindings before recursing into its
|
|
148
|
+
* children, so that IIFE fires every collected mark before any
|
|
149
|
+
* descendant expression runs. Its own expression resolves to
|
|
150
|
+
* `undefined`, which the SSR renderer drops, so no attribute appears and
|
|
151
|
+
* the marks are the only output.
|
|
152
|
+
*
|
|
153
|
+
* Register it BEFORE `vRegisterHintTransform`. The pre-order pass here
|
|
154
|
+
* captures each expression's original, un-wrapped text into a
|
|
155
|
+
* per-template state map, the hint transform then wraps the in-place
|
|
156
|
+
* directive expression, and the exit hook on the first root element
|
|
157
|
+
* builds the preamble from the captured originals. An element's exit
|
|
158
|
+
* hooks fire before `transformElement`'s codegen exit, so the injected
|
|
159
|
+
* prop lands in the rendered output.
|
|
160
|
+
*
|
|
161
|
+
* For a `v-for` descendant the hint transform's per-element wrapper
|
|
162
|
+
* stays load-bearing: those bindings cannot hoist, their path
|
|
163
|
+
* expressions referencing loop-scoped identifiers.
|
|
164
|
+
*/
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Vue compiler node transform that hoists `v-register`'s SSR connection
|
|
168
|
+
* marks to the root of the template. With `vRegisterHintTransform`, it
|
|
169
|
+
* is what lets an expression EARLIER in the template read
|
|
170
|
+
* `getFieldState(path).connected` correctly during the server's
|
|
171
|
+
* single-pass render.
|
|
45
172
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
173
|
+
* It must run before `vRegisterHintTransform`. `attaform/vite` and
|
|
174
|
+
* `attaform/nuxt` wire both.
|
|
48
175
|
*/
|
|
49
176
|
declare const vRegisterPreambleTransform: NodeTransform;
|
|
50
177
|
|
package/dist/transforms.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { c as componentBridgeTransform, i as inputTextAreaNodeTransform, r as redundantBindingWarnTransform, v as vRegisterHintTransform, a as vRegisterPreambleTransform } from './shared/attaform.
|
|
1
|
+
export { c as componentBridgeTransform, i as inputTextAreaNodeTransform, r as redundantBindingWarnTransform, v as vRegisterHintTransform, a as vRegisterPreambleTransform } from './shared/attaform.ZYn2ahzJ.mjs';
|