@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.cjs +91 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -12
- package/dist/index.js +91 -56
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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`, `
|
|
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.
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
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 =
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
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 ?
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
}
|