@kubb/adapter-oas 5.0.0-beta.58 → 5.0.0-beta.59
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 +126 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +9 -11
- package/dist/index.js +125 -89
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/constants.ts +3 -3
- package/src/discriminator.ts +40 -0
- package/src/parser.ts +22 -13
- package/src/resolvers.ts +1 -1
- package/src/stream.ts +2 -2
- package/src/types.ts +9 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/adapter-oas",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.59",
|
|
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",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"api-ref-bundler": "0.5.1",
|
|
47
47
|
"swagger2openapi": "^7.0.8",
|
|
48
48
|
"yaml": "^2.9.0",
|
|
49
|
-
"@kubb/ast": "5.0.0-beta.
|
|
50
|
-
"@kubb/core": "5.0.0-beta.
|
|
49
|
+
"@kubb/ast": "5.0.0-beta.59",
|
|
50
|
+
"@kubb/core": "5.0.0-beta.59"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/json-schema": "^7.0.15",
|
package/src/constants.ts
CHANGED
|
@@ -73,7 +73,7 @@ export const structuralKeys = new Set(['properties', 'items', 'additionalPropert
|
|
|
73
73
|
*
|
|
74
74
|
* Only formats whose AST type differs from the OAS `type` field appear here.
|
|
75
75
|
* Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled separately
|
|
76
|
-
* in the parser. `ipv4` and `ipv6` map to their own dedicated schema types
|
|
76
|
+
* in the parser. `ipv4` and `ipv6` map to their own dedicated schema types. `hostname` and
|
|
77
77
|
* `idn-hostname` map to `'url'` as the closest generic string-format type.
|
|
78
78
|
*
|
|
79
79
|
* @example
|
|
@@ -126,8 +126,8 @@ export const formatMap = {
|
|
|
126
126
|
export const enumExtensionKeys = ['x-enumNames', 'x-enum-varnames'] as const
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
* Maps
|
|
130
|
-
*
|
|
129
|
+
* Maps the `unknownType`/`emptySchemaType` option string to its `ScalarSchemaType` constant.
|
|
130
|
+
* A `Map` (over a plain object) lets callers test key membership with `.has()`.
|
|
131
131
|
*/
|
|
132
132
|
export const typeOptionMap = new Map<'any' | 'unknown' | 'void', ast.ScalarSchemaType>([
|
|
133
133
|
['any', ast.schemaTypes.any],
|
package/src/discriminator.ts
CHANGED
|
@@ -90,3 +90,43 @@ export function patchDiscriminatorNode(node: ast.SchemaNode, entry: { propertyNa
|
|
|
90
90
|
|
|
91
91
|
return { ...objectNode, properties: newProperties }
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Creates a single-property object schema used as a discriminator literal.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* createDiscriminantNode({ propertyName: 'type', value: 'dog' })
|
|
100
|
+
* // -> { type: 'object', properties: [{ name: 'type', required: true, schema: enum('dog') }] }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export function createDiscriminantNode({ propertyName, value }: { propertyName: string; value: string }): ast.SchemaNode {
|
|
104
|
+
return ast.factory.createSchema({
|
|
105
|
+
type: 'object',
|
|
106
|
+
primitive: 'object',
|
|
107
|
+
properties: [
|
|
108
|
+
ast.factory.createProperty({
|
|
109
|
+
name: propertyName,
|
|
110
|
+
schema: ast.factory.createSchema({
|
|
111
|
+
type: 'enum',
|
|
112
|
+
primitive: 'string',
|
|
113
|
+
enumValues: [value],
|
|
114
|
+
}),
|
|
115
|
+
required: true,
|
|
116
|
+
}),
|
|
117
|
+
],
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Returns the discriminator key whose mapping value matches `ref`, or `null` when there is no match.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* findDiscriminator({ dog: '#/components/schemas/Dog' }, '#/components/schemas/Dog') // 'dog'
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export function findDiscriminator(mapping: Record<string, string> | undefined, ref: string | undefined): string | null {
|
|
130
|
+
if (!mapping || !ref) return null
|
|
131
|
+
return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null
|
|
132
|
+
}
|
package/src/parser.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { pascalCase } from '@internals/utils'
|
|
2
|
-
import { childName, enumPropName, extractRefName
|
|
2
|
+
import { childName, enumPropName, extractRefName } from '@kubb/ast/utils'
|
|
3
3
|
import { ast } from '@kubb/core'
|
|
4
4
|
import { DEFAULT_PARSER_OPTIONS, enumExtensionKeys, SCHEMA_REF_PREFIX, typeOptionMap } from './constants.ts'
|
|
5
5
|
import { oasDialect, type OasDialect } from './dialect.ts'
|
|
6
|
+
import { createDiscriminantNode, findDiscriminator } from './discriminator.ts'
|
|
6
7
|
import { getOperationId, getOperations, getRequestContentType, getResponseByStatusCode, getResponseStatusCodes } from './operation.ts'
|
|
7
8
|
import {
|
|
8
9
|
buildSchemaNode,
|
|
@@ -66,11 +67,17 @@ type SchemaContext = {
|
|
|
66
67
|
* that is not convertible falls through to plain `type` handling).
|
|
67
68
|
*/
|
|
68
69
|
type SchemaRule = {
|
|
69
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Identifies the rule when reading the table or debugging which branch ran.
|
|
72
|
+
*/
|
|
70
73
|
name: string
|
|
71
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Returns `true` when this rule is responsible for the given context.
|
|
76
|
+
*/
|
|
72
77
|
match: (context: SchemaContext) => boolean
|
|
73
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Produces a node for the context, or `null` to fall through to the next rule.
|
|
80
|
+
*/
|
|
74
81
|
convert: (context: SchemaContext) => ast.SchemaNode | null
|
|
75
82
|
}
|
|
76
83
|
|
|
@@ -78,9 +85,9 @@ type SchemaRule = {
|
|
|
78
85
|
* Normalizes malformed `{ type: 'array', enum: [...] }` schemas by moving enum values into items.
|
|
79
86
|
*
|
|
80
87
|
* This pattern violates the OpenAPI spec but appears in real specs. The fix moves enum values
|
|
81
|
-
* from the array to its items sub-schema,
|
|
88
|
+
* from the array to its items sub-schema, so they are valid for downstream processing.
|
|
82
89
|
*
|
|
83
|
-
* @note
|
|
90
|
+
* @note A defensive measure for non-compliant specs.
|
|
84
91
|
*/
|
|
85
92
|
function normalizeArrayEnum(schema: SchemaObject): SchemaObject {
|
|
86
93
|
const isItemsObject = typeof schema.items === 'object' && !Array.isArray(schema.items)
|
|
@@ -98,7 +105,7 @@ function normalizeArrayEnum(schema: SchemaObject): SchemaObject {
|
|
|
98
105
|
*
|
|
99
106
|
* Returns closures that share mutable state (`resolvingRefs` set for cycle detection).
|
|
100
107
|
* Each converter branch (`convertRef`, `convertAllOf`, etc.) mutually recursively calls `parseSchema`,
|
|
101
|
-
*
|
|
108
|
+
* which works because function declarations hoist.
|
|
102
109
|
*
|
|
103
110
|
* @internal
|
|
104
111
|
*/
|
|
@@ -264,7 +271,7 @@ export function createSchemaParser(ctx: OasParserContext, dialect: OasDialect =
|
|
|
264
271
|
}
|
|
265
272
|
|
|
266
273
|
for (const { propertyName, value } of filteredDiscriminantValues) {
|
|
267
|
-
allOfMembers.push(
|
|
274
|
+
allOfMembers.push(createDiscriminantNode({ propertyName, value }))
|
|
268
275
|
}
|
|
269
276
|
|
|
270
277
|
return ast.factory.createSchema({
|
|
@@ -337,7 +344,7 @@ export function createSchemaParser(ctx: OasParserContext, dialect: OasDialect =
|
|
|
337
344
|
members: [
|
|
338
345
|
memberNode,
|
|
339
346
|
narrowedDiscriminatorNode ??
|
|
340
|
-
|
|
347
|
+
createDiscriminantNode({
|
|
341
348
|
propertyName: discriminator.propertyName,
|
|
342
349
|
value: discriminatorValue,
|
|
343
350
|
}),
|
|
@@ -1048,10 +1055,11 @@ export function createSchemaParser(ctx: OasParserContext, dialect: OasDialect =
|
|
|
1048
1055
|
/**
|
|
1049
1056
|
* Parses a single OpenAPI `SchemaObject` into a `SchemaNode`.
|
|
1050
1057
|
*
|
|
1051
|
-
*
|
|
1052
|
-
*
|
|
1058
|
+
* Reach for this when you only need one schema, not the whole spec. To parse a full spec
|
|
1059
|
+
* with its operations and schemas, call `parseOas()`.
|
|
1053
1060
|
*
|
|
1054
|
-
* @note
|
|
1061
|
+
* @note Internal state tracks `$ref` paths under resolution, so circular schemas stop
|
|
1062
|
+
* recursing instead of looping.
|
|
1055
1063
|
*
|
|
1056
1064
|
* @example
|
|
1057
1065
|
* ```ts
|
|
@@ -1072,7 +1080,8 @@ export function parseSchema(
|
|
|
1072
1080
|
* Parses an OpenAPI specification into Kubb's universal `InputNode` AST.
|
|
1073
1081
|
*
|
|
1074
1082
|
* This is the main entry point for `@kubb/adapter-oas`. It converts OpenAPI/Swagger specs into a spec-agnostic tree
|
|
1075
|
-
* that downstream plugins (`plugin-ts`, `plugin-zod`, etc.) consume for code generation. No code is generated here
|
|
1083
|
+
* that downstream plugins (`plugin-ts`, `plugin-zod`, etc.) consume for code generation. No code is generated here.
|
|
1084
|
+
* The tree is a pure data structure of all schemas and operations.
|
|
1076
1085
|
*
|
|
1077
1086
|
* Returns the AST root and a `nameMapping` for resolving schema references.
|
|
1078
1087
|
*
|
package/src/resolvers.ts
CHANGED
|
@@ -470,7 +470,7 @@ export function getSchemas(document: Document, { contentType }: GetSchemasOption
|
|
|
470
470
|
|
|
471
471
|
/**
|
|
472
472
|
* Resolves the AST type descriptor for a date/time format, honoring the `dateType` option.
|
|
473
|
-
* Returns `null` when `dateType: false`,
|
|
473
|
+
* Returns `null` when `dateType: false`, so the format falls through to `string`.
|
|
474
474
|
*/
|
|
475
475
|
export function getDateType(
|
|
476
476
|
options: ast.ParserOptions,
|
package/src/stream.ts
CHANGED
|
@@ -23,7 +23,7 @@ export type PreScanResult = {
|
|
|
23
23
|
*
|
|
24
24
|
* Only enums and objects are candidates, and object shapes that reference a circular schema are
|
|
25
25
|
* rejected to avoid hoisting recursive structures. Inline shapes reuse their context-derived
|
|
26
|
-
* name (collision-resolved against existing component names)
|
|
26
|
+
* name (collision-resolved against existing component names). Shapes without a name stay inline.
|
|
27
27
|
*/
|
|
28
28
|
function createDedupePlan({
|
|
29
29
|
schemaNodes,
|
|
@@ -218,7 +218,7 @@ export function createInputStream({
|
|
|
218
218
|
meta: ast.InputMeta
|
|
219
219
|
}): ast.InputNode<true> {
|
|
220
220
|
// Rewrites a top-level schema against the dedupe plan: a structurally identical sibling
|
|
221
|
-
// becomes a `ref` alias to the canonical one (keeping its own name)
|
|
221
|
+
// becomes a `ref` alias to the canonical one (keeping its own name). Otherwise nested
|
|
222
222
|
// duplicates are collapsed while the schema's own root is preserved.
|
|
223
223
|
const rewriteTopLevelSchema = (node: ast.SchemaNode): ast.SchemaNode => {
|
|
224
224
|
if (!dedupePlan) return node
|
package/src/types.ts
CHANGED
|
@@ -7,8 +7,7 @@ import type { Operation } from './operation.ts'
|
|
|
7
7
|
export type { Operation }
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* Supports `'application/json'` or any other media type.
|
|
10
|
+
* Media type used to pick a schema from an operation's request or response.
|
|
12
11
|
*
|
|
13
12
|
* @example
|
|
14
13
|
* ```ts
|
|
@@ -68,13 +67,13 @@ export type SchemaObject = {
|
|
|
68
67
|
*/
|
|
69
68
|
items?: SchemaObject | ReferenceObject
|
|
70
69
|
/**
|
|
71
|
-
*
|
|
70
|
+
* Allowed values for this schema.
|
|
72
71
|
*/
|
|
73
72
|
enum?: Array<string | number | boolean | null>
|
|
74
73
|
} & (OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject | JSONSchema4 | JSONSchema6 | JSONSchema7)
|
|
75
74
|
|
|
76
75
|
/**
|
|
77
|
-
* HTTP method
|
|
76
|
+
* HTTP method in the lowercase form an OpenAPI path item uses for its keys.
|
|
78
77
|
*/
|
|
79
78
|
export type HttpMethod = Lowercase<ast.HttpMethod>
|
|
80
79
|
|
|
@@ -104,7 +103,7 @@ export type DiscriminatorObject = OpenAPIV3.DiscriminatorObject | OpenAPIV3_1.Di
|
|
|
104
103
|
export type ReferenceObject = OpenAPIV3.ReferenceObject
|
|
105
104
|
|
|
106
105
|
/**
|
|
107
|
-
* OpenAPI response object
|
|
106
|
+
* OpenAPI response object holding the content and headers for one status code.
|
|
108
107
|
*/
|
|
109
108
|
export type ResponseObject = OpenAPIV3.ResponseObject | OpenAPIV3_1.ResponseObject
|
|
110
109
|
|
|
@@ -131,9 +130,8 @@ export type ParameterObject = {
|
|
|
131
130
|
export type ServerObject = OpenAPIV3.ServerObject | OpenAPIV3_1.ServerObject
|
|
132
131
|
|
|
133
132
|
/**
|
|
134
|
-
* Configuration
|
|
135
|
-
*
|
|
136
|
-
* from the spec.
|
|
133
|
+
* Configuration for the OpenAPI adapter: spec validation, content-type selection,
|
|
134
|
+
* server URL resolution, and how schema types are derived.
|
|
137
135
|
*
|
|
138
136
|
* @example
|
|
139
137
|
* ```ts
|
|
@@ -194,9 +192,9 @@ export type AdapterOasOptions = {
|
|
|
194
192
|
*
|
|
195
193
|
* Duplicated inline shapes (especially enums repeated across many properties) are hoisted
|
|
196
194
|
* into one named schema. Every other occurrence, and any structurally identical top-level
|
|
197
|
-
* component, becomes a `ref` to it. Equality is shape-only
|
|
198
|
-
* `description` and `example` is ignored.
|
|
199
|
-
*
|
|
195
|
+
* component, becomes a `ref` to it. Equality is shape-only, so documentation such as
|
|
196
|
+
* `description` and `example` is ignored. Set to `false` to keep every occurrence inline
|
|
197
|
+
* and produce byte-for-byte identical output to earlier versions.
|
|
200
198
|
*
|
|
201
199
|
* @default true
|
|
202
200
|
*/
|