@kubb/adapter-oas 5.0.0-alpha.7 → 5.0.0-alpha.9
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 +37 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +38 -20
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +2 -2
- package/src/constants.ts +9 -5
- package/src/oas/Oas.ts +16 -9
- package/src/oas/utils.ts +1 -1
- package/src/parser.ts +7 -7
- package/src/utils.ts +8 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/adapter-oas",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.9",
|
|
4
4
|
"description": "OpenAPI / Swagger adapter for Kubb — converts OAS input into a @kubb/ast RootNode.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openapi",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"openapi-types": "^12.1.3",
|
|
47
47
|
"remeda": "^2.33.6",
|
|
48
48
|
"swagger2openapi": "^7.0.8",
|
|
49
|
-
"@kubb/ast": "5.0.0-alpha.
|
|
50
|
-
"@kubb/core": "5.0.0-alpha.
|
|
49
|
+
"@kubb/ast": "5.0.0-alpha.9",
|
|
50
|
+
"@kubb/core": "5.0.0-alpha.9"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/swagger2openapi": "^7.0.4",
|
package/src/adapter.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import { createRoot } from '@kubb/ast'
|
|
3
3
|
import type { AdapterSource } from '@kubb/core'
|
|
4
|
-
import {
|
|
4
|
+
import { createAdapter } from '@kubb/core'
|
|
5
5
|
import { resolveServerUrl } from './oas/resolveServerUrl.ts'
|
|
6
6
|
import { parseFromConfig } from './oas/utils.ts'
|
|
7
7
|
import { createOasParser } from './parser.ts'
|
|
@@ -28,7 +28,7 @@ export const adapterOasName = 'oas' satisfies OasAdapter['name']
|
|
|
28
28
|
* })
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
|
-
export const adapterOas =
|
|
31
|
+
export const adapterOas = createAdapter<OasAdapter>((options) => {
|
|
32
32
|
const {
|
|
33
33
|
validate = true,
|
|
34
34
|
oasClass,
|
package/src/constants.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SchemaType } from '@kubb/ast/types'
|
|
2
2
|
import type { HttpMethods as OASHttpMethods } from 'oas/types'
|
|
3
3
|
|
|
4
4
|
// ─── Merge defaults ────────────────────────────────────────────────────────────
|
|
@@ -25,7 +25,7 @@ export const MERGE_DEFAULT_VERSION = '1.0.0' as const
|
|
|
25
25
|
* A schema fragment containing any of these keys must not be inlined into its
|
|
26
26
|
* parent during `allOf` flattening — it carries semantic meaning of its own.
|
|
27
27
|
*/
|
|
28
|
-
export const structuralKeys = new Set
|
|
28
|
+
export const structuralKeys = new Set(['properties', 'items', 'additionalProperties', 'oneOf', 'anyOf', 'allOf', 'not'] as const)
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Maps OAS/JSON Schema `format` strings to their Kubb `SchemaType` equivalents.
|
|
@@ -59,9 +59,8 @@ export const formatMap = {
|
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
* Exhaustive list of media types that Kubb recognizes.
|
|
62
|
-
* Kept as a module-level constant to avoid re-allocating the array on every call.
|
|
63
62
|
*/
|
|
64
|
-
export const knownMediaTypes = [
|
|
63
|
+
export const knownMediaTypes = new Set([
|
|
65
64
|
'application/json',
|
|
66
65
|
'application/xml',
|
|
67
66
|
'application/x-www-form-urlencoded',
|
|
@@ -81,7 +80,7 @@ export const knownMediaTypes = [
|
|
|
81
80
|
'image/svg+xml',
|
|
82
81
|
'audio/mpeg',
|
|
83
82
|
'video/mp4',
|
|
84
|
-
] as const
|
|
83
|
+
] as const)
|
|
85
84
|
|
|
86
85
|
/**
|
|
87
86
|
* Vendor extension keys used to attach human-readable labels to enum values.
|
|
@@ -89,6 +88,11 @@ export const knownMediaTypes = [
|
|
|
89
88
|
*/
|
|
90
89
|
export const enumExtensionKeys = ['x-enumNames', 'x-enum-varnames'] as const
|
|
91
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Scalar primitive schema types used for union member simplification.
|
|
93
|
+
*/
|
|
94
|
+
export const SCALAR_PRIMITIVE_TYPES = new Set(['string', 'number', 'integer', 'bigint', 'boolean'] as const)
|
|
95
|
+
|
|
92
96
|
// ─── HTTP ──────────────────────────────────────────────────────────────────────
|
|
93
97
|
|
|
94
98
|
/**
|
package/src/oas/Oas.ts
CHANGED
|
@@ -431,14 +431,15 @@ export class Oas extends BaseOas {
|
|
|
431
431
|
return this.dereferenceWithRef(schema)
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
434
|
+
/**
|
|
435
|
+
* Returns all resolved parameters for an operation, merging path-level and operation-level
|
|
436
|
+
* parameters and deduplicating by `in:name` (operation-level takes precedence).
|
|
437
|
+
*
|
|
438
|
+
* oas v31+ filters out `$ref` parameters in `getParameters()`, so this method accesses the
|
|
439
|
+
* raw `operation.schema.parameters` and path-item parameters directly and resolves `$ref`
|
|
440
|
+
* pointers via `dereferenceWithRef` to preserve backward compatibility.
|
|
441
|
+
*/
|
|
442
|
+
getParameters(operation: Operation): Array<ParameterObject> {
|
|
442
443
|
const resolveParams = (params: unknown[]): Array<ParameterObject> =>
|
|
443
444
|
params.map((p) => this.dereferenceWithRef(p)).filter((p): p is ParameterObject => !!p && typeof p === 'object' && 'in' in p && 'name' in p)
|
|
444
445
|
|
|
@@ -459,7 +460,13 @@ export class Oas extends BaseOas {
|
|
|
459
460
|
}
|
|
460
461
|
}
|
|
461
462
|
|
|
462
|
-
|
|
463
|
+
return Array.from(paramMap.values())
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
getParametersSchema(operation: Operation, inKey: 'path' | 'query' | 'header'): SchemaObject | null {
|
|
467
|
+
const { contentType = operation.getContentType() } = this.#options
|
|
468
|
+
|
|
469
|
+
const params = this.getParameters(operation).filter((v) => v.in === inKey)
|
|
463
470
|
|
|
464
471
|
if (!params.length) {
|
|
465
472
|
return null
|
package/src/oas/utils.ts
CHANGED
|
@@ -183,7 +183,7 @@ export function flattenSchema(schema: SchemaObject | null): SchemaObject | null
|
|
|
183
183
|
if (!schema?.allOf || schema.allOf.length === 0) return schema ?? null
|
|
184
184
|
if (schema.allOf.some((item) => isRef(item))) return schema
|
|
185
185
|
|
|
186
|
-
const isPlainFragment = (item: SchemaObject) => !Object.keys(item).some((key) => structuralKeys.has(key))
|
|
186
|
+
const isPlainFragment = (item: SchemaObject) => !Object.keys(item).some((key) => structuralKeys.has(key as 'properties'))
|
|
187
187
|
if (!schema.allOf.every((item) => isPlainFragment(item as SchemaObject))) return schema
|
|
188
188
|
|
|
189
189
|
const merged: SchemaObject = { ...schema }
|
package/src/parser.ts
CHANGED
|
@@ -183,7 +183,7 @@ function getPrimitiveType(type: string | undefined): PrimitiveSchemaType {
|
|
|
183
183
|
* Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
|
|
184
184
|
*/
|
|
185
185
|
function toMediaType(contentType: string): MediaType | undefined {
|
|
186
|
-
return knownMediaTypes.
|
|
186
|
+
return knownMediaTypes.has(contentType as MediaType) ? (contentType as MediaType) : undefined
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
/**
|
|
@@ -973,6 +973,7 @@ export function createOasParser(oas: Oas, { contentType, collisionDetection }: O
|
|
|
973
973
|
in: param['in'] as ParameterLocation,
|
|
974
974
|
schema: {
|
|
975
975
|
...schema,
|
|
976
|
+
description: (param['description'] as string | undefined) ?? schema.description,
|
|
976
977
|
optional: !required || !!schema.optional ? true : undefined,
|
|
977
978
|
},
|
|
978
979
|
required,
|
|
@@ -984,11 +985,7 @@ export function createOasParser(oas: Oas, { contentType, collisionDetection }: O
|
|
|
984
985
|
* request body, and all response codes into their AST node equivalents.
|
|
985
986
|
*/
|
|
986
987
|
function parseOperation(options: Options, oas: Oas, operation: Operation): OperationNode {
|
|
987
|
-
const parameters: Array<ParameterNode> =
|
|
988
|
-
const dereferenced = oas.dereferenceWithRef(param) as unknown as Record<string, unknown>
|
|
989
|
-
|
|
990
|
-
return parseParameter(options, dereferenced)
|
|
991
|
-
})
|
|
988
|
+
const parameters: Array<ParameterNode> = oas.getParameters(operation).map((param) => parseParameter(options, param as unknown as Record<string, unknown>))
|
|
992
989
|
|
|
993
990
|
const requestBodySchema = oas.getRequestSchema(operation)
|
|
994
991
|
const requestBody = requestBodySchema ? convertSchema({ schema: requestBodySchema }, options) : undefined
|
|
@@ -997,7 +994,10 @@ export function createOasParser(oas: Oas, { contentType, collisionDetection }: O
|
|
|
997
994
|
const responseObj = operation.getResponseByStatusCode(statusCode)
|
|
998
995
|
const responseSchema = oas.getResponseSchema(operation, statusCode)
|
|
999
996
|
|
|
1000
|
-
const schema =
|
|
997
|
+
const schema =
|
|
998
|
+
responseSchema && Object.keys(responseSchema).length > 0
|
|
999
|
+
? convertSchema({ schema: responseSchema }, options)
|
|
1000
|
+
: createSchema({ type: resolveTypeOption(options.emptySchemaType) })
|
|
1001
1001
|
|
|
1002
1002
|
const description = typeof responseObj === 'object' && responseObj !== null && !Array.isArray(responseObj) ? responseObj.description : undefined
|
|
1003
1003
|
|
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { collect, createProperty, createSchema, narrowSchema } from '@kubb/ast'
|
|
2
2
|
import type { SchemaNode } from '@kubb/ast/types'
|
|
3
3
|
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
4
|
+
import { SCALAR_PRIMITIVE_TYPES } from './constants.ts'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Extracts the schema name from a `$ref` string.
|
|
@@ -96,9 +97,13 @@ export function mergeAdjacentAnonymousObjects(members: Array<SchemaNode>): Array
|
|
|
96
97
|
*
|
|
97
98
|
* Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
|
|
98
99
|
* considered — object, array, and ref members are left untouched.
|
|
100
|
+
*
|
|
101
|
+
* Const-derived enums (those without an `enumType`, produced from an OpenAPI `const`
|
|
102
|
+
* keyword) are **never** removed — `'accepted' | string` must stay as-is because the
|
|
103
|
+
* literal is intentional.
|
|
99
104
|
*/
|
|
100
105
|
export function simplifyUnionMembers(members: Array<SchemaNode>): Array<SchemaNode> {
|
|
101
|
-
const scalarPrimitives = new Set(members.filter((m) =>
|
|
106
|
+
const scalarPrimitives = new Set(members.filter((m) => SCALAR_PRIMITIVE_TYPES.has(m.type as 'string')).map((m) => m.type as string))
|
|
102
107
|
if (!scalarPrimitives.size) return members
|
|
103
108
|
|
|
104
109
|
return members.filter((m) => {
|
|
@@ -106,6 +111,8 @@ export function simplifyUnionMembers(members: Array<SchemaNode>): Array<SchemaNo
|
|
|
106
111
|
const prim = m.primitive
|
|
107
112
|
// Keep the enum if its primitive isn't fully subsumed.
|
|
108
113
|
if (!prim) return true
|
|
114
|
+
// Const-derived enums have no `enumType`; keep them as intentional literals.
|
|
115
|
+
if (!m.enumType) return true
|
|
109
116
|
// `number` subsumes `integer` literals and vice-versa for our purposes.
|
|
110
117
|
if (scalarPrimitives.has(prim)) return false
|
|
111
118
|
if ((prim === 'integer' || prim === 'number') && (scalarPrimitives.has('integer') || scalarPrimitives.has('number'))) return false
|