@kubb/plugin-zod 5.0.0-beta.56 → 5.0.0-beta.64

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/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { t as __name } from "./chunk-C0LytTxp.js";
2
2
  import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
3
- import { buildList, buildObject, extractRefName, objectKey, stringify, stringifyObject, toRegExpString } from "@kubb/ast/utils";
3
+ import { buildList, buildObject, caseParams, containsCircularRef, extractRefName, lazyGetter, mapSchemaItems, mapSchemaMembers, mapSchemaProperties, objectKey, stringify, stringifyObject, syncSchemaRef, toRegExpString } from "@kubb/ast/utils";
4
4
  import { Const, File, Type, jsxRenderer } from "@kubb/renderer-jsx";
5
5
  import { Fragment, jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
6
6
  //#region ../../internals/utils/src/casing.ts
@@ -431,7 +431,7 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
431
431
  if (seen.has(refName)) return false;
432
432
  seen.add(refName);
433
433
  }
434
- const resolved = ast.syncSchemaRef(node);
434
+ const resolved = syncSchemaRef(node);
435
435
  if (resolved.type === "ref") return false;
436
436
  return containsCodec(resolved, seen);
437
437
  }
@@ -443,6 +443,13 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
443
443
  return children.some((child) => containsCodec(child, seen));
444
444
  }
445
445
  /**
446
+ * Collects the names of `$ref` schemas that transitively contain a codec, so the generator can route
447
+ * them to their input (encode) variant.
448
+ */
449
+ function collectCodecRefNames(node) {
450
+ return ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? extractRefName(n.ref) ?? void 0 : void 0 });
451
+ }
452
+ /**
446
453
  * Collects all resolved schema names for an operation's parameters and responses
447
454
  * into a single lookup object, useful for building imports and type references.
448
455
  */
@@ -567,7 +574,7 @@ function strictOneOfMember$1(member, node) {
567
574
  if (node.type === "object" && node.additionalProperties === void 0) return `${member}.strict()`;
568
575
  if (node.type === "ref") {
569
576
  if (member.startsWith("z.lazy(")) return member;
570
- const schema = ast.syncSchemaRef(node);
577
+ const schema = syncSchemaRef(node);
571
578
  if (schema.type === "object" && (schema.additionalProperties === void 0 || schema.additionalProperties === false)) return `${member}.strict()`;
572
579
  }
573
580
  return member;
@@ -659,17 +666,17 @@ const printerZod = ast.definePrinter((options) => {
659
666
  return resolvedName;
660
667
  },
661
668
  object(node) {
662
- const objectBase = `z.object(${buildObject(node.properties.map((prop) => {
663
- const { name: propName, schema } = prop;
664
- const meta = ast.syncSchemaRef(schema);
665
- const isNullable = meta.nullable;
666
- const isOptional = schema.optional;
667
- const isNullish = schema.nullish;
668
- const hasSelfRef = this.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
669
+ const isCyclic = (schema) => this.options.cyclicSchemas != null && containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
670
+ const objectBase = `z.object(${buildObject(mapSchemaProperties(node, (schema) => {
671
+ const hasSelfRef = isCyclic(schema);
669
672
  const savedCyclicSchemas = this.options.cyclicSchemas;
670
673
  if (hasSelfRef) this.options.cyclicSchemas = void 0;
671
- const baseOutput = this.transform(schema) ?? this.transform(ast.createSchema({ type: "unknown" }));
674
+ const baseOutput = this.transform(schema) ?? this.transform(ast.factory.createSchema({ type: "unknown" }));
672
675
  if (hasSelfRef) this.options.cyclicSchemas = savedCyclicSchemas;
676
+ return baseOutput;
677
+ }).map(({ name: propName, property, output: baseOutput }) => {
678
+ const { schema } = property;
679
+ const meta = syncSchemaRef(schema);
673
680
  const wrappedOutput = this.options.wrapOutput ? this.options.wrapOutput({
674
681
  output: baseOutput,
675
682
  schema
@@ -677,38 +684,37 @@ const printerZod = ast.definePrinter((options) => {
677
684
  const descriptionToApply = schema.type !== "ref" && meta.type === "ref" ? void 0 : meta.description;
678
685
  const value = applyModifiers({
679
686
  value: wrappedOutput,
680
- nullable: isNullable,
681
- optional: isOptional,
682
- nullish: isNullish,
687
+ nullable: meta.nullable,
688
+ optional: schema.optional || property.required === false,
689
+ nullish: schema.nullish,
683
690
  defaultValue: meta.default,
684
691
  description: descriptionToApply
685
692
  });
686
- if (hasSelfRef) return `get ${objectKey(propName)}() { return ${value} }`;
687
- return `${objectKey(propName)}: ${value}`;
693
+ return isCyclic(schema) ? lazyGetter({
694
+ name: propName,
695
+ body: value
696
+ }) : `${objectKey(propName)}: ${value}`;
688
697
  }))})`;
689
698
  return (() => {
690
699
  if (node.additionalProperties && node.additionalProperties !== true) {
691
700
  const catchallType = this.transform(node.additionalProperties);
692
701
  return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
693
702
  }
694
- if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(ast.createSchema({ type: "unknown" }))})`;
703
+ if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(ast.factory.createSchema({ type: "unknown" }))})`;
695
704
  if (node.additionalProperties === false) return `${objectBase}.strict()`;
696
705
  return objectBase;
697
706
  })();
698
707
  },
699
708
  array(node) {
700
- const base = `z.array(${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ") || this.transform(ast.createSchema({ type: "unknown" }))})${lengthConstraints(node)}`;
709
+ const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints(node)}`;
701
710
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
702
711
  },
703
712
  tuple(node) {
704
- return `z.tuple(${buildList((node.items ?? []).map((item) => this.transform(item)).filter(Boolean))})`;
713
+ return `z.tuple(${buildList(mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
705
714
  },
706
715
  union(node) {
707
716
  const nodeMembers = node.members ?? [];
708
- const members = nodeMembers.map((memberNode) => {
709
- const member = this.transform(memberNode);
710
- return member && node.strategy === "one" ? strictOneOfMember$1(member, memberNode) : member;
711
- }).filter(Boolean);
717
+ const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember$1(output, schema) : output).filter(Boolean);
712
718
  if (members.length === 0) return "";
713
719
  if (members.length === 1) return members[0];
714
720
  if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, ${buildList(members)})`;
@@ -734,7 +740,7 @@ const printerZod = ast.definePrinter((options) => {
734
740
  const { keysToOmit } = this.options;
735
741
  const transformed = this.transform(node);
736
742
  if (!transformed) return null;
737
- const meta = ast.syncSchemaRef(node);
743
+ const meta = syncSchemaRef(node);
738
744
  return applyModifiers({
739
745
  value: (() => {
740
746
  if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
@@ -837,44 +843,43 @@ const printerZodMini = ast.definePrinter((options) => {
837
843
  return resolvedName;
838
844
  },
839
845
  object(node) {
840
- return `z.object(${buildObject(node.properties.map((prop) => {
841
- const { name: propName, schema } = prop;
842
- const meta = ast.syncSchemaRef(schema);
843
- const isNullable = meta.nullable;
844
- const isOptional = schema.optional;
845
- const isNullish = schema.nullish;
846
- const hasSelfRef = this.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
846
+ const isCyclic = (schema) => this.options.cyclicSchemas != null && containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
847
+ return `z.object(${buildObject(mapSchemaProperties(node, (schema) => {
848
+ const hasSelfRef = isCyclic(schema);
847
849
  const savedCyclicSchemas = this.options.cyclicSchemas;
848
850
  if (hasSelfRef) this.options.cyclicSchemas = void 0;
849
- const baseOutput = this.transform(schema) ?? this.transform(ast.createSchema({ type: "unknown" }));
851
+ const baseOutput = this.transform(schema) ?? this.transform(ast.factory.createSchema({ type: "unknown" }));
850
852
  if (hasSelfRef) this.options.cyclicSchemas = savedCyclicSchemas;
853
+ return baseOutput;
854
+ }).map(({ name: propName, property, output: baseOutput }) => {
855
+ const { schema } = property;
856
+ const meta = syncSchemaRef(schema);
851
857
  const value = applyMiniModifiers({
852
858
  value: this.options.wrapOutput ? this.options.wrapOutput({
853
859
  output: baseOutput,
854
860
  schema
855
861
  }) || baseOutput : baseOutput,
856
- nullable: isNullable,
857
- optional: isOptional,
858
- nullish: isNullish,
862
+ nullable: meta.nullable,
863
+ optional: schema.optional || property.required === false,
864
+ nullish: schema.nullish,
859
865
  defaultValue: meta.default
860
866
  });
861
- if (hasSelfRef) return `get ${objectKey(propName)}() { return ${value} }`;
862
- return `${objectKey(propName)}: ${value}`;
867
+ return isCyclic(schema) ? lazyGetter({
868
+ name: propName,
869
+ body: value
870
+ }) : `${objectKey(propName)}: ${value}`;
863
871
  }))})`;
864
872
  },
865
873
  array(node) {
866
- const base = `z.array(${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ") || this.transform(ast.createSchema({ type: "unknown" }))})${lengthChecksMini(node)}`;
874
+ const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini(node)}`;
867
875
  return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
868
876
  },
869
877
  tuple(node) {
870
- return `z.tuple(${buildList((node.items ?? []).map((item) => this.transform(item)).filter(Boolean))})`;
878
+ return `z.tuple(${buildList(mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
871
879
  },
872
880
  union(node) {
873
881
  const nodeMembers = node.members ?? [];
874
- const members = nodeMembers.map((memberNode) => {
875
- const member = this.transform(memberNode);
876
- return member && node.strategy === "one" ? strictOneOfMember(member, memberNode) : member;
877
- }).filter(Boolean);
882
+ const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema) : output).filter(Boolean);
878
883
  if (members.length === 0) return "";
879
884
  if (members.length === 1) return members[0];
880
885
  if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, ${buildList(members)})`;
@@ -900,7 +905,7 @@ const printerZodMini = ast.definePrinter((options) => {
900
905
  const { keysToOmit } = this.options;
901
906
  const transformed = this.transform(node);
902
907
  if (!transformed) return null;
903
- const meta = ast.syncSchemaRef(node);
908
+ const meta = syncSchemaRef(node);
904
909
  return applyMiniModifiers({
905
910
  value: (() => {
906
911
  if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
@@ -985,7 +990,7 @@ const zodGenerator = defineGenerator({
985
990
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
986
991
  const cyclicSchemas = new Set(ctx.meta.circularNames);
987
992
  const hasCodec = !mini && containsCodec(node);
988
- const codecRefNames = new Set(hasCodec ? ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? extractRefName(n.ref) ?? void 0 : void 0 }) : []);
993
+ const codecRefNames = new Set(hasCodec ? collectCodecRefNames(node) : []);
989
994
  const importEntries = adapter.getImports(node, (schemaName) => ({
990
995
  name: resolver.resolveSchemaName(schemaName),
991
996
  path: resolver.resolveFile({
@@ -1097,7 +1102,7 @@ const zodGenerator = defineGenerator({
1097
1102
  const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, paramsCasing, printer } = ctx.options;
1098
1103
  const dateType = adapter.options.dateType;
1099
1104
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1100
- const params = ast.caseParams(node.parameters, paramsCasing);
1105
+ const params = caseParams(node.parameters, paramsCasing);
1101
1106
  const meta = { file: resolver.resolveFile({
1102
1107
  name: node.operationId,
1103
1108
  extname: ".ts",
@@ -1112,7 +1117,7 @@ const zodGenerator = defineGenerator({
1112
1117
  function renderSchemaEntry({ schema, name, keysToOmit, direction = "output" }) {
1113
1118
  if (!schema) return null;
1114
1119
  const inferTypeName = inferred ? resolver.resolveTypeName(name) : null;
1115
- const codecRefNames = direction === "input" && !mini ? new Set(ast.collect(schema, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? extractRefName(n.ref) ?? void 0 : void 0 })) : null;
1120
+ const codecRefNames = direction === "input" && !mini ? new Set(collectCodecRefNames(schema)) : null;
1116
1121
  const imports = adapter.getImports(schema, (schemaName) => ({
1117
1122
  name: codecRefNames?.has(schemaName) ? resolver.resolveInputSchemaName(schemaName) : resolver.resolveSchemaName(schemaName),
1118
1123
  path: resolver.resolveFile({
@@ -1171,9 +1176,9 @@ const zodGenerator = defineGenerator({
1171
1176
  }
1172
1177
  function buildContentTypeVariants(entries, baseName, decorate, direction) {
1173
1178
  const variants = resolveContentTypeVariants(entries, baseName);
1174
- const unionSchema = ast.createSchema({
1179
+ const unionSchema = ast.factory.createSchema({
1175
1180
  type: "union",
1176
- members: variants.map((variant) => ast.createSchema({
1181
+ members: variants.map((variant) => ast.factory.createSchema({
1177
1182
  type: "ref",
1178
1183
  name: variant.name
1179
1184
  }))
@@ -1211,12 +1216,12 @@ const zodGenerator = defineGenerator({
1211
1216
  name: resolver.resolveSchemaName(schemaName),
1212
1217
  path: ""
1213
1218
  })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseUnionName)) return null;
1214
- const members = responsesWithSchema.map((res) => ast.createSchema({
1219
+ const members = responsesWithSchema.map((res) => ast.factory.createSchema({
1215
1220
  type: "ref",
1216
1221
  name: resolver.resolveResponseStatusName(node, res.statusCode)
1217
1222
  }));
1218
1223
  return renderSchemaEntry({
1219
- schema: members.length === 1 ? members[0] : ast.createSchema({
1224
+ schema: members.length === 1 ? members[0] : ast.factory.createSchema({
1220
1225
  type: "union",
1221
1226
  members
1222
1227
  }),
@@ -1294,7 +1299,7 @@ const zodGenerator = defineGenerator({
1294
1299
  return {
1295
1300
  node,
1296
1301
  data: buildSchemaNames(node, {
1297
- params: ast.caseParams(node.parameters, paramsCasing),
1302
+ params: caseParams(node.parameters, paramsCasing),
1298
1303
  resolver
1299
1304
  })
1300
1305
  };
@@ -1462,7 +1467,7 @@ const pluginZod = definePlugin((options) => {
1462
1467
  const { output = {
1463
1468
  path: "zod",
1464
1469
  barrel: { type: "named" }
1465
- }, group, exclude = [], include, override = [], typed = false, operations = false, mini = false, guidType = "uuid", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, wrapOutput = void 0, paramsCasing, printer, resolver: userResolver, transformer: userTransformer, generators: userGenerators = [] } = options;
1470
+ }, group, exclude = [], include, override = [], typed = false, operations = false, mini = false, guidType = "uuid", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, wrapOutput = void 0, paramsCasing, printer, resolver: userResolver, macros: userMacros, generators: userGenerators = [] } = options;
1466
1471
  const groupConfig = createGroupConfig(group);
1467
1472
  return {
1468
1473
  name: pluginZodName,
@@ -1489,7 +1494,7 @@ const pluginZod = definePlugin((options) => {
1489
1494
  ...resolverZod,
1490
1495
  ...userResolver
1491
1496
  } : resolverZod);
1492
- if (userTransformer) ctx.setTransformer(userTransformer);
1497
+ if (userMacros?.length) ctx.setMacros(userMacros);
1493
1498
  ctx.addGenerator(zodGenerator);
1494
1499
  for (const gen of userGenerators) ctx.addGenerator(gen);
1495
1500
  } }