@kubb/plugin-zod 5.0.0-beta.75 → 5.0.0-beta.76

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.cjs CHANGED
@@ -442,6 +442,28 @@ function regexFunc(regexType) {
442
442
  return regexType === "constructor" ? "RegExp" : null;
443
443
  }
444
444
  /**
445
+ * Builds a Zod record key schema that enforces the `patternProperties` regexes a plain
446
+ * `.catchall()` would drop. Several patterns combine into one alternation (`(^a)|(^b)`).
447
+ */
448
+ function patternKeySchema({ patterns, regexType }) {
449
+ return `z.string().regex(${patternKeySource({
450
+ patterns,
451
+ regexType
452
+ })})`;
453
+ }
454
+ /**
455
+ * `zod/mini` variant of {@link patternKeySchema}, wrapping the regex in `.check(z.regex(...))`.
456
+ */
457
+ function patternKeySchemaMini({ patterns, regexType }) {
458
+ return `z.string().check(z.regex(${patternKeySource({
459
+ patterns,
460
+ regexType
461
+ })}))`;
462
+ }
463
+ function patternKeySource({ patterns, regexType }) {
464
+ return (0, _kubb_ast_utils.toRegExpString)(patterns.length === 1 ? patterns[0] : patterns.map((pattern) => `(${pattern})`).join("|"), regexFunc(regexType));
465
+ }
466
+ /**
445
467
  * Build `.min()` / `.max()` / `.gt()` / `.lt()` constraint chains for numbers
446
468
  * using the standard chainable Zod v4 API.
447
469
  */
@@ -631,7 +653,7 @@ const printerZod = _kubb_core.ast.createPrinter((options) => {
631
653
  },
632
654
  object(node) {
633
655
  const isCyclic = (schema) => this.options.cyclicSchemas != null && (0, _kubb_ast_utils.containsCircularRef)(schema, { circularSchemas: this.options.cyclicSchemas });
634
- const objectBase = `z.object(${(0, _kubb_ast_utils.buildObject)((0, _kubb_ast_utils.mapSchemaProperties)(node, (schema) => {
656
+ const entries = (0, _kubb_ast_utils.mapSchemaProperties)(node, (schema) => {
635
657
  const hasSelfRef = isCyclic(schema);
636
658
  const savedCyclicSchemas = this.options.cyclicSchemas;
637
659
  if (hasSelfRef) this.options.cyclicSchemas = void 0;
@@ -659,14 +681,29 @@ const printerZod = _kubb_core.ast.createPrinter((options) => {
659
681
  name: propName,
660
682
  body: value
661
683
  }) : `${(0, _kubb_ast_utils.objectKey)(propName)}: ${value}`;
662
- }))})`;
684
+ });
685
+ const objectBase = `z.object(${(0, _kubb_ast_utils.buildObject)(entries)})`;
663
686
  return (() => {
687
+ const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
664
688
  if (node.additionalProperties && node.additionalProperties !== true) {
665
689
  const catchallType = this.transform(node.additionalProperties);
666
690
  return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
667
691
  }
668
692
  if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})`;
669
- if (node.additionalProperties === false) return `${objectBase}.strict()`;
693
+ if (node.additionalProperties === false && patterns.length === 0) return `${objectBase}.strict()`;
694
+ if (patterns.length > 0) {
695
+ const values = patterns.map(([, valueSchema]) => {
696
+ const valueType = this.transform(valueSchema) ?? this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }));
697
+ return valueSchema.nullable ? `${valueType}.nullable()` : valueType;
698
+ });
699
+ const distinct = [...new Set(values)];
700
+ const value = distinct.length === 1 ? distinct[0] : `z.union([${distinct.join(", ")}])`;
701
+ if (entries.length > 0) return `${objectBase}.catchall(${value})`;
702
+ return `z.record(${patternKeySchema({
703
+ patterns: patterns.map(([pattern]) => pattern),
704
+ regexType: this.options.regexType
705
+ })}, ${value})`;
706
+ }
670
707
  return objectBase;
671
708
  })();
672
709
  },
@@ -834,7 +871,7 @@ const printerZodMini = _kubb_core.ast.createPrinter((options) => {
834
871
  },
835
872
  object(node) {
836
873
  const isCyclic = (schema) => this.options.cyclicSchemas != null && (0, _kubb_ast_utils.containsCircularRef)(schema, { circularSchemas: this.options.cyclicSchemas });
837
- return `z.object(${(0, _kubb_ast_utils.buildObject)((0, _kubb_ast_utils.mapSchemaProperties)(node, (schema) => {
874
+ const entries = (0, _kubb_ast_utils.mapSchemaProperties)(node, (schema) => {
838
875
  const hasSelfRef = isCyclic(schema);
839
876
  const savedCyclicSchemas = this.options.cyclicSchemas;
840
877
  if (hasSelfRef) this.options.cyclicSchemas = void 0;
@@ -858,7 +895,29 @@ const printerZodMini = _kubb_core.ast.createPrinter((options) => {
858
895
  name: propName,
859
896
  body: value
860
897
  }) : `${(0, _kubb_ast_utils.objectKey)(propName)}: ${value}`;
861
- }))})`;
898
+ });
899
+ const objectBase = `z.object(${(0, _kubb_ast_utils.buildObject)(entries)})`;
900
+ const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
901
+ if (node.additionalProperties && node.additionalProperties !== true) {
902
+ const catchallType = this.transform(node.additionalProperties);
903
+ return catchallType ? `z.catchall(${objectBase}, ${catchallType})` : objectBase;
904
+ }
905
+ if (node.additionalProperties === true) return `z.catchall(${objectBase}, ${this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})`;
906
+ if (node.additionalProperties === false && patterns.length === 0) return objectBase.replace(/^z\.object\(/, "z.strictObject(");
907
+ if (patterns.length > 0) {
908
+ const values = patterns.map(([, valueSchema]) => {
909
+ const valueType = this.transform(valueSchema) ?? this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }));
910
+ return valueSchema.nullable ? `z.nullable(${valueType})` : valueType;
911
+ });
912
+ const distinct = [...new Set(values)];
913
+ const value = distinct.length === 1 ? distinct[0] : `z.union([${distinct.join(", ")}])`;
914
+ if (entries.length > 0) return `z.catchall(${objectBase}, ${value})`;
915
+ return `z.record(${patternKeySchemaMini({
916
+ patterns: patterns.map(([pattern]) => pattern),
917
+ regexType: this.options.regexType
918
+ })}, ${value})`;
919
+ }
920
+ return objectBase;
862
921
  },
863
922
  array(node) {
864
923
  const base = `z.array(${(0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini({
@@ -1237,6 +1296,25 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1237
1296
  name: responseUnionName
1238
1297
  });
1239
1298
  })() : null;
1299
+ const errorResponsesWithSchema = responsesWithSchema.filter((res) => !isSuccessStatusCode(res.statusCode));
1300
+ const errorUnionSchema = errorResponsesWithSchema.length > 0 ? (() => {
1301
+ const errorUnionName = resolver.resolveErrorName(node);
1302
+ if (new Set(errorResponsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1303
+ name: resolver.resolveSchemaName(schemaName),
1304
+ path: ""
1305
+ })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(errorUnionName)) return null;
1306
+ const members = errorResponsesWithSchema.map((res) => _kubb_core.ast.factory.createSchema({
1307
+ type: "ref",
1308
+ name: resolver.resolveResponseStatusName(node, res.statusCode)
1309
+ }));
1310
+ return renderSchemaEntry({
1311
+ schema: members.length === 1 ? members[0] : _kubb_core.ast.factory.createSchema({
1312
+ type: "union",
1313
+ members
1314
+ }),
1315
+ name: errorUnionName
1316
+ });
1317
+ })() : null;
1240
1318
  const requestBodyContent = node.requestBody?.content ?? [];
1241
1319
  const requestSchema = (() => {
1242
1320
  if (requestBodyContent.length === 0) return null;
@@ -1287,6 +1365,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
1287
1365
  paramSchemas,
1288
1366
  responseSchemas,
1289
1367
  responseUnionSchema,
1368
+ errorUnionSchema,
1290
1369
  requestSchema
1291
1370
  ]
1292
1371
  });
@@ -1350,6 +1429,9 @@ const resolverZod = (0, _kubb_core.defineResolver)(() => {
1350
1429
  resolveResponseName(node) {
1351
1430
  return this.resolveSchemaName(`${node.operationId} Response`);
1352
1431
  },
1432
+ resolveErrorName(node) {
1433
+ return this.resolveSchemaName(`${node.operationId} Error`);
1434
+ },
1353
1435
  resolvePathParamsName(node, param) {
1354
1436
  return this.resolveParamName(node, param);
1355
1437
  },