@kubb/adapter-oas 5.0.0-beta.93 → 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 CHANGED
@@ -28,8 +28,8 @@ node_path = __toESM(node_path, 1);
28
28
  let node_fs_promises = require("node:fs/promises");
29
29
  let _readme_openapi_parser = require("@readme/openapi-parser");
30
30
  let _scalar_openapi_upgrader = require("@scalar/openapi-upgrader");
31
- let yaml = require("yaml");
32
31
  let api_ref_bundler = require("api-ref-bundler");
32
+ let yaml = require("yaml");
33
33
  //#region src/constants.ts
34
34
  /**
35
35
  * Default parser options applied when no explicit options are provided.
@@ -367,7 +367,7 @@ async function read(path) {
367
367
  return (0, node_fs_promises.readFile)(path, { encoding: "utf8" });
368
368
  }
369
369
  //#endregion
370
- //#region src/bundler.ts
370
+ //#region src/factory.ts
371
371
  const urlRegExp = /^https?:\/+/i;
372
372
  async function readSource(sourcePath) {
373
373
  if (urlRegExp.test(sourcePath)) {
@@ -410,8 +410,6 @@ async function bundleDocument(pathOrUrl) {
410
410
  await resolver(pathOrUrl);
411
411
  return await (0, api_ref_bundler.bundle)(pathOrUrl, resolver);
412
412
  }
413
- //#endregion
414
- //#region src/factory.ts
415
413
  /**
416
414
  * Loads and bundles an OpenAPI document, returning the raw `Document`.
417
415
  *
@@ -481,19 +479,12 @@ async function validateDocument(document, { throwOnError = false } = {}) {
481
479
  }
482
480
  }
483
481
  //#endregion
484
- //#region src/guards.ts
482
+ //#region src/oas.ts
485
483
  /**
486
484
  * Returns `true` when a schema should be treated as nullable.
487
485
  *
488
486
  * Recognizes all nullable signals across OAS versions: `nullable: true` (OAS 3.0),
489
487
  * `x-nullable: true` (vendor extension), `type: 'null'`, and `type: ['null', ...]` (OAS 3.1).
490
- *
491
- * @example
492
- * ```ts
493
- * isNullable({ type: 'string', nullable: true }) // true
494
- * isNullable({ type: ['string', 'null'] }) // true
495
- * isNullable({ type: 'string' }) // false
496
- * ```
497
488
  */
498
489
  function isNullable(schema) {
499
490
  if ((schema?.nullable ?? schema?.["x-nullable"]) === true) return true;
@@ -504,24 +495,13 @@ function isNullable(schema) {
504
495
  }
505
496
  /**
506
497
  * Returns `true` when `obj` is an OpenAPI `$ref` pointer object.
507
- *
508
- * @example
509
- * ```ts
510
- * isReference({ $ref: '#/components/schemas/Pet' }) // true
511
- * isReference({ type: 'string' }) // false
512
- * ```
513
498
  */
514
499
  function isReference(obj) {
515
500
  return !!obj && typeof obj === "object" && "$ref" in obj;
516
501
  }
517
502
  /**
518
- * Returns `true` when `obj` is a schema with a structured OAS 3.x `discriminator` object.
519
- *
520
- * @example
521
- * ```ts
522
- * isDiscriminator({ discriminator: { propertyName: 'type', mapping: {} } }) // true
523
- * isDiscriminator({ discriminator: 'type' }) // false (Swagger 2 string form)
524
- * ```
503
+ * Returns `true` when `obj` is a schema with a structured OAS 3.x `discriminator` object,
504
+ * excluding the Swagger 2 string form.
525
505
  */
526
506
  function isDiscriminator(obj) {
527
507
  const record = obj;
@@ -529,18 +509,10 @@ function isDiscriminator(obj) {
529
509
  }
530
510
  /**
531
511
  * Returns `true` when a schema is a binary payload: an octet-stream string body.
532
- *
533
- * @example
534
- * ```ts
535
- * isBinary({ type: 'string', contentMediaType: 'application/octet-stream' }) // true
536
- * isBinary({ type: 'string' }) // false
537
- * ```
538
512
  */
539
513
  function isBinary(schema) {
540
514
  return schema.type === "string" && schema.contentMediaType === "application/octet-stream";
541
515
  }
542
- //#endregion
543
- //#region src/mime.ts
544
516
  /**
545
517
  * MIME type fragments that mark a media type as JSON-like.
546
518
  *
@@ -633,6 +605,23 @@ function dereferenceWithRef(document, schema) {
633
605
  };
634
606
  return schema;
635
607
  }
608
+ /**
609
+ * Resolves a `$ref` slot in place: when `container[key]` holds a `$ref`, replaces it with the
610
+ * resolved value and returns that value. Returns `null` when the slot is empty, cannot be resolved,
611
+ * or is still a `$ref` after resolving. A non-`$ref` value is returned untouched, without writing.
612
+ *
613
+ * @example
614
+ * ```ts
615
+ * derefInPlace<ResponseObject>({ document, container: operation.schema.responses, key: '200' })
616
+ * ```
617
+ */
618
+ function derefInPlace({ document, container, key }) {
619
+ const value = container[key];
620
+ if (!isReference(value)) return value ? value : null;
621
+ const resolved = resolveRef(document, value.$ref);
622
+ container[key] = resolved;
623
+ return resolved && !isReference(resolved) ? resolved : null;
624
+ }
636
625
  //#endregion
637
626
  //#region src/operation.ts
638
627
  /**
@@ -664,31 +653,22 @@ function getResponseStatusCodes({ schema }) {
664
653
  function getResponseByStatusCode({ document, operation, statusCode }) {
665
654
  const responses = operation.schema.responses;
666
655
  if (!responses || isReference(responses)) return false;
667
- const response = responses[statusCode];
668
- if (!response) return false;
669
- if (isReference(response)) {
670
- const resolved = resolveRef(document, response.$ref);
671
- responses[statusCode] = resolved;
672
- if (!resolved || isReference(resolved)) return false;
673
- return resolved;
674
- }
675
- return response;
656
+ return derefInPlace({
657
+ document,
658
+ container: responses,
659
+ key: statusCode
660
+ }) ?? false;
676
661
  }
677
662
  /**
678
663
  * Resolves the request body (dereferencing a `$ref` in place) and returns its content map, or
679
664
  * `undefined` when the operation has no request body.
680
665
  */
681
666
  function getRequestBodyContent({ document, operation }) {
682
- const { schema } = operation;
683
- let requestBody = schema.requestBody;
684
- if (!requestBody) return;
685
- if (isReference(requestBody)) {
686
- const resolved = resolveRef(document, requestBody.$ref);
687
- schema.requestBody = resolved;
688
- if (!resolved || isReference(resolved)) return;
689
- requestBody = resolved;
690
- }
691
- return requestBody.content;
667
+ return derefInPlace({
668
+ document,
669
+ container: operation.schema,
670
+ key: "requestBody"
671
+ })?.content;
692
672
  }
693
673
  /**
694
674
  * Returns the request body media type. With `mediaType` set, returns that entry or `false`.
@@ -737,14 +717,12 @@ function getOperations(document) {
737
717
  if (!paths) return operations;
738
718
  for (const path of Object.keys(paths)) {
739
719
  if (path.startsWith("x-")) continue;
740
- let pathItem = paths[path];
720
+ const pathItem = derefInPlace({
721
+ document,
722
+ container: paths,
723
+ key: path
724
+ });
741
725
  if (!pathItem) continue;
742
- if (isReference(pathItem)) {
743
- const resolved = resolveRef(document, pathItem.$ref);
744
- paths[path] = resolved;
745
- if (!resolved || isReference(resolved)) continue;
746
- pathItem = resolved;
747
- }
748
726
  const item = pathItem;
749
727
  for (const method of Object.keys(item)) {
750
728
  if (!SUPPORTED_METHODS.has(method)) continue;
@@ -872,6 +850,15 @@ function getResponseBody(responseBody, contentType) {
872
850
  if (!availableContentType) return false;
873
851
  return body.content[availableContentType];
874
852
  }
853
+ function resolveResponseRefs(document, operation) {
854
+ const responses = operation.schema.responses;
855
+ if (!responses) return;
856
+ for (const key in responses) derefInPlace({
857
+ document,
858
+ container: responses,
859
+ key
860
+ });
861
+ }
875
862
  /**
876
863
  * Returns the response schema for a given operation and HTTP status code.
877
864
  *
@@ -883,14 +870,6 @@ function getResponseBody(responseBody, contentType) {
883
870
  * getResponseSchema(document, operation, '4XX') // {}
884
871
  * ```
885
872
  */
886
- function resolveResponseRefs(document, operation) {
887
- const responses = operation.schema.responses;
888
- if (!responses) return;
889
- for (const key in responses) {
890
- const schema = responses[key];
891
- if (schema && isReference(schema)) responses[key] = resolveRef(document, schema.$ref);
892
- }
893
- }
894
873
  function getResponseSchema(document, operation, statusCode, options = {}) {
895
874
  resolveResponseRefs(document, operation);
896
875
  const responseBody = getResponseBody(getResponseByStatusCode({
@@ -929,6 +908,16 @@ function getRequestSchema(document, operation, options = {}) {
929
908
  return dereferenceWithRef(document, schema);
930
909
  }
931
910
  /**
911
+ * Returns `true` when `fragment` carries any JSON Schema keyword that makes it
912
+ * structurally significant on its own (see `structuralKeys`).
913
+ *
914
+ * A fragment with a structural keyword can't be safely merged into a parent schema.
915
+ */
916
+ function hasStructuralKeywords(fragment) {
917
+ for (const key in fragment) if (structuralKeys.has(key)) return true;
918
+ return false;
919
+ }
920
+ /**
932
921
  * Flattens a keyword-only `allOf` into its parent schema.
933
922
  *
934
923
  * Only flattens when every member is a plain fragment, with no `$ref` and no structural keywords
@@ -947,16 +936,6 @@ function getRequestSchema(document, operation, options = {}) {
947
936
  * // returned unchanged, contains a $ref
948
937
  * ```
949
938
  */
950
- /**
951
- * Returns `true` when `fragment` carries any JSON Schema keyword that makes it
952
- * structurally significant on its own (see `structuralKeys`).
953
- *
954
- * A fragment with a structural keyword can't be safely merged into a parent schema.
955
- */
956
- function hasStructuralKeywords(fragment) {
957
- for (const key in fragment) if (structuralKeys.has(key)) return true;
958
- return false;
959
- }
960
939
  function flattenSchema(schema) {
961
940
  if (!schema?.allOf || schema.allOf.length === 0) return schema ?? null;
962
941
  const allOfFragments = schema.allOf;
@@ -1058,7 +1037,7 @@ function resolveSchemaRef(document, schema) {
1058
1037
  *
1059
1038
  * @example
1060
1039
  * ```ts
1061
- * const { schemas, nameMapping } = getSchemas(document, { contentType: 'application/json' })
1040
+ * const { schemas, renames } = getSchemas(document, { contentType: 'application/json' })
1062
1041
  * ```
1063
1042
  */
1064
1043
  function getSchemas(document, { contentType }) {
@@ -1083,7 +1062,7 @@ function getSchemas(document, { contentType }) {
1083
1062
  normalizedNames.set(key, bucket);
1084
1063
  }
1085
1064
  const schemas = {};
1086
- const nameMapping = /* @__PURE__ */ new Map();
1065
+ const renames = /* @__PURE__ */ new Map();
1087
1066
  for (const [, items] of normalizedNames) {
1088
1067
  const isSingle = items.length === 1;
1089
1068
  let hasMultipleSources = false;
@@ -1098,12 +1077,12 @@ function getSchemas(document, { contentType }) {
1098
1077
  const suffix = isSingle ? "" : hasMultipleSources ? semanticSuffixes[item.source] : index === 0 ? "" : String(index + 1);
1099
1078
  const uniqueName = item.originalName + suffix;
1100
1079
  schemas[uniqueName] = item.schema;
1101
- nameMapping.set(`#/components/${item.source}/${item.originalName}`, uniqueName);
1080
+ if (suffix) renames.set(`#/components/${item.source}/${item.originalName}`, uniqueName);
1102
1081
  });
1103
1082
  }
1104
1083
  return {
1105
1084
  schemas: sortSchemas(schemas),
1106
- nameMapping
1085
+ renames
1107
1086
  };
1108
1087
  }
1109
1088
  /**
@@ -1208,7 +1187,7 @@ function getResponseBodyContentTypes(document, operation, statusCode) {
1208
1187
  return body.content ? Object.keys(body.content) : [];
1209
1188
  }
1210
1189
  //#endregion
1211
- //#region src/parser.ts
1190
+ //#region src/converters.ts
1212
1191
  /**
1213
1192
  * Normalizes malformed `{ type: 'array', enum: [...] }` schemas by moving enum values into items.
1214
1193
  *
@@ -1232,7 +1211,7 @@ function normalizeArrayEnum(schema) {
1232
1211
  * Builds a `null` scalar node carrying the schema's documentation. Shared by the `const: null`
1233
1212
  * and the drf-spectacular `NullEnum` (`{ enum: [null] }`) branches, which render identically.
1234
1213
  */
1235
- function createNullSchema(schema, name, nullable) {
1214
+ function createNullNode(schema, name, nullable) {
1236
1215
  return _kubb_ast.ast.factory.createSchema({
1237
1216
  type: "null",
1238
1217
  primitive: "null",
@@ -1262,620 +1241,638 @@ function nameEnums(node, options) {
1262
1241
  return named;
1263
1242
  }
1264
1243
  /**
1265
- * Factory function that creates schema and operation converters for a given OpenAPI context.
1244
+ * Converts a `$ref` schema into a `RefSchemaNode`.
1266
1245
  *
1267
- * Returns closures that share mutable state (`resolvingRefs` set for cycle detection).
1268
- * Each converter branch (`convertRef`, `convertAllOf`, etc.) mutually recursively calls `parseSchema`,
1269
- * which works because function declarations hoist.
1270
- *
1271
- * @internal
1246
+ * The resolved schema is stored in `node.schema`. Usage-site sibling fields
1247
+ * (description, readOnly, nullable, etc.) are stored directly on the ref node.
1248
+ * Use `syncSchemaRef(node)` in printers to get a merged view of both.
1249
+ * Circular refs are detected in `resolveRefNode` and leave `schema` as `null`.
1250
+ */
1251
+ function convertRef({ schema, name, nullable, defaultValue, rawOptions, document, resolveRefNode, refExists, renames }) {
1252
+ const refPath = schema.$ref;
1253
+ const resolvedSchema = refPath ? resolveRefNode(refPath, rawOptions) : null;
1254
+ if (refPath && document.components && !refExists(refPath)) return _kubb_ast.ast.factory.createSchema({
1255
+ ...buildSchemaNode(schema, name, nullable, defaultValue),
1256
+ type: "unknown"
1257
+ });
1258
+ const targetName = renames?.get(schema.$ref);
1259
+ return _kubb_ast.ast.factory.createSchema({
1260
+ ...buildSchemaNode(schema, name, nullable, defaultValue),
1261
+ type: "ref",
1262
+ name: (0, _kubb_ast.extractRefName)(schema.$ref),
1263
+ ref: schema.$ref,
1264
+ ...targetName ? { targetName } : {},
1265
+ schema: resolvedSchema
1266
+ });
1267
+ }
1268
+ /**
1269
+ * Converts an `allOf` schema into a flattened node or an `IntersectionSchemaNode`.
1272
1270
  */
1273
- function createSchemaParser(ctx) {
1274
- const document = ctx.document;
1275
- /**
1276
- * Tracks `$ref` paths that are currently being resolved to prevent infinite
1277
- * recursion when schemas contain circular references (e.g. `Pet → parent → Pet`).
1278
- */
1279
- const resolvingRefs = /* @__PURE__ */ new Set();
1280
- /**
1281
- * Cache of `$ref` schemas already resolved in this parser instance, keyed by ref path.
1282
- *
1283
- * Without it, a shared schema (e.g. `customer`) is re-expanded for every `$ref` that points at
1284
- * it. In cross-referenced specs like Stripe (~1400 schemas) that becomes exponential blowup,
1285
- * since one schema can be referenced from dozens of parents, each re-walking its whole subtree.
1286
- * Memoizing by ref path drops the work from O(2^depth) to O(N) unique schema names.
1287
- */
1288
- const resolvedRefCache = /* @__PURE__ */ new Map();
1289
- /**
1290
- * Memoized record of whether a `$ref` path resolves to a node the document actually defines.
1291
- * A circular ref still resolves to an existing target, so this stays `true` for cycles and only
1292
- * goes `false` for a `$ref` that points at a component the spec never declares.
1293
- */
1294
- const refExistence = /* @__PURE__ */ new Map();
1295
- function refExists(refPath) {
1296
- if (!refExistence.has(refPath)) {
1297
- let exists = false;
1298
- try {
1299
- exists = !!resolveRef(document, refPath);
1300
- } catch {
1301
- exists = false;
1302
- }
1303
- refExistence.set(refPath, exists);
1304
- }
1305
- return refExistence.get(refPath) ?? false;
1306
- }
1307
- /**
1308
- * Converts a `$ref` schema into a `RefSchemaNode`.
1309
- *
1310
- * The resolved schema is stored in `node.schema`. Usage-site sibling fields
1311
- * (description, readOnly, nullable, etc.) are stored directly on the ref node.
1312
- * Use `syncSchemaRef(node)` in printers to get a merged view of both.
1313
- * Circular refs are detected via `resolvingRefs` and leave `schema` as `undefined`.
1314
- */
1315
- function convertRef({ schema, name, nullable, defaultValue, rawOptions }) {
1316
- let resolvedSchema = null;
1317
- const refPath = schema.$ref;
1318
- if (refPath && !resolvingRefs.has(refPath)) {
1319
- if (!resolvedRefCache.has(refPath)) {
1320
- try {
1321
- const referenced = resolveRef(document, refPath);
1322
- if (referenced) {
1323
- resolvingRefs.add(refPath);
1324
- resolvedSchema = parseSchema({ schema: referenced }, rawOptions);
1325
- resolvingRefs.delete(refPath);
1326
- }
1327
- } catch {}
1328
- resolvedRefCache.set(refPath, resolvedSchema);
1329
- }
1330
- resolvedSchema = resolvedRefCache.get(refPath) ?? null;
1331
- }
1332
- if (refPath && document.components && !refExists(refPath)) return _kubb_ast.ast.factory.createSchema({
1333
- ...buildSchemaNode(schema, name, nullable, defaultValue),
1334
- type: "unknown"
1335
- });
1271
+ function convertAllOf({ schema, name, nullable, defaultValue, rawOptions, parse, document }) {
1272
+ if (schema.allOf.length === 1 && !schema.properties && !(Array.isArray(schema.required) && schema.required.length) && schema.additionalProperties === void 0) {
1273
+ const [memberSchema] = schema.allOf;
1274
+ const memberNode = parse({
1275
+ schema: memberSchema,
1276
+ name
1277
+ }, rawOptions);
1278
+ const { kind: _kind, ...memberNodeProps } = memberNode;
1279
+ const mergedNullable = nullable || memberNode.nullable || void 0;
1280
+ const mergedDefault = schema.default === null && mergedNullable ? void 0 : schema.default ?? memberNode.default;
1336
1281
  return _kubb_ast.ast.factory.createSchema({
1337
- ...buildSchemaNode(schema, name, nullable, defaultValue),
1338
- type: "ref",
1339
- name: (0, _kubb_ast.extractRefName)(schema.$ref),
1340
- ref: schema.$ref,
1341
- schema: resolvedSchema
1282
+ ...memberNodeProps,
1283
+ name,
1284
+ title: schema.title ?? memberNode.title,
1285
+ description: schema.description ?? memberNode.description,
1286
+ deprecated: schema.deprecated ?? memberNode.deprecated,
1287
+ nullable: mergedNullable,
1288
+ readOnly: schema.readOnly ?? memberNode.readOnly,
1289
+ writeOnly: schema.writeOnly ?? memberNode.writeOnly,
1290
+ default: mergedDefault,
1291
+ examples: extractExamples(schema) ?? memberNode.examples,
1292
+ pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0),
1293
+ format: schema.format ?? memberNode.format
1342
1294
  });
1343
1295
  }
1344
- /**
1345
- * Converts an `allOf` schema into a flattened node or an `IntersectionSchemaNode`.
1346
- */
1347
- function convertAllOf({ schema, name, nullable, defaultValue, rawOptions }) {
1348
- if (schema.allOf.length === 1 && !schema.properties && !(Array.isArray(schema.required) && schema.required.length) && schema.additionalProperties === void 0) {
1349
- const [memberSchema] = schema.allOf;
1350
- const memberNode = parseSchema({
1351
- schema: memberSchema,
1352
- name
1353
- }, rawOptions);
1354
- const { kind: _kind, ...memberNodeProps } = memberNode;
1355
- const mergedNullable = nullable || memberNode.nullable || void 0;
1356
- const mergedDefault = schema.default === null && mergedNullable ? void 0 : schema.default ?? memberNode.default;
1357
- return _kubb_ast.ast.factory.createSchema({
1358
- ...memberNodeProps,
1359
- name,
1360
- title: schema.title ?? memberNode.title,
1361
- description: schema.description ?? memberNode.description,
1362
- deprecated: schema.deprecated ?? memberNode.deprecated,
1363
- nullable: mergedNullable,
1364
- readOnly: schema.readOnly ?? memberNode.readOnly,
1365
- writeOnly: schema.writeOnly ?? memberNode.writeOnly,
1366
- default: mergedDefault,
1367
- examples: extractExamples(schema) ?? memberNode.examples,
1368
- pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0),
1369
- format: schema.format ?? memberNode.format
1296
+ const filteredDiscriminantValues = [];
1297
+ const allOfMembers = schema.allOf.filter((item) => {
1298
+ if (!isReference(item) || !name) return true;
1299
+ const deref = resolveRef(document, item.$ref);
1300
+ if (!deref || !isDiscriminator(deref)) return true;
1301
+ const parentUnion = deref.oneOf ?? deref.anyOf;
1302
+ if (!parentUnion) return true;
1303
+ const childRef = `${SCHEMA_REF_PREFIX}${name}`;
1304
+ const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1305
+ const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1306
+ if (inOneOf || inMapping) {
1307
+ const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef);
1308
+ if (discriminatorValue) filteredDiscriminantValues.push({
1309
+ propertyName: deref.discriminator.propertyName,
1310
+ value: discriminatorValue
1370
1311
  });
1312
+ return false;
1371
1313
  }
1372
- const filteredDiscriminantValues = [];
1373
- const allOfMembers = schema.allOf.filter((item) => {
1374
- if (!isReference(item) || !name) return true;
1375
- const deref = resolveRef(document, item.$ref);
1376
- if (!deref || !isDiscriminator(deref)) return true;
1377
- const parentUnion = deref.oneOf ?? deref.anyOf;
1378
- if (!parentUnion) return true;
1379
- const childRef = `${SCHEMA_REF_PREFIX}${name}`;
1380
- const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1381
- const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1382
- if (inOneOf || inMapping) {
1383
- const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef);
1384
- if (discriminatorValue) filteredDiscriminantValues.push({
1385
- propertyName: deref.discriminator.propertyName,
1386
- value: discriminatorValue
1387
- });
1388
- return false;
1389
- }
1390
- return true;
1391
- }).map((s) => parseSchema({
1392
- schema: s,
1393
- name
1394
- }, rawOptions));
1395
- const syntheticStart = allOfMembers.length;
1396
- if (Array.isArray(schema.required) && schema.required.length) {
1397
- const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
1398
- const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
1399
- if (missingRequired.length) {
1400
- const resolvedMembers = schema.allOf.flatMap((item) => {
1401
- if (!isReference(item)) return [item];
1402
- const deref = resolveRef(document, item.$ref);
1403
- return deref && !isReference(deref) ? [deref] : [];
1404
- });
1405
- for (const key of missingRequired) for (const resolved of resolvedMembers) if (resolved.properties?.[key]) {
1406
- allOfMembers.push(parseSchema({
1407
- schema: {
1408
- properties: { [key]: resolved.properties[key] },
1409
- required: [key]
1410
- },
1314
+ return true;
1315
+ }).map((s) => parse({
1316
+ schema: s,
1317
+ name
1318
+ }, rawOptions));
1319
+ const syntheticStart = allOfMembers.length;
1320
+ if (Array.isArray(schema.required) && schema.required.length) {
1321
+ const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
1322
+ const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
1323
+ if (missingRequired.length) {
1324
+ const resolvedMembers = schema.allOf.flatMap((item) => {
1325
+ if (!isReference(item)) return [item];
1326
+ const deref = resolveRef(document, item.$ref);
1327
+ return deref && !isReference(deref) ? [deref] : [];
1328
+ });
1329
+ for (const key of missingRequired) for (const resolved of resolvedMembers) {
1330
+ const prop = resolved.properties?.[key];
1331
+ if (prop) {
1332
+ const memberSchema = {
1333
+ properties: { [key]: prop },
1334
+ required: [key]
1335
+ };
1336
+ allOfMembers.push(parse({
1337
+ schema: memberSchema,
1411
1338
  name
1412
1339
  }, rawOptions));
1413
1340
  break;
1414
1341
  }
1415
1342
  }
1416
1343
  }
1417
- if (schema.properties) {
1418
- const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1419
- allOfMembers.push(parseSchema({ schema: schemaWithoutAllOf }, rawOptions));
1420
- }
1421
- for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createDiscriminantNode({
1422
- propertyName,
1423
- value
1424
- }));
1344
+ }
1345
+ if (schema.properties) {
1346
+ const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1347
+ allOfMembers.push(parse({ schema: schemaWithoutAllOf }, rawOptions));
1348
+ }
1349
+ for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createDiscriminantNode({
1350
+ propertyName,
1351
+ value
1352
+ }));
1353
+ return _kubb_ast.ast.factory.createSchema({
1354
+ type: "intersection",
1355
+ members: [...(0, _kubb_ast.mergeAdjacentObjectsLazy)(allOfMembers.slice(0, syntheticStart)), ...(0, _kubb_ast.mergeAdjacentObjectsLazy)(allOfMembers.slice(syntheticStart))],
1356
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1357
+ });
1358
+ }
1359
+ /**
1360
+ * Converts a `oneOf` / `anyOf` schema into a `UnionSchemaNode`.
1361
+ */
1362
+ function convertUnion({ schema, name, nullable, defaultValue, rawOptions, parse, document }) {
1363
+ function pickDiscriminatorPropertyNode(node, propertyName) {
1364
+ const discriminatorProperty = _kubb_ast.ast.narrowSchema(node, "object")?.properties?.find((property) => property.name === propertyName);
1365
+ if (!discriminatorProperty) return null;
1425
1366
  return _kubb_ast.ast.factory.createSchema({
1426
- type: "intersection",
1427
- members: [...(0, _kubb_ast.mergeAdjacentObjectsLazy)(allOfMembers.slice(0, syntheticStart)), ...(0, _kubb_ast.mergeAdjacentObjectsLazy)(allOfMembers.slice(syntheticStart))],
1428
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1367
+ type: "object",
1368
+ primitive: "object",
1369
+ properties: [discriminatorProperty]
1429
1370
  });
1430
1371
  }
1431
- /**
1432
- * Converts a `oneOf` / `anyOf` schema into a `UnionSchemaNode`.
1433
- */
1434
- function convertUnion({ schema, name, nullable, defaultValue, rawOptions }) {
1435
- function pickDiscriminatorPropertyNode(node, propertyName) {
1436
- const discriminatorProperty = _kubb_ast.ast.narrowSchema(node, "object")?.properties?.find((property) => property.name === propertyName);
1437
- if (!discriminatorProperty) return null;
1438
- return _kubb_ast.ast.factory.createSchema({
1439
- type: "object",
1440
- primitive: "object",
1441
- properties: [discriminatorProperty]
1372
+ function resolveRefSilent($ref) {
1373
+ if (!$ref.startsWith("#")) return null;
1374
+ return decodeURIComponent($ref.substring(1)).split("/").filter(Boolean).reduce((obj, key) => obj?.[key], document) ?? null;
1375
+ }
1376
+ function implicitDiscriminantValue(member) {
1377
+ if (!discriminator || discriminator.mapping || !isReference(member)) return null;
1378
+ const value = (0, _kubb_ast.extractRefName)(member.$ref);
1379
+ if (!value) return null;
1380
+ const variant = resolveRefSilent(member.$ref);
1381
+ if (!variant) return null;
1382
+ const propertyName = discriminator.propertyName;
1383
+ const seen = /* @__PURE__ */ new Set([member.$ref]);
1384
+ function constrains(v) {
1385
+ const prop = v.properties?.[propertyName];
1386
+ const resolved = prop && isReference(prop) ? resolveRefSilent(prop.$ref) : prop;
1387
+ if (resolved && (Array.isArray(resolved.enum) || resolved.const !== void 0)) return true;
1388
+ const composition = v.allOf ?? v.oneOf ?? v.anyOf;
1389
+ if (!composition) return false;
1390
+ return composition.some((m) => {
1391
+ if (!isReference(m)) return constrains(m);
1392
+ if (seen.has(m.$ref)) return false;
1393
+ seen.add(m.$ref);
1394
+ const r = resolveRefSilent(m.$ref);
1395
+ return r ? constrains(r) : false;
1442
1396
  });
1443
1397
  }
1444
- function resolveRefSilent($ref) {
1445
- if (!$ref.startsWith("#")) return null;
1446
- return decodeURIComponent($ref.substring(1)).split("/").filter(Boolean).reduce((obj, key) => obj?.[key], document) ?? null;
1447
- }
1448
- function implicitDiscriminantValue(member) {
1449
- if (!discriminator || discriminator.mapping || !isReference(member)) return null;
1450
- const value = (0, _kubb_ast.extractRefName)(member.$ref);
1451
- if (!value) return null;
1452
- const variant = resolveRefSilent(member.$ref);
1453
- if (!variant) return null;
1454
- const propertyName = discriminator.propertyName;
1455
- const seen = /* @__PURE__ */ new Set([member.$ref]);
1456
- function constrains(v) {
1457
- const prop = v.properties?.[propertyName];
1458
- const resolved = prop && isReference(prop) ? resolveRefSilent(prop.$ref) : prop;
1459
- if (resolved && (Array.isArray(resolved.enum) || resolved.const !== void 0)) return true;
1460
- const composition = v.allOf ?? v.oneOf ?? v.anyOf;
1461
- if (!composition) return false;
1462
- return composition.some((m) => {
1463
- if (!isReference(m)) return constrains(m);
1464
- if (seen.has(m.$ref)) return false;
1465
- seen.add(m.$ref);
1466
- const r = resolveRefSilent(m.$ref);
1467
- return r ? constrains(r) : false;
1468
- });
1469
- }
1470
- return constrains(variant) ? null : value;
1471
- }
1472
- const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
1473
- const strategy = schema.oneOf ? "one" : "any";
1474
- const unionBase = {
1475
- ...buildSchemaNode(schema, name, nullable, defaultValue),
1476
- discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1477
- strategy
1478
- };
1479
- const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1480
- const { oneOf: _o, anyOf: _a, discriminator: _d, ...memberBaseSchema } = schema;
1481
- const sharedPropertiesNode = schema.properties ? parseSchema({
1482
- schema: memberBaseSchema,
1483
- name
1484
- }, rawOptions) : void 0;
1485
- if (sharedPropertiesNode || discriminator) {
1486
- const members = unionMembers.map((s) => {
1487
- const ref = isReference(s) ? s.$ref : void 0;
1488
- const discriminatorValue = findDiscriminator(discriminator?.mapping, ref) ?? implicitDiscriminantValue(s);
1489
- const memberNode = parseSchema({
1490
- schema: s,
1491
- name
1492
- }, rawOptions);
1493
- if (!discriminatorValue || !discriminator) return memberNode;
1494
- const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(_kubb_ast.ast.applyMacros(sharedPropertiesNode, [(0, _kubb_ast.macroDiscriminatorEnum)({
1495
- propertyName: discriminator.propertyName,
1496
- values: [discriminatorValue]
1497
- })], { depth: "shallow" }), discriminator.propertyName) : void 0;
1498
- return _kubb_ast.ast.factory.createSchema({
1499
- type: "intersection",
1500
- members: [memberNode, narrowedDiscriminatorNode ?? createDiscriminantNode({
1501
- propertyName: discriminator.propertyName,
1502
- value: discriminatorValue
1503
- })]
1504
- });
1505
- });
1506
- const unionNode = _kubb_ast.ast.factory.createSchema({
1507
- type: "union",
1508
- ...unionBase,
1509
- members
1510
- });
1511
- if (!sharedPropertiesNode) return unionNode;
1398
+ return constrains(variant) ? null : value;
1399
+ }
1400
+ const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
1401
+ const strategy = schema.oneOf ? "one" : "any";
1402
+ const unionBase = {
1403
+ ...buildSchemaNode(schema, name, nullable, defaultValue),
1404
+ discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
1405
+ strategy
1406
+ };
1407
+ const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1408
+ const { oneOf: _o, anyOf: _a, discriminator: _d, ...memberBaseSchema } = schema;
1409
+ const sharedPropertiesNode = schema.properties ? parse({
1410
+ schema: memberBaseSchema,
1411
+ name
1412
+ }, rawOptions) : void 0;
1413
+ if (sharedPropertiesNode || discriminator) {
1414
+ const members = unionMembers.map((s) => {
1415
+ const ref = isReference(s) ? s.$ref : void 0;
1416
+ const discriminatorValue = findDiscriminator(discriminator?.mapping, ref) ?? implicitDiscriminantValue(s);
1417
+ const memberNode = parse({
1418
+ schema: s,
1419
+ name
1420
+ }, rawOptions);
1421
+ if (!discriminatorValue || !discriminator) return memberNode;
1422
+ const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(_kubb_ast.ast.applyMacros(sharedPropertiesNode, [(0, _kubb_ast.macroDiscriminatorEnum)({
1423
+ propertyName: discriminator.propertyName,
1424
+ values: [discriminatorValue]
1425
+ })], { depth: "shallow" }), discriminator.propertyName) : void 0;
1512
1426
  return _kubb_ast.ast.factory.createSchema({
1513
1427
  type: "intersection",
1514
- ...buildSchemaNode(schema, name, nullable, defaultValue),
1515
- members: [unionNode, sharedPropertiesNode]
1428
+ members: [memberNode, narrowedDiscriminatorNode ?? createDiscriminantNode({
1429
+ propertyName: discriminator.propertyName,
1430
+ value: discriminatorValue
1431
+ })]
1516
1432
  });
1517
- }
1433
+ });
1518
1434
  const unionNode = _kubb_ast.ast.factory.createSchema({
1519
1435
  type: "union",
1520
1436
  ...unionBase,
1521
- members: unionMembers.map((s) => parseSchema({
1522
- schema: s,
1523
- name
1524
- }, rawOptions))
1437
+ members
1525
1438
  });
1526
- return _kubb_ast.ast.applyMacros(unionNode, [_kubb_ast.macroSimplifyUnion], { depth: "shallow" });
1527
- }
1528
- /**
1529
- * Converts an OAS 3.1 `const` schema into a null scalar or a single-value `EnumSchemaNode`.
1530
- */
1531
- function convertConst({ schema, name, nullable, defaultValue }) {
1532
- const constValue = schema.const;
1533
- if (constValue === null) return createNullSchema(schema, name);
1534
- const constPrimitive = getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string");
1439
+ if (!sharedPropertiesNode) return unionNode;
1535
1440
  return _kubb_ast.ast.factory.createSchema({
1536
- type: "enum",
1537
- primitive: constPrimitive,
1538
- enumValues: [constValue],
1539
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1441
+ type: "intersection",
1442
+ ...buildSchemaNode(schema, name, nullable, defaultValue),
1443
+ members: [unionNode, sharedPropertiesNode]
1540
1444
  });
1541
1445
  }
1542
- /**
1543
- * Converts a format-annotated schema into a special-type `SchemaNode`.
1544
- * Returns `null` when the format should fall through to string handling (`dateType: false`).
1545
- */
1546
- function convertFormat({ schema, name, nullable, defaultValue, options }) {
1547
- const base = buildSchemaNode(schema, name, nullable, defaultValue);
1548
- if (schema.format === "int64") return _kubb_ast.ast.factory.createSchema({
1549
- type: options.integerType === "bigint" ? "bigint" : "integer",
1550
- primitive: "integer",
1446
+ const unionNode = _kubb_ast.ast.factory.createSchema({
1447
+ type: "union",
1448
+ ...unionBase,
1449
+ members: unionMembers.map((s) => parse({
1450
+ schema: s,
1451
+ name
1452
+ }, rawOptions))
1453
+ });
1454
+ return _kubb_ast.ast.applyMacros(unionNode, [_kubb_ast.macroSimplifyUnion], { depth: "shallow" });
1455
+ }
1456
+ /**
1457
+ * Converts an OAS 3.1 `const` schema into a null scalar or a single-value `EnumSchemaNode`.
1458
+ */
1459
+ function convertConst({ schema, name, nullable, defaultValue }) {
1460
+ const constValue = schema.const;
1461
+ if (constValue === null) return createNullNode(schema, name);
1462
+ const constPrimitive = getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string");
1463
+ return _kubb_ast.ast.factory.createSchema({
1464
+ type: "enum",
1465
+ primitive: constPrimitive,
1466
+ enumValues: [constValue],
1467
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1468
+ });
1469
+ }
1470
+ /**
1471
+ * Converts a format-annotated schema into a special-type `SchemaNode`.
1472
+ * Returns `null` when the format should fall through to string handling (`dateType: false`).
1473
+ */
1474
+ function convertFormat({ schema, name, nullable, defaultValue, options }) {
1475
+ const base = buildSchemaNode(schema, name, nullable, defaultValue);
1476
+ if (schema.format === "int64") return _kubb_ast.ast.factory.createSchema({
1477
+ type: options.integerType === "bigint" ? "bigint" : "integer",
1478
+ primitive: "integer",
1479
+ ...base,
1480
+ min: schema.minimum,
1481
+ max: schema.maximum,
1482
+ exclusiveMinimum: typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : void 0,
1483
+ exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0
1484
+ });
1485
+ if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") {
1486
+ const dateType = getDateType(options, schema.format);
1487
+ if (!dateType) return null;
1488
+ if (dateType.type === "datetime") return _kubb_ast.ast.factory.createSchema({
1551
1489
  ...base,
1552
- min: schema.minimum,
1553
- max: schema.maximum,
1554
- exclusiveMinimum: typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : void 0,
1555
- exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0
1490
+ primitive: "string",
1491
+ type: "datetime",
1492
+ offset: dateType.offset,
1493
+ local: dateType.local
1556
1494
  });
1557
- if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") {
1558
- const dateType = getDateType(options, schema.format);
1559
- if (!dateType) return null;
1560
- if (dateType.type === "datetime") return _kubb_ast.ast.factory.createSchema({
1561
- ...base,
1562
- primitive: "string",
1563
- type: "datetime",
1564
- offset: dateType.offset,
1565
- local: dateType.local
1566
- });
1567
- return _kubb_ast.ast.factory.createSchema({
1568
- ...base,
1569
- primitive: "string",
1570
- type: dateType.type,
1571
- representation: dateType.representation
1572
- });
1573
- }
1574
- const specialType = getSchemaType(schema.format);
1575
- if (!specialType) return null;
1576
- const specialPrimitive = specialType === "number" || specialType === "integer" || specialType === "bigint" ? specialType : "string";
1577
- const hasLength = specialType === "url" || specialType === "uuid" || specialType === "email";
1578
1495
  return _kubb_ast.ast.factory.createSchema({
1579
1496
  ...base,
1580
- primitive: specialPrimitive,
1581
- type: specialType,
1582
- ...hasLength ? {
1583
- min: schema.minLength,
1584
- max: schema.maxLength
1585
- } : {}
1497
+ primitive: "string",
1498
+ type: dateType.type,
1499
+ representation: dateType.representation
1586
1500
  });
1587
1501
  }
1588
- /**
1589
- * Converts an `enum` schema into an `EnumSchemaNode`.
1590
- */
1591
- function convertEnum({ schema, name, nullable, type, rawOptions }) {
1592
- if (type === "array") return parseSchema({
1593
- schema: normalizeArrayEnum(schema),
1594
- name
1595
- }, rawOptions);
1596
- const nullInEnum = schema.enum.includes(null);
1597
- const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
1598
- if (nullInEnum && filteredValues.length === 0) return createNullSchema(schema, name);
1599
- const enumNullable = nullable || nullInEnum || void 0;
1600
- const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
1601
- const enumPrimitive = getPrimitiveType(type);
1602
- const enumBase = {
1603
- type: "enum",
1604
- primitive: enumPrimitive,
1605
- ...buildSchemaNode(schema, name, enumNullable, enumDefault)
1606
- };
1607
- const extensionKey = enumExtensionKeys.find((key) => key in schema);
1608
- const descriptionKey = enumDescriptionKeys.find((key) => key in schema);
1609
- if (extensionKey || descriptionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
1610
- const enumPrimitiveType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
1611
- const rawEnumNames = extensionKey ? schema[extensionKey] : void 0;
1612
- const rawEnumDescriptions = descriptionKey ? schema[descriptionKey] : void 0;
1613
- const uniqueValues = [...new Set(filteredValues)];
1614
- const seenNames = /* @__PURE__ */ new Set();
1615
- return _kubb_ast.ast.factory.createSchema({
1616
- ...enumBase,
1617
- primitive: enumPrimitiveType,
1618
- namedEnumValues: uniqueValues.map((value, index) => ({
1619
- name: String(rawEnumNames?.[index] ?? value),
1620
- value,
1621
- primitive: enumPrimitiveType,
1622
- description: rawEnumDescriptions?.[index]
1623
- })).filter((entry) => {
1624
- if (seenNames.has(entry.name)) return false;
1625
- seenNames.add(entry.name);
1626
- return true;
1627
- })
1628
- });
1629
- }
1502
+ const specialType = getSchemaType(schema.format);
1503
+ if (!specialType) return null;
1504
+ const specialPrimitive = specialType === "number" || specialType === "integer" || specialType === "bigint" ? specialType : "string";
1505
+ const hasLength = specialType === "url" || specialType === "uuid" || specialType === "email";
1506
+ return _kubb_ast.ast.factory.createSchema({
1507
+ ...base,
1508
+ primitive: specialPrimitive,
1509
+ type: specialType,
1510
+ ...hasLength ? {
1511
+ min: schema.minLength,
1512
+ max: schema.maxLength
1513
+ } : {}
1514
+ });
1515
+ }
1516
+ /**
1517
+ * Converts an `enum` schema into an `EnumSchemaNode`.
1518
+ */
1519
+ function convertEnum({ schema, name, nullable, type, rawOptions, parse }) {
1520
+ if (type === "array") return parse({
1521
+ schema: normalizeArrayEnum(schema),
1522
+ name
1523
+ }, rawOptions);
1524
+ const nullInEnum = schema.enum.includes(null);
1525
+ const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
1526
+ if (nullInEnum && filteredValues.length === 0) return createNullNode(schema, name);
1527
+ const enumNullable = nullable || nullInEnum || void 0;
1528
+ const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
1529
+ const enumPrimitive = getPrimitiveType(type);
1530
+ const enumBase = {
1531
+ type: "enum",
1532
+ primitive: enumPrimitive,
1533
+ ...buildSchemaNode(schema, name, enumNullable, enumDefault)
1534
+ };
1535
+ const extensionKey = enumExtensionKeys.find((key) => key in schema);
1536
+ const descriptionKey = enumDescriptionKeys.find((key) => key in schema);
1537
+ if (extensionKey || descriptionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
1538
+ const enumPrimitiveType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
1539
+ const rawEnumNames = extensionKey ? schema[extensionKey] : void 0;
1540
+ const rawEnumDescriptions = descriptionKey ? schema[descriptionKey] : void 0;
1541
+ const uniqueValues = [...new Set(filteredValues)];
1542
+ const seenNames = /* @__PURE__ */ new Set();
1630
1543
  return _kubb_ast.ast.factory.createSchema({
1631
1544
  ...enumBase,
1632
- enumValues: [...new Set(filteredValues)]
1633
- });
1634
- }
1635
- /**
1636
- * Converts an object-like schema into an `ObjectSchemaNode`.
1637
- */
1638
- function convertObject({ schema, name, nullable, defaultValue, rawOptions, options }) {
1639
- const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1640
- const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1641
- const resolvedPropSchema = propSchema;
1642
- const propNullable = isNullable(resolvedPropSchema);
1643
- const schemaNode = nameEnums(parseSchema({
1644
- schema: resolvedPropSchema,
1645
- name: (0, _kubb_ast.childName)(name, propName)
1646
- }, rawOptions), {
1647
- parentName: name,
1648
- propName,
1649
- enumSuffix: options.enumSuffix
1650
- });
1651
- return _kubb_ast.ast.factory.createProperty({
1652
- name: propName,
1653
- schema: {
1654
- ...schemaNode,
1655
- nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0
1656
- },
1657
- required
1658
- });
1659
- }) : [];
1660
- const additionalProperties = schema.additionalProperties;
1661
- const additionalPropertiesNode = (() => {
1662
- if (additionalProperties === true) return true;
1663
- if (additionalProperties === false) return false;
1664
- if (additionalProperties && Object.keys(additionalProperties).length > 0) return parseSchema({ schema: additionalProperties }, rawOptions);
1665
- if (additionalProperties) return _kubb_ast.ast.factory.createSchema({ type: options.unknownType });
1666
- })();
1667
- const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1668
- const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? _kubb_ast.ast.factory.createSchema({ type: options.unknownType }) : parseSchema({ schema: patternSchema }, rawOptions)])) : void 0;
1669
- const objectNode = _kubb_ast.ast.factory.createSchema({
1670
- type: "object",
1671
- primitive: "object",
1672
- properties,
1673
- additionalProperties: additionalPropertiesNode,
1674
- patternProperties,
1675
- minProperties: schema.minProperties,
1676
- maxProperties: schema.maxProperties,
1677
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1678
- });
1679
- if (isDiscriminator(schema) && schema.discriminator.mapping) {
1680
- const discPropName = schema.discriminator.propertyName;
1681
- const values = Object.keys(schema.discriminator.mapping);
1682
- const enumName = name ? (0, _kubb_ast.enumPropName)(name, discPropName, options.enumSuffix) : void 0;
1683
- return _kubb_ast.ast.applyMacros(objectNode, [(0, _kubb_ast.macroDiscriminatorEnum)({
1684
- propertyName: discPropName,
1685
- values,
1686
- enumName
1687
- })], { depth: "shallow" });
1688
- }
1689
- return objectNode;
1690
- }
1691
- /**
1692
- * Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
1693
- */
1694
- function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
1695
- const tupleItems = (schema.prefixItems ?? []).map((item) => parseSchema({ schema: item }, rawOptions));
1696
- const rest = schema.items === false ? void 0 : !schema.items || schema.items === true ? _kubb_ast.ast.factory.createSchema({ type: "any" }) : parseSchema({ schema: schema.items }, rawOptions);
1697
- return _kubb_ast.ast.factory.createSchema({
1698
- type: "tuple",
1699
- primitive: "array",
1700
- items: tupleItems,
1701
- rest,
1702
- min: schema.minItems,
1703
- max: schema.maxItems,
1704
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1545
+ primitive: enumPrimitiveType,
1546
+ namedEnumValues: uniqueValues.map((value, index) => ({
1547
+ name: String(rawEnumNames?.[index] ?? value),
1548
+ value,
1549
+ primitive: enumPrimitiveType,
1550
+ description: rawEnumDescriptions?.[index]
1551
+ })).filter((entry) => {
1552
+ if (seenNames.has(entry.name)) return false;
1553
+ seenNames.add(entry.name);
1554
+ return true;
1555
+ })
1705
1556
  });
1706
1557
  }
1707
- /**
1708
- * Converts a `type: 'array'` schema into an `ArraySchemaNode`.
1709
- */
1710
- function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }) {
1711
- const rawItems = schema.items;
1712
- const itemName = rawItems?.enum?.length && name ? (0, _kubb_ast.enumPropName)(null, name, options.enumSuffix) : name;
1713
- const items = rawItems ? [parseSchema({
1714
- schema: rawItems,
1715
- name: itemName
1716
- }, rawOptions)] : [];
1717
- return _kubb_ast.ast.factory.createSchema({
1718
- type: "array",
1719
- primitive: "array",
1720
- items,
1721
- min: schema.minItems,
1722
- max: schema.maxItems,
1723
- unique: schema.uniqueItems ?? void 0,
1724
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1558
+ return _kubb_ast.ast.factory.createSchema({
1559
+ ...enumBase,
1560
+ enumValues: [...new Set(filteredValues)]
1561
+ });
1562
+ }
1563
+ /**
1564
+ * Converts an object-like schema into an `ObjectSchemaNode`.
1565
+ */
1566
+ function convertObject({ schema, name, nullable, defaultValue, rawOptions, options, parse }) {
1567
+ const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1568
+ const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1569
+ const resolvedPropSchema = propSchema;
1570
+ const propNullable = isNullable(resolvedPropSchema);
1571
+ const schemaNode = nameEnums(parse({
1572
+ schema: resolvedPropSchema,
1573
+ name: (0, _kubb_ast.childName)(name, propName)
1574
+ }, rawOptions), {
1575
+ parentName: name,
1576
+ propName,
1577
+ enumSuffix: options.enumSuffix
1725
1578
  });
1726
- }
1727
- /**
1728
- * Converts a `type: 'string'` schema into a `StringSchemaNode`.
1729
- */
1730
- function convertString({ schema, name, nullable, defaultValue }) {
1731
- return _kubb_ast.ast.factory.createSchema({
1732
- type: "string",
1733
- primitive: "string",
1734
- min: schema.minLength,
1735
- max: schema.maxLength,
1736
- pattern: schema.pattern,
1737
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1579
+ return _kubb_ast.ast.factory.createProperty({
1580
+ name: propName,
1581
+ schema: {
1582
+ ...schemaNode,
1583
+ nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0
1584
+ },
1585
+ required
1738
1586
  });
1587
+ }) : [];
1588
+ const additionalProperties = schema.additionalProperties;
1589
+ const additionalPropertiesNode = (() => {
1590
+ if (additionalProperties === true) return true;
1591
+ if (additionalProperties === false) return false;
1592
+ if (additionalProperties && Object.keys(additionalProperties).length > 0) return parse({ schema: additionalProperties }, rawOptions);
1593
+ if (additionalProperties) return _kubb_ast.ast.factory.createSchema({ type: options.unknownType });
1594
+ })();
1595
+ const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1596
+ const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? _kubb_ast.ast.factory.createSchema({ type: options.unknownType }) : parse({ schema: patternSchema }, rawOptions)])) : void 0;
1597
+ const objectNode = _kubb_ast.ast.factory.createSchema({
1598
+ type: "object",
1599
+ primitive: "object",
1600
+ properties,
1601
+ additionalProperties: additionalPropertiesNode,
1602
+ patternProperties,
1603
+ minProperties: schema.minProperties,
1604
+ maxProperties: schema.maxProperties,
1605
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1606
+ });
1607
+ if (isDiscriminator(schema) && schema.discriminator.mapping) {
1608
+ const discPropName = schema.discriminator.propertyName;
1609
+ const values = Object.keys(schema.discriminator.mapping);
1610
+ const enumName = name ? (0, _kubb_ast.enumPropName)(name, discPropName, options.enumSuffix) : void 0;
1611
+ return _kubb_ast.ast.applyMacros(objectNode, [(0, _kubb_ast.macroDiscriminatorEnum)({
1612
+ propertyName: discPropName,
1613
+ values,
1614
+ enumName
1615
+ })], { depth: "shallow" });
1739
1616
  }
1740
- /**
1741
- * Converts a `type: 'number'` or `type: 'integer'` schema.
1742
- */
1743
- function convertNumeric({ schema, name, nullable, defaultValue }, type) {
1744
- return _kubb_ast.ast.factory.createSchema({
1745
- type,
1746
- primitive: type,
1747
- min: schema.minimum,
1748
- max: schema.maximum,
1749
- exclusiveMinimum: typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : void 0,
1750
- exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0,
1751
- multipleOf: schema.multipleOf,
1752
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1753
- });
1617
+ return objectNode;
1618
+ }
1619
+ /**
1620
+ * Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
1621
+ */
1622
+ function convertTuple({ schema, name, nullable, defaultValue, rawOptions, parse }) {
1623
+ const tupleItems = (schema.prefixItems ?? []).map((item) => parse({ schema: item }, rawOptions));
1624
+ const rest = schema.items === false ? void 0 : !schema.items || schema.items === true ? _kubb_ast.ast.factory.createSchema({ type: "any" }) : parse({ schema: schema.items }, rawOptions);
1625
+ return _kubb_ast.ast.factory.createSchema({
1626
+ type: "tuple",
1627
+ primitive: "array",
1628
+ items: tupleItems,
1629
+ rest,
1630
+ min: schema.minItems,
1631
+ max: schema.maxItems,
1632
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1633
+ });
1634
+ }
1635
+ /**
1636
+ * Converts a `type: 'array'` schema into an `ArraySchemaNode`.
1637
+ */
1638
+ function convertArray({ schema, name, nullable, defaultValue, rawOptions, options, parse }) {
1639
+ const rawItems = schema.items;
1640
+ const itemName = rawItems?.enum?.length && name ? (0, _kubb_ast.enumPropName)(null, name, options.enumSuffix) : name;
1641
+ const items = rawItems ? [parse({
1642
+ schema: rawItems,
1643
+ name: itemName
1644
+ }, rawOptions)] : [];
1645
+ return _kubb_ast.ast.factory.createSchema({
1646
+ type: "array",
1647
+ primitive: "array",
1648
+ items,
1649
+ min: schema.minItems,
1650
+ max: schema.maxItems,
1651
+ unique: schema.uniqueItems ?? void 0,
1652
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1653
+ });
1654
+ }
1655
+ /**
1656
+ * Converts a `type: 'string'` schema into a `StringSchemaNode`.
1657
+ */
1658
+ function convertString({ schema, name, nullable, defaultValue }) {
1659
+ return _kubb_ast.ast.factory.createSchema({
1660
+ type: "string",
1661
+ primitive: "string",
1662
+ min: schema.minLength,
1663
+ max: schema.maxLength,
1664
+ pattern: schema.pattern,
1665
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1666
+ });
1667
+ }
1668
+ /**
1669
+ * Converts a `type: 'number'` or `type: 'integer'` schema.
1670
+ */
1671
+ function convertNumeric({ schema, name, nullable, defaultValue }, type) {
1672
+ return _kubb_ast.ast.factory.createSchema({
1673
+ type,
1674
+ primitive: type,
1675
+ min: schema.minimum,
1676
+ max: schema.maximum,
1677
+ exclusiveMinimum: typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : void 0,
1678
+ exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0,
1679
+ multipleOf: schema.multipleOf,
1680
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1681
+ });
1682
+ }
1683
+ /**
1684
+ * Converts a `type: 'boolean'` schema.
1685
+ */
1686
+ function convertBoolean({ schema, name, nullable, defaultValue }) {
1687
+ return _kubb_ast.ast.factory.createSchema({
1688
+ type: "boolean",
1689
+ primitive: "boolean",
1690
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1691
+ });
1692
+ }
1693
+ /**
1694
+ * Converts a binary string schema (`type: 'string'`, `contentMediaType: 'application/octet-stream'`)
1695
+ * into a `blob` node.
1696
+ */
1697
+ function convertBinary({ schema, name, nullable, defaultValue }) {
1698
+ return _kubb_ast.ast.factory.createSchema({
1699
+ type: "blob",
1700
+ primitive: "string",
1701
+ ...buildSchemaNode(schema, name, nullable, defaultValue)
1702
+ });
1703
+ }
1704
+ /**
1705
+ * Converts an OAS 3.1 multi-type array (e.g. `type: ['string', 'number']`) into a `UnionSchemaNode`.
1706
+ *
1707
+ * Returns `null` when only one non-`null` type remains (e.g. `['string', 'null']`), so `parse`
1708
+ * falls through and handles it as that single type with nullability already folded in.
1709
+ */
1710
+ function convertMultiType({ schema, name, nullable, defaultValue, rawOptions, parse }) {
1711
+ const types = schema.type;
1712
+ const nonNullTypes = types.filter((t) => t !== "null");
1713
+ if (nonNullTypes.length <= 1) return null;
1714
+ const arrayNullable = types.includes("null") || nullable || void 0;
1715
+ return _kubb_ast.ast.factory.createSchema({
1716
+ type: "union",
1717
+ members: nonNullTypes.map((t) => {
1718
+ return parse({
1719
+ schema: {
1720
+ ...schema,
1721
+ type: t
1722
+ },
1723
+ name
1724
+ }, rawOptions);
1725
+ }),
1726
+ ...buildSchemaNode(schema, name, arrayNullable, defaultValue)
1727
+ });
1728
+ }
1729
+ /**
1730
+ * Ordered schema rule table. Order is significant: composition keywords (`$ref`, `allOf`,
1731
+ * `oneOf`/`anyOf`) take precedence over `const`/`format`, which take precedence over the plain
1732
+ * `type`. The first matching rule that produces a node wins. See {@link SchemaRule} for the
1733
+ * match/convert/fall-through contract.
1734
+ */
1735
+ const schemaRules = [
1736
+ {
1737
+ match: ({ schema }) => isReference(schema),
1738
+ convert: convertRef
1739
+ },
1740
+ {
1741
+ match: ({ schema }) => !!schema.allOf?.length,
1742
+ convert: convertAllOf
1743
+ },
1744
+ {
1745
+ match: ({ schema }) => !!(schema.oneOf?.length || schema.anyOf?.length),
1746
+ convert: convertUnion
1747
+ },
1748
+ {
1749
+ match: ({ schema }) => "const" in schema && schema.const !== void 0,
1750
+ convert: convertConst
1751
+ },
1752
+ {
1753
+ match: ({ schema }) => !!schema.format,
1754
+ convert: convertFormat
1755
+ },
1756
+ {
1757
+ match: ({ schema }) => isBinary(schema),
1758
+ convert: convertBinary
1759
+ },
1760
+ {
1761
+ match: ({ schema }) => Array.isArray(schema.type) && schema.type.length > 1,
1762
+ convert: convertMultiType
1763
+ },
1764
+ {
1765
+ match: ({ schema, type }) => !type && (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern !== void 0),
1766
+ convert: convertString
1767
+ },
1768
+ {
1769
+ match: ({ schema, type }) => !type && (schema.minimum !== void 0 || schema.maximum !== void 0),
1770
+ convert: (ctx) => convertNumeric(ctx, "number")
1771
+ },
1772
+ {
1773
+ match: ({ schema }) => !!schema.enum?.length,
1774
+ convert: convertEnum
1775
+ },
1776
+ {
1777
+ match: ({ schema, type }) => type === "object" || !!schema.properties || !!schema.additionalProperties || "patternProperties" in schema,
1778
+ convert: convertObject
1779
+ },
1780
+ {
1781
+ match: ({ schema }) => "prefixItems" in schema,
1782
+ convert: convertTuple
1783
+ },
1784
+ {
1785
+ match: ({ schema, type }) => type === "array" || "items" in schema,
1786
+ convert: convertArray
1787
+ },
1788
+ {
1789
+ match: ({ type }) => type === "string",
1790
+ convert: convertString
1791
+ },
1792
+ {
1793
+ match: ({ type }) => type === "number",
1794
+ convert: (ctx) => convertNumeric(ctx, "number")
1795
+ },
1796
+ {
1797
+ match: ({ type }) => type === "integer",
1798
+ convert: (ctx) => convertNumeric(ctx, "integer")
1799
+ },
1800
+ {
1801
+ match: ({ type }) => type === "boolean",
1802
+ convert: convertBoolean
1803
+ },
1804
+ {
1805
+ match: ({ type }) => type === "null",
1806
+ convert: ({ schema, name, nullable }) => createNullNode(schema, name, nullable)
1754
1807
  }
1808
+ ];
1809
+ //#endregion
1810
+ //#region src/parser.ts
1811
+ /**
1812
+ * Creates the schema and operation converters bound to one OpenAPI document.
1813
+ *
1814
+ * Owns the per-instance `$ref` state (cycle detection, resolved-node cache, existence cache) and
1815
+ * the `parseSchema` recursion seam, then dispatches each schema through the ordered `schemaRules`
1816
+ * table from `converters.ts`. Every converter is a standalone function that recurses through the
1817
+ * `parse` function passed to it, so this file only wires state to the converters.
1818
+ *
1819
+ * @internal
1820
+ */
1821
+ function createSchemaParser(ctx) {
1822
+ const document = ctx.document;
1755
1823
  /**
1756
- * Converts a `type: 'boolean'` schema.
1824
+ * Tracks `$ref` paths that are currently being resolved to prevent infinite
1825
+ * recursion when schemas contain circular references (e.g. `Pet → parent → Pet`).
1757
1826
  */
1758
- function convertBoolean({ schema, name, nullable, defaultValue }) {
1759
- return _kubb_ast.ast.factory.createSchema({
1760
- type: "boolean",
1761
- primitive: "boolean",
1762
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1763
- });
1764
- }
1827
+ const resolvingRefs = /* @__PURE__ */ new Set();
1765
1828
  /**
1766
- * Converts a binary string schema (`type: 'string'`, `contentMediaType: 'application/octet-stream'`)
1767
- * into a `blob` node.
1829
+ * Cache of `$ref` schemas already resolved in this parser instance, keyed by ref path.
1830
+ *
1831
+ * Without it, a shared schema (e.g. `customer`) is re-expanded for every `$ref` that points at
1832
+ * it. In cross-referenced specs like Stripe (~1400 schemas) that becomes exponential blowup,
1833
+ * since one schema can be referenced from dozens of parents, each re-walking its whole subtree.
1834
+ * Memoizing by ref path drops the work from O(2^depth) to O(N) unique schema names.
1768
1835
  */
1769
- function convertBlob({ schema, name, nullable, defaultValue }) {
1770
- return _kubb_ast.ast.factory.createSchema({
1771
- type: "blob",
1772
- primitive: "string",
1773
- ...buildSchemaNode(schema, name, nullable, defaultValue)
1774
- });
1775
- }
1836
+ const resolvedRefCache = /* @__PURE__ */ new Map();
1776
1837
  /**
1777
- * Converts an OAS 3.1 multi-type array (e.g. `type: ['string', 'number']`) into a `UnionSchemaNode`.
1778
- *
1779
- * Returns `null` when only one non-`null` type remains (e.g. `['string', 'null']`), so `parseSchema`
1780
- * falls through and handles it as that single type with nullability already folded in.
1838
+ * Memoized record of whether a `$ref` path resolves to a node the document actually defines.
1839
+ * A circular ref still resolves to an existing target, so this stays `true` for cycles and only
1840
+ * goes `false` for a `$ref` that points at a component the spec never declares.
1781
1841
  */
1782
- function convertMultiType({ schema, name, nullable, defaultValue, rawOptions }) {
1783
- const types = schema.type;
1784
- const nonNullTypes = types.filter((t) => t !== "null");
1785
- if (nonNullTypes.length <= 1) return null;
1786
- const arrayNullable = types.includes("null") || nullable || void 0;
1787
- return _kubb_ast.ast.factory.createSchema({
1788
- type: "union",
1789
- members: nonNullTypes.map((t) => parseSchema({
1790
- schema: {
1791
- ...schema,
1792
- type: t
1793
- },
1794
- name
1795
- }, rawOptions)),
1796
- ...buildSchemaNode(schema, name, arrayNullable, defaultValue)
1797
- });
1842
+ const refExistence = /* @__PURE__ */ new Map();
1843
+ function refExists(refPath) {
1844
+ if (!refExistence.has(refPath)) {
1845
+ let exists = false;
1846
+ try {
1847
+ exists = !!resolveRef(document, refPath);
1848
+ } catch {
1849
+ exists = false;
1850
+ }
1851
+ refExistence.set(refPath, exists);
1852
+ }
1853
+ return refExistence.get(refPath) ?? false;
1798
1854
  }
1799
1855
  /**
1800
- * Ordered schema rule table. Order is significant: composition keywords (`$ref`, `allOf`,
1801
- * `oneOf`/`anyOf`) take precedence over `const`/`format`, which take precedence over the plain
1802
- * `type`. The first matching rule that produces a node wins. See {@link SchemaRule} for the
1803
- * match/convert/fall-through contract.
1856
+ * Resolves a `$ref` to its parsed node, guarding against cycles and memoizing per instance.
1857
+ * Returns `null` when the ref is currently being resolved (a cycle) or cannot be resolved
1858
+ * (e.g. a minimal document in a unit test).
1804
1859
  */
1805
- const schemaRules = [
1806
- {
1807
- match: ({ schema }) => isReference(schema),
1808
- convert: convertRef
1809
- },
1810
- {
1811
- match: ({ schema }) => !!schema.allOf?.length,
1812
- convert: convertAllOf
1813
- },
1814
- {
1815
- match: ({ schema }) => !!(schema.oneOf?.length || schema.anyOf?.length),
1816
- convert: convertUnion
1817
- },
1818
- {
1819
- match: ({ schema }) => "const" in schema && schema.const !== void 0,
1820
- convert: convertConst
1821
- },
1822
- {
1823
- match: ({ schema }) => !!schema.format,
1824
- convert: convertFormat
1825
- },
1826
- {
1827
- match: ({ schema }) => isBinary(schema),
1828
- convert: convertBlob
1829
- },
1830
- {
1831
- match: ({ schema }) => Array.isArray(schema.type) && schema.type.length > 1,
1832
- convert: convertMultiType
1833
- },
1834
- {
1835
- match: ({ schema, type }) => !type && (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern !== void 0),
1836
- convert: convertString
1837
- },
1838
- {
1839
- match: ({ schema, type }) => !type && (schema.minimum !== void 0 || schema.maximum !== void 0),
1840
- convert: (ctx) => convertNumeric(ctx, "number")
1841
- },
1842
- {
1843
- match: ({ schema }) => !!schema.enum?.length,
1844
- convert: convertEnum
1845
- },
1846
- {
1847
- match: ({ schema, type }) => type === "object" || !!schema.properties || !!schema.additionalProperties || "patternProperties" in schema,
1848
- convert: convertObject
1849
- },
1850
- {
1851
- match: ({ schema }) => "prefixItems" in schema,
1852
- convert: convertTuple
1853
- },
1854
- {
1855
- match: ({ schema, type }) => type === "array" || "items" in schema,
1856
- convert: convertArray
1857
- },
1858
- {
1859
- match: ({ type }) => type === "string",
1860
- convert: convertString
1861
- },
1862
- {
1863
- match: ({ type }) => type === "number",
1864
- convert: (ctx) => convertNumeric(ctx, "number")
1865
- },
1866
- {
1867
- match: ({ type }) => type === "integer",
1868
- convert: (ctx) => convertNumeric(ctx, "integer")
1869
- },
1870
- {
1871
- match: ({ type }) => type === "boolean",
1872
- convert: convertBoolean
1873
- },
1874
- {
1875
- match: ({ type }) => type === "null",
1876
- convert: ({ schema, name, nullable }) => createNullSchema(schema, name, nullable)
1860
+ function resolveRefNode(refPath, rawOptions) {
1861
+ if (resolvingRefs.has(refPath)) return null;
1862
+ if (!resolvedRefCache.has(refPath)) {
1863
+ let resolved = null;
1864
+ try {
1865
+ const referenced = resolveRef(document, refPath);
1866
+ if (referenced) {
1867
+ resolvingRefs.add(refPath);
1868
+ resolved = parseSchema({ schema: referenced }, rawOptions);
1869
+ resolvingRefs.delete(refPath);
1870
+ }
1871
+ } catch {}
1872
+ resolvedRefCache.set(refPath, resolved);
1877
1873
  }
1878
- ];
1874
+ return resolvedRefCache.get(refPath) ?? null;
1875
+ }
1879
1876
  /**
1880
1877
  * Converts an OAS `SchemaObject` into a `SchemaNode`.
1881
1878
  *
@@ -1894,18 +1891,23 @@ function createSchemaParser(ctx) {
1894
1891
  name
1895
1892
  }, rawOptions);
1896
1893
  const nullable = isNullable(schema) || void 0;
1897
- const schemaCtx = {
1894
+ const context = {
1898
1895
  schema,
1899
1896
  name,
1900
1897
  nullable,
1901
1898
  defaultValue: schema.default === null && nullable ? void 0 : schema.default,
1902
1899
  type: Array.isArray(schema.type) ? schema.type[0] : schema.type,
1903
1900
  rawOptions,
1904
- options
1901
+ options,
1902
+ parse: parseSchema,
1903
+ document,
1904
+ resolveRefNode,
1905
+ refExists,
1906
+ renames: ctx.renames
1905
1907
  };
1906
1908
  for (const rule of schemaRules) {
1907
- if (!rule.match(schemaCtx)) continue;
1908
- const node = rule.convert(schemaCtx);
1909
+ if (!rule.match(context)) continue;
1910
+ const node = rule.convert(context);
1909
1911
  if (node) return node;
1910
1912
  }
1911
1913
  const emptyType = options.emptySchemaType;
@@ -2202,7 +2204,6 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
2202
2204
  emptySchemaType,
2203
2205
  enumSuffix
2204
2206
  };
2205
- let nameMapping = /* @__PURE__ */ new Map();
2206
2207
  let parsedDocument = null;
2207
2208
  const documentCache = /* @__PURE__ */ new WeakMap();
2208
2209
  const schemasCache = /* @__PURE__ */ new WeakMap();
@@ -2223,16 +2224,16 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
2223
2224
  const cached = schemasCache.get(document);
2224
2225
  if (cached) return cached;
2225
2226
  const result = getSchemas(document, { contentType });
2226
- nameMapping = result.nameMapping;
2227
- schemasCache.set(document, result.schemas);
2228
- return result.schemas;
2227
+ schemasCache.set(document, result);
2228
+ return result;
2229
2229
  }
2230
- function ensureSchemaParser(document) {
2230
+ function ensureSchemaParser({ document, renames }) {
2231
2231
  const cached = schemaParserCache.get(document);
2232
2232
  if (cached) return cached;
2233
2233
  const parser = createSchemaParser({
2234
2234
  document,
2235
- contentType
2235
+ contentType,
2236
+ renames
2236
2237
  });
2237
2238
  schemaParserCache.set(document, parser);
2238
2239
  return parser;
@@ -2314,8 +2315,7 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
2314
2315
  integerType,
2315
2316
  unknownType,
2316
2317
  emptySchemaType,
2317
- enumSuffix,
2318
- nameMapping
2318
+ enumSuffix
2319
2319
  };
2320
2320
  },
2321
2321
  get document() {
@@ -2325,24 +2325,16 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
2325
2325
  await assertInputExists(input);
2326
2326
  await validateDocument(await parseDocument(input), options);
2327
2327
  },
2328
- getImports(node, resolve) {
2329
- return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
2330
- const schemaRef = (0, _kubb_ast.narrowSchema)(schemaNode, "ref");
2331
- if (!schemaRef?.ref) return null;
2332
- const result = resolve(nameMapping.get(schemaRef.ref) ?? (0, _kubb_ast.extractRefName)(schemaRef.ref));
2333
- if (!result) return null;
2334
- return _kubb_ast.ast.factory.createImport({
2335
- name: [result.name],
2336
- path: result.path
2337
- });
2338
- } });
2339
- },
2340
2328
  async parse(source) {
2341
2329
  const document = await ensureDocument(source);
2330
+ const { schemas, renames } = ensureSchemas(document);
2342
2331
  return parseInput({
2343
2332
  document,
2344
- schemas: ensureSchemas(document),
2345
- parser: ensureSchemaParser(document)
2333
+ schemas,
2334
+ parser: ensureSchemaParser({
2335
+ document,
2336
+ renames
2337
+ })
2346
2338
  });
2347
2339
  }
2348
2340
  };