@kubb/ast 5.0.0-beta.28 → 5.0.0-beta.29

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/ast",
3
- "version": "5.0.0-beta.28",
3
+ "version": "5.0.0-beta.29",
4
4
  "description": "Spec-agnostic AST layer for Kubb. Defines the node tree, visitor pattern, factory functions, and type guards used across all code generation plugins.",
5
5
  "keywords": [
6
6
  "ast",
package/src/factory.ts CHANGED
@@ -322,21 +322,32 @@ export function createParameter(
322
322
  /**
323
323
  * Creates a `ResponseNode`.
324
324
  *
325
+ * Response body schemas live inside `content`. For convenience a single legacy `schema`
326
+ * (with optional `mediaType`/`keysToOmit`) is normalized into one `content` entry, so the same
327
+ * schema is never stored both at the node root and inside `content`.
328
+ *
325
329
  * @example
326
330
  * ```ts
327
331
  * const response = createResponse({
328
332
  * statusCode: '200',
329
- * description: 'Success',
330
- * schema: createSchema({ type: 'object', properties: [] }),
333
+ * content: [{ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) }],
331
334
  * })
332
335
  * ```
333
336
  */
334
337
  export function createResponse(
335
- props: Pick<ResponseNode, 'statusCode' | 'schema'> & Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'schema'>>,
338
+ props: Pick<ResponseNode, 'statusCode'> &
339
+ Partial<Omit<ResponseNode, 'kind' | 'statusCode'>> & {
340
+ schema?: SchemaNode
341
+ mediaType?: string | null
342
+ keysToOmit?: Array<string> | null
343
+ },
336
344
  ): ResponseNode {
345
+ const { schema, mediaType, keysToOmit, content, ...rest } = props
346
+
337
347
  return {
338
- ...props,
348
+ ...rest,
339
349
  kind: 'Response',
350
+ content: content ?? (schema ? [{ contentType: mediaType ?? 'application/json', schema, keysToOmit: keysToOmit ?? null }] : undefined),
340
351
  }
341
352
  }
342
353
 
@@ -1,16 +1,20 @@
1
1
  import type { BaseNode } from './base.ts'
2
- import type { MediaType, StatusCode } from './http.ts'
2
+ import type { StatusCode } from './http.ts'
3
3
  import type { SchemaNode } from './schema.ts'
4
4
 
5
5
  /**
6
6
  * AST node representing one operation response variant.
7
7
  *
8
+ * Mirrors {@link OperationNode.requestBody}: the response body schemas live exclusively inside
9
+ * the `content` array (one entry per content type), so the same schema is never duplicated at the
10
+ * node root and inside `content`.
11
+ *
8
12
  * @example
9
13
  * ```ts
10
14
  * const response: ResponseNode = {
11
15
  * kind: 'Response',
12
16
  * statusCode: '200',
13
- * schema: createSchema({ type: 'string' }),
17
+ * content: [{ contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
14
18
  * }
15
19
  * ```
16
20
  */
@@ -28,16 +32,33 @@ export type ResponseNode = BaseNode & {
28
32
  */
29
33
  description?: string
30
34
  /**
31
- * Response body schema.
32
- */
33
- schema: SchemaNode
34
- /**
35
- * Response media type.
36
- */
37
- mediaType?: MediaType | null
38
- /**
39
- * Property keys to exclude from the generated type via `Omit<Type, Keys>`.
40
- * Set when a referenced schema has `writeOnly` fields that should not appear in response types.
35
+ * All available content type entries for this response.
36
+ *
37
+ * When the adapter `contentType` option is set, this array contains exactly one entry for that
38
+ * content type. Otherwise it contains one entry per content type declared in the spec, so that
39
+ * plugins can generate a union of response types (e.g. `application/json` and `application/xml`).
40
+ * Body-less responses keep a single entry whose `schema` is the empty/`void` placeholder.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * // spec response declares both application/json and application/xml
45
+ * response.content[0].contentType // 'application/json'
46
+ * response.content[1].contentType // 'application/xml'
47
+ * ```
41
48
  */
42
- keysToOmit?: Array<string> | null
49
+ content?: Array<{
50
+ /**
51
+ * The content type for this entry (e.g. `'application/json'`).
52
+ */
53
+ contentType: string
54
+ /**
55
+ * Response body schema for this content type.
56
+ */
57
+ schema?: SchemaNode
58
+ /**
59
+ * Property keys to exclude from the generated type via `Omit<Type, Keys>`.
60
+ * Set when a referenced schema has `writeOnly` fields that should not appear in response types.
61
+ */
62
+ keysToOmit?: Array<string> | null
63
+ }>
43
64
  }
package/src/visitor.ts CHANGED
@@ -319,7 +319,11 @@ function* getChildren(node: Node, recurse: boolean): Generator<Node, void, undef
319
319
  return
320
320
  }
321
321
  if (node.kind === 'Response') {
322
- if (node.schema) yield node.schema
322
+ if (node.content) {
323
+ for (const c of node.content) {
324
+ if (c.schema) yield c.schema
325
+ }
326
+ }
323
327
  return
324
328
  }
325
329
  }
@@ -498,7 +502,10 @@ export function transform(node: Node, options: TransformOptions): Node {
498
502
 
499
503
  return {
500
504
  ...response,
501
- schema: transform(response.schema, { ...options, parent: response }),
505
+ content: response.content?.map((entry) => ({
506
+ ...entry,
507
+ schema: entry.schema ? transform(entry.schema, { ...options, parent: response }) : entry.schema,
508
+ })),
502
509
  }
503
510
  }
504
511