@kubb/adapter-oas 5.0.0-beta.25 → 5.0.0-beta.27

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/adapter-oas",
3
- "version": "5.0.0-beta.25",
3
+ "version": "5.0.0-beta.27",
4
4
  "description": "OpenAPI and Swagger adapter for Kubb. Parses and validates OAS 2.0/3.x specifications into a @kubb/ast RootNode for downstream code generation plugins.",
5
5
  "keywords": [
6
6
  "adapter",
@@ -43,11 +43,11 @@
43
43
  "registry": "https://registry.npmjs.org/"
44
44
  },
45
45
  "dependencies": {
46
- "@redocly/openapi-core": "^2.30.6",
46
+ "@redocly/openapi-core": "^2.31.2",
47
47
  "oas": "^32.1.18",
48
48
  "oas-normalize": "^16.0.4",
49
49
  "swagger2openapi": "^7.0.8",
50
- "@kubb/core": "5.0.0-beta.25"
50
+ "@kubb/core": "5.0.0-beta.27"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/swagger2openapi": "^7.0.4",
package/src/adapter.ts CHANGED
@@ -153,8 +153,8 @@ export const adapterOas = createAdapter<AdapterOas>((options) => {
153
153
  async parse(source) {
154
154
  const streamNode = await createStream(source)
155
155
 
156
- const collect = async <T>(iter: AsyncIterable<T>): Promise<T[]> => {
157
- const out: T[] = []
156
+ const collect = async <T>(iter: AsyncIterable<T>): Promise<Array<T>> => {
157
+ const out: Array<T> = []
158
158
  for await (const item of iter) out.push(item)
159
159
  return out
160
160
  }
@@ -14,7 +14,7 @@ export type DiscriminatorTarget = {
14
14
  * small pre-parsed subset of schemas (only the discriminator parents) rather than on all
15
15
  * schemas at once.
16
16
  */
17
- export function buildDiscriminatorChildMap(schemas: ast.SchemaNode[]): Map<string, DiscriminatorTarget> {
17
+ export function buildDiscriminatorChildMap(schemas: Array<ast.SchemaNode>): Map<string, DiscriminatorTarget> {
18
18
  const childMap = new Map<string, DiscriminatorTarget>()
19
19
 
20
20
  for (const schema of schemas) {
package/src/parser.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { URLPath } from '@internals/utils'
1
+ import { pascalCase, URLPath } from '@internals/utils'
2
2
  import { ast } from '@kubb/core'
3
3
  import BaseOas from 'oas'
4
4
  import { DEFAULT_PARSER_OPTIONS, enumExtensionKeys, SCHEMA_REF_PREFIX, typeOptionMap } from './constants.ts'
@@ -161,7 +161,7 @@ export function createSchemaParser(ctx: OasParserContext) {
161
161
  schema.additionalProperties === undefined
162
162
  ) {
163
163
  const [memberSchema] = schema.allOf as Array<SchemaObject | ReferenceObject>
164
- const memberNode = parseSchema({ schema: memberSchema! as SchemaObject, name: null }, rawOptions)
164
+ const memberNode = parseSchema({ schema: memberSchema! as SchemaObject, name }, rawOptions)
165
165
  const { kind: _kind, ...memberNodeProps } = memberNode
166
166
  const mergedNullable = nullable || memberNode.nullable || undefined
167
167
  const mergedDefault = schema.default === null && mergedNullable ? undefined : (schema.default ?? memberNode.default)
@@ -208,7 +208,7 @@ export function createSchemaParser(ctx: OasParserContext) {
208
208
  }
209
209
  return true
210
210
  })
211
- .map((s) => parseSchema({ schema: s as SchemaObject }, rawOptions))
211
+ .map((s) => parseSchema({ schema: s as SchemaObject, name }, rawOptions))
212
212
 
213
213
  const syntheticStart = allOfMembers.length
214
214
 
@@ -233,6 +233,7 @@ export function createSchemaParser(ctx: OasParserContext) {
233
233
  properties: { [key]: resolved.properties[key] },
234
234
  required: [key],
235
235
  } as SchemaObject,
236
+ name,
236
237
  },
237
238
  rawOptions,
238
239
  ),
@@ -246,6 +247,9 @@ export function createSchemaParser(ctx: OasParserContext) {
246
247
 
247
248
  if (schema.properties) {
248
249
  const { allOf: _allOf, ...schemaWithoutAllOf } = schema
250
+ // Don't pass `name` here — the result must stay anonymous so it can be merged with the
251
+ // adjacent synthetic object in `mergeAdjacentObjectsLazy`. Nested enum qualification
252
+ // happens upstream via `convertObject`'s `setEnumName` propagation.
249
253
  allOfMembers.push(parseSchema({ schema: schemaWithoutAllOf }, rawOptions))
250
254
  }
251
255
 
@@ -301,7 +305,7 @@ export function createSchemaParser(ctx: OasParserContext) {
301
305
  const members = unionMembers.map((s) => {
302
306
  const ref = isReference(s) ? s.$ref : undefined
303
307
  const discriminatorValue = ast.findDiscriminator(discriminator?.mapping, ref)
304
- const memberNode = parseSchema({ schema: s as SchemaObject }, rawOptions)
308
+ const memberNode = parseSchema({ schema: s as SchemaObject, name }, rawOptions)
305
309
 
306
310
  if (!discriminatorValue || !discriminator) {
307
311
  return memberNode
@@ -351,7 +355,7 @@ export function createSchemaParser(ctx: OasParserContext) {
351
355
  return ast.createSchema({
352
356
  type: 'union',
353
357
  ...unionBase,
354
- members: ast.simplifyUnion(unionMembers.map((s) => parseSchema({ schema: s as SchemaObject }, rawOptions))),
358
+ members: ast.simplifyUnion(unionMembers.map((s) => parseSchema({ schema: s as SchemaObject, name }, rawOptions))),
355
359
  })
356
360
  }
357
361
 
@@ -646,7 +650,7 @@ export function createSchemaParser(ctx: OasParserContext) {
646
650
  */
647
651
  function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }: SchemaContext): ast.SchemaNode {
648
652
  const rawItems = schema.items as SchemaObject | undefined
649
- const itemName = rawItems?.enum?.length && name ? ast.enumPropName(null, name, options.enumSuffix) : undefined
653
+ const itemName = rawItems?.enum?.length && name ? ast.enumPropName(null, name, options.enumSuffix) : name
650
654
  const items = rawItems ? [parseSchema({ schema: rawItems, name: itemName }, rawOptions)] : []
651
655
 
652
656
  return ast.createSchema({
@@ -770,7 +774,7 @@ export function createSchemaParser(ctx: OasParserContext) {
770
774
  }
771
775
 
772
776
  if (Array.isArray(schema.type) && schema.type.length > 1) {
773
- const nonNullTypes = schema.type.filter((t) => t !== 'null') as string[]
777
+ const nonNullTypes = schema.type.filter((t) => t !== 'null') as Array<string>
774
778
  const arrayNullable = schema.type.includes('null') || nullable || undefined
775
779
 
776
780
  if (nonNullTypes.length > 1) {
@@ -814,15 +818,17 @@ export function createSchemaParser(ctx: OasParserContext) {
814
818
  /**
815
819
  * Converts a dereferenced OAS parameter object into a `ParameterNode`.
816
820
  */
817
- function parseParameter(options: ast.ParserOptions, param: Record<string, unknown>): ast.ParameterNode {
821
+ function parseParameter(options: ast.ParserOptions, param: Record<string, unknown>, parentName?: string): ast.ParameterNode {
818
822
  const required = (param['required'] as boolean | undefined) ?? false
823
+ const paramName = param['name'] as string
824
+ const schemaName = parentName && paramName ? pascalCase(`${parentName} ${paramName}`) : undefined
819
825
 
820
826
  const schema: ast.SchemaNode = param['schema']
821
- ? parseSchema({ schema: param['schema'] as SchemaObject }, options)
827
+ ? parseSchema({ schema: param['schema'] as SchemaObject, name: schemaName }, options)
822
828
  : ast.createSchema({ type: typeOptionMap.get(options.unknownType)! })
823
829
 
824
830
  return ast.createParameter({
825
- name: param['name'] as string,
831
+ name: paramName,
826
832
  in: param['in'] as ast.ParameterLocation,
827
833
  schema: {
828
834
  ...schema,
@@ -871,10 +877,10 @@ export function createSchemaParser(ctx: OasParserContext) {
871
877
  * Collects property names whose schema has a truthy boolean flag (`readOnly` or `writeOnly`).
872
878
  * `$ref` entries are skipped since their flags live on the dereferenced target.
873
879
  */
874
- function collectPropertyKeysByFlag(schema: SchemaObject | null, flag: 'readOnly' | 'writeOnly'): string[] | null {
880
+ function collectPropertyKeysByFlag(schema: SchemaObject | null, flag: 'readOnly' | 'writeOnly'): Array<string> | null {
875
881
  if (!schema?.properties) return null
876
882
 
877
- const keys: string[] = []
883
+ const keys: Array<string> = []
878
884
  for (const key in schema.properties) {
879
885
  const prop = schema.properties[key]
880
886
  if (prop && !isReference(prop) && (prop as Record<string, unknown>)[flag]) {
@@ -888,8 +894,10 @@ export function createSchemaParser(ctx: OasParserContext) {
888
894
  * Converts an OAS `Operation` into an `OperationNode`.
889
895
  */
890
896
  function parseOperation(options: ast.ParserOptions, operation: Operation): ast.OperationNode {
897
+ const operationId = operation.getOperationId()
898
+ const operationName = operationId ? pascalCase(operationId) : undefined
891
899
  const parameters: Array<ast.ParameterNode> = getParameters(document, operation).map((param) =>
892
- parseParameter(options, param as unknown as Record<string, unknown>),
900
+ parseParameter(options, param as unknown as Record<string, unknown>, operationName),
893
901
  )
894
902
 
895
903
  // Determine which content types to include in requestBody.content.
@@ -898,6 +906,7 @@ export function createSchemaParser(ctx: OasParserContext) {
898
906
  const allContentTypes = ctx.contentType ? [ctx.contentType] : getRequestBodyContentTypes(document, operation)
899
907
 
900
908
  const requestBodyMeta = getRequestBodyMeta(operation)
909
+ const requestBodyName = operationName ? `${operationName}Request` : undefined
901
910
 
902
911
  const content = allContentTypes.flatMap((ct) => {
903
912
  const schema = getRequestSchema(document, operation, { contentType: ct })
@@ -905,7 +914,7 @@ export function createSchemaParser(ctx: OasParserContext) {
905
914
  return [
906
915
  {
907
916
  contentType: ct,
908
- schema: ast.syncOptionality(parseSchema({ schema }, options), requestBodyMeta.required),
917
+ schema: ast.syncOptionality(parseSchema({ schema, name: requestBodyName }, options), requestBodyMeta.required),
909
918
  keysToOmit: collectPropertyKeysByFlag(schema, 'readOnly'),
910
919
  },
911
920
  ]
@@ -924,9 +933,13 @@ export function createSchemaParser(ctx: OasParserContext) {
924
933
  const responseObj = operation.getResponseByStatusCode(statusCode)
925
934
  const responseSchema = getResponseSchema(document, operation, statusCode, { contentType: ctx.contentType })
926
935
 
936
+ // Use `Status<code>` (matching plugin-ts's resolveResponseStatusName convention) so the
937
+ // qualified names for nested enums don't collide with top-level component schemas that
938
+ // happen to be named `<operation><statusCode>` (e.g. `GetMaintenance200`).
939
+ const responseName = operationName ? `${operationName}Status${statusCode}` : undefined
927
940
  const schema =
928
941
  responseSchema && Object.keys(responseSchema).length > 0
929
- ? parseSchema({ schema: responseSchema }, options)
942
+ ? parseSchema({ schema: responseSchema, name: responseName }, options)
930
943
  : ast.createSchema({
931
944
  type: typeOptionMap.get(options.emptySchemaType)!,
932
945
  })
@@ -946,7 +959,7 @@ export function createSchemaParser(ctx: OasParserContext) {
946
959
  const urlPath = new URLPath(operation.path)
947
960
 
948
961
  return ast.createOperation({
949
- operationId: operation.getOperationId(),
962
+ operationId,
950
963
  method: operation.method.toUpperCase() as ast.HttpMethod,
951
964
  path: urlPath.path,
952
965
  tags: operation.getTags().map((tag) => tag.name),
package/src/resolvers.ts CHANGED
@@ -86,7 +86,7 @@ export type OperationsOptions = {
86
86
  * ```
87
87
  */
88
88
  export function getParameters(document: Document, operation: Operation): Array<ParameterObject> {
89
- const resolveParams = (params: unknown[]): Array<ParameterObject> =>
89
+ const resolveParams = (params: Array<unknown>): Array<ParameterObject> =>
90
90
  params.map((p) => dereferenceWithRef(document, p)).filter((p): p is ParameterObject => !!p && typeof p === 'object' && 'in' in p && 'name' in p)
91
91
 
92
92
  const operationParams = resolveParams(operation.schema?.parameters || [])
@@ -108,7 +108,7 @@ export function getParameters(document: Document, operation: Operation): Array<P
108
108
  return Array.from(paramMap.values())
109
109
  }
110
110
 
111
- function getResponseBody(responseBody: boolean | ResponseObject, contentType?: string): MediaTypeObject | false | [string, MediaTypeObject, ...string[]] {
111
+ function getResponseBody(responseBody: boolean | ResponseObject, contentType?: string): MediaTypeObject | false | [string, MediaTypeObject, ...Array<string>] {
112
112
  if (!responseBody) return false
113
113
  if (isReference(responseBody)) return false
114
114
 
@@ -260,7 +260,7 @@ function hasStructuralKeywords(fragment: SchemaObject): boolean {
260
260
  export function flattenSchema(schema: SchemaObject | null): SchemaObject | null {
261
261
  if (!schema?.allOf || schema.allOf.length === 0) return schema ?? null
262
262
 
263
- const allOfFragments = schema.allOf as SchemaObject[]
263
+ const allOfFragments = schema.allOf as Array<SchemaObject>
264
264
  if (allOfFragments.some((item) => isRef(item))) return schema
265
265
  if (allOfFragments.some(hasStructuralKeywords)) return schema
266
266
 
@@ -339,13 +339,13 @@ function* collectRefs(schema: unknown): Generator<string, void, undefined> {
339
339
  * ```
340
340
  */
341
341
  export function sortSchemas(schemas: Record<string, SchemaObject>): Record<string, SchemaObject> {
342
- const deps = new Map<string, string[]>()
342
+ const deps = new Map<string, Array<string>>()
343
343
 
344
344
  for (const [name, schema] of Object.entries(schemas)) {
345
345
  deps.set(name, [...new Set(collectRefs(schema))])
346
346
  }
347
347
 
348
- const sorted: string[] = []
348
+ const sorted: Array<string> = []
349
349
  const visited = new Set<string>()
350
350
 
351
351
  function visit(name: string, stack: Set<string>) {
@@ -402,7 +402,7 @@ function resolveSchemaRef(document: Document, schema: SchemaObject): SchemaObjec
402
402
  export function getSchemas(document: Document, { contentType }: GetSchemasOptions): GetSchemasResult {
403
403
  const components = document.components
404
404
 
405
- const candidates: SchemaWithMetadata[] = [
405
+ const candidates: Array<SchemaWithMetadata> = [
406
406
  ...Object.entries((components?.schemas as Record<string, SchemaObject>) ?? {}).map(([name, schema]) => ({
407
407
  schema: resolveSchemaRef(document, schema),
408
408
  source: 'schemas' as const,
@@ -424,7 +424,7 @@ export function getSchemas(document: Document, { contentType }: GetSchemasOption
424
424
  ),
425
425
  ]
426
426
 
427
- const normalizedNames = new Map<string, SchemaWithMetadata[]>()
427
+ const normalizedNames = new Map<string, Array<SchemaWithMetadata>>()
428
428
  for (const item of candidates) {
429
429
  const key = pascalCase(item.originalName)
430
430
  const bucket = normalizedNames.get(key) ?? []
@@ -529,7 +529,7 @@ export function buildSchemaNode(schema: SchemaObject, name: string | null | unde
529
529
  * // ['application/json', 'multipart/form-data']
530
530
  * ```
531
531
  */
532
- export function getRequestBodyContentTypes(document: Document, operation: Operation): string[] {
532
+ export function getRequestBodyContentTypes(document: Document, operation: Operation): Array<string> {
533
533
  if (operation.schema.requestBody) {
534
534
  operation.schema.requestBody = dereferenceWithRef(document, operation.schema.requestBody)
535
535
  }
package/src/stream.ts CHANGED
@@ -8,8 +8,8 @@ import type { AdapterOas, Document, SchemaObject } from './types.ts'
8
8
 
9
9
  export type PreScanResult = {
10
10
  refAliasMap: Map<string, ast.SchemaNode>
11
- enumNames: string[]
12
- circularNames: string[]
11
+ enumNames: Array<string>
12
+ circularNames: Array<string>
13
13
  discriminatorChildMap: Map<string, DiscriminatorTarget> | null
14
14
  }
15
15
 
@@ -74,10 +74,10 @@ export function preScan({
74
74
  parserOptions: ast.ParserOptions
75
75
  discriminator: AdapterOas['options']['discriminator']
76
76
  }): PreScanResult {
77
- const allNodes: ast.SchemaNode[] = []
77
+ const allNodes: Array<ast.SchemaNode> = []
78
78
  const refAliasMap = new Map<string, ast.SchemaNode>()
79
- const enumNames: string[] = []
80
- const discriminatorParentNodes: ast.SchemaNode[] = []
79
+ const enumNames: Array<string> = []
80
+ const discriminatorParentNodes: Array<ast.SchemaNode> = []
81
81
 
82
82
  for (const [name, schema] of Object.entries(schemas)) {
83
83
  const node = parseSchema({ schema, name }, parserOptions)