attaform 0.28.0 → 0.29.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 (64) hide show
  1. package/dist/abstract.d.mts +5 -5
  2. package/dist/abstract.mjs +4 -4
  3. package/dist/chunks/fingerprint.mjs +1 -1
  4. package/dist/chunks/fingerprint2.mjs +2 -2
  5. package/dist/dev/abstract.mjs +4 -4
  6. package/dist/dev/chunks/devtools.mjs +1 -1
  7. package/dist/dev/chunks/fingerprint.mjs +1 -1
  8. package/dist/dev/chunks/fingerprint2.mjs +2 -2
  9. package/dist/dev/directive.mjs +1 -1
  10. package/dist/dev/history.mjs +1 -1
  11. package/dist/dev/index.mjs +5 -5
  12. package/dist/dev/runtime/plugins/attaform.mjs +1 -1
  13. package/dist/dev/shared/{attaform-dev.Dr2YzS5B.mjs → attaform-dev.A-TpJW0B.mjs} +11 -1
  14. package/dist/dev/shared/{attaform-dev.oYrkP9dj.mjs → attaform-dev.BO-71R54.mjs} +51 -158
  15. package/dist/dev/shared/{attaform-dev.6qxD-Yqo.mjs → attaform-dev.BgM6FdtA.mjs} +143 -36
  16. package/dist/{shared/attaform.h0i6LijT.mjs → dev/shared/attaform-dev.ButTkwHd.mjs} +149 -16
  17. package/dist/{shared/attaform.BJGA_UOS.mjs → dev/shared/attaform-dev.BxfsuwBR.mjs} +8 -0
  18. package/dist/dev/shared/{attaform-dev.P7cseiEG.mjs → attaform-dev.D8aoKb89.mjs} +13 -4
  19. package/dist/dev/shared/{attaform-dev.BXE2cr0L.mjs → attaform-dev.DD5m2W51.mjs} +1 -1
  20. package/dist/dev/shared/{attaform-dev.WmuhD_CZ.mjs → attaform-dev.DHuydLAC.mjs} +344 -96
  21. package/dist/dev/shared/{attaform-dev.BR8u0YOZ.mjs → attaform-dev.DrzObAZo.mjs} +4 -4
  22. package/dist/dev/shared/{attaform-dev.D2I8e_Mm.mjs → attaform-dev.q6UutkCx.mjs} +170 -132
  23. package/dist/dev/zod-v3.mjs +6 -6
  24. package/dist/dev/zod-v4.mjs +6 -6
  25. package/dist/dev/zod.mjs +5 -5
  26. package/dist/directive.d.mts +2 -2
  27. package/dist/directive.mjs +1 -1
  28. package/dist/history.d.mts +1 -1
  29. package/dist/history.mjs +1 -1
  30. package/dist/index.d.mts +9 -7
  31. package/dist/index.mjs +5 -5
  32. package/dist/nuxt.d.mts +10 -10
  33. package/dist/runtime/plugins/attaform.mjs +1 -1
  34. package/dist/shared/{attaform.C09fpdLS.mjs → attaform.B0dKL8ST.mjs} +143 -36
  35. package/dist/shared/{attaform.Cs2Rbdlo.mjs → attaform.BK0cgu2K.mjs} +123 -139
  36. package/dist/shared/{attaform.D6DCnnQu.mjs → attaform.BndjUUYX.mjs} +4 -4
  37. package/dist/{dev/shared/attaform-dev.BJGA_UOS.mjs → shared/attaform.BxfsuwBR.mjs} +8 -0
  38. package/dist/shared/{attaform.NLmerepI.mjs → attaform.C2MVyuxC.mjs} +42 -151
  39. package/dist/shared/{attaform.B4VkS43-.d.mts → attaform.CIWLMY-R.d.mts} +1 -1
  40. package/dist/shared/{attaform.B8k8JrmK.mjs → attaform.CZMAYwSK.mjs} +338 -95
  41. package/dist/shared/{attaform.wfY8XFvm.mjs → attaform.CZYt_5N_.mjs} +11 -1
  42. package/dist/shared/{attaform.Cgu-hdSb.d.mts → attaform.CsoeRi3P.d.mts} +224 -32
  43. package/dist/{dev/shared/attaform-dev.By4PRjt0.mjs → shared/attaform.Cvao8bW5.mjs} +132 -22
  44. package/dist/shared/{attaform.Dq4vWxuG.mjs → attaform.D0x-qSXm.mjs} +1 -1
  45. package/dist/shared/{attaform.CJP3RkGa.mjs → attaform.D1fnTifF.mjs} +168 -132
  46. package/dist/shared/{attaform.D5V4tZWq.d.mts → attaform.DDtqHYv1.d.mts} +88 -7
  47. package/dist/shared/{attaform.uLbun31C.mjs → attaform.DffRL5pP.mjs} +12 -4
  48. package/dist/shared/{attaform.JfSWdEcb.d.mts → attaform.axHXVQO7.d.mts} +1 -1
  49. package/dist/transforms.d.mts +0 -22
  50. package/dist/transforms.mjs +1 -1
  51. package/dist/vite.d.mts +13 -4
  52. package/dist/vite.mjs +3 -2
  53. package/dist/zod-v3.d.mts +6 -4
  54. package/dist/zod-v3.mjs +6 -6
  55. package/dist/zod-v4.d.mts +14 -27
  56. package/dist/zod-v4.mjs +6 -6
  57. package/dist/zod.d.mts +4 -4
  58. package/dist/zod.mjs +5 -5
  59. package/package.json +17 -14
  60. package/skills/attaform/SKILL.md +5 -2
  61. package/skills/attaform/references/custom-components.md +7 -2
  62. package/skills/attaform/references/errors.md +8 -3
  63. package/skills/attaform/references/saving.md +77 -0
  64. package/skills/attaform/references/wizards.md +10 -8
@@ -1,16 +1,30 @@
1
- import { A as AttaformErrorCode, n as isPlainRecord, s as slimKindOf } from './attaform.B8k8JrmK.mjs';
2
- import { e as canonicalizePath } from './attaform.wfY8XFvm.mjs';
3
- import { a as safeOwnRead, b as safeAssign } from './attaform.h0i6LijT.mjs';
1
+ import { A as AttaformErrorCode, n as isPlainRecord, s as slimKindOf, o as crossCopyState } from './attaform.CZMAYwSK.mjs';
2
+ import { e as canonicalizePath, h as SET_MEMBER_SEGMENT } from './attaform.CZYt_5N_.mjs';
3
+ import { a as safeOwnRead, b as safeAssign } from './attaform.Cvao8bW5.mjs';
4
4
 
5
5
  const PATH_SEPARATOR = ".";
6
+ function isOpaqueKind(kind) {
7
+ return kind === "any" || kind === "unknown" || kind === "custom";
8
+ }
6
9
  function createAbstractSchema(rootSchema, intro, services, formKey, options) {
7
10
  const maxRecursionDepth = options.maxRecursionDepth;
8
11
  const leafCache = /* @__PURE__ */ new Map();
9
12
  const preprocessOrCoerceCache = /* @__PURE__ */ new Map();
13
+ const opaqueLeafCache = /* @__PURE__ */ new Map();
10
14
  const discriminatorCache = /* @__PURE__ */ new Map();
15
+ const entryKeyKindCache = /* @__PURE__ */ new Map();
11
16
  let asyncValidationFlag = null;
12
17
  let containerRefineFlag = null;
13
18
  let discriminatedUnionFlag = null;
19
+ function mapKeySegmentKind(schema) {
20
+ const keyType = intro.getMapKeyType(schema);
21
+ if (keyType === void 0) return void 0;
22
+ const kinds = services.slimPrimitivesOf(keyType, maxRecursionDepth);
23
+ const string = kinds.has("string");
24
+ const number = kinds.has("number");
25
+ if (string === number) return void 0;
26
+ return string ? "string" : "number";
27
+ }
14
28
  function computeDiscriminator(path) {
15
29
  const candidates = path.length === 0 ? [rootSchema] : services.getNestedSchemasAtPath(rootSchema, path, maxRecursionDepth);
16
30
  let matchedUnion;
@@ -102,6 +116,32 @@ function createAbstractSchema(rootSchema, intro, services, formKey, options) {
102
116
  if (resolved.length === 0) return false;
103
117
  return resolved.every((s) => intro.kindOf(services.peelAllWrappers(s)) === "object");
104
118
  },
119
+ entryKeyKindAtPath(path) {
120
+ const cacheKey = canonicalizePath(path).key;
121
+ if (entryKeyKindCache.has(cacheKey)) return entryKeyKindCache.get(cacheKey);
122
+ const resolved = path.length === 0 ? [rootSchema] : services.getNestedSchemasAtPath(rootSchema, path, maxRecursionDepth);
123
+ let answer;
124
+ const only = resolved.length === 1 ? resolved[0] : void 0;
125
+ if (only !== void 0) {
126
+ switch (intro.kindOf(services.peelAllWrappers(only))) {
127
+ case "array":
128
+ case "tuple":
129
+ answer = "number";
130
+ break;
131
+ case "object":
132
+ case "record":
133
+ answer = "string";
134
+ break;
135
+ case "map":
136
+ answer = mapKeySegmentKind(services.peelAllWrappers(only));
137
+ break;
138
+ default:
139
+ answer = void 0;
140
+ }
141
+ }
142
+ entryKeyKindCache.set(cacheKey, answer);
143
+ return answer;
144
+ },
105
145
  getSchemasAtPath(path) {
106
146
  const resolved = services.getNestedSchemasInSlimMode(rootSchema, path, maxRecursionDepth);
107
147
  if (resolved.length === 0) return [];
@@ -123,8 +163,9 @@ function createAbstractSchema(rootSchema, intro, services, formKey, options) {
123
163
  const cacheKey = canonicalizePath(path).key;
124
164
  const cached = leafCache.get(cacheKey);
125
165
  if (cached !== void 0) return cached;
126
- const prim = this.getSlimPrimitiveTypesAtPath(path);
127
- const isLeaf = prim.size > 0 && !prim.has("object") && !prim.has("array") && !prim.has("map") && !prim.has("set");
166
+ const opaque = path.length > 0 && this.isOpaqueLeafAtPath(path);
167
+ const prim = opaque ? void 0 : this.getSlimPrimitiveTypesAtPath(path);
168
+ const isLeaf = opaque || prim !== void 0 && prim.size > 0 && !prim.has("object") && !prim.has("array") && !prim.has("map") && !prim.has("set");
128
169
  leafCache.set(cacheKey, isLeaf);
129
170
  return isLeaf;
130
171
  },
@@ -146,6 +187,17 @@ function createAbstractSchema(rootSchema, intro, services, formKey, options) {
146
187
  preprocessOrCoerceCache.set(cacheKey, hit);
147
188
  return hit;
148
189
  },
190
+ isOpaqueLeafAtPath(path) {
191
+ const cacheKey = canonicalizePath(path).key;
192
+ const cached = opaqueLeafCache.get(cacheKey);
193
+ if (cached !== void 0) return cached;
194
+ const resolved = path.length === 0 ? [rootSchema] : services.getNestedSchemasAtPath(rootSchema, path, maxRecursionDepth);
195
+ const opaque = resolved.length > 0 && resolved.every(
196
+ (candidate) => isOpaqueKind(intro.kindOf(services.peelAllWrappers(candidate)))
197
+ );
198
+ opaqueLeafCache.set(cacheKey, opaque);
199
+ return opaque;
200
+ },
149
201
  isRequiredAtPath(path) {
150
202
  if (path.length === 0) return true;
151
203
  const resolved = services.getNestedSchemasAtPath(rootSchema, path, maxRecursionDepth);
@@ -289,6 +341,7 @@ function walkPathSegments(schema, segments, intro, maxDepth, lazyDepth) {
289
341
  return inner === void 0 ? [] : walkPathSegments(inner, rest, intro, maxDepth, lazyDepth);
290
342
  }
291
343
  case "set": {
344
+ if (head !== SET_MEMBER_SEGMENT) return [];
292
345
  const inner = intro.getSetValueType(schema);
293
346
  return inner === void 0 ? [] : walkPathSegments(inner, rest, intro, maxDepth, lazyDepth);
294
347
  }
@@ -296,6 +349,10 @@ function walkPathSegments(schema, segments, intro, maxDepth, lazyDepth) {
296
349
  const inner = intro.getRecordValueType(schema);
297
350
  return inner === void 0 ? [] : walkPathSegments(inner, rest, intro, maxDepth, lazyDepth);
298
351
  }
352
+ case "map": {
353
+ const inner = intro.getMapValueType(schema);
354
+ return inner === void 0 ? [] : walkPathSegments(inner, rest, intro, maxDepth, lazyDepth);
355
+ }
299
356
  case "tuple": {
300
357
  const index = Number(head);
301
358
  if (!Number.isInteger(index)) return [];
@@ -349,11 +406,13 @@ function walkPathSegments(schema, segments, intro, maxDepth, lazyDepth) {
349
406
  const rightResults = right === void 0 ? [] : walkPathSegments(right, segments, intro, maxDepth, lazyDepth);
350
407
  return [...leftResults, ...rightResults];
351
408
  }
352
- // Leaves — can't descend further. The unsupported kinds (`map` /
353
- // `symbol` / `function` / `promise`) are rejected at adapter
354
- // construction by `assertSupportedKinds`; falling through to `[]`
355
- // keeps the walker defensive in case construction is skipped
356
- // (e.g. a downstream test instantiates a sub-schema directly).
409
+ // Leaves — can't descend further. Opaque leaves (`any` /
410
+ // `unknown` / `custom`) land here too and `[]` is the truthful
411
+ // answer: the schema declares no sub-paths under them, so none are
412
+ // fabricated. `symbol` / `function` / `promise` hold a value
413
+ // without declaring anything inside it and land here for the same
414
+ // reason. No kind is refused at construction (#607), so this is
415
+ // the only branch they ever take.
357
416
  default:
358
417
  return [];
359
418
  }
@@ -461,6 +520,15 @@ function fixNode(schema, value, ctx, lazyDepth) {
461
520
  }
462
521
  return value;
463
522
  }
523
+ case "map": {
524
+ if (!(value instanceof Map)) return value;
525
+ const valueType = intro.getMapValueType(schema);
526
+ if (valueType === void 0) return value;
527
+ for (const [key, entry] of [...value]) {
528
+ value.set(key, fixNode(valueType, entry, ctx, lazyDepth));
529
+ }
530
+ return value;
531
+ }
464
532
  case "intersection": {
465
533
  const left = intro.getIntersectionLeft(schema);
466
534
  const right = intro.getIntersectionRight(schema);
@@ -684,58 +752,63 @@ function deriveDefaultWalk(schema, useDefault, intro, maxDepth, ctx, lazyDepth =
684
752
  }
685
753
  case "file":
686
754
  return null;
755
+ case "map":
756
+ return /* @__PURE__ */ new Map();
757
+ case "template-literal":
758
+ return "";
687
759
  case "any":
688
760
  case "unknown":
761
+ case "custom":
689
762
  case "void":
690
763
  case "never":
691
764
  case "promise":
692
- case "custom":
693
- case "template-literal":
694
- case "transform":
695
- case "map":
696
765
  case "symbol":
697
766
  case "function":
767
+ case "transform":
698
768
  return void 0;
699
769
  default:
700
770
  return ctx.unsupportedKindFallback(schema, kind);
701
771
  }
702
772
  }
703
773
 
704
- const store = /* @__PURE__ */ new WeakMap();
705
- const lists = /* @__PURE__ */ new WeakMap();
774
+ const state = crossCopyState(/* @__PURE__ */ Symbol.for("attaform:field-meta-state"), () => ({
775
+ store: /* @__PURE__ */ new WeakMap(),
776
+ lists: /* @__PURE__ */ new WeakMap(),
777
+ pathMapBuilder: null
778
+ }));
706
779
  const registry = {
707
780
  add(schema, payload) {
708
- store.set(schema, payload);
709
- const list = lists.get(schema) ?? [];
781
+ state.store.set(schema, payload);
782
+ const list = state.lists.get(schema) ?? [];
710
783
  list.push(payload);
711
- lists.set(schema, list);
784
+ state.lists.set(schema, list);
712
785
  return registry;
713
786
  },
714
787
  get(schema) {
715
- return store.get(schema);
788
+ return state.store.get(schema);
716
789
  },
717
790
  has(schema) {
718
- return store.has(schema);
791
+ return state.store.has(schema);
719
792
  },
720
793
  remove(schema) {
721
- store.delete(schema);
722
- lists.delete(schema);
794
+ state.store.delete(schema);
795
+ state.lists.delete(schema);
723
796
  return registry;
724
797
  }
725
798
  };
726
799
  const fieldMetaStore = registry;
727
800
  function getFieldMetaForSchema(schema) {
728
- return store.get(schema);
801
+ return state.store.get(schema);
729
802
  }
730
803
  function getFieldMetaListForSchema(schema) {
731
- return lists.get(schema) ?? [];
804
+ return state.lists.get(schema) ?? [];
732
805
  }
733
- let pathMapBuilder = null;
734
806
  function installFieldMetaPathMapBuilder(builder) {
735
- pathMapBuilder = builder;
807
+ state.pathMapBuilder = builder;
736
808
  }
737
809
  function buildFieldMetaPathMap(rootSchema, services) {
738
- return pathMapBuilder === null ? void 0 : pathMapBuilder(rootSchema, services);
810
+ const builder = state.pathMapBuilder;
811
+ return builder === null ? void 0 : builder(rootSchema, services);
739
812
  }
740
813
 
741
814
  const PERMISSIVE_SLIM_KINDS = /* @__PURE__ */ new Set([
@@ -764,6 +837,16 @@ const KIND_UNDEFINED = /* @__PURE__ */ new Set(["undefined"]);
764
837
  const KIND_OBJECT = /* @__PURE__ */ new Set(["object"]);
765
838
  const KIND_ARRAY = /* @__PURE__ */ new Set(["array"]);
766
839
  const KIND_SET = /* @__PURE__ */ new Set(["set"]);
840
+ const KIND_MAP = /* @__PURE__ */ new Set(["map"]);
841
+ const KIND_SYMBOL = /* @__PURE__ */ new Set(["symbol", "undefined"]);
842
+ const KIND_FUNCTION = /* @__PURE__ */ new Set([
843
+ "function",
844
+ "undefined"
845
+ ]);
846
+ const KIND_PROMISE = /* @__PURE__ */ new Set([
847
+ "object",
848
+ "undefined"
849
+ ]);
767
850
  const KIND_FILE = /* @__PURE__ */ new Set(["file", "null"]);
768
851
  const EMPTY_KINDS = /* @__PURE__ */ new Set();
769
852
  function slimPrimitivesWalk(schema, intro, maxDepth, lazyDepth = 0) {
@@ -820,6 +903,16 @@ function slimPrimitivesWalk(schema, intro, maxDepth, lazyDepth = 0) {
820
903
  return KIND_ARRAY;
821
904
  case "set":
822
905
  return KIND_SET;
906
+ case "map":
907
+ return KIND_MAP;
908
+ case "symbol":
909
+ return KIND_SYMBOL;
910
+ case "function":
911
+ return KIND_FUNCTION;
912
+ case "promise":
913
+ return KIND_PROMISE;
914
+ case "template-literal":
915
+ return KIND_STRING;
823
916
  case "optional": {
824
917
  const inner = intro.unwrapInner(schema);
825
918
  const innerSet = inner === void 0 ? EMPTY_KINDS : slimPrimitivesWalk(inner, intro, maxDepth, lazyDepth);
@@ -883,14 +976,19 @@ function slimPrimitivesWalk(schema, intro, maxDepth, lazyDepth = 0) {
883
976
  }
884
977
  case "never":
885
978
  return EMPTY_KINDS;
979
+ // Opaque leaves: the schema says nothing about the value's shape,
980
+ // so every kind is admissible. `custom` is the kind
981
+ // `z.instanceof(X)` and `z.custom<T>()` compile to on v4 (#542);
982
+ // it belongs with `any` / `unknown` rather than in the defensive
983
+ // fallthrough, because it reaches here through the public surface.
886
984
  case "any":
887
985
  case "unknown":
986
+ case "custom":
888
987
  return PERMISSIVE_SLIM_KINDS;
889
- // Opaque / unsupported kinds: be permissive so legitimate writes
890
- // aren't false-rejected. The unsupported kinds (`map` / `symbol` /
891
- // `function` / `promise`) are rejected at adapter construction by
892
- // `assertSupportedKinds`; this fallthrough keeps the walker
893
- // defensive in case construction is skipped.
988
+ // A kind this walker has no case for — in practice a kind a newer
989
+ // Zod introduced. Be permissive rather than reject: the adapter
990
+ // carries the value opaquely and the schema's own parse is what
991
+ // decides whether it was legal.
894
992
  default:
895
993
  return PERMISSIVE_SLIM_KINDS;
896
994
  }
@@ -984,11 +1082,20 @@ function walkForMeta(schema, path, map, counters, lastPathPerSchema, inProgress,
984
1082
  case "set": {
985
1083
  const inner = intro.getSetValueType(schema);
986
1084
  if (inner !== void 0)
987
- walkForMeta(inner, [...path, 0], map, counters, lastPathPerSchema, inProgress, services);
1085
+ walkForMeta(
1086
+ inner,
1087
+ [...path, SET_MEMBER_SEGMENT],
1088
+ map,
1089
+ counters,
1090
+ lastPathPerSchema,
1091
+ inProgress,
1092
+ services
1093
+ );
988
1094
  return;
989
1095
  }
990
- case "record": {
991
- const inner = intro.getRecordValueType(schema);
1096
+ case "record":
1097
+ case "map": {
1098
+ const inner = kind === "map" ? intro.getMapValueType(schema) : intro.getRecordValueType(schema);
992
1099
  if (inner !== void 0)
993
1100
  walkForMeta(inner, [...path, "*"], map, counters, lastPathPerSchema, inProgress, services);
994
1101
  return;