@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/adapter-oas",
3
- "version": "5.0.0-beta.58",
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.58",
50
- "@kubb/core": "5.0.0-beta.58"
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; `hostname` and
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 `'any' | 'unknown' | 'void'` option strings to their `ScalarSchemaType` constant.
130
- * Replaces a plain object lookup with a `Map` for explicit key membership testing via `.has()`.
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],
@@ -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, findDiscriminator } from '@kubb/ast/utils'
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
- /** Identifies the rule when reading the table or debugging which branch ran. */
70
+ /**
71
+ * Identifies the rule when reading the table or debugging which branch ran.
72
+ */
70
73
  name: string
71
- /** Returns `true` when this rule is responsible for the given context. */
74
+ /**
75
+ * Returns `true` when this rule is responsible for the given context.
76
+ */
72
77
  match: (context: SchemaContext) => boolean
73
- /** Produces a node for the context, or `null` to fall through to the next rule. */
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, making them valid for downstream processing.
88
+ * from the array to its items sub-schema, so they are valid for downstream processing.
82
89
  *
83
- * @note This is a defensive measure for robustness with non-compliant specs.
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
- * made possible by hoisting of function declarations.
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(ast.factory.createDiscriminantNode({ propertyName, value }))
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
- ast.factory.createDiscriminantNode({
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
- * Use this for targeted schema parsing when you don't need the full spec.
1052
- * For complete spec parsing, use `parseOas()` instead which handles operations and all schemas together.
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 Circular schema references are tracked via internal state and resolve appropriately.
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, * the tree is a pure data structure representing all schemas and operations.
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`, signalling the format should fall through to `string`.
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); shapes without a name stay inline.
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); otherwise nested
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
- * Content-type string for selecting request/response schemas from an OpenAPI spec.
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
- * Enum values for this schema (narrowed from `unknown[]`).
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 as a lowercase string (`'get' | 'post' | ...`).
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 from a spec that contains schema, status code, and headers.
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 options for the OpenAPI adapter. Controls spec validation,
135
- * content-type selection, server URL resolution, and how types are derived
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: documentation such as
198
- * `description` and `example` is ignored. Enabled by default. Set to `false` to keep every
199
- * occurrence inline and produce byte-for-byte identical output to earlier versions.
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
  */