@kubb/plugin-zod 5.1.0 → 5.3.0-canary.20260827T082213

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 CHANGED
@@ -789,68 +789,6 @@ function shouldCoerce(coercion, type) {
789
789
  return !!coercion[type];
790
790
  }
791
791
  /**
792
- * Registered codecs, checked in order.
793
- */
794
- const codecs = [{
795
- matches(node) {
796
- return node.type === "date" && node.representation === "date";
797
- },
798
- decode(node) {
799
- return node.format === "date" ? "z.iso.date().transform((value) => new Date(value))" : "z.iso.datetime().transform((value) => new Date(value))";
800
- },
801
- encode(node) {
802
- return node.format === "date" ? "z.date().transform((value) => value.toISOString().slice(0, 10))" : "z.date().transform((value) => value.toISOString())";
803
- }
804
- }];
805
- /**
806
- * Returns the codec for this node, or `undefined` when the node needs no
807
- * encode/decode (its wire and runtime types match).
808
- */
809
- function getCodec(node) {
810
- if (!node) return void 0;
811
- return codecs.find((codec) => codec.matches(node));
812
- }
813
- /**
814
- * Returns `true` when the node itself is encoded/decoded by a codec.
815
- */
816
- function hasCodec(node) {
817
- return getCodec(node) !== void 0;
818
- }
819
- /**
820
- * Returns `true` when the schema transitively contains a codec node —
821
- * a value whose runtime type differs from its wire type (see {@link hasCodec}),
822
- * so it must be decoded (response) or encoded (request) at the validation boundary.
823
- * `$ref`s are followed via their resolved schema; a `seen` set guards cycles.
824
- */
825
- function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
826
- if (!node) return false;
827
- if (hasCodec(node)) return true;
828
- if (node.type === "ref") {
829
- if (!node.ref) return false;
830
- const refName = (0, kubb_kit.extractRefName)(node.ref);
831
- if (refName) {
832
- if (seen.has(refName)) return false;
833
- seen.add(refName);
834
- }
835
- const resolved = (0, kubb_kit.syncSchemaRef)(node);
836
- if (resolved.type === "ref") return false;
837
- return containsCodec(resolved, seen);
838
- }
839
- const children = [];
840
- if ("properties" in node && node.properties) children.push(...node.properties.map((prop) => prop.schema));
841
- if ("items" in node && node.items) children.push(...node.items);
842
- if ("members" in node && node.members) children.push(...node.members);
843
- if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) children.push(node.additionalProperties);
844
- return children.some((child) => containsCodec(child, seen));
845
- }
846
- /**
847
- * Collects the names of `$ref` schemas that transitively contain a codec, so the generator can route
848
- * them to their input (encode) variant.
849
- */
850
- function collectCodecRefNames(node) {
851
- return kubb_kit.ast.collectSync(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? kubb_kit.ast.resolveRefName(n) ?? void 0 : void 0 });
852
- }
853
- /**
854
792
  * Whether the node is a plain inline object whose shape can be lifted into an `.extend({ … })`
855
793
  * argument. A catchall, `patternProperties`, or a nullable/optional wrapper cannot, so those stay
856
794
  * on `.and(…)`.
@@ -1163,6 +1101,168 @@ function buildZodObjectShape(ctx, node) {
1163
1101
  }));
1164
1102
  }
1165
1103
  /**
1104
+ * Types the direction probe skips. They delegate to their children rather than reading
1105
+ * `direction` themselves, so {@link containsDirectionalNode} walks into the children instead.
1106
+ */
1107
+ const CONTAINER_TYPES = /* @__PURE__ */ new Set([
1108
+ "object",
1109
+ "array",
1110
+ "tuple",
1111
+ "union",
1112
+ "intersection",
1113
+ "ref"
1114
+ ]);
1115
+ /**
1116
+ * Runs the node's effective handler (a `printer.nodes` override, else the built-in) once per
1117
+ * direction and reports whether the two disagree. That difference is what makes a component
1118
+ * need an `${name}InputSchema` variant.
1119
+ */
1120
+ function variesByDirection({ node, printerOptions }) {
1121
+ if (CONTAINER_TYPES.has(node.type)) return false;
1122
+ const handler = printerOptions.nodes?.[node.type] ?? scalarNodes[node.type];
1123
+ if (!handler) return false;
1124
+ const call = (direction) => {
1125
+ const context = {
1126
+ options: {
1127
+ ...printerOptions,
1128
+ direction
1129
+ },
1130
+ transform: () => null,
1131
+ base: () => null
1132
+ };
1133
+ return handler.call(context, node);
1134
+ };
1135
+ return call("decode") !== call("encode");
1136
+ }
1137
+ /**
1138
+ * Whether the schema transitively contains a node that prints differently per direction, so it
1139
+ * must decode on responses and encode on requests. Follows `$ref`s through their resolved
1140
+ * schema, with `seen` guarding cycles.
1141
+ */
1142
+ function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */ new Set() }) {
1143
+ if (!node) return false;
1144
+ if (node.type === "ref") {
1145
+ if (!node.ref) return false;
1146
+ const refName = (0, kubb_kit.extractRefName)(node.ref);
1147
+ if (refName) {
1148
+ if (seen.has(refName)) return false;
1149
+ seen.add(refName);
1150
+ }
1151
+ const resolved = (0, kubb_kit.syncSchemaRef)(node);
1152
+ if (resolved.type === "ref") return false;
1153
+ return containsDirectionalNode({
1154
+ node: resolved,
1155
+ printerOptions,
1156
+ seen
1157
+ });
1158
+ }
1159
+ if (variesByDirection({
1160
+ node,
1161
+ printerOptions
1162
+ })) return true;
1163
+ const children = [];
1164
+ if ("properties" in node && node.properties) children.push(...node.properties.map((prop) => prop.schema));
1165
+ if ("items" in node && node.items) children.push(...node.items);
1166
+ if ("members" in node && node.members) children.push(...node.members);
1167
+ if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) children.push(node.additionalProperties);
1168
+ return children.some((child) => containsDirectionalNode({
1169
+ node: child,
1170
+ printerOptions,
1171
+ seen
1172
+ }));
1173
+ }
1174
+ /**
1175
+ * Names of the `$ref` schemas the generator should route to their input (encode) variant.
1176
+ */
1177
+ function collectDirectionalRefNames({ node, printerOptions }) {
1178
+ return kubb_kit.ast.collectSync(node, { schema: (n) => n.type === "ref" && n.ref && containsDirectionalNode({
1179
+ node: n,
1180
+ printerOptions
1181
+ }) ? kubb_kit.ast.resolveRefName(n) ?? void 0 : void 0 });
1182
+ }
1183
+ /**
1184
+ * Handlers that never recurse into children, so {@link variesByDirection} can call one directly
1185
+ * to probe both directions without building a printer.
1186
+ *
1187
+ * `date` is the built-in two-way conversion, decoding `string → Date` on responses and encoding
1188
+ * back on requests, keeping `date` and `date-time` precision apart. Only `representation: 'date'`
1189
+ * fields convert; ISO-string fields print `z.iso.date()` either way. A `printer.nodes.date`
1190
+ * override replaces the whole handler, direction branch included.
1191
+ */
1192
+ const scalarNodes = {
1193
+ any: () => "z.any()",
1194
+ unknown: () => "z.unknown()",
1195
+ void: () => "z.void()",
1196
+ never: () => "z.never()",
1197
+ boolean: () => "z.boolean()",
1198
+ null: () => "z.null()",
1199
+ string(node) {
1200
+ const base = shouldCoerce(this.options.coercion, "strings") ? "z.coerce.string()" : "z.string()";
1201
+ const pattern = node.pattern ?? integerFormatPattern(node.format);
1202
+ return `${base}${lengthConstraints({
1203
+ ...node,
1204
+ pattern,
1205
+ regexType: this.options.regexType
1206
+ })}`;
1207
+ },
1208
+ number(node) {
1209
+ return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number()" : "z.number()"}${numberConstraints(node)}`;
1210
+ },
1211
+ integer(node) {
1212
+ return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number().int()" : "z.int()"}${numberConstraints(node)}`;
1213
+ },
1214
+ bigint() {
1215
+ return shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.bigint()" : "z.bigint()";
1216
+ },
1217
+ date(node) {
1218
+ if (node.representation !== "date") return "z.iso.date()";
1219
+ if (this.options.direction === "encode") return node.format === "date" ? "z.date().transform((value) => value.toISOString().slice(0, 10))" : "z.date().transform((value) => value.toISOString())";
1220
+ const decoded = node.format === "date" ? "z.iso.date().transform((value) => new Date(value))" : "z.iso.datetime().transform((value) => new Date(value))";
1221
+ return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : decoded;
1222
+ },
1223
+ datetime(node) {
1224
+ const offset = node.offset || this.options.dateType === "stringOffset";
1225
+ const local = node.local || this.options.dateType === "stringLocal";
1226
+ if (offset) return "z.iso.datetime({ offset: true })";
1227
+ if (local) return "z.iso.datetime({ local: true })";
1228
+ return "z.iso.datetime()";
1229
+ },
1230
+ time(node) {
1231
+ if (node.representation === "string") return "z.iso.time()";
1232
+ return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : "z.date()";
1233
+ },
1234
+ uuid(node) {
1235
+ return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthConstraints({
1236
+ ...node,
1237
+ regexType: this.options.regexType
1238
+ })}`;
1239
+ },
1240
+ email(node) {
1241
+ return `z.email()${lengthConstraints({
1242
+ ...node,
1243
+ regexType: this.options.regexType
1244
+ })}`;
1245
+ },
1246
+ url(node) {
1247
+ return `z.url()${lengthConstraints({
1248
+ ...node,
1249
+ regexType: this.options.regexType
1250
+ })}`;
1251
+ },
1252
+ ipv4: () => "z.ipv4()",
1253
+ ipv6: () => "z.ipv6()",
1254
+ blob: () => "z.instanceof(File)",
1255
+ enum(node) {
1256
+ const nonNullValues = (node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []).filter((v) => v !== null);
1257
+ if (node.namedEnumValues?.length) {
1258
+ const literals = nonNullValues.map((v) => `z.literal(${formatLiteral(v)})`);
1259
+ if (literals.length === 1) return literals[0];
1260
+ return `z.union([${literals.join(", ")}])`;
1261
+ }
1262
+ return buildEnum(nonNullValues);
1263
+ }
1264
+ };
1265
+ /**
1166
1266
  * Zod v4 printer built with `definePrinter`.
1167
1267
  *
1168
1268
  * Converts a `SchemaNode` AST into a Zod v4 code string using the chainable API
@@ -1180,84 +1280,15 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
1180
1280
  name: "zod",
1181
1281
  options,
1182
1282
  nodes: {
1183
- any: () => "z.any()",
1184
- unknown: () => "z.unknown()",
1185
- void: () => "z.void()",
1186
- never: () => "z.never()",
1187
- boolean: () => "z.boolean()",
1188
- null: () => "z.null()",
1189
- string(node) {
1190
- const base = shouldCoerce(this.options.coercion, "strings") ? "z.coerce.string()" : "z.string()";
1191
- const pattern = node.pattern ?? integerFormatPattern(node.format);
1192
- return `${base}${lengthConstraints({
1193
- ...node,
1194
- pattern,
1195
- regexType: this.options.regexType
1196
- })}`;
1197
- },
1198
- number(node) {
1199
- return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number()" : "z.number()"}${numberConstraints(node)}`;
1200
- },
1201
- integer(node) {
1202
- return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number().int()" : "z.int()"}${numberConstraints(node)}`;
1203
- },
1204
- bigint() {
1205
- return shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.bigint()" : "z.bigint()";
1206
- },
1207
- date(node) {
1208
- const codec = getCodec(node);
1209
- if (codec) {
1210
- if (this.options.direction === "input") return codec.encode(node);
1211
- return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : codec.decode(node);
1212
- }
1213
- return "z.iso.date()";
1214
- },
1215
- datetime(node) {
1216
- const offset = node.offset || this.options.dateType === "stringOffset";
1217
- const local = node.local || this.options.dateType === "stringLocal";
1218
- if (offset) return "z.iso.datetime({ offset: true })";
1219
- if (local) return "z.iso.datetime({ local: true })";
1220
- return "z.iso.datetime()";
1221
- },
1222
- time(node) {
1223
- if (node.representation === "string") return "z.iso.time()";
1224
- return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : "z.date()";
1225
- },
1226
- uuid(node) {
1227
- return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthConstraints({
1228
- ...node,
1229
- regexType: this.options.regexType
1230
- })}`;
1231
- },
1232
- email(node) {
1233
- return `z.email()${lengthConstraints({
1234
- ...node,
1235
- regexType: this.options.regexType
1236
- })}`;
1237
- },
1238
- url(node) {
1239
- return `z.url()${lengthConstraints({
1240
- ...node,
1241
- regexType: this.options.regexType
1242
- })}`;
1243
- },
1244
- ipv4: () => "z.ipv4()",
1245
- ipv6: () => "z.ipv6()",
1246
- blob: () => "z.instanceof(File)",
1247
- enum(node) {
1248
- const nonNullValues = (node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []).filter((v) => v !== null);
1249
- if (node.namedEnumValues?.length) {
1250
- const literals = nonNullValues.map((v) => `z.literal(${formatLiteral(v)})`);
1251
- if (literals.length === 1) return literals[0];
1252
- return `z.union([${literals.join(", ")}])`;
1253
- }
1254
- return buildEnum(nonNullValues);
1255
- },
1283
+ ...scalarNodes,
1256
1284
  ref(node) {
1257
1285
  if (!node.name) return null;
1258
1286
  const refName = kubb_kit.ast.resolveRefName(node);
1259
1287
  if (!refName) return null;
1260
- const useInputVariant = node.ref != null && this.options.direction === "input" && containsCodec(node);
1288
+ const useInputVariant = node.ref != null && this.options.direction === "encode" && containsDirectionalNode({
1289
+ node,
1290
+ printerOptions: this.options
1291
+ });
1261
1292
  const resolvedName = node.ref ? useInputVariant ? this.options.resolver?.schema.inputName(refName) ?? refName : this.options.resolver?.name(refName) ?? refName : node.name;
1262
1293
  if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
1263
1294
  return resolvedName;
@@ -1584,29 +1615,28 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
1584
1615
  const zodPrinterCache = /* @__PURE__ */ new WeakMap();
1585
1616
  const zodMiniPrinterCache = /* @__PURE__ */ new WeakMap();
1586
1617
  /**
1587
- * Returns the cached `output`/`input` direction printers for a resolver, building them on
1588
- * first use. The `input` printer encodes `Date → string` for request bodies, and `output` decodes
1589
- * `string → Date` for responses. Schemas without `dateType: 'date'` fields print identically.
1618
+ * Cached printer per direction for a resolver, built on first use. Schemas holding nothing that
1619
+ * converts print the same either way.
1590
1620
  */
1591
1621
  function getStdPrinters(resolver, params) {
1592
1622
  const cached = zodPrinterCache.get(resolver);
1593
1623
  if (cached && cached.coercion === params.coercion && cached.guidType === params.guidType && cached.regexType === params.regexType && cached.dateType === params.dateType && cached.nodes === params.nodes) return {
1594
- output: cached.output,
1595
- input: cached.input
1624
+ decode: cached.decode,
1625
+ encode: cached.encode
1596
1626
  };
1597
- const output = printerZod({
1627
+ const decode = printerZod({
1598
1628
  ...params,
1599
1629
  resolver,
1600
- direction: "output"
1630
+ direction: "decode"
1601
1631
  });
1602
- const input = printerZod({
1632
+ const encode = printerZod({
1603
1633
  ...params,
1604
1634
  resolver,
1605
- direction: "input"
1635
+ direction: "encode"
1606
1636
  });
1607
1637
  zodPrinterCache.set(resolver, {
1608
- output,
1609
- input,
1638
+ decode,
1639
+ encode,
1610
1640
  coercion: params.coercion,
1611
1641
  guidType: params.guidType,
1612
1642
  regexType: params.regexType,
@@ -1614,8 +1644,8 @@ function getStdPrinters(resolver, params) {
1614
1644
  nodes: params.nodes
1615
1645
  });
1616
1646
  return {
1617
- output,
1618
- input
1647
+ decode,
1648
+ encode
1619
1649
  };
1620
1650
  }
1621
1651
  function getMiniPrinter(resolver, params) {
@@ -1649,15 +1679,30 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1649
1679
  if (!node.name) return;
1650
1680
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1651
1681
  const cyclicSchemas = new Set(ctx.meta.circularNames);
1652
- const hasCodec = !mini && containsCodec(node);
1653
- const codecRefNames = new Set(hasCodec ? collectCodecRefNames(node) : []);
1682
+ const printerOptions = {
1683
+ coercion,
1684
+ guidType,
1685
+ regexType,
1686
+ dateType,
1687
+ resolver,
1688
+ cyclicSchemas,
1689
+ nodes: printer?.nodes
1690
+ };
1691
+ const hasDirectionalNode = !mini && containsDirectionalNode({
1692
+ node,
1693
+ printerOptions
1694
+ });
1695
+ const directionalRefNames = new Set(hasDirectionalNode ? collectDirectionalRefNames({
1696
+ node,
1697
+ printerOptions
1698
+ }) : []);
1654
1699
  const importEntries = resolver.imports({
1655
1700
  node,
1656
1701
  root,
1657
1702
  output,
1658
1703
  group: group ?? void 0
1659
1704
  });
1660
- const inputImportEntries = hasCodec ? [...codecRefNames].map((schemaName) => ({
1705
+ const inputImportEntries = hasDirectionalNode ? [...directionalRefNames].map((schemaName) => ({
1661
1706
  name: [resolver.schema.inputName(schemaName)],
1662
1707
  path: resolver.file({
1663
1708
  name: schemaName,
@@ -1698,7 +1743,7 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1698
1743
  regexType,
1699
1744
  cyclicSchemas,
1700
1745
  nodes: printer?.nodes
1701
- }) : stdPrinters.output;
1746
+ }) : stdPrinters.decode;
1702
1747
  return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
1703
1748
  baseName: meta.file.baseName,
1704
1749
  path: meta.file.path,
@@ -1741,10 +1786,10 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1741
1786
  inferTypeName,
1742
1787
  cyclic: cyclicSchemas.has(node.name)
1743
1788
  }),
1744
- hasCodec && stdPrinters && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Zod, {
1789
+ hasDirectionalNode && stdPrinters && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Zod, {
1745
1790
  name: resolver.schema.inputName(node.name),
1746
1791
  node,
1747
- printer: stdPrinters.input,
1792
+ printer: stdPrinters.encode,
1748
1793
  inferTypeName: inferred ? resolver.schema.inputTypeName(node.name) : null,
1749
1794
  cyclic: cyclicSchemas.has(node.name)
1750
1795
  })
@@ -1767,16 +1812,28 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1767
1812
  group: group ?? void 0
1768
1813
  }) };
1769
1814
  const cyclicSchemas = new Set(ctx.meta.circularNames);
1770
- function renderSchemaEntry({ schema, name, keysToOmit, direction = "output" }) {
1815
+ const printerOptions = {
1816
+ coercion,
1817
+ guidType,
1818
+ regexType,
1819
+ dateType,
1820
+ resolver,
1821
+ cyclicSchemas,
1822
+ nodes: printer?.nodes
1823
+ };
1824
+ function renderSchemaEntry({ schema, name, keysToOmit, direction = "decode" }) {
1771
1825
  if (!schema) return null;
1772
1826
  const inferTypeName = inferred ? resolver.schema.type(name) : null;
1773
- const codecRefNames = direction === "input" && !mini ? new Set(collectCodecRefNames(schema)) : null;
1827
+ const directionalRefNames = direction === "encode" && !mini ? new Set(collectDirectionalRefNames({
1828
+ node: schema,
1829
+ printerOptions
1830
+ })) : null;
1774
1831
  const imports = resolver.imports({
1775
1832
  node: schema,
1776
1833
  root,
1777
1834
  output,
1778
1835
  group: group ?? void 0,
1779
- name: (schemaName) => codecRefNames?.has(schemaName) ? resolver.schema.inputName(schemaName) : resolver.name(schemaName)
1836
+ name: (schemaName) => directionalRefNames?.has(schemaName) ? resolver.schema.inputName(schemaName) : resolver.name(schemaName)
1780
1837
  });
1781
1838
  const schemaPrinter = mini ? keysToOmit?.length ? printerZodMini({
1782
1839
  guidType,
@@ -1865,7 +1922,7 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1865
1922
  const paramSchemas = node.parameters.map((param) => renderSchemaEntry({
1866
1923
  schema: param.schema,
1867
1924
  name: resolver.param.name(node, param),
1868
- direction: "input"
1925
+ direction: "encode"
1869
1926
  }));
1870
1927
  const responseSchemas = node.responses.map((res) => {
1871
1928
  const variants = (res.content ?? []).filter((entry) => entry.schema);
@@ -1903,13 +1960,13 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1903
1960
  },
1904
1961
  name: resolver.response.body(node),
1905
1962
  keysToOmit: entry.keysToOmit,
1906
- direction: "input"
1963
+ direction: "encode"
1907
1964
  });
1908
1965
  }
1909
1966
  return buildContentTypeVariants(requestBodyContent, resolver.response.body(node), (schema) => ({
1910
1967
  ...schema,
1911
1968
  description: node.requestBody.description ?? schema.description
1912
- }), "input");
1969
+ }), "encode");
1913
1970
  })();
1914
1971
  const { path, query, header } = getOperationParameters(node);
1915
1972
  const paramGroupSchemas = inferred ? [
@@ -1928,12 +1985,12 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1928
1985
  ].filter(({ params }) => params.length > 0).map(({ kind, params }) => renderSchemaEntry({
1929
1986
  schema: buildGroupedParamsSchema({ params }),
1930
1987
  name: resolver.param[kind](node, params[0]),
1931
- direction: "input"
1988
+ direction: "encode"
1932
1989
  })) : [];
1933
1990
  const optionsSchema = inferred ? renderSchemaEntry({
1934
1991
  schema: buildOptionsSchema(node, resolver),
1935
1992
  name: resolver.name(`${node.operationId} Options`),
1936
- direction: "input"
1993
+ direction: "encode"
1937
1994
  }) : null;
1938
1995
  const responsesSchema = inferred ? renderSchemaEntry({
1939
1996
  schema: buildResponses(node, resolver),