zod-nest 2.0.1 → 2.1.1
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.mts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +62 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +62 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -118,6 +118,15 @@ declare const registerSchema: (schema: z.ZodType, registry?: ZodNestRegistry, op
|
|
|
118
118
|
interface LineageEntry {
|
|
119
119
|
readonly op: 'extend';
|
|
120
120
|
readonly parent: z.ZodObject;
|
|
121
|
+
/**
|
|
122
|
+
* Keys the child redeclared with a *different* schema than the parent's
|
|
123
|
+
* (e.g. narrowing `type: SomeEnum` to `type: z.literal('A')`). Computed by
|
|
124
|
+
* reference comparison at `extend()` time — Zod's `.extend()` keeps the same
|
|
125
|
+
* shape reference for untouched keys and assigns a fresh one for overrides.
|
|
126
|
+
* The composition override keeps these in the delta instead of dropping them
|
|
127
|
+
* as parent-owned, so the narrowing survives in the emitted `allOf`.
|
|
128
|
+
*/
|
|
129
|
+
readonly overriddenKeys: ReadonlySet<string>;
|
|
121
130
|
}
|
|
122
131
|
/**
|
|
123
132
|
* Wraps a derived `z.ZodObject` and records the parent → child link so
|
|
@@ -831,6 +840,18 @@ interface ApplyZodNestOptions {
|
|
|
831
840
|
* `@ZodQuery({ ref })` override takes precedence over this preference.
|
|
832
841
|
*/
|
|
833
842
|
queryParamStyle?: QueryParamStyle;
|
|
843
|
+
/**
|
|
844
|
+
* Copy each named component's `title` (when set via `.meta({ title })`) onto
|
|
845
|
+
* every `$ref` that targets it, as a sibling: `{ $ref, title }` (default
|
|
846
|
+
* `true`).
|
|
847
|
+
*
|
|
848
|
+
* OpenAPI 3.1 allows siblings next to `$ref`, and Swagger UI's 3.1 renderer
|
|
849
|
+
* inlines referenced schemas without showing their component name
|
|
850
|
+
* (swagger-api/swagger-ui#9540); the sibling `title` gives the renderer (and
|
|
851
|
+
* other 3.1-aware tools) a name to display. The annotation is semantically
|
|
852
|
+
* inert. Set `false` to emit bare `$ref`s.
|
|
853
|
+
*/
|
|
854
|
+
refTitles?: boolean;
|
|
834
855
|
}
|
|
835
856
|
/**
|
|
836
857
|
* Post-processor over the OpenAPI document emitted by
|
|
@@ -856,6 +877,9 @@ interface ApplyZodNestOptions {
|
|
|
856
877
|
* transitive `$ref` deps, plus any `{ expose: true }` opt-ins) are kept —
|
|
857
878
|
* unreferenced registered schemas are pruned. Exposure is document-scoped, so
|
|
858
879
|
* several documents sharing one registry each carry only what they use.
|
|
880
|
+
* - Each named component's `title` is copied onto every `$ref` that targets it
|
|
881
|
+
* as a `{ $ref, title }` sibling (`applyRefTitles`, unless `refTitles: false`)
|
|
882
|
+
* so Swagger UI's 3.1 renderer surfaces the component name. Inert annotation.
|
|
859
883
|
* - Every `$ref` whose target is missing throws `ZodNestDocumentError(DANGLING_REF)`.
|
|
860
884
|
* - `doc.openapi` is set to `'3.1.0'` — zod-nest emits OpenAPI 3.1 only; this
|
|
861
885
|
* guarantees the version string matches the emitted body regardless of the
|
package/dist/index.d.ts
CHANGED
|
@@ -118,6 +118,15 @@ declare const registerSchema: (schema: z.ZodType, registry?: ZodNestRegistry, op
|
|
|
118
118
|
interface LineageEntry {
|
|
119
119
|
readonly op: 'extend';
|
|
120
120
|
readonly parent: z.ZodObject;
|
|
121
|
+
/**
|
|
122
|
+
* Keys the child redeclared with a *different* schema than the parent's
|
|
123
|
+
* (e.g. narrowing `type: SomeEnum` to `type: z.literal('A')`). Computed by
|
|
124
|
+
* reference comparison at `extend()` time — Zod's `.extend()` keeps the same
|
|
125
|
+
* shape reference for untouched keys and assigns a fresh one for overrides.
|
|
126
|
+
* The composition override keeps these in the delta instead of dropping them
|
|
127
|
+
* as parent-owned, so the narrowing survives in the emitted `allOf`.
|
|
128
|
+
*/
|
|
129
|
+
readonly overriddenKeys: ReadonlySet<string>;
|
|
121
130
|
}
|
|
122
131
|
/**
|
|
123
132
|
* Wraps a derived `z.ZodObject` and records the parent → child link so
|
|
@@ -831,6 +840,18 @@ interface ApplyZodNestOptions {
|
|
|
831
840
|
* `@ZodQuery({ ref })` override takes precedence over this preference.
|
|
832
841
|
*/
|
|
833
842
|
queryParamStyle?: QueryParamStyle;
|
|
843
|
+
/**
|
|
844
|
+
* Copy each named component's `title` (when set via `.meta({ title })`) onto
|
|
845
|
+
* every `$ref` that targets it, as a sibling: `{ $ref, title }` (default
|
|
846
|
+
* `true`).
|
|
847
|
+
*
|
|
848
|
+
* OpenAPI 3.1 allows siblings next to `$ref`, and Swagger UI's 3.1 renderer
|
|
849
|
+
* inlines referenced schemas without showing their component name
|
|
850
|
+
* (swagger-api/swagger-ui#9540); the sibling `title` gives the renderer (and
|
|
851
|
+
* other 3.1-aware tools) a name to display. The annotation is semantically
|
|
852
|
+
* inert. Set `false` to emit bare `$ref`s.
|
|
853
|
+
*/
|
|
854
|
+
refTitles?: boolean;
|
|
834
855
|
}
|
|
835
856
|
/**
|
|
836
857
|
* Post-processor over the OpenAPI document emitted by
|
|
@@ -856,6 +877,9 @@ interface ApplyZodNestOptions {
|
|
|
856
877
|
* transitive `$ref` deps, plus any `{ expose: true }` opt-ins) are kept —
|
|
857
878
|
* unreferenced registered schemas are pruned. Exposure is document-scoped, so
|
|
858
879
|
* several documents sharing one registry each carry only what they use.
|
|
880
|
+
* - Each named component's `title` is copied onto every `$ref` that targets it
|
|
881
|
+
* as a `{ $ref, title }` sibling (`applyRefTitles`, unless `refTitles: false`)
|
|
882
|
+
* so Swagger UI's 3.1 renderer surfaces the component name. Inert annotation.
|
|
859
883
|
* - Every `$ref` whose target is missing throws `ZodNestDocumentError(DANGLING_REF)`.
|
|
860
884
|
* - `doc.openapi` is set to `'3.1.0'` — zod-nest emits OpenAPI 3.1 only; this
|
|
861
885
|
* guarantees the version string matches the emitted body regardless of the
|
package/dist/index.js
CHANGED
|
@@ -246,11 +246,22 @@ var computeShapeKeys = /* @__PURE__ */ __name((schema) => {
|
|
|
246
246
|
required
|
|
247
247
|
};
|
|
248
248
|
}, "computeShapeKeys");
|
|
249
|
+
var computeOverriddenKeys = /* @__PURE__ */ __name((parent, child) => {
|
|
250
|
+
const overriddenKeys = /* @__PURE__ */ new Set();
|
|
251
|
+
for (const key of Object.keys(child.shape)) {
|
|
252
|
+
const parentProp = parent.shape[key];
|
|
253
|
+
if (parentProp !== void 0 && parentProp !== child.shape[key]) {
|
|
254
|
+
overriddenKeys.add(key);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return overriddenKeys;
|
|
258
|
+
}, "computeOverriddenKeys");
|
|
249
259
|
var extend = /* @__PURE__ */ __name((parent, build) => {
|
|
250
260
|
const result = build(parent);
|
|
251
261
|
lineageMap.set(result, {
|
|
252
262
|
op: "extend",
|
|
253
|
-
parent
|
|
263
|
+
parent,
|
|
264
|
+
overriddenKeys: computeOverriddenKeys(parent, result)
|
|
254
265
|
});
|
|
255
266
|
if (!propsMap.has(parent)) {
|
|
256
267
|
propsMap.set(parent, computeShapeKeys(parent));
|
|
@@ -284,7 +295,7 @@ var createCompositionOverride = /* @__PURE__ */ __name((opts) => {
|
|
|
284
295
|
const parentReqSet = new Set(parentCache.required);
|
|
285
296
|
const deltaProps = {};
|
|
286
297
|
for (const [key, value] of Object.entries(childProps)) {
|
|
287
|
-
if (parentPropSet.has(key)) {
|
|
298
|
+
if (parentPropSet.has(key) && !entry.overriddenKeys.has(key)) {
|
|
288
299
|
continue;
|
|
289
300
|
}
|
|
290
301
|
deltaProps[key] = value;
|
|
@@ -1334,7 +1345,7 @@ var ZodResponse = /* @__PURE__ */ __name((opts) => {
|
|
|
1334
1345
|
}, "ZodResponse");
|
|
1335
1346
|
|
|
1336
1347
|
// src/decorators/internal/zod-schema-ref.ts
|
|
1337
|
-
|
|
1348
|
+
function resolveSchemaRef(schema, options) {
|
|
1338
1349
|
const registry = options?.registry ?? defaultRegistry;
|
|
1339
1350
|
const id = registerSchema(schema, registry, {
|
|
1340
1351
|
id: options?.id
|
|
@@ -1371,7 +1382,8 @@ var resolveSchemaRef = /* @__PURE__ */ __name((schema, options) => {
|
|
|
1371
1382
|
kind: "inline",
|
|
1372
1383
|
schema: body
|
|
1373
1384
|
};
|
|
1374
|
-
}
|
|
1385
|
+
}
|
|
1386
|
+
__name(resolveSchemaRef, "resolveSchemaRef");
|
|
1375
1387
|
|
|
1376
1388
|
// src/decorators/internal/zod-param-expand.ts
|
|
1377
1389
|
var isZodObject = /* @__PURE__ */ __name((schema) => schema._zod.def.type === "object", "isZodObject");
|
|
@@ -1505,12 +1517,11 @@ var resolveBodySchema = /* @__PURE__ */ __name((schema, options) => {
|
|
|
1505
1517
|
if (options?.flatten === true) {
|
|
1506
1518
|
return flattenObjectIntersection(schema, options.registry ?? defaultRegistry, "@ZodBody");
|
|
1507
1519
|
}
|
|
1508
|
-
|
|
1520
|
+
return resolveSchemaRef(schema, {
|
|
1509
1521
|
id: options?.id,
|
|
1510
1522
|
registry: options?.registry,
|
|
1511
1523
|
deferAnonInline: true
|
|
1512
|
-
});
|
|
1513
|
-
return resolution.kind === "ref" ? resolution.ref : resolution.schema;
|
|
1524
|
+
}).ref;
|
|
1514
1525
|
}, "resolveBodySchema");
|
|
1515
1526
|
|
|
1516
1527
|
// src/decorators/internal/query-marker.ts
|
|
@@ -2382,6 +2393,47 @@ var decorateIfPresent = /* @__PURE__ */ __name((schemas, key) => {
|
|
|
2382
2393
|
};
|
|
2383
2394
|
}, "decorateIfPresent");
|
|
2384
2395
|
|
|
2396
|
+
// src/document/ref-titles.ts
|
|
2397
|
+
var applyRefTitles = /* @__PURE__ */ __name((doc) => {
|
|
2398
|
+
const schemas = doc.components?.schemas;
|
|
2399
|
+
if (schemas === void 0) {
|
|
2400
|
+
return;
|
|
2401
|
+
}
|
|
2402
|
+
const titleById = /* @__PURE__ */ new Map();
|
|
2403
|
+
for (const [id, body] of Object.entries(schemas)) {
|
|
2404
|
+
if (isPlainRecord5(body) && typeof body.title === "string" && body.title !== "") {
|
|
2405
|
+
titleById.set(id, body.title);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
if (titleById.size === 0) {
|
|
2409
|
+
return;
|
|
2410
|
+
}
|
|
2411
|
+
addRefTitles(doc.paths, titleById);
|
|
2412
|
+
addRefTitles(schemas, titleById);
|
|
2413
|
+
}, "applyRefTitles");
|
|
2414
|
+
var isPlainRecord5 = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && !Array.isArray(value), "isPlainRecord");
|
|
2415
|
+
var addRefTitles = /* @__PURE__ */ __name((node, titleById) => {
|
|
2416
|
+
if (Array.isArray(node)) {
|
|
2417
|
+
for (const item of node) {
|
|
2418
|
+
addRefTitles(item, titleById);
|
|
2419
|
+
}
|
|
2420
|
+
return;
|
|
2421
|
+
}
|
|
2422
|
+
if (!isPlainRecord5(node)) {
|
|
2423
|
+
return;
|
|
2424
|
+
}
|
|
2425
|
+
const ref = node.$ref;
|
|
2426
|
+
if (typeof ref === "string" && ref.startsWith(COMPONENTS_SCHEMAS_PREFIX) && node.title === void 0) {
|
|
2427
|
+
const title = titleById.get(ref.slice(COMPONENTS_SCHEMAS_PREFIX.length));
|
|
2428
|
+
if (title !== void 0) {
|
|
2429
|
+
node.title = title;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
for (const value of Object.values(node)) {
|
|
2433
|
+
addRefTitles(value, titleById);
|
|
2434
|
+
}
|
|
2435
|
+
}, "addRefTitles");
|
|
2436
|
+
|
|
2385
2437
|
// src/document/rewrite-refs.ts
|
|
2386
2438
|
var rewriteRefs2 = /* @__PURE__ */ __name((params) => {
|
|
2387
2439
|
const { doc, renames, divergentOutputIds } = params;
|
|
@@ -2527,6 +2579,9 @@ var applyZodNest = /* @__PURE__ */ __name((doc, opts = {}) => {
|
|
|
2527
2579
|
doc,
|
|
2528
2580
|
registry
|
|
2529
2581
|
});
|
|
2582
|
+
if (opts.refTitles !== false) {
|
|
2583
|
+
applyRefTitles(doc);
|
|
2584
|
+
}
|
|
2530
2585
|
assertNoDanglingRefs({
|
|
2531
2586
|
doc,
|
|
2532
2587
|
collected: extended
|