@kubb/adapter-oas 5.0.0-alpha.1 → 5.0.0-alpha.11

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
@@ -39,6 +39,110 @@ jsonpointer = __toESM(jsonpointer);
39
39
  let oas = require("oas");
40
40
  oas = __toESM(oas);
41
41
  let oas_utils = require("oas/utils");
42
+ //#region src/constants.ts
43
+ /**
44
+ * Default values for all `Options` fields.
45
+ */
46
+ const DEFAULT_PARSER_OPTIONS = {
47
+ dateType: "string",
48
+ integerType: "number",
49
+ unknownType: "any",
50
+ emptySchemaType: "any",
51
+ enumSuffix: "enum"
52
+ };
53
+ /**
54
+ * OpenAPI version string written into merged document stubs.
55
+ */
56
+ const MERGE_OPENAPI_VERSION = "3.0.0";
57
+ /**
58
+ * Fallback `info.title` used when merging multiple API documents.
59
+ */
60
+ const MERGE_DEFAULT_TITLE = "Merged API";
61
+ /**
62
+ * Fallback `info.version` used when merging multiple API documents.
63
+ */
64
+ const MERGE_DEFAULT_VERSION = "1.0.0";
65
+ /**
66
+ * JSON Schema keywords that indicate structural composition.
67
+ * A schema fragment containing any of these keys must not be inlined into its
68
+ * parent during `allOf` flattening — it carries semantic meaning of its own.
69
+ */
70
+ const structuralKeys = new Set([
71
+ "properties",
72
+ "items",
73
+ "additionalProperties",
74
+ "oneOf",
75
+ "anyOf",
76
+ "allOf",
77
+ "not"
78
+ ]);
79
+ /**
80
+ * Maps OAS/JSON Schema `format` strings to their Kubb `SchemaType` equivalents.
81
+ *
82
+ * Only formats that need a type different from the raw OAS `type` are listed.
83
+ * `int64`, `date-time`, `date`, and `time` are handled separately because their
84
+ * mapping depends on runtime parser options.
85
+ *
86
+ * Note: `ipv4`, `ipv6`, and `hostname` map to `'url'` — the closest supported
87
+ * scalar type in the Kubb AST, even though these are not strictly URLs.
88
+ */
89
+ const formatMap = {
90
+ uuid: "uuid",
91
+ email: "email",
92
+ "idn-email": "email",
93
+ uri: "url",
94
+ "uri-reference": "url",
95
+ url: "url",
96
+ ipv4: "url",
97
+ ipv6: "url",
98
+ hostname: "url",
99
+ "idn-hostname": "url",
100
+ binary: "blob",
101
+ byte: "blob",
102
+ int32: "integer",
103
+ float: "number",
104
+ double: "number"
105
+ };
106
+ /**
107
+ * Exhaustive list of media types that Kubb recognizes.
108
+ */
109
+ const knownMediaTypes = new Set([
110
+ "application/json",
111
+ "application/xml",
112
+ "application/x-www-form-urlencoded",
113
+ "application/octet-stream",
114
+ "application/pdf",
115
+ "application/zip",
116
+ "application/graphql",
117
+ "multipart/form-data",
118
+ "text/plain",
119
+ "text/html",
120
+ "text/csv",
121
+ "text/xml",
122
+ "image/png",
123
+ "image/jpeg",
124
+ "image/gif",
125
+ "image/webp",
126
+ "image/svg+xml",
127
+ "audio/mpeg",
128
+ "video/mp4"
129
+ ]);
130
+ /**
131
+ * Vendor extension keys used to attach human-readable labels to enum values.
132
+ * Checked in priority order: the first key found wins.
133
+ */
134
+ const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
135
+ /**
136
+ * Scalar primitive schema types used for union member simplification.
137
+ */
138
+ const SCALAR_PRIMITIVE_TYPES = new Set([
139
+ "string",
140
+ "number",
141
+ "integer",
142
+ "bigint",
143
+ "boolean"
144
+ ]);
145
+ //#endregion
42
146
  //#region src/oas/resolveServerUrl.ts
43
147
  /**
44
148
  * Resolves an OpenAPI server URL by substituting `{variable}` placeholders.
@@ -117,6 +221,27 @@ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
117
221
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
118
222
  }
119
223
  //#endregion
224
+ //#region ../../internals/utils/src/names.ts
225
+ /**
226
+ * Returns a unique name by appending an incrementing numeric suffix when the name has already been used.
227
+ * Mutates `data` in-place as a usage counter so subsequent calls remain consistent.
228
+ *
229
+ * @example
230
+ * const seen: Record<string, number> = {}
231
+ * getUniqueName('Foo', seen) // 'Foo'
232
+ * getUniqueName('Foo', seen) // 'Foo2'
233
+ * getUniqueName('Foo', seen) // 'Foo3'
234
+ */
235
+ function getUniqueName(originalName, data) {
236
+ let used = data[originalName] || 0;
237
+ if (used) {
238
+ data[originalName] = ++used;
239
+ originalName += used;
240
+ }
241
+ data[originalName] = 1;
242
+ return originalName;
243
+ }
244
+ //#endregion
120
245
  //#region ../../internals/utils/src/reserved.ts
121
246
  /**
122
247
  * Returns `true` when `name` is a syntactically valid JavaScript variable name.
@@ -233,91 +358,6 @@ var URLPath = class {
233
358
  }
234
359
  };
235
360
  //#endregion
236
- //#region src/constants.ts
237
- /**
238
- * OpenAPI version string written into merged document stubs.
239
- */
240
- const MERGE_OPENAPI_VERSION = "3.0.0";
241
- /**
242
- * Fallback `info.title` used when merging multiple API documents.
243
- */
244
- const MERGE_DEFAULT_TITLE = "Merged API";
245
- /**
246
- * Fallback `info.version` used when merging multiple API documents.
247
- */
248
- const MERGE_DEFAULT_VERSION = "1.0.0";
249
- /**
250
- * JSON Schema keywords that indicate structural composition.
251
- * A schema fragment containing any of these keys must not be inlined into its
252
- * parent during `allOf` flattening — it carries semantic meaning of its own.
253
- */
254
- const structuralKeys = new Set([
255
- "properties",
256
- "items",
257
- "additionalProperties",
258
- "oneOf",
259
- "anyOf",
260
- "allOf",
261
- "not"
262
- ]);
263
- /**
264
- * Maps OAS/JSON Schema `format` strings to their Kubb `SchemaType` equivalents.
265
- *
266
- * Only formats that need a type different from the raw OAS `type` are listed.
267
- * `int64`, `date-time`, `date`, and `time` are handled separately because their
268
- * mapping depends on runtime parser options.
269
- *
270
- * Note: `ipv4`, `ipv6`, and `hostname` map to `'url'` — the closest supported
271
- * scalar type in the Kubb AST, even though these are not strictly URLs.
272
- */
273
- const formatMap = {
274
- uuid: "uuid",
275
- email: "email",
276
- "idn-email": "email",
277
- uri: "url",
278
- "uri-reference": "url",
279
- url: "url",
280
- ipv4: "url",
281
- ipv6: "url",
282
- hostname: "url",
283
- "idn-hostname": "url",
284
- binary: "blob",
285
- byte: "blob",
286
- int32: "integer",
287
- float: "number",
288
- double: "number"
289
- };
290
- /**
291
- * Exhaustive list of media types that Kubb recognizes.
292
- * Kept as a module-level constant to avoid re-allocating the array on every call.
293
- */
294
- const knownMediaTypes = [
295
- "application/json",
296
- "application/xml",
297
- "application/x-www-form-urlencoded",
298
- "application/octet-stream",
299
- "application/pdf",
300
- "application/zip",
301
- "application/graphql",
302
- "multipart/form-data",
303
- "text/plain",
304
- "text/html",
305
- "text/csv",
306
- "text/xml",
307
- "image/png",
308
- "image/jpeg",
309
- "image/gif",
310
- "image/webp",
311
- "image/svg+xml",
312
- "audio/mpeg",
313
- "video/mp4"
314
- ];
315
- /**
316
- * Vendor extension keys used to attach human-readable labels to enum values.
317
- * Checked in priority order: the first key found wins.
318
- */
319
- const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
320
- //#endregion
321
361
  //#region src/oas/Oas.ts
322
362
  /**
323
363
  * Prefix used to create synthetic `$ref` values for anonymous (inline) discriminator schemas.
@@ -529,8 +569,15 @@ var Oas = class extends oas.default {
529
569
  if (!schema) return;
530
570
  return this.dereferenceWithRef(schema);
531
571
  }
532
- getParametersSchema(operation, inKey) {
533
- const { contentType = operation.getContentType() } = this.#options;
572
+ /**
573
+ * Returns all resolved parameters for an operation, merging path-level and operation-level
574
+ * parameters and deduplicating by `in:name` (operation-level takes precedence).
575
+ *
576
+ * oas v31+ filters out `$ref` parameters in `getParameters()`, so this method accesses the
577
+ * raw `operation.schema.parameters` and path-item parameters directly and resolves `$ref`
578
+ * pointers via `dereferenceWithRef` to preserve backward compatibility.
579
+ */
580
+ getParameters(operation) {
534
581
  const resolveParams = (params) => params.map((p) => this.dereferenceWithRef(p)).filter((p) => !!p && typeof p === "object" && "in" in p && "name" in p);
535
582
  const operationParams = resolveParams(operation.schema?.parameters || []);
536
583
  const pathItem = this.api?.paths?.[operation.path];
@@ -538,7 +585,11 @@ var Oas = class extends oas.default {
538
585
  const paramMap = /* @__PURE__ */ new Map();
539
586
  for (const p of pathLevelParams) if (p.name && p.in) paramMap.set(`${p.in}:${p.name}`, p);
540
587
  for (const p of operationParams) if (p.name && p.in) paramMap.set(`${p.in}:${p.name}`, p);
541
- const params = Array.from(paramMap.values()).filter((v) => v.in === inKey);
588
+ return Array.from(paramMap.values());
589
+ }
590
+ getParametersSchema(operation, inKey) {
591
+ const { contentType = operation.getContentType() } = this.#options;
592
+ const params = this.getParameters(operation).filter((v) => v.in === inKey);
542
593
  if (!params.length) return null;
543
594
  return params.reduce((schema, pathParameters) => {
544
595
  const property = pathParameters.content?.[contentType]?.schema ?? pathParameters.schema;
@@ -928,17 +979,137 @@ function resolveCollisions(schemasWithMeta) {
928
979
  };
929
980
  }
930
981
  //#endregion
931
- //#region src/parser.ts
982
+ //#region src/utils.ts
932
983
  /**
933
- * Default values for all `Options` fields.
984
+ * Extracts the schema name from a `$ref` string.
985
+ * For `#/components/schemas/Order` this returns `'Order'`.
986
+ * Falls back to the full ref string when no slash is present.
934
987
  */
935
- const DEFAULT_OPTIONS = {
936
- dateType: "string",
937
- integerType: "number",
938
- unknownType: "any",
939
- emptySchemaType: "any",
940
- enumSuffix: "enum"
941
- };
988
+ function extractRefName($ref) {
989
+ return $ref.split("/").at(-1) ?? $ref;
990
+ }
991
+ /**
992
+ * Replaces the discriminator property's schema inside an `ObjectSchemaNode`
993
+ * with an enum of the given `values`.
994
+ *
995
+ * - When `enumName` is provided the enum is named, which lets printers emit a
996
+ * standalone enum declaration + type reference (e.g. `PetTypeEnum`).
997
+ * - When `enumName` is omitted the enum stays anonymous, so printers inline it
998
+ * as a literal union (e.g. `'dog'`).
999
+ *
1000
+ * Returns the node unchanged when it is not an object or lacks the target property.
1001
+ */
1002
+ function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
1003
+ if (node.type !== "object" || !node.properties?.length) return node;
1004
+ if (!node.properties.some((prop) => prop.name === propertyName)) return node;
1005
+ return (0, _kubb_ast.createSchema)({
1006
+ ...node,
1007
+ properties: node.properties.map((prop) => {
1008
+ if (prop.name !== propertyName) return prop;
1009
+ const enumSchema = (0, _kubb_ast.createSchema)({
1010
+ type: "enum",
1011
+ primitive: "string",
1012
+ enumValues: values,
1013
+ name: enumName,
1014
+ readOnly: prop.schema.readOnly,
1015
+ writeOnly: prop.schema.writeOnly
1016
+ });
1017
+ return (0, _kubb_ast.createProperty)({
1018
+ ...prop,
1019
+ schema: enumSchema
1020
+ });
1021
+ })
1022
+ });
1023
+ }
1024
+ /**
1025
+ * Merges consecutive anonymous (`name`-less) `ObjectSchemaNode`s in `members` into a
1026
+ * single object by combining their `properties` arrays.
1027
+ *
1028
+ * Only adjacent pairs are merged — non-object or named nodes act as boundaries.
1029
+ * This collapses patterns like `Address & { streetNumber } & { streetName }` into
1030
+ * `Address & { streetNumber; streetName }`.
1031
+ */
1032
+ function mergeAdjacentAnonymousObjects(members) {
1033
+ return members.reduce((acc, member) => {
1034
+ const obj = (0, _kubb_ast.narrowSchema)(member, "object");
1035
+ if (obj && !obj.name) {
1036
+ const prev = acc[acc.length - 1];
1037
+ const prevObj = prev ? (0, _kubb_ast.narrowSchema)(prev, "object") : null;
1038
+ if (prevObj && !prevObj.name) {
1039
+ acc[acc.length - 1] = (0, _kubb_ast.createSchema)({
1040
+ ...prevObj,
1041
+ properties: [...prevObj.properties ?? [], ...obj.properties ?? []]
1042
+ });
1043
+ return acc;
1044
+ }
1045
+ }
1046
+ acc.push(member);
1047
+ return acc;
1048
+ }, []);
1049
+ }
1050
+ /**
1051
+ * Simplifies a union member list by removing `enum` nodes whose `primitive` type is
1052
+ * already represented by a broader scalar node in the same union.
1053
+ *
1054
+ * For example `['placed', 'approved'] | string` collapses to `string` because
1055
+ * `string` subsumes all string literals. `'' | string` similarly becomes `string`.
1056
+ *
1057
+ * Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
1058
+ * considered — object, array, and ref members are left untouched.
1059
+ *
1060
+ * Const-derived enums (those without an `enumType`, produced from an OpenAPI `const`
1061
+ * keyword) are **never** removed — `'accepted' | string` must stay as-is because the
1062
+ * literal is intentional.
1063
+ */
1064
+ function simplifyUnionMembers(members) {
1065
+ const scalarPrimitives = new Set(members.filter((m) => SCALAR_PRIMITIVE_TYPES.has(m.type)).map((m) => m.type));
1066
+ if (!scalarPrimitives.size) return members;
1067
+ return members.filter((m) => {
1068
+ if (m.type !== "enum") return true;
1069
+ const prim = m.primitive;
1070
+ if (!prim) return true;
1071
+ if (!m.enumType) return true;
1072
+ if (scalarPrimitives.has(prim)) return false;
1073
+ if ((prim === "integer" || prim === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
1074
+ return true;
1075
+ });
1076
+ }
1077
+ /**
1078
+ * `nameMapping`, and calls `resolve` to obtain the `{ name, path }` pair for
1079
+ * each import. When `oas` is supplied, only `$ref`s that are resolvable in the
1080
+ * spec are included; omit it to skip the existence check.
1081
+ *
1082
+ * This function is the pure, state-free alternative to `OasParser.getImports`.
1083
+ * Because it receives `nameMapping` explicitly it can be called without holding
1084
+ * a reference to the parser or the OAS instance.
1085
+ *
1086
+ * @example
1087
+ * ```ts
1088
+ * // Use adapter state directly — no parser reference needed
1089
+ * const imports = getImports({
1090
+ * node: schemaNode,
1091
+ * nameMapping: adapter.options.nameMapping,
1092
+ * resolve: (schemaName) => ({
1093
+ * name: schemaManager.getName(schemaName, { type: 'type' }),
1094
+ * path: schemaManager.getFile(schemaName).path,
1095
+ * }),
1096
+ * })
1097
+ * ```
1098
+ */
1099
+ function getImports({ node, nameMapping, resolve }) {
1100
+ return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
1101
+ if (schemaNode.type !== "ref" || !schemaNode.ref) return;
1102
+ const rawName = extractRefName(schemaNode.ref);
1103
+ const result = resolve(nameMapping.get(rawName) ?? rawName);
1104
+ if (!result) return;
1105
+ return {
1106
+ name: [result.name],
1107
+ path: result.path
1108
+ };
1109
+ } });
1110
+ }
1111
+ //#endregion
1112
+ //#region src/parser.ts
942
1113
  /**
943
1114
  * Looks up the Kubb `SchemaType` for a given OAS `format` string.
944
1115
  * Returns `undefined` for formats not in `formatMap` (e.g. `int64`, `date-time`),
@@ -948,14 +1119,6 @@ function formatToSchemaType(format) {
948
1119
  return formatMap[format];
949
1120
  }
950
1121
  /**
951
- * Extracts the final path segment of a JSON Pointer `$ref` string.
952
- * For `#/components/schemas/Order` this returns `'Order'`.
953
- * Falls back to the full ref string when no slash is present.
954
- */
955
- function extractRefName($ref) {
956
- return $ref.split("/").at(-1) ?? $ref;
957
- }
958
- /**
959
1122
  * Maps an OAS primitive type string to its `PrimitiveSchemaType` equivalent.
960
1123
  * Numeric types (`number`, `integer`, `bigint`) are returned unchanged;
961
1124
  * `boolean` maps to `'boolean'`; everything else defaults to `'string'`.
@@ -970,27 +1133,7 @@ function getPrimitiveType(type) {
970
1133
  * Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
971
1134
  */
972
1135
  function toMediaType(contentType) {
973
- return knownMediaTypes.includes(contentType) ? contentType : void 0;
974
- }
975
- /**
976
- * When a discriminator is present, replaces the discriminator property's schema with
977
- * an enum of the mapping keys so downstream code emits a precise literal-union type.
978
- * Returns the original schema unchanged when there is no discriminator or no mapping.
979
- */
980
- function applyDiscriminatorEnum(schema) {
981
- if (!isDiscriminator(schema)) return schema;
982
- const propName = schema.discriminator.propertyName;
983
- if (!schema.properties?.[propName]) return schema;
984
- return {
985
- ...schema,
986
- properties: {
987
- ...schema.properties,
988
- [propName]: {
989
- ...schema.properties[propName],
990
- enum: schema.discriminator.mapping ? Object.keys(schema.discriminator.mapping) : void 0
991
- }
992
- }
993
- };
1136
+ return knownMediaTypes.has(contentType) ? contentType : void 0;
994
1137
  }
995
1138
  /**
996
1139
  * Creates an OAS parser that converts an OpenAPI/Swagger spec into
@@ -1016,6 +1159,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1016
1159
  contentType,
1017
1160
  collisionDetection
1018
1161
  });
1162
+ const usedEnumNames = {};
1163
+ const isLegacyNaming = collisionDetection === false;
1019
1164
  /**
1020
1165
  * Maps an `'any' | 'unknown' | 'void'` option string to the corresponding `SchemaType` constant.
1021
1166
  * Used for both `unknownType` (unannotated schemas) and `emptySchemaType` (empty `{}` schemas).
@@ -1062,7 +1207,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1062
1207
  * Shared metadata fields included in every `createSchema` call.
1063
1208
  * Centralizes the common properties so sub-handlers don't repeat them.
1064
1209
  */
1065
- function buildSchemaBase(schema, name, nullable, defaultValue) {
1210
+ function renderSchemaBase(schema, name, nullable, defaultValue) {
1066
1211
  return {
1067
1212
  name,
1068
1213
  nullable,
@@ -1083,18 +1228,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1083
1228
  * reflected in generated JSDoc and type modifiers.
1084
1229
  */
1085
1230
  function convertRef({ schema, nullable, defaultValue }) {
1086
- const schemaObject = schema;
1087
1231
  return (0, _kubb_ast.createSchema)({
1088
1232
  type: "ref",
1089
- name: extractRefName(schemaObject.$ref),
1090
- ref: schemaObject.$ref,
1233
+ name: extractRefName(schema.$ref),
1234
+ ref: schema.$ref,
1091
1235
  nullable,
1092
- description: schemaObject.description,
1093
- deprecated: schemaObject.deprecated,
1094
- readOnly: schemaObject.readOnly,
1095
- writeOnly: schemaObject.writeOnly,
1096
- pattern: schemaObject.type === "string" ? schemaObject.pattern : void 0,
1097
- example: schemaObject.example,
1236
+ description: schema.description,
1237
+ deprecated: schema.deprecated,
1238
+ readOnly: schema.readOnly,
1239
+ writeOnly: schema.writeOnly,
1240
+ pattern: schema.type === "string" ? schema.pattern : void 0,
1241
+ example: schema.example,
1098
1242
  default: defaultValue
1099
1243
  });
1100
1244
  }
@@ -1145,6 +1289,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1145
1289
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1146
1290
  return !inOneOf && !inMapping;
1147
1291
  }).map((s) => convertSchema({ schema: s }, options));
1292
+ const syntheticStart = allOfMembers.length;
1148
1293
  if (Array.isArray(schema.required) && schema.required.length) {
1149
1294
  const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
1150
1295
  const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
@@ -1169,8 +1314,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1169
1314
  }
1170
1315
  return (0, _kubb_ast.createSchema)({
1171
1316
  type: "intersection",
1172
- members: allOfMembers,
1173
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1317
+ members: [...allOfMembers.slice(0, syntheticStart), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
1318
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1174
1319
  });
1175
1320
  }
1176
1321
  /**
@@ -1184,25 +1329,39 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1184
1329
  function convertUnion({ schema, name, nullable, defaultValue, options }) {
1185
1330
  const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
1186
1331
  const unionBase = {
1187
- ...buildSchemaBase(schema, name, nullable, defaultValue),
1332
+ ...renderSchemaBase(schema, name, nullable, defaultValue),
1188
1333
  discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0
1189
1334
  };
1190
1335
  if (schema.properties) {
1191
1336
  const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
1192
- const propertiesNode = convertSchema({ schema: schemaWithoutUnion }, options);
1337
+ const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
1338
+ const sharedPropertiesNode = convertSchema({
1339
+ schema: discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion,
1340
+ name: isLegacyNaming ? void 0 : name
1341
+ }, options);
1193
1342
  return (0, _kubb_ast.createSchema)({
1194
1343
  type: "union",
1195
1344
  ...unionBase,
1196
- members: unionMembers.map((s) => (0, _kubb_ast.createSchema)({
1197
- type: "intersection",
1198
- members: [convertSchema({ schema: s }, options), propertiesNode]
1199
- }))
1345
+ members: unionMembers.map((s) => {
1346
+ const ref = isReference(s) ? s.$ref : void 0;
1347
+ const discriminatorValue = discriminator?.mapping && ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
1348
+ let propertiesNode = sharedPropertiesNode;
1349
+ if (discriminatorValue && discriminator) propertiesNode = applyDiscriminatorEnum({
1350
+ node: propertiesNode,
1351
+ propertyName: discriminator.propertyName,
1352
+ values: [discriminatorValue]
1353
+ });
1354
+ return (0, _kubb_ast.createSchema)({
1355
+ type: "intersection",
1356
+ members: [convertSchema({ schema: s }, options), propertiesNode]
1357
+ });
1358
+ })
1200
1359
  });
1201
1360
  }
1202
1361
  return (0, _kubb_ast.createSchema)({
1203
1362
  type: "union",
1204
1363
  ...unionBase,
1205
- members: unionMembers.map((s) => convertSchema({ schema: s }, options))
1364
+ members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s }, options)))
1206
1365
  });
1207
1366
  }
1208
1367
  /**
@@ -1225,7 +1384,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1225
1384
  type: "enum",
1226
1385
  primitive: getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string"),
1227
1386
  enumValues: [constValue],
1228
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1387
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1229
1388
  });
1230
1389
  }
1231
1390
  /**
@@ -1234,7 +1393,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1234
1393
  * (i.e. `format: 'date-time'` with `dateType: false`).
1235
1394
  */
1236
1395
  function convertFormat({ schema, name, nullable, defaultValue, mergedOptions }) {
1237
- const base = buildSchemaBase(schema, name, nullable, defaultValue);
1396
+ const base = renderSchemaBase(schema, name, nullable, defaultValue);
1238
1397
  if (schema.format === "int64") return (0, _kubb_ast.createSchema)({
1239
1398
  type: mergedOptions.integerType === "bigint" ? "bigint" : "integer",
1240
1399
  primitive: "integer",
@@ -1269,6 +1428,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1269
1428
  primitive: specialPrimitive,
1270
1429
  type: specialType
1271
1430
  });
1431
+ if (specialType === "url") return (0, _kubb_ast.createSchema)({
1432
+ ...base,
1433
+ primitive: "string",
1434
+ type: "url"
1435
+ });
1272
1436
  return (0, _kubb_ast.createSchema)({
1273
1437
  ...base,
1274
1438
  primitive: specialPrimitive,
@@ -1287,9 +1451,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1287
1451
  */
1288
1452
  function convertEnum({ schema, name, nullable, type, options }) {
1289
1453
  if (type === "array") {
1290
- const rawSchema = schema;
1291
1454
  const normalizedItems = {
1292
- ...typeof rawSchema.items === "object" && !Array.isArray(rawSchema.items) ? rawSchema.items : {},
1455
+ ...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
1293
1456
  enum: schema.enum
1294
1457
  };
1295
1458
  const { enum: _enum, ...schemaWithoutEnum } = schema;
@@ -1368,23 +1531,62 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1368
1531
  * - not required + not nullable → `optional: true`
1369
1532
  * - not required + nullable → `nullish: true`
1370
1533
  */
1534
+ /**
1535
+ * Builds the propagation name for a child property during recursive schema conversion.
1536
+ *
1537
+ * - **Legacy naming** (`isLegacyNaming`): only the immediate property key is used
1538
+ * (e.g. `Params` for property `params`), keeping nested names short.
1539
+ * - **Default naming**: the parent name is prepended so the full path is encoded
1540
+ * (e.g. `OrderParams` when parent is `Order`).
1541
+ */
1542
+ function resolveChildName(parentName, propName) {
1543
+ if (isLegacyNaming) return pascalCase(propName);
1544
+ return parentName ? pascalCase([parentName, propName].join(" ")) : void 0;
1545
+ }
1546
+ /**
1547
+ * Derives the final name for an enum property schema node.
1548
+ *
1549
+ * The raw name always includes the enum suffix (e.g. `StatusEnum`).
1550
+ * In legacy mode an additional deduplication step appends a numeric suffix
1551
+ * when the same name has already been used (e.g. `ParamsStatusEnum2`).
1552
+ */
1553
+ function resolveEnumPropName(parentName, propName, enumSuffix) {
1554
+ const raw = pascalCase([
1555
+ parentName,
1556
+ propName,
1557
+ enumSuffix
1558
+ ].filter(Boolean).join(" "));
1559
+ return isLegacyNaming ? getUniqueName(raw, usedEnumNames) : raw;
1560
+ }
1561
+ /**
1562
+ * Given a freshly-converted property schema, returns the node with a correct
1563
+ * `name` attached — or stripped — depending on whether the node is a named
1564
+ * enum, a boolean const-enum (always inlined), or a regular schema.
1565
+ */
1566
+ function applyEnumName(propNode, parentName, propName, enumSuffix) {
1567
+ const enumNode = (0, _kubb_ast.narrowSchema)(propNode, "enum");
1568
+ if (enumNode?.primitive === "boolean") return {
1569
+ ...propNode,
1570
+ name: void 0
1571
+ };
1572
+ if (enumNode) return {
1573
+ ...propNode,
1574
+ name: resolveEnumPropName(parentName, propName, enumSuffix)
1575
+ };
1576
+ return propNode;
1577
+ }
1371
1578
  function convertObject({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1372
- const resolvedSchema = applyDiscriminatorEnum(schema);
1373
- const properties = resolvedSchema.properties ? Object.entries(resolvedSchema.properties).map(([propName, propSchema]) => {
1374
- const required = Array.isArray(resolvedSchema.required) ? resolvedSchema.required.includes(propName) : !!resolvedSchema.required;
1579
+ const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
1580
+ const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
1375
1581
  const resolvedPropSchema = propSchema;
1376
1582
  const propNullable = isNullable(resolvedPropSchema);
1377
1583
  return (0, _kubb_ast.createProperty)({
1378
1584
  name: propName,
1379
1585
  schema: {
1380
- ...convertSchema({
1586
+ ...applyEnumName(convertSchema({
1381
1587
  schema: resolvedPropSchema,
1382
- name: name ? pascalCase([
1383
- name,
1384
- propName,
1385
- mergedOptions.enumSuffix
1386
- ].filter(Boolean).join(" ")) : void 0
1387
- }, options),
1588
+ name: resolveChildName(name, propName)
1589
+ }, options), name, propName, mergedOptions.enumSuffix),
1388
1590
  nullable: propNullable || void 0,
1389
1591
  optional: !required && !propNullable ? true : void 0,
1390
1592
  nullish: !required && propNullable ? true : void 0
@@ -1392,22 +1594,32 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1392
1594
  required
1393
1595
  });
1394
1596
  }) : [];
1395
- const additionalProperties = resolvedSchema.additionalProperties;
1597
+ const additionalProperties = schema.additionalProperties;
1396
1598
  let additionalPropertiesNode;
1397
1599
  if (additionalProperties === true) additionalPropertiesNode = true;
1398
1600
  else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, options);
1399
1601
  else if (additionalProperties === false) additionalPropertiesNode = void 0;
1400
1602
  else if (additionalProperties) additionalPropertiesNode = (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) });
1401
- const rawPatternProperties = "patternProperties" in resolvedSchema ? resolvedSchema.patternProperties : void 0;
1402
- const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || Object.keys(patternSchema).length === 0 ? (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
1403
- return (0, _kubb_ast.createSchema)({
1603
+ const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1604
+ const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
1605
+ const objectNode = (0, _kubb_ast.createSchema)({
1404
1606
  type: "object",
1405
1607
  primitive: "object",
1406
1608
  properties,
1407
1609
  additionalProperties: additionalPropertiesNode,
1408
1610
  patternProperties,
1409
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1611
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1410
1612
  });
1613
+ if (isDiscriminator(schema) && schema.discriminator.mapping) {
1614
+ const discPropName = schema.discriminator.propertyName;
1615
+ return applyDiscriminatorEnum({
1616
+ node: objectNode,
1617
+ propertyName: discPropName,
1618
+ values: Object.keys(schema.discriminator.mapping),
1619
+ enumName: name ? resolveEnumPropName(name, discPropName, mergedOptions.enumSuffix) : void 0
1620
+ });
1621
+ }
1622
+ return objectNode;
1411
1623
  }
1412
1624
  /**
1413
1625
  * Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
@@ -1416,15 +1628,14 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1416
1628
  * after the prefix items is mapped to the rest parameter of the tuple.
1417
1629
  */
1418
1630
  function convertTuple({ schema, name, nullable, defaultValue, options }) {
1419
- const rawSchema = schema;
1420
1631
  return (0, _kubb_ast.createSchema)({
1421
1632
  type: "tuple",
1422
1633
  primitive: "array",
1423
- items: rawSchema.prefixItems.map((item) => convertSchema({ schema: item }, options)),
1424
- rest: rawSchema.items ? convertSchema({ schema: rawSchema.items }, options) : void 0,
1634
+ items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
1635
+ rest: schema.items ? convertSchema({ schema: schema.items }, options) : void 0,
1425
1636
  min: schema.minItems,
1426
1637
  max: schema.maxItems,
1427
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1638
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1428
1639
  });
1429
1640
  }
1430
1641
  /**
@@ -1434,19 +1645,19 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1434
1645
  * `enumSuffix` is forwarded so generators can emit a named enum declaration.
1435
1646
  */
1436
1647
  function convertArray({ schema, name, nullable, defaultValue, options, mergedOptions }) {
1437
- const rawSchema = schema;
1438
- const itemName = rawSchema.items?.enum?.length && name ? pascalCase([name, mergedOptions.enumSuffix].join(" ")) : void 0;
1648
+ const rawItems = schema.items;
1649
+ const itemName = rawItems?.enum?.length && name ? resolveEnumPropName(void 0, name, mergedOptions.enumSuffix) : void 0;
1439
1650
  return (0, _kubb_ast.createSchema)({
1440
1651
  type: "array",
1441
1652
  primitive: "array",
1442
- items: rawSchema.items ? [convertSchema({
1443
- schema: rawSchema.items,
1653
+ items: rawItems ? [convertSchema({
1654
+ schema: rawItems,
1444
1655
  name: itemName
1445
1656
  }, options)] : [],
1446
1657
  min: schema.minItems,
1447
1658
  max: schema.maxItems,
1448
1659
  unique: schema.uniqueItems ?? void 0,
1449
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1660
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1450
1661
  });
1451
1662
  }
1452
1663
  /**
@@ -1459,7 +1670,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1459
1670
  min: schema.minLength,
1460
1671
  max: schema.maxLength,
1461
1672
  pattern: schema.pattern,
1462
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1673
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1463
1674
  });
1464
1675
  }
1465
1676
  /**
@@ -1473,7 +1684,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1473
1684
  max: schema.maximum,
1474
1685
  exclusiveMinimum: typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : void 0,
1475
1686
  exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0,
1476
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1687
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1477
1688
  });
1478
1689
  }
1479
1690
  /**
@@ -1483,7 +1694,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1483
1694
  return (0, _kubb_ast.createSchema)({
1484
1695
  type: "boolean",
1485
1696
  primitive: "boolean",
1486
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1697
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1487
1698
  });
1488
1699
  }
1489
1700
  /**
@@ -1518,7 +1729,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1518
1729
  */
1519
1730
  function convertSchema({ schema, name }, options) {
1520
1731
  const mergedOptions = {
1521
- ...DEFAULT_OPTIONS,
1732
+ ...DEFAULT_PARSER_OPTIONS,
1522
1733
  ...options
1523
1734
  };
1524
1735
  const flattenedSchema = flattenSchema(schema);
@@ -1549,18 +1760,21 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1549
1760
  if (schema.type === "string" && schema.contentMediaType === "application/octet-stream") return (0, _kubb_ast.createSchema)({
1550
1761
  type: "blob",
1551
1762
  primitive: "string",
1552
- ...buildSchemaBase(schema, name, nullable, defaultValue)
1763
+ ...renderSchemaBase(schema, name, nullable, defaultValue)
1553
1764
  });
1554
1765
  if (Array.isArray(schema.type) && schema.type.length > 1) {
1555
1766
  const nonNullTypes = schema.type.filter((t) => t !== "null");
1556
1767
  const arrayNullable = schema.type.includes("null") || nullable || void 0;
1557
1768
  if (nonNullTypes.length > 1) return (0, _kubb_ast.createSchema)({
1558
1769
  type: "union",
1559
- members: nonNullTypes.map((t) => convertSchema({ schema: {
1560
- ...schema,
1561
- type: t
1562
- } }, options)),
1563
- ...buildSchemaBase(schema, name, arrayNullable, defaultValue)
1770
+ members: nonNullTypes.map((t) => convertSchema({
1771
+ schema: {
1772
+ ...schema,
1773
+ type: t
1774
+ },
1775
+ name
1776
+ }, options)),
1777
+ ...renderSchemaBase(schema, name, arrayNullable, defaultValue)
1564
1778
  });
1565
1779
  }
1566
1780
  if (!type) {
@@ -1588,12 +1802,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1588
1802
  * When the parameter has no `schema` or its schema is a `$ref`, falls back to `unknownType`.
1589
1803
  */
1590
1804
  function parseParameter(options, param) {
1805
+ const required = param["required"] ?? false;
1591
1806
  const schema = param["schema"] && !isReference(param["schema"]) ? convertSchema({ schema: param["schema"] }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.unknownType) });
1592
1807
  return (0, _kubb_ast.createParameter)({
1593
1808
  name: param["name"],
1594
1809
  in: param["in"],
1595
- schema,
1596
- required: param["required"] ?? false
1810
+ schema: {
1811
+ ...schema,
1812
+ description: param["description"] ?? schema.description,
1813
+ optional: !required || !!schema.optional ? true : void 0
1814
+ },
1815
+ required
1597
1816
  });
1598
1817
  }
1599
1818
  /**
@@ -1601,15 +1820,13 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1601
1820
  * request body, and all response codes into their AST node equivalents.
1602
1821
  */
1603
1822
  function parseOperation(options, oas, operation) {
1604
- const parameters = operation.getParameters().map((param) => {
1605
- return parseParameter(options, oas.dereferenceWithRef(param));
1606
- });
1823
+ const parameters = oas.getParameters(operation).map((param) => parseParameter(options, param));
1607
1824
  const requestBodySchema = oas.getRequestSchema(operation);
1608
1825
  const requestBody = requestBodySchema ? convertSchema({ schema: requestBodySchema }, options) : void 0;
1609
1826
  const responses = operation.getResponseStatusCodes().map((statusCode) => {
1610
1827
  const responseObj = operation.getResponseByStatusCode(statusCode);
1611
1828
  const responseSchema = oas.getResponseSchema(operation, statusCode);
1612
- const schema = responseSchema && Object.keys(responseSchema).length > 0 ? convertSchema({ schema: responseSchema }, options) : void 0;
1829
+ const schema = responseSchema && Object.keys(responseSchema).length > 0 ? convertSchema({ schema: responseSchema }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.emptySchemaType) });
1613
1830
  const description = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.description : void 0;
1614
1831
  const rawContent = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.content : void 0;
1615
1832
  return (0, _kubb_ast.createResponse)({
@@ -1622,7 +1839,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1622
1839
  return (0, _kubb_ast.createOperation)({
1623
1840
  operationId: operation.getOperationId(),
1624
1841
  method: operation.method.toUpperCase(),
1625
- path: operation.path,
1842
+ path: new URLPath(operation.path).URL,
1626
1843
  tags: operation.getTags().map((tag) => tag.name),
1627
1844
  summary: operation.getSummary() || void 0,
1628
1845
  description: operation.getDescription() || void 0,
@@ -1638,7 +1855,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1638
1855
  */
1639
1856
  function parse(options) {
1640
1857
  const mergedOptions = {
1641
- ...DEFAULT_OPTIONS,
1858
+ ...DEFAULT_PARSER_OPTIONS,
1642
1859
  ...options
1643
1860
  };
1644
1861
  const schemas = Object.entries(schemaObjects).map(([name, schemaObject]) => convertSchema({
@@ -1679,31 +1896,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
1679
1896
  }
1680
1897
  } });
1681
1898
  }
1682
- /**
1683
- * Collects all `KubbFile.Import` descriptors needed by a `SchemaNode` tree.
1684
- *
1685
- * Walks the tree looking for `ref` nodes, verifies each `$ref` is resolvable in the spec,
1686
- * applies collision-resolved names from `nameMapping`, and calls `resolve` to obtain the
1687
- * import path and name. Returns an empty array for refs that cannot be resolved.
1688
- */
1689
- function getImports(node, resolve) {
1690
- return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
1691
- if (schemaNode.type !== "ref" || !schemaNode.ref) return;
1692
- if (!oas.get(schemaNode.ref)) return;
1693
- const rawName = extractRefName(schemaNode.ref);
1694
- const result = resolve(nameMapping.get(rawName) ?? rawName);
1695
- if (!result) return;
1696
- return {
1697
- name: [result.name],
1698
- path: result.path
1699
- };
1700
- } });
1701
- }
1702
1899
  return {
1703
1900
  parse,
1704
1901
  convertSchema,
1705
1902
  resolveRefs,
1706
- getImports
1903
+ nameMapping
1707
1904
  };
1708
1905
  }
1709
1906
  //#endregion
@@ -1727,8 +1924,9 @@ const adapterOasName = "oas";
1727
1924
  * })
1728
1925
  * ```
1729
1926
  */
1730
- const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
1731
- const { validate = true, oasClass, contentType, serverIndex, serverVariables, discriminator = "strict", collisionDetection = false, dateType = "string", integerType = "number", unknownType = "any", emptySchemaType = unknownType } = options;
1927
+ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
1928
+ const { validate = true, oasClass, contentType, serverIndex, serverVariables, discriminator = "strict", collisionDetection = true, dateType = DEFAULT_PARSER_OPTIONS.dateType, integerType = DEFAULT_PARSER_OPTIONS.integerType, unknownType = DEFAULT_PARSER_OPTIONS.unknownType, enumSuffix = DEFAULT_PARSER_OPTIONS.enumSuffix, emptySchemaType = unknownType || DEFAULT_PARSER_OPTIONS.emptySchemaType } = options;
1929
+ const nameMapping = /* @__PURE__ */ new Map();
1732
1930
  return {
1733
1931
  name: "oas",
1734
1932
  options: {
@@ -1742,7 +1940,16 @@ const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
1742
1940
  dateType,
1743
1941
  integerType,
1744
1942
  unknownType,
1745
- emptySchemaType
1943
+ emptySchemaType,
1944
+ enumSuffix,
1945
+ nameMapping
1946
+ },
1947
+ getImports(node, resolve) {
1948
+ return getImports({
1949
+ node,
1950
+ nameMapping,
1951
+ resolve
1952
+ });
1746
1953
  },
1747
1954
  async parse(source) {
1748
1955
  const oas = await parseFromConfig(sourceToFakeConfig(source), oasClass);
@@ -1756,18 +1963,23 @@ const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
1756
1963
  } catch (_err) {}
1757
1964
  const server = serverIndex !== void 0 ? oas.api.servers?.at(serverIndex) : void 0;
1758
1965
  const baseURL = server?.url ? resolveServerUrl(server, serverVariables) : void 0;
1966
+ const parser = createOasParser(oas, {
1967
+ contentType,
1968
+ collisionDetection
1969
+ });
1970
+ nameMapping.clear();
1971
+ for (const [key, value] of parser.nameMapping) nameMapping.set(key, value);
1759
1972
  return (0, _kubb_ast.createRoot)({
1760
- ...createOasParser(oas, {
1761
- contentType,
1762
- collisionDetection
1763
- }).parse({
1973
+ ...parser.parse({
1764
1974
  dateType,
1765
1975
  integerType,
1766
1976
  unknownType,
1767
- emptySchemaType
1977
+ emptySchemaType,
1978
+ enumSuffix
1768
1979
  }),
1769
1980
  meta: {
1770
1981
  title: oas.api.info?.title,
1982
+ description: oas.api.info?.description,
1771
1983
  version: oas.api.info?.version,
1772
1984
  baseURL
1773
1985
  }