zod-nest 2.1.2 → 2.1.4
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/README.md +3 -0
- package/dist/index.js +111 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +111 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -531,11 +531,14 @@ See [`docs/recipes/custom-openapi-overrides.md`](docs/recipes/custom-openapi-ove
|
|
|
531
531
|
| ------------------------- | ------ | ---------------- | -------------- | ----------------- | ------ | ------------------ |
|
|
532
532
|
| `floor` | 4.4.0 | 11.0.1 | 11.0.1 | 11.0.0 | 7.6.0 | 0.2.0 |
|
|
533
533
|
| `zod-latest` | latest | 11.0.1 | 11.0.1 | 11.0.0 | 7.6.0 | 0.2.0 |
|
|
534
|
+
| `zod-4.5` | 4.5.4 | 11.0.1 | 11.0.1 | 11.0.0 | 7.6.0 | 0.2.0 |
|
|
534
535
|
| `nest-latest` | 4.4.0 | latest | latest | latest | 7.6.0 | 0.2.0 |
|
|
535
536
|
| `rxjs-latest` | 4.4.0 | 11.0.1 | 11.0.1 | 11.0.0 | latest | 0.2.0 |
|
|
536
537
|
| `reflect-metadata-latest` | 4.4.0 | 11.0.1 | 11.0.1 | 11.0.0 | 7.6.0 | latest |
|
|
537
538
|
| `all-latest` | latest | latest | latest | latest | latest | latest |
|
|
538
539
|
|
|
540
|
+
One emission difference is visible across the supported `zod` range: from 4.5, a union of primitives — including `.nullable()` — emits `{ "type": ["string", "null"] }` where 4.4 emitted `{ "anyOf": [{ "type": "string" }, { "type": "null" }] }`. Both are valid OpenAPI 3.1 and validate identically; only the spelling changes. Everything else — `$ref` layout, composition `allOf`, input/output siblings, `paths` — is byte-identical across 4.4 and 4.5.
|
|
541
|
+
|
|
539
542
|
Cell definitions live in [`.github/compat-matrix.json`](.github/compat-matrix.json). The CI workflow ([`.github/workflows/compat-matrix.yml`](.github/workflows/compat-matrix.yml)) runs on every push to `main` and weekly on Monday — when a cell fails, the workflow opens (or comments on) a GitHub issue labelled `compat-matrix-failure` so the regression is tracked outside the Actions UI. Editing the JSON is the formal way to extend or shrink supported ranges. Node is not matrixed — the `>=22` floor is enforced by `engines`.
|
|
540
543
|
|
|
541
544
|
## Migration from `nestjs-zod`
|
package/dist/index.js
CHANGED
|
@@ -419,10 +419,10 @@ var combine = /* @__PURE__ */ __name((...overrides) => {
|
|
|
419
419
|
}, "combine");
|
|
420
420
|
|
|
421
421
|
// src/schema/post-process.ts
|
|
422
|
-
var rewriteRefs = /* @__PURE__ */ __name((node,
|
|
422
|
+
var rewriteRefs = /* @__PURE__ */ __name((node, rootRef) => {
|
|
423
423
|
if (Array.isArray(node)) {
|
|
424
424
|
for (const item of node) {
|
|
425
|
-
rewriteRefs(item,
|
|
425
|
+
rewriteRefs(item, rootRef);
|
|
426
426
|
}
|
|
427
427
|
return;
|
|
428
428
|
}
|
|
@@ -433,32 +433,120 @@ var rewriteRefs = /* @__PURE__ */ __name((node, selfRef) => {
|
|
|
433
433
|
const ref = obj.$ref;
|
|
434
434
|
if (typeof ref === "string" && ref.startsWith(DEFS_PREFIX)) {
|
|
435
435
|
obj.$ref = COMPONENTS_SCHEMAS_PREFIX + ref.slice(DEFS_PREFIX.length);
|
|
436
|
-
} else if (ref === "#" &&
|
|
437
|
-
obj.$ref =
|
|
436
|
+
} else if (ref === "#" && rootRef !== void 0) {
|
|
437
|
+
obj.$ref = rootRef;
|
|
438
438
|
}
|
|
439
439
|
for (const value of Object.values(obj)) {
|
|
440
|
-
rewriteRefs(value,
|
|
440
|
+
rewriteRefs(value, rootRef);
|
|
441
441
|
}
|
|
442
442
|
}, "rewriteRefs");
|
|
443
|
-
var
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
for (const [id, body] of Object.entries(rawDefs)) {
|
|
448
|
-
refs.set(id, body);
|
|
443
|
+
var refsIn = /* @__PURE__ */ __name(function* (node) {
|
|
444
|
+
if (Array.isArray(node)) {
|
|
445
|
+
for (const item of node) {
|
|
446
|
+
yield* refsIn(item);
|
|
449
447
|
}
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
if (node === null || typeof node !== "object") {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const obj = node;
|
|
454
|
+
if (typeof obj.$ref === "string") {
|
|
455
|
+
yield obj.$ref;
|
|
450
456
|
}
|
|
457
|
+
for (const value of Object.values(obj)) {
|
|
458
|
+
yield* refsIn(value);
|
|
459
|
+
}
|
|
460
|
+
}, "refsIn");
|
|
461
|
+
var rootDefId = /* @__PURE__ */ __name((raw) => {
|
|
462
|
+
const ref = raw.$ref;
|
|
463
|
+
if (typeof ref !== "string" || !ref.startsWith(DEFS_PREFIX)) {
|
|
464
|
+
return void 0;
|
|
465
|
+
}
|
|
466
|
+
return ref.slice(DEFS_PREFIX.length);
|
|
467
|
+
}, "rootDefId");
|
|
468
|
+
var isReferenced = /* @__PURE__ */ __name((defs, id) => {
|
|
469
|
+
const ownRef = `${DEFS_PREFIX}${id}`;
|
|
470
|
+
for (const ref of refsIn(defs)) {
|
|
471
|
+
if (ref === "#" || ref === ownRef) {
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return false;
|
|
476
|
+
}, "isReferenced");
|
|
477
|
+
var referencesRoot = /* @__PURE__ */ __name((raw) => {
|
|
478
|
+
for (const ref of refsIn(raw)) {
|
|
479
|
+
if (ref === "#") {
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return false;
|
|
484
|
+
}, "referencesRoot");
|
|
485
|
+
var stripEnvelope = /* @__PURE__ */ __name((raw) => {
|
|
451
486
|
const root = {
|
|
452
487
|
...raw
|
|
453
488
|
};
|
|
454
489
|
delete root.$schema;
|
|
455
490
|
delete root.$defs;
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
491
|
+
return root;
|
|
492
|
+
}, "stripEnvelope");
|
|
493
|
+
var resolveRoot = /* @__PURE__ */ __name((raw, refs, options) => {
|
|
494
|
+
const liftedId = rootDefId(raw);
|
|
495
|
+
if (liftedId !== void 0) {
|
|
496
|
+
const body = refs.get(liftedId);
|
|
497
|
+
if (body !== void 0 && !isReferenced(raw.$defs, liftedId)) {
|
|
498
|
+
refs.delete(liftedId);
|
|
499
|
+
return {
|
|
500
|
+
schema: body,
|
|
501
|
+
rootRef: void 0
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
return {
|
|
505
|
+
schema: stripEnvelope(raw),
|
|
506
|
+
rootRef: `${COMPONENTS_SCHEMAS_PREFIX}${liftedId}`
|
|
507
|
+
};
|
|
459
508
|
}
|
|
509
|
+
const root = stripEnvelope(raw);
|
|
510
|
+
if (!referencesRoot(raw)) {
|
|
511
|
+
return {
|
|
512
|
+
schema: root,
|
|
513
|
+
rootRef: void 0
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
const rootId = options?.rootId;
|
|
517
|
+
if (rootId === void 0) {
|
|
518
|
+
if (options?.strict ?? true) {
|
|
519
|
+
throw new ZodNestError('A schema referenced from inside its own emission has no id, so the reference cannot be resolved. Add `.meta({ id: "\u2026" })` to the root schema, or set strict: false to leave the reference unresolved.');
|
|
520
|
+
}
|
|
521
|
+
return {
|
|
522
|
+
schema: root,
|
|
523
|
+
rootRef: void 0
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
refs.set(rootId, root);
|
|
527
|
+
const rootRef = `${COMPONENTS_SCHEMAS_PREFIX}${rootId}`;
|
|
460
528
|
return {
|
|
461
|
-
schema:
|
|
529
|
+
schema: {
|
|
530
|
+
$ref: rootRef
|
|
531
|
+
},
|
|
532
|
+
rootRef
|
|
533
|
+
};
|
|
534
|
+
}, "resolveRoot");
|
|
535
|
+
var postProcess = /* @__PURE__ */ __name((raw, options) => {
|
|
536
|
+
const refs = /* @__PURE__ */ new Map();
|
|
537
|
+
const rawDefs = raw.$defs;
|
|
538
|
+
if (rawDefs !== void 0) {
|
|
539
|
+
for (const [id, body] of Object.entries(rawDefs)) {
|
|
540
|
+
refs.set(id, body);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const { schema, rootRef } = resolveRoot(raw, refs, options);
|
|
544
|
+
rewriteRefs(schema, rootRef);
|
|
545
|
+
for (const body of refs.values()) {
|
|
546
|
+
rewriteRefs(body, rootRef);
|
|
547
|
+
}
|
|
548
|
+
return {
|
|
549
|
+
schema,
|
|
462
550
|
refs
|
|
463
551
|
};
|
|
464
552
|
}, "postProcess");
|
|
@@ -545,6 +633,10 @@ var buildToJsonSchemaOptions = /* @__PURE__ */ __name((params) => {
|
|
|
545
633
|
}, "consumeUnrepresentable")
|
|
546
634
|
};
|
|
547
635
|
}, "buildToJsonSchemaOptions");
|
|
636
|
+
var resolveRootId = /* @__PURE__ */ __name((schema, registry) => {
|
|
637
|
+
const id = registry.zodRegistry.get(schema)?.id;
|
|
638
|
+
return typeof id === "string" && id !== "" ? id : void 0;
|
|
639
|
+
}, "resolveRootId");
|
|
548
640
|
var toOpenApi = /* @__PURE__ */ __name((schema, opts) => {
|
|
549
641
|
const built = buildToJsonSchemaOptions({
|
|
550
642
|
registry: opts.registry,
|
|
@@ -555,7 +647,10 @@ var toOpenApi = /* @__PURE__ */ __name((schema, opts) => {
|
|
|
555
647
|
});
|
|
556
648
|
const raw = zod.z.toJSONSchema(schema, built.options);
|
|
557
649
|
built.consumeUnrepresentable();
|
|
558
|
-
const result = postProcess(raw
|
|
650
|
+
const result = postProcess(raw, {
|
|
651
|
+
rootId: resolveRootId(schema, opts.registry),
|
|
652
|
+
strict: opts.strict
|
|
653
|
+
});
|
|
559
654
|
for (const [id] of opts.registry.getCollisions()) {
|
|
560
655
|
if (!result.refs.has(id)) {
|
|
561
656
|
continue;
|