@kubb/plugin-zod 5.0.0-beta.87 → 5.0.0-beta.95

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.d.ts CHANGED
@@ -82,12 +82,6 @@ type PrinterZodOptions = {
82
82
  * variant for each date-bearing component.
83
83
  */
84
84
  direction?: 'input' | 'output';
85
- /**
86
- * Maps a component `$ref` path to its collision-resolved name. When two components collide
87
- * (across sections or by case), the adapter renames one of them; the `ref()` handler resolves
88
- * the referenced name through this map so the emitted schema reference matches the renamed component.
89
- */
90
- nameMapping?: ReadonlyMap<string, string>;
91
85
  /**
92
86
  * Custom handler map for node type overrides.
93
87
  */
@@ -162,12 +156,6 @@ type PrinterZodMiniOptions = {
162
156
  * Properties referencing these emit lazy getters wrapping refs in `z.lazy(() => …)`.
163
157
  */
164
158
  cyclicSchemas?: ReadonlySet<string>;
165
- /**
166
- * Maps a component `$ref` path to its collision-resolved name. When two components collide
167
- * (across sections or by case), the adapter renames one of them; the `ref()` handler resolves
168
- * the referenced name through this map so the emitted schema reference matches the renamed component.
169
- */
170
- nameMapping?: ReadonlyMap<string, string>;
171
159
  /**
172
160
  * Custom handler map for node type overrides.
173
161
  */
package/dist/index.js CHANGED
@@ -431,7 +431,7 @@ function getSuccessResponses(responses) {
431
431
  //#region ../../internals/shared/src/adapter.ts
432
432
  /**
433
433
  * Narrows the generic `Adapter` from a generator context to the OpenAPI adapter,
434
- * so OAS-only options (`dateType`, `nameMapping`) and the parsed `document` are typed.
434
+ * so OAS-only options (`dateType`, `enums`) and the parsed `document` are typed.
435
435
  *
436
436
  * Throws when a non-OAS adapter is configured, turning a silently wrong cast into a
437
437
  * clear, actionable error at the point of use.
@@ -446,6 +446,72 @@ function getOasAdapter(adapter) {
446
446
  return adapter;
447
447
  }
448
448
  //#endregion
449
+ //#region ../../internals/shared/src/resolver.ts
450
+ /**
451
+ * Resolves a single operation parameter name with the
452
+ * `<operationId> <in> <name>` template.
453
+ *
454
+ * @example
455
+ * `operationParamName.call(resolver, node, param) // → 'DeletePetPathPetId'`
456
+ */
457
+ function operationParamName(node, param) {
458
+ return this.name(`${node.operationId} ${param.in} ${param.name}`);
459
+ }
460
+ /**
461
+ * Builds the shared `response` namespace. Spread the result into
462
+ * `createResolver` and add plugin-specific methods (`options`, `error`) next
463
+ * to it.
464
+ *
465
+ * @example
466
+ * ```ts
467
+ * createResolver<PluginTs>({ response: { ...createOperationResponseResolver(), options(node) {...} }, ... })
468
+ * ```
469
+ */
470
+ function createOperationResponseResolver() {
471
+ return {
472
+ status(node, statusCode) {
473
+ return this.name(`${node.operationId} Status ${statusCode}`);
474
+ },
475
+ body(node) {
476
+ return this.name(`${node.operationId} Body`);
477
+ },
478
+ responses(node) {
479
+ return this.name(`${node.operationId} Responses`);
480
+ },
481
+ response(node) {
482
+ return this.name(`${node.operationId} Response`);
483
+ }
484
+ };
485
+ }
486
+ /**
487
+ * Builds a resolver `file` override whose base name runs every path segment
488
+ * through `toFilePath`, casing the final segment with `caseLast`.
489
+ *
490
+ * @example
491
+ * ```ts
492
+ * createResolver<PluginTs>({ file: createCasedFile(pascalCase), ... })
493
+ * ```
494
+ */
495
+ function createCasedFile(caseLast) {
496
+ return { baseName({ name, extname }) {
497
+ return `${toFilePath(name, caseLast)}${extname}`;
498
+ } };
499
+ }
500
+ //#endregion
501
+ //#region ../../internals/shared/src/refs.ts
502
+ /**
503
+ * Collects the resolved target name of every pointer-carrying ref in a schema tree, in
504
+ * first-occurrence order. Use this for name-only checks (e.g. redeclaration detection) where
505
+ * `resolver.imports` would resolve file paths that are then discarded.
506
+ */
507
+ function collectRefNames(schema) {
508
+ return ast.collect(schema, { schema: (node) => {
509
+ const refNode = ast.narrowSchema(node, "ref");
510
+ if (!refNode?.ref) return null;
511
+ return ast.resolveRefName(refNode);
512
+ } });
513
+ }
514
+ //#endregion
449
515
  //#region ../../internals/shared/src/group.ts
450
516
  /**
451
517
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -581,7 +647,7 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
581
647
  * them to their input (encode) variant.
582
648
  */
583
649
  function collectCodecRefNames(node) {
584
- return ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? ast.extractRefName(n.ref) ?? void 0 : void 0 });
650
+ return ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? ast.resolveRefName(n) ?? void 0 : void 0 });
585
651
  }
586
652
  /**
587
653
  * Whether the node is a plain inline object whose shape can be lifted into an `.extend({ … })`
@@ -602,7 +668,7 @@ function isObjectSchemaNode(node, cyclicSchemas) {
602
668
  if (node.nullable || node.optional || node.nullish) return false;
603
669
  if (node.type === "object") return true;
604
670
  if (node.type === "ref") {
605
- const refName = (node.ref ? ast.extractRefName(node.ref) : void 0) ?? node.name;
671
+ const refName = ast.resolveRefName(node);
606
672
  if (refName && cyclicSchemas?.has(refName)) return false;
607
673
  const resolved = ast.syncSchemaRef(node);
608
674
  return resolved.type === "ref" || isObjectSchemaNode(resolved, cyclicSchemas);
@@ -810,7 +876,7 @@ function strictOneOfMember$1(member, node, cyclicSchemas) {
810
876
  if (node.type === "object" && node.additionalProperties === void 0) return `${member}.strict()`;
811
877
  if (node.type === "ref") {
812
878
  if (member.startsWith("z.lazy(")) return member;
813
- const refName = (node.ref ? ast.extractRefName(node.ref) : void 0) ?? node.name;
879
+ const refName = ast.resolveRefName(node);
814
880
  if (refName && cyclicSchemas?.has(refName)) return member;
815
881
  const schema = ast.syncSchemaRef(node);
816
882
  if (schema.nullable || schema.optional || node.nullable || node.optional) return member;
@@ -955,7 +1021,8 @@ const printerZod = ast.createPrinter((options) => {
955
1021
  },
956
1022
  ref(node) {
957
1023
  if (!node.name) return null;
958
- const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? ast.extractRefName(node.ref) ?? node.name : node.name;
1024
+ const refName = ast.resolveRefName(node);
1025
+ if (!refName) return null;
959
1026
  const useInputVariant = node.ref != null && this.options.direction === "input" && containsCodec(node);
960
1027
  const resolvedName = node.ref ? useInputVariant ? this.options.resolver?.schema.inputName(refName) ?? refName : this.options.resolver?.name(refName) ?? refName : node.name;
961
1028
  if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
@@ -1183,7 +1250,8 @@ const printerZodMini = ast.createPrinter((options) => {
1183
1250
  },
1184
1251
  ref(node) {
1185
1252
  if (!node.name) return null;
1186
- const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? ast.extractRefName(node.ref) ?? node.name : node.name;
1253
+ const refName = ast.resolveRefName(node);
1254
+ if (!refName) return null;
1187
1255
  const resolvedName = node.ref ? this.options.resolver?.name(refName) ?? refName : node.name;
1188
1256
  if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
1189
1257
  return resolvedName;
@@ -1347,16 +1415,12 @@ const zodGenerator = defineGenerator({
1347
1415
  const cyclicSchemas = new Set(ctx.meta.circularNames);
1348
1416
  const hasCodec = !mini && containsCodec(node);
1349
1417
  const codecRefNames = new Set(hasCodec ? collectCodecRefNames(node) : []);
1350
- const importEntries = adapter.getImports(node, (schemaName) => ({
1351
- name: resolver.name(schemaName),
1352
- path: resolver.file({
1353
- name: schemaName,
1354
- extname: ".ts",
1355
- root,
1356
- output,
1357
- group: group ?? void 0
1358
- }).path
1359
- }));
1418
+ const importEntries = resolver.imports({
1419
+ node,
1420
+ root,
1421
+ output,
1422
+ group: group ?? void 0
1423
+ });
1360
1424
  const inputImportEntries = hasCodec ? [...codecRefNames].map((schemaName) => ({
1361
1425
  name: [resolver.schema.inputName(schemaName)],
1362
1426
  path: resolver.file({
@@ -1385,21 +1449,18 @@ const zodGenerator = defineGenerator({
1385
1449
  })
1386
1450
  };
1387
1451
  const inferTypeName = inferred ? resolver.schema.typeName(node.name) : null;
1388
- const nameMapping = getOasAdapter(adapter).options.nameMapping;
1389
1452
  const stdPrinters = mini ? null : getStdPrinters(resolver, {
1390
1453
  coercion,
1391
1454
  guidType,
1392
1455
  regexType,
1393
1456
  dateType,
1394
1457
  cyclicSchemas,
1395
- nameMapping,
1396
1458
  nodes: printer?.nodes
1397
1459
  });
1398
1460
  const schemaPrinter = mini ? getMiniPrinter(resolver, {
1399
1461
  guidType,
1400
1462
  regexType,
1401
1463
  cyclicSchemas,
1402
- nameMapping,
1403
1464
  nodes: printer?.nodes
1404
1465
  }) : stdPrinters.output;
1405
1466
  return /* @__PURE__ */ jsxs(File, {
@@ -1471,34 +1532,28 @@ const zodGenerator = defineGenerator({
1471
1532
  group: group ?? void 0
1472
1533
  }) };
1473
1534
  const cyclicSchemas = new Set(ctx.meta.circularNames);
1474
- const nameMapping = getOasAdapter(adapter).options.nameMapping;
1475
1535
  function renderSchemaEntry({ schema, name, keysToOmit, direction = "output" }) {
1476
1536
  if (!schema) return null;
1477
1537
  const inferTypeName = inferred ? resolver.schema.type(name) : null;
1478
1538
  const codecRefNames = direction === "input" && !mini ? new Set(collectCodecRefNames(schema)) : null;
1479
- const imports = adapter.getImports(schema, (schemaName) => ({
1480
- name: codecRefNames?.has(schemaName) ? resolver.schema.inputName(schemaName) : resolver.name(schemaName),
1481
- path: resolver.file({
1482
- name: schemaName,
1483
- extname: ".ts",
1484
- root,
1485
- output,
1486
- group: group ?? void 0
1487
- }).path
1488
- }));
1539
+ const imports = resolver.imports({
1540
+ node: schema,
1541
+ root,
1542
+ output,
1543
+ group: group ?? void 0,
1544
+ name: (schemaName) => codecRefNames?.has(schemaName) ? resolver.schema.inputName(schemaName) : resolver.name(schemaName)
1545
+ });
1489
1546
  const schemaPrinter = mini ? keysToOmit?.length ? printerZodMini({
1490
1547
  guidType,
1491
1548
  regexType,
1492
1549
  resolver,
1493
1550
  keysToOmit,
1494
1551
  cyclicSchemas,
1495
- nameMapping,
1496
1552
  nodes: printer?.nodes
1497
1553
  }) : getMiniPrinter(resolver, {
1498
1554
  guidType,
1499
1555
  regexType,
1500
1556
  cyclicSchemas,
1501
- nameMapping,
1502
1557
  nodes: printer?.nodes
1503
1558
  }) : keysToOmit?.length ? printerZod({
1504
1559
  coercion,
@@ -1508,7 +1563,6 @@ const zodGenerator = defineGenerator({
1508
1563
  resolver,
1509
1564
  keysToOmit,
1510
1565
  cyclicSchemas,
1511
- nameMapping,
1512
1566
  nodes: printer?.nodes,
1513
1567
  direction
1514
1568
  }) : getStdPrinters(resolver, {
@@ -1517,7 +1571,6 @@ const zodGenerator = defineGenerator({
1517
1571
  regexType,
1518
1572
  dateType,
1519
1573
  cyclicSchemas,
1520
- nameMapping,
1521
1574
  nodes: printer?.nodes
1522
1575
  })[direction];
1523
1576
  return /* @__PURE__ */ jsxs(Fragment, { children: [imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
@@ -1557,10 +1610,7 @@ const zodGenerator = defineGenerator({
1557
1610
  })] });
1558
1611
  }
1559
1612
  function buildResponseUnion({ responses, name, fallbackUnknown }) {
1560
- if (new Set(responses.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1561
- name: resolver.name(schemaName),
1562
- path: ""
1563
- })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(name)) return null;
1613
+ if (new Set(responses.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? collectRefNames(entry.schema).map((refName) => resolver.name(refName)) : []))).has(name)) return null;
1564
1614
  const members = responses.map((res) => ast.factory.createSchema({
1565
1615
  type: "ref",
1566
1616
  name: resolver.response.status(node, res.statusCode)
@@ -1683,9 +1733,7 @@ const resolverZod = createResolver({
1683
1733
  name(name) {
1684
1734
  return ensureValidVarName(camelCase(name, { suffix: "schema" }));
1685
1735
  },
1686
- file: { baseName({ name, extname }) {
1687
- return `${toFilePath(name, (part) => camelCase(part, { suffix: "schema" }))}${extname}`;
1688
- } },
1736
+ file: createCasedFile((part) => camelCase(part, { suffix: "schema" })),
1689
1737
  schema: {
1690
1738
  typeName(name) {
1691
1739
  return ensureValidVarName(pascalCase(name, { suffix: "schema type" }));
@@ -1701,9 +1749,7 @@ const resolverZod = createResolver({
1701
1749
  }
1702
1750
  },
1703
1751
  param: {
1704
- name(node, param) {
1705
- return this.name(`${node.operationId} ${param.in} ${param.name}`);
1706
- },
1752
+ name: operationParamName,
1707
1753
  path(node, param) {
1708
1754
  return this.param.name(node, param);
1709
1755
  },
@@ -1715,18 +1761,7 @@ const resolverZod = createResolver({
1715
1761
  }
1716
1762
  },
1717
1763
  response: {
1718
- status(node, statusCode) {
1719
- return this.name(`${node.operationId} Status ${statusCode}`);
1720
- },
1721
- body(node) {
1722
- return this.name(`${node.operationId} Body`);
1723
- },
1724
- responses(node) {
1725
- return this.name(`${node.operationId} Responses`);
1726
- },
1727
- response(node) {
1728
- return this.name(`${node.operationId} Response`);
1729
- },
1764
+ ...createOperationResponseResolver(),
1730
1765
  error(node) {
1731
1766
  return this.name(`${node.operationId} Error`);
1732
1767
  }