zod-nest 1.8.0 → 1.9.0

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 CHANGED
@@ -148,6 +148,8 @@ Every DTO is one Zod schema wrapped in a class. The class exists so NestJS' intr
148
148
 
149
149
  The class returned by `createZodDto(schema)` carries `schema`, `id`, `io: 'input'`, and a lazy `Output` sibling. `parse` / `safeParse` are static methods on the class. The class is tagged with `Symbol.for('zod-nest.dto')` so `ZodValidationPipe` and `ZodSerializerInterceptor` can discriminate it from plain constructors. The id comes from `schema.meta({ id })` when present (preferred) or from the second-argument options.
150
150
 
151
+ **Naming is exposing.** Every schema put through `registerSchema()` — directly, or transitively via `createZodDto` / `@ZodBody` / `extend` / descendant discovery — lands in `components.schemas` when `applyZodNest` runs, regardless of whether any `$ref` in the doc points at it. If you give a schema `.meta({ id })`, you're declaring it documented. Anonymous schemas without an id stay inlined where used.
152
+
151
153
  See [`docs/dto.md`](docs/dto.md) for the full surface.
152
154
 
153
155
  ### Schemas that don't fit a class
package/dist/index.js CHANGED
@@ -1263,6 +1263,7 @@ var flattenObjectIntersection = /* @__PURE__ */ __name((schema, registry, decora
1263
1263
  }
1264
1264
  }
1265
1265
  const merged = zod.z.object(mergedShape);
1266
+ registerSchema(schema, registry);
1266
1267
  for (const [child, childId] of discoverDependents(schema)) {
1267
1268
  registry.register(child, childId);
1268
1269
  }
@@ -1552,6 +1553,31 @@ var forEachOperation = /* @__PURE__ */ __name((doc, fn) => {
1552
1553
  }
1553
1554
  }, "forEachOperation");
1554
1555
 
1556
+ // src/document/walk-refs.ts
1557
+ var walkRefs = /* @__PURE__ */ __name((node, visit) => {
1558
+ if (node === null || typeof node !== "object") {
1559
+ return;
1560
+ }
1561
+ if (Array.isArray(node)) {
1562
+ for (const item of node) {
1563
+ walkRefs(item, visit);
1564
+ }
1565
+ return;
1566
+ }
1567
+ const obj = node;
1568
+ for (const key of Object.keys(obj)) {
1569
+ const value = obj[key];
1570
+ if (key === "$ref" && typeof value === "string") {
1571
+ const next = visit(value);
1572
+ if (next !== void 0) {
1573
+ obj[key] = next;
1574
+ }
1575
+ continue;
1576
+ }
1577
+ walkRefs(value, visit);
1578
+ }
1579
+ }, "walkRefs");
1580
+
1555
1581
  // src/document/collect-usage.ts
1556
1582
  var isPlainRecord2 = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && !Array.isArray(value), "isPlainRecord");
1557
1583
  var collectUsage = /* @__PURE__ */ __name((doc, app, registry) => {
@@ -1655,19 +1681,19 @@ var collectRefFromSchema = /* @__PURE__ */ __name((schema, classToDtoId, knownId
1655
1681
  if (!isPlainRecord2(schema)) {
1656
1682
  return;
1657
1683
  }
1658
- const ref = schema.$ref;
1659
- if (typeof ref !== "string" || !ref.startsWith(COMPONENTS_SCHEMAS_PREFIX)) {
1660
- return;
1661
- }
1662
- const className = ref.slice(COMPONENTS_SCHEMAS_PREFIX.length);
1663
- const renamed = classToDtoId.get(className);
1664
- if (renamed !== void 0) {
1665
- ids.add(renamed);
1666
- return;
1667
- }
1668
- if (knownIds.has(className)) {
1669
- ids.add(className);
1670
- }
1684
+ walkRefs(schema, (ref) => {
1685
+ if (!ref.startsWith(COMPONENTS_SCHEMAS_PREFIX)) {
1686
+ return void 0;
1687
+ }
1688
+ const className = ref.slice(COMPONENTS_SCHEMAS_PREFIX.length);
1689
+ const renamed = classToDtoId.get(className);
1690
+ if (renamed !== void 0) {
1691
+ ids.add(renamed);
1692
+ } else if (knownIds.has(className)) {
1693
+ ids.add(className);
1694
+ }
1695
+ return void 0;
1696
+ });
1671
1697
  }, "collectRefFromSchema");
1672
1698
  var collectOutputExposedIds = /* @__PURE__ */ __name((app) => {
1673
1699
  const ids = /* @__PURE__ */ new Set();
@@ -1729,31 +1755,6 @@ var ZodNestDocumentError = class extends ZodNestError {
1729
1755
  }
1730
1756
  };
1731
1757
 
1732
- // src/document/walk-refs.ts
1733
- var walkRefs = /* @__PURE__ */ __name((node, visit) => {
1734
- if (node === null || typeof node !== "object") {
1735
- return;
1736
- }
1737
- if (Array.isArray(node)) {
1738
- for (const item of node) {
1739
- walkRefs(item, visit);
1740
- }
1741
- return;
1742
- }
1743
- const obj = node;
1744
- for (const key of Object.keys(obj)) {
1745
- const value = obj[key];
1746
- if (key === "$ref" && typeof value === "string") {
1747
- const next = visit(value);
1748
- if (next !== void 0) {
1749
- obj[key] = next;
1750
- }
1751
- continue;
1752
- }
1753
- walkRefs(value, visit);
1754
- }
1755
- }, "walkRefs");
1756
-
1757
1758
  // src/document/dangling-refs.ts
1758
1759
  var assertNoDanglingRefs = /* @__PURE__ */ __name((params) => {
1759
1760
  const { doc, collected } = params;
@@ -2147,16 +2148,35 @@ var stripMarkerFromSchema = /* @__PURE__ */ __name((schema) => {
2147
2148
  }, "stripMarkerFromSchema");
2148
2149
 
2149
2150
  // src/document/apply-zod-nest.ts
2151
+ var withRegistryExposure = /* @__PURE__ */ __name((collected, registry) => {
2152
+ const alreadyExposed = /* @__PURE__ */ new Set([
2153
+ ...collected.inputExposedIds,
2154
+ ...collected.outputExposedIds
2155
+ ]);
2156
+ const extras = registry.ids().filter((id) => !alreadyExposed.has(id));
2157
+ if (extras.length === 0) {
2158
+ return collected;
2159
+ }
2160
+ return {
2161
+ inputExposedIds: /* @__PURE__ */ new Set([
2162
+ ...collected.inputExposedIds,
2163
+ ...extras
2164
+ ]),
2165
+ outputExposedIds: collected.outputExposedIds,
2166
+ classToDtoId: collected.classToDtoId
2167
+ };
2168
+ }, "withRegistryExposure");
2150
2169
  var OPENAPI_VERSION = "3.1.0";
2151
2170
  var applyZodNest = /* @__PURE__ */ __name((doc, opts) => {
2152
2171
  const registry = opts.registry ?? defaultRegistry;
2153
2172
  const collected = collectUsage(doc, opts.app, registry);
2173
+ const exposed = withRegistryExposure(collected, registry);
2154
2174
  const { inputSchemas, outputSchemas } = bulkEmit({
2155
2175
  registry,
2156
2176
  override: opts.override,
2157
2177
  strict: opts.strict
2158
2178
  });
2159
- const extended = extendExposureViaRefs(collected, inputSchemas, outputSchemas);
2179
+ const extended = extendExposureViaRefs(exposed, inputSchemas, outputSchemas);
2160
2180
  const { divergentOutputIds, renames } = mergeSchemas({
2161
2181
  doc,
2162
2182
  inputSchemas,