@kubb/ast 5.0.0-beta.60 → 5.0.0-beta.62

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.
Files changed (87) hide show
  1. package/README.md +2 -1
  2. package/dist/defineMacro-BryDiuQl.cjs +115 -0
  3. package/dist/defineMacro-BryDiuQl.cjs.map +1 -0
  4. package/dist/defineMacro-CNkUpxia.js +99 -0
  5. package/dist/defineMacro-CNkUpxia.js.map +1 -0
  6. package/dist/defineMacro-Vw-xQvq7.d.ts +467 -0
  7. package/dist/factory.cjs +64 -4
  8. package/dist/factory.cjs.map +1 -0
  9. package/dist/factory.d.ts +2 -37
  10. package/dist/factory.js +58 -3
  11. package/dist/factory.js.map +1 -0
  12. package/dist/{index-BzjwdK2M.d.ts → index-CTaN_ee_.d.ts} +235 -198
  13. package/dist/index.cjs +33 -32
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +36 -36
  16. package/dist/index.js +19 -14
  17. package/dist/index.js.map +1 -1
  18. package/dist/macros.cjs +130 -0
  19. package/dist/macros.cjs.map +1 -0
  20. package/dist/macros.d.ts +61 -0
  21. package/dist/macros.js +128 -0
  22. package/dist/macros.js.map +1 -0
  23. package/dist/{operationParams-BZ07xDm0.d.ts → operationParams-B44p6EQy.d.ts} +2 -2
  24. package/dist/{response-DS5S3IG4.cjs → response-BeG6hq2D.cjs} +389 -173
  25. package/dist/response-BeG6hq2D.cjs.map +1 -0
  26. package/dist/{response-DKxTr522.js → response-Rd1uisM1.js} +377 -162
  27. package/dist/response-Rd1uisM1.js.map +1 -0
  28. package/dist/types-DQTgVSwE.d.ts +314 -0
  29. package/dist/types.d.ts +5 -5
  30. package/dist/{utils-D83JA6Xx.cjs → utils-BDI3kXlb.cjs} +20 -753
  31. package/dist/utils-BDI3kXlb.cjs.map +1 -0
  32. package/dist/{utils-Dj_KoXMv.js → utils-DW9rnfsD.js} +11 -630
  33. package/dist/utils-DW9rnfsD.js.map +1 -0
  34. package/dist/utils.cjs +11 -9
  35. package/dist/utils.d.ts +38 -4
  36. package/dist/utils.js +4 -3
  37. package/dist/visitor-B7Zlnp4c.cjs +604 -0
  38. package/dist/visitor-B7Zlnp4c.cjs.map +1 -0
  39. package/dist/visitor-DepQEKyp.js +510 -0
  40. package/dist/visitor-DepQEKyp.js.map +1 -0
  41. package/package.json +5 -1
  42. package/src/constants.ts +0 -30
  43. package/src/dedupe.ts +1 -9
  44. package/src/defineMacro.ts +139 -0
  45. package/src/{node.ts → defineNode.ts} +19 -42
  46. package/src/dialect.ts +42 -19
  47. package/src/factory.ts +3 -90
  48. package/src/index.ts +9 -15
  49. package/src/macros/index.ts +3 -0
  50. package/src/macros/macroDiscriminatorEnum.ts +50 -0
  51. package/src/macros/macroEnumName.ts +33 -0
  52. package/src/macros/macroSimplifyUnion.ts +60 -0
  53. package/src/nodes/code.ts +32 -75
  54. package/src/nodes/content.ts +2 -7
  55. package/src/nodes/file.ts +102 -14
  56. package/src/nodes/function.ts +46 -46
  57. package/src/nodes/index.ts +2 -3
  58. package/src/nodes/input.ts +13 -9
  59. package/src/nodes/operation.ts +5 -5
  60. package/src/nodes/output.ts +1 -1
  61. package/src/nodes/parameter.ts +6 -6
  62. package/src/nodes/property.ts +6 -6
  63. package/src/nodes/requestBody.ts +6 -13
  64. package/src/nodes/response.ts +93 -8
  65. package/src/nodes/schema.ts +1 -1
  66. package/src/registry.ts +1 -1
  67. package/src/types.ts +4 -4
  68. package/src/utils/extractStringsFromNodes.ts +1 -0
  69. package/src/utils/index.ts +2 -2
  70. package/src/utils/operationParams.ts +1 -1
  71. package/src/utils/refs.ts +27 -1
  72. package/src/utils/schemaMerge.ts +34 -0
  73. package/src/visitor.ts +2 -13
  74. package/dist/extractStringsFromNodes-WMYJ8nQL.d.ts +0 -82
  75. package/dist/factory-Cl8Z7mcc.cjs +0 -299
  76. package/dist/factory-Cl8Z7mcc.cjs.map +0 -1
  77. package/dist/factory-Du7nEP4B.js +0 -282
  78. package/dist/factory-Du7nEP4B.js.map +0 -1
  79. package/dist/response-DKxTr522.js.map +0 -1
  80. package/dist/response-DS5S3IG4.cjs.map +0 -1
  81. package/dist/types-olVl9v5p.d.ts +0 -764
  82. package/dist/utils-D83JA6Xx.cjs.map +0 -1
  83. package/dist/utils-Dj_KoXMv.js.map +0 -1
  84. package/src/mocks.ts +0 -56
  85. package/src/nodes/http.ts +0 -85
  86. package/src/transformers.ts +0 -191
  87. /package/src/{printer.ts → definePrinter.ts} +0 -0
package/src/nodes/code.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { defineNode } from '../node.ts'
1
+ import { defineNode } from '../defineNode.ts'
2
2
  import type { BaseNode } from './base.ts'
3
3
 
4
4
  /**
@@ -164,55 +164,12 @@ export type FunctionNode = BaseNode & {
164
164
  * // export const getPet = () => ...
165
165
  * ```
166
166
  */
167
- export type ArrowFunctionNode = BaseNode & {
167
+ export type ArrowFunctionNode = Omit<FunctionNode, 'kind'> & {
168
168
  kind: 'ArrowFunction'
169
- /**
170
- * Name of the arrow function (used as the `const` variable name).
171
- */
172
- name: string
173
- /**
174
- * Whether the function is a default export.
175
- */
176
- default?: boolean | null
177
- /**
178
- * Function parameter list rendered as a string (e.g. from `FunctionParams.toConstructor()`).
179
- */
180
- params?: string | null
181
- /**
182
- * Whether the arrow function should be exported.
183
- */
184
- export?: boolean | null
185
- /**
186
- * Whether the arrow function is async. When `true`, the return type is wrapped in `Promise<>`.
187
- */
188
- async?: boolean | null
189
- /**
190
- * TypeScript generic type parameters.
191
- *
192
- * @example Constrained generics
193
- * `['T', 'U extends string']`
194
- */
195
- generics?: string | Array<string> | null
196
- /**
197
- * Return type annotation.
198
- *
199
- * @example Type reference
200
- * `'Pet'`
201
- */
202
- returnType?: string | null
203
- /**
204
- * JSDoc documentation metadata.
205
- */
206
- JSDoc?: JSDocNode | null
207
169
  /**
208
170
  * Render the arrow function body as a single-line expression.
209
171
  */
210
172
  singleLine?: boolean | null
211
- /**
212
- * Child nodes representing the function body (children of the `Function.Arrow` component).
213
- * Each entry is a {@link CodeNode}. Use {@link TextNode} for raw string content.
214
- */
215
- nodes?: Array<CodeNode>
216
173
  }
217
174
 
218
175
  /**
@@ -285,6 +242,36 @@ export type CodeNode = ConstNode | TypeNode | FunctionNode | ArrowFunctionNode |
285
242
  */
286
243
  export const constDef = defineNode<ConstNode>({ kind: 'Const' })
287
244
 
245
+ /**
246
+ * Definition for the {@link TypeNode}.
247
+ */
248
+ export const typeDef = defineNode<TypeNode>({ kind: 'Type' })
249
+
250
+ /**
251
+ * Definition for the {@link FunctionNode}.
252
+ */
253
+ export const functionDef = defineNode<FunctionNode>({ kind: 'Function' })
254
+
255
+ /**
256
+ * Definition for the {@link ArrowFunctionNode}.
257
+ */
258
+ export const arrowFunctionDef = defineNode<ArrowFunctionNode>({ kind: 'ArrowFunction' })
259
+
260
+ /**
261
+ * Definition for the {@link TextNode}.
262
+ */
263
+ export const textDef = defineNode<TextNode, string>({ kind: 'Text', build: (value) => ({ value }) })
264
+
265
+ /**
266
+ * Definition for the {@link BreakNode}.
267
+ */
268
+ export const breakDef = defineNode<BreakNode, void>({ kind: 'Break', build: () => ({}) })
269
+
270
+ /**
271
+ * Definition for the {@link JsxNode}.
272
+ */
273
+ export const jsxDef = defineNode<JsxNode, string>({ kind: 'Jsx', build: (value) => ({ value }) })
274
+
288
275
  /**
289
276
  * Creates a `ConstNode` representing a TypeScript `const` declaration.
290
277
  *
@@ -296,11 +283,6 @@ export const constDef = defineNode<ConstNode>({ kind: 'Const' })
296
283
  */
297
284
  export const createConst = constDef.create
298
285
 
299
- /**
300
- * Definition for the {@link TypeNode}.
301
- */
302
- export const typeDef = defineNode<TypeNode>({ kind: 'Type' })
303
-
304
286
  /**
305
287
  * Creates a `TypeNode` representing a TypeScript `type` alias declaration.
306
288
  *
@@ -312,11 +294,6 @@ export const typeDef = defineNode<TypeNode>({ kind: 'Type' })
312
294
  */
313
295
  export const createType = typeDef.create
314
296
 
315
- /**
316
- * Definition for the {@link FunctionNode}.
317
- */
318
- export const functionDef = defineNode<FunctionNode>({ kind: 'Function' })
319
-
320
297
  /**
321
298
  * Creates a `FunctionNode` representing a TypeScript `function` declaration.
322
299
  *
@@ -328,11 +305,6 @@ export const functionDef = defineNode<FunctionNode>({ kind: 'Function' })
328
305
  */
329
306
  export const createFunction = functionDef.create
330
307
 
331
- /**
332
- * Definition for the {@link ArrowFunctionNode}.
333
- */
334
- export const arrowFunctionDef = defineNode<ArrowFunctionNode>({ kind: 'ArrowFunction' })
335
-
336
308
  /**
337
309
  * Creates an `ArrowFunctionNode` representing a TypeScript arrow function.
338
310
  *
@@ -344,11 +316,6 @@ export const arrowFunctionDef = defineNode<ArrowFunctionNode>({ kind: 'ArrowFunc
344
316
  */
345
317
  export const createArrowFunction = arrowFunctionDef.create
346
318
 
347
- /**
348
- * Definition for the {@link TextNode}.
349
- */
350
- export const textDef = defineNode<TextNode, string>({ kind: 'Text', build: (value) => ({ value }) })
351
-
352
319
  /**
353
320
  * Creates a {@link TextNode} representing a raw string fragment in the source output.
354
321
  *
@@ -360,11 +327,6 @@ export const textDef = defineNode<TextNode, string>({ kind: 'Text', build: (valu
360
327
  */
361
328
  export const createText = textDef.create
362
329
 
363
- /**
364
- * Definition for the {@link BreakNode}.
365
- */
366
- export const breakDef = defineNode<BreakNode, void>({ kind: 'Break', build: () => ({}) })
367
-
368
330
  /**
369
331
  * Creates a {@link BreakNode} representing a line break in the source output.
370
332
  *
@@ -378,11 +340,6 @@ export function createBreak(): BreakNode {
378
340
  return breakDef.create()
379
341
  }
380
342
 
381
- /**
382
- * Definition for the {@link JsxNode}.
383
- */
384
- export const jsxDef = defineNode<JsxNode, string>({ kind: 'Jsx', build: (value) => ({ value }) })
385
-
386
343
  /**
387
344
  * Creates a {@link JsxNode} representing a raw JSX fragment in the source output.
388
345
  *
@@ -1,4 +1,4 @@
1
- import { defineNode } from '../node.ts'
1
+ import { defineNode } from '../defineNode.ts'
2
2
  import type { BaseNode } from './base.ts'
3
3
  import type { SchemaNode } from './schema.ts'
4
4
 
@@ -37,15 +37,10 @@ export type ContentNode = BaseNode & {
37
37
  keysToOmit?: Array<string> | null
38
38
  }
39
39
 
40
- /**
41
- * Loosely-typed content entry accepted by the builders, normalized into a {@link ContentNode}.
42
- */
43
- export type UserContent = Omit<ContentNode, 'kind'>
44
-
45
40
  /**
46
41
  * Definition for the {@link ContentNode}.
47
42
  */
48
- export const contentDef = defineNode<ContentNode, UserContent>({
43
+ export const contentDef = defineNode<ContentNode>({
49
44
  kind: 'Content',
50
45
  children: ['schema'],
51
46
  })
package/src/nodes/file.ts CHANGED
@@ -1,4 +1,9 @@
1
- import { defineNode } from '../node.ts'
1
+ import { hash } from 'node:crypto'
2
+ import path from 'node:path'
3
+ import { trimExtName } from '@internals/utils'
4
+ import { defineNode } from '../defineNode.ts'
5
+ import { extractStringsFromNodes } from '../utils/extractStringsFromNodes.ts'
6
+ import { combineExports, combineImports, combineSources } from '../utils/fileMerge.ts'
2
7
  import type { BaseNode } from './base.ts'
3
8
  import type { CodeNode } from './code.ts'
4
9
 
@@ -242,6 +247,22 @@ export type FileNode<TMeta extends object = object> = BaseNode & {
242
247
  */
243
248
  export const importDef = defineNode<ImportNode>({ kind: 'Import' })
244
249
 
250
+ /**
251
+ * Definition for the {@link ExportNode}.
252
+ */
253
+ export const exportDef = defineNode<ExportNode>({ kind: 'Export' })
254
+
255
+ /**
256
+ * Definition for the {@link SourceNode}.
257
+ */
258
+ export const sourceDef = defineNode<SourceNode>({ kind: 'Source' })
259
+
260
+ /**
261
+ * Definition for the {@link FileNode}. The fully resolved builder lives in
262
+ * `createFile`, so this definition only supplies the guard.
263
+ */
264
+ export const fileDef = defineNode<FileNode>({ kind: 'File' })
265
+
245
266
  /**
246
267
  * Creates an `ImportNode` representing a language-agnostic import/dependency declaration.
247
268
  *
@@ -253,11 +274,6 @@ export const importDef = defineNode<ImportNode>({ kind: 'Import' })
253
274
  */
254
275
  export const createImport = importDef.create
255
276
 
256
- /**
257
- * Definition for the {@link ExportNode}.
258
- */
259
- export const exportDef = defineNode<ExportNode>({ kind: 'Export' })
260
-
261
277
  /**
262
278
  * Creates an `ExportNode` representing a language-agnostic export/public API declaration.
263
279
  *
@@ -269,11 +285,6 @@ export const exportDef = defineNode<ExportNode>({ kind: 'Export' })
269
285
  */
270
286
  export const createExport = exportDef.create
271
287
 
272
- /**
273
- * Definition for the {@link SourceNode}.
274
- */
275
- export const sourceDef = defineNode<SourceNode>({ kind: 'Source' })
276
-
277
288
  /**
278
289
  * Creates a `SourceNode` representing a fragment of source code within a file.
279
290
  *
@@ -285,7 +296,84 @@ export const sourceDef = defineNode<SourceNode>({ kind: 'Source' })
285
296
  export const createSource = sourceDef.create
286
297
 
287
298
  /**
288
- * Definition for the {@link FileNode}. The fully resolved builder lives in
289
- * `createFile`, so this definition only supplies the guard.
299
+ * Input descriptor for {@link createFile}, before `id`, `name`, and `extname` are computed
300
+ * and `imports`/`exports`/`sources` are deduplicated.
290
301
  */
291
- export const fileDef = defineNode<FileNode>({ kind: 'File' })
302
+ export type UserFileNode<TMeta extends object = object> = Omit<FileNode<TMeta>, 'kind' | 'id' | 'name' | 'extname' | 'imports' | 'exports' | 'sources'> &
303
+ Pick<Partial<FileNode<TMeta>>, 'imports' | 'exports' | 'sources'>
304
+
305
+ /**
306
+ * Creates a fully resolved `FileNode` from a file input descriptor.
307
+ *
308
+ * Computes:
309
+ * - `id` SHA256 hash of the file path
310
+ * - `name` `baseName` without extension
311
+ * - `extname` extension extracted from `baseName`
312
+ *
313
+ * Deduplicates:
314
+ * - `sources` via `combineSources`
315
+ * - `exports` via `combineExports`
316
+ * - `imports` via `combineImports` (also filters unused imports)
317
+ *
318
+ * @throws {Error} when `baseName` has no extension.
319
+ *
320
+ * @example
321
+ * ```ts
322
+ * const file = createFile({
323
+ * baseName: 'petStore.ts',
324
+ * path: 'src/models/petStore.ts',
325
+ * sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')] })],
326
+ * imports: [createImport({ name: ['z'], path: 'zod' })],
327
+ * exports: [createExport({ name: ['Pet'], path: './petStore' })],
328
+ * })
329
+ * // file.id = SHA256 hash of 'src/models/petStore.ts'
330
+ * // file.name = 'petStore'
331
+ * // file.extname = '.ts'
332
+ * ```
333
+ */
334
+ export function createFile<TMeta extends object = object>(input: UserFileNode<TMeta>): FileNode<TMeta> {
335
+ const rawExtname = path.extname(input.baseName)
336
+ // Handle dotfile basename like '.ts' where path.extname returns ''
337
+ const extname = (rawExtname || (input.baseName.startsWith('.') ? input.baseName : '')) as `.${string}`
338
+ if (!extname) {
339
+ throw new Error(`No extname found for ${input.baseName}`)
340
+ }
341
+
342
+ const source = (input.sources ?? [])
343
+ .flatMap((item) => item.nodes ?? [])
344
+ .map((node) => extractStringsFromNodes([node]))
345
+ .filter(Boolean)
346
+ .join('\n\n')
347
+ const resolvedExports = input.exports?.length ? combineExports(input.exports) : []
348
+ const combinedImports = input.imports?.length ? combineImports(input.imports, resolvedExports, source || undefined) : []
349
+ const localNames = new Set((input.sources ?? []).map((item) => item.name).filter((name): name is string => Boolean(name)))
350
+ const nameOf = (item: string | { propertyName: string; name?: string }): string => (typeof item === 'string' ? item : (item.name ?? item.propertyName))
351
+ // Drop self-imports. Consolidating output (`mode: 'file'`) can place a symbol's
352
+ // definition and a cross-file import of it in the same file. The first pass catches imports that
353
+ // resolve to this file's own path. The second drops imports of names the file already defines,
354
+ // the case consolidation produces when the import path no longer matches `input.path`. Sources
355
+ // stay intact, so the local definition remains. Bare specifiers like `'zod'` never match a path.
356
+ const resolvedImports = combinedImports
357
+ .filter((imp) => imp.path !== input.path)
358
+ .flatMap((imp) => {
359
+ if (!Array.isArray(imp.name)) {
360
+ return typeof imp.name === 'string' && localNames.has(imp.name) ? [] : [imp]
361
+ }
362
+ const kept = imp.name.filter((item) => !localNames.has(nameOf(item)))
363
+ if (!kept.length) return []
364
+ return [kept.length === imp.name.length ? imp : { ...imp, name: kept }]
365
+ })
366
+ const resolvedSources = input.sources?.length ? combineSources(input.sources) : []
367
+
368
+ return {
369
+ kind: 'File',
370
+ ...input,
371
+ id: hash('sha256', input.path, 'hex'),
372
+ name: trimExtName(input.baseName),
373
+ extname,
374
+ imports: resolvedImports,
375
+ exports: resolvedExports,
376
+ sources: resolvedSources,
377
+ meta: input.meta ?? ({} as TMeta),
378
+ }
379
+ }
@@ -1,4 +1,4 @@
1
- import { defineNode } from '../node.ts'
1
+ import { defineNode } from '../defineNode.ts'
2
2
  import type { BaseNode } from './base.ts'
3
3
 
4
4
  /**
@@ -43,11 +43,11 @@ export type TypeLiteralNode = BaseNode & {
43
43
 
44
44
  /**
45
45
  * AST node for a single field accessed from a named group type.
46
- * TypeScript renders as `objectType['indexType']`.
46
+ * TypeScript renders as `target['key']`.
47
47
  *
48
48
  * @example
49
49
  * ```ts
50
- * createIndexedAccessType({ objectType: 'GetPetPathParams', indexType: 'petId' })
50
+ * createIndexedAccessType({ target: 'GetPetPathParams', key: 'petId' })
51
51
  * // GetPetPathParams['petId']
52
52
  * ```
53
53
  */
@@ -56,11 +56,11 @@ export type IndexedAccessTypeNode = BaseNode & {
56
56
  /**
57
57
  * Name of the type being indexed, e.g. `'GetPetPathParams'`.
58
58
  */
59
- objectType: string
59
+ target: string
60
60
  /**
61
61
  * Field key to access, e.g. `'petId'`.
62
62
  */
63
- indexType: string
63
+ key: string
64
64
  }
65
65
 
66
66
  /**
@@ -168,49 +168,16 @@ export type FunctionParamKind = FunctionParamNode['kind']
168
168
  */
169
169
  export const typeLiteralDef = defineNode<TypeLiteralNode, Pick<TypeLiteralNode, 'members'>>({ kind: 'TypeLiteral' })
170
170
 
171
- /**
172
- * Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
173
- *
174
- * @example
175
- * ```ts
176
- * createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
177
- * // { petId: string }
178
- * ```
179
- */
180
- export const createTypeLiteral = typeLiteralDef.create
181
-
182
171
  /**
183
172
  * Definition for the {@link IndexedAccessTypeNode}.
184
173
  */
185
174
  export const indexedAccessTypeDef = defineNode<IndexedAccessTypeNode, Omit<IndexedAccessTypeNode, 'kind'>>({ kind: 'IndexedAccessType' })
186
175
 
187
- /**
188
- * Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
189
- *
190
- * @example
191
- * ```ts
192
- * createIndexedAccessType({ objectType: 'DeletePetPathParams', indexType: 'petId' })
193
- * // DeletePetPathParams['petId']
194
- * ```
195
- */
196
- export const createIndexedAccessType = indexedAccessTypeDef.create
197
-
198
176
  /**
199
177
  * Definition for the {@link ObjectBindingPatternNode}.
200
178
  */
201
179
  export const objectBindingPatternDef = defineNode<ObjectBindingPatternNode, Pick<ObjectBindingPatternNode, 'elements'>>({ kind: 'ObjectBindingPattern' })
202
180
 
203
- /**
204
- * Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
205
- *
206
- * @example
207
- * ```ts
208
- * createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
209
- * // { id, name }
210
- * ```
211
- */
212
- export const createObjectBindingPattern = objectBindingPatternDef.create
213
-
214
181
  /**
215
182
  * Plain property descriptor for a destructured group built by {@link createFunctionParameter}.
216
183
  */
@@ -244,6 +211,47 @@ export const functionParameterDef = defineNode<FunctionParameterNode, FunctionPa
244
211
  },
245
212
  })
246
213
 
214
+ /**
215
+ * Definition for the {@link FunctionParametersNode}.
216
+ */
217
+ export const functionParametersDef = defineNode<FunctionParametersNode, Partial<Omit<FunctionParametersNode, 'kind'>>>({
218
+ kind: 'FunctionParameters',
219
+ defaults: { params: [] },
220
+ })
221
+
222
+ /**
223
+ * Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
228
+ * // { petId: string }
229
+ * ```
230
+ */
231
+ export const createTypeLiteral = typeLiteralDef.create
232
+
233
+ /**
234
+ * Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
235
+ *
236
+ * @example
237
+ * ```ts
238
+ * createIndexedAccessType({ target: 'DeletePetPathParams', key: 'petId' })
239
+ * // DeletePetPathParams['petId']
240
+ * ```
241
+ */
242
+ export const createIndexedAccessType = indexedAccessTypeDef.create
243
+
244
+ /**
245
+ * Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
246
+ *
247
+ * @example
248
+ * ```ts
249
+ * createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
250
+ * // { id, name }
251
+ * ```
252
+ */
253
+ export const createObjectBindingPattern = objectBindingPatternDef.create
254
+
247
255
  /**
248
256
  * Creates a `FunctionParameterNode`. `optional` defaults to `false`.
249
257
  *
@@ -261,14 +269,6 @@ export const functionParameterDef = defineNode<FunctionParameterNode, FunctionPa
261
269
  */
262
270
  export const createFunctionParameter = functionParameterDef.create
263
271
 
264
- /**
265
- * Definition for the {@link FunctionParametersNode}.
266
- */
267
- export const functionParametersDef = defineNode<FunctionParametersNode, Partial<Omit<FunctionParametersNode, 'kind'>>>({
268
- kind: 'FunctionParameters',
269
- defaults: { params: [] },
270
- })
271
-
272
272
  /**
273
273
  * Creates a `FunctionParametersNode` from an ordered list of parameters.
274
274
  *
@@ -14,7 +14,7 @@ import type { SchemaNode } from './schema.ts'
14
14
  export type { NodeKind } from './base.ts'
15
15
  export type { ArrowFunctionNode, BreakNode, CodeNode, ConstNode, FunctionNode, JSDocNode, JsxNode, TextNode, TypeNode } from './code.ts'
16
16
  export type { ContentNode } from './content.ts'
17
- export type { ExportNode, FileNode, ImportNode, SourceNode } from './file.ts'
17
+ export type { ExportNode, FileNode, ImportNode, SourceNode, UserFileNode } from './file.ts'
18
18
  export type {
19
19
  FunctionParamKind,
20
20
  FunctionParameterNode,
@@ -25,14 +25,13 @@ export type {
25
25
  TypeExpression,
26
26
  TypeLiteralNode,
27
27
  } from './function.ts'
28
- export type { StatusCode } from './http.ts'
29
28
  export type { InputMeta, InputNode } from './input.ts'
30
29
  export type { GenericOperationNode, HttpMethod, HttpOperationNode, OperationNode } from './operation.ts'
31
30
  export type { OutputNode } from './output.ts'
32
31
  export type { ParameterLocation, ParameterNode } from './parameter.ts'
33
32
  export type { PropertyNode } from './property.ts'
34
33
  export type { RequestBodyNode } from './requestBody.ts'
35
- export type { ResponseNode } from './response.ts'
34
+ export type { ResponseNode, StatusCode } from './response.ts'
36
35
  export type {
37
36
  ArraySchemaNode,
38
37
  DateSchemaNode,
@@ -1,5 +1,5 @@
1
1
  import type { Streamable } from '@internals/utils'
2
- import { defineNode } from '../node.ts'
2
+ import { defineNode } from '../defineNode.ts'
3
3
  import type { BaseNode } from './base.ts'
4
4
  import type { OperationNode } from './operation.ts'
5
5
  import type { SchemaNode } from './schema.ts'
@@ -68,8 +68,7 @@ export type InputMeta = {
68
68
  * Produced by the adapter and consumed by all Kubb plugins.
69
69
  *
70
70
  * `Stream` switches `schemas` and `operations` between eager `Array`s (the default) and lazy
71
- * `AsyncIterable`s. The streaming variant `InputNode<true>` yields nodes one at a time and makes
72
- * `meta` optional, since the adapter can emit metadata before the first node is parsed.
71
+ * `AsyncIterable`s. The streaming variant `InputNode<true>` yields nodes one at a time.
73
72
  *
74
73
  * @example
75
74
  * ```ts
@@ -101,7 +100,11 @@ export type InputNode<Stream extends boolean = false> = BaseNode & {
101
100
  * All operation nodes in the document.
102
101
  */
103
102
  operations: Streamable<OperationNode, Stream>
104
- } & (Stream extends true ? { meta?: InputMeta } : { meta: InputMeta })
103
+ /**
104
+ * Document metadata populated by the adapter.
105
+ */
106
+ meta: InputMeta
107
+ }
105
108
 
106
109
  /**
107
110
  * Definition for the {@link InputNode}.
@@ -115,8 +118,8 @@ export const inputDef = defineNode<InputNode, Partial<Omit<InputNode, 'kind'>>>(
115
118
 
116
119
  /**
117
120
  * Creates an `InputNode`. Pass `stream: true` for the streaming variant whose `schemas` and
118
- * `operations` are `AsyncIterable` sources and whose `meta` is optional. Otherwise it builds the
119
- * eager variant with array `schemas`/`operations` and the defaulted `meta`.
121
+ * `operations` are `AsyncIterable` sources. Otherwise it builds the eager variant with array
122
+ * `schemas`/`operations`. Both variants get the defaulted `meta`.
120
123
  *
121
124
  * @example Eager
122
125
  * ```ts
@@ -131,10 +134,11 @@ export const inputDef = defineNode<InputNode, Partial<Omit<InputNode, 'kind'>>>(
131
134
  */
132
135
  export function createInput<Stream extends boolean = false>(options: Partial<Omit<InputNode<Stream>, 'kind'>> & { stream?: Stream } = {}): InputNode<Stream> {
133
136
  const { stream, ...overrides } = options
134
- // Streaming inputs carry AsyncIterable sources, so skip the array/meta defaults that
135
- // inputDef.create applies for the eager variant.
137
+ // Streaming inputs carry AsyncIterable sources, so skip the array defaults that
138
+ // inputDef.create applies for the eager variant. Keep the meta default.
136
139
  if (stream) {
137
- return { kind: 'Input', ...overrides } as InputNode<Stream>
140
+ return { kind: 'Input', meta: { circularNames: [], enumNames: [] }, ...overrides } as InputNode<Stream>
138
141
  }
142
+
139
143
  return inputDef.create(overrides as Partial<Omit<InputNode, 'kind'>>) as InputNode<Stream>
140
144
  }
@@ -1,7 +1,7 @@
1
- import { defineNode } from '../node.ts'
1
+ import { defineNode } from '../defineNode.ts'
2
2
  import type { BaseNode } from './base.ts'
3
3
  import type { ParameterNode } from './parameter.ts'
4
- import { createRequestBody, type RequestBodyNode, type UserRequestBody } from './requestBody.ts'
4
+ import { createRequestBody, type RequestBodyNode } from './requestBody.ts'
5
5
  import type { ResponseNode } from './response.ts'
6
6
 
7
7
  export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'TRACE'
@@ -111,7 +111,7 @@ type OperationInput = {
111
111
  operationId: string
112
112
  method?: HttpOperationNode['method']
113
113
  path?: HttpOperationNode['path']
114
- requestBody?: UserRequestBody
114
+ requestBody?: Omit<RequestBodyNode, 'kind'>
115
115
  [key: string]: unknown
116
116
  }
117
117
 
@@ -151,13 +151,13 @@ export const operationDef = defineNode<OperationNode, OperationInput>({
151
151
  export function createOperation(
152
152
  props: Pick<HttpOperationNode, 'operationId' | 'method' | 'path'> &
153
153
  Partial<Omit<HttpOperationNode, 'kind' | 'operationId' | 'method' | 'path' | 'requestBody'>> & {
154
- requestBody?: UserRequestBody
154
+ requestBody?: Omit<RequestBodyNode, 'kind'>
155
155
  },
156
156
  ): HttpOperationNode
157
157
  export function createOperation(
158
158
  props: Pick<GenericOperationNode, 'operationId'> &
159
159
  Partial<Omit<GenericOperationNode, 'kind' | 'operationId' | 'requestBody'>> & {
160
- requestBody?: UserRequestBody
160
+ requestBody?: Omit<RequestBodyNode, 'kind'>
161
161
  },
162
162
  ): GenericOperationNode
163
163
  export function createOperation(props: OperationInput): OperationNode {
@@ -1,4 +1,4 @@
1
- import { defineNode } from '../node.ts'
1
+ import { defineNode } from '../defineNode.ts'
2
2
  import type { BaseNode } from './base.ts'
3
3
  import type { FileNode } from './file.ts'
4
4
 
@@ -1,4 +1,4 @@
1
- import { defineNode, syncOptionality } from '../node.ts'
1
+ import { defineNode } from '../defineNode.ts'
2
2
  import type { BaseNode } from './base.ts'
3
3
  import type { SchemaNode } from './schema.ts'
4
4
 
@@ -41,18 +41,18 @@ export type ParameterNode = BaseNode & {
41
41
  type UserParameterNode = Pick<ParameterNode, 'name' | 'in' | 'schema'> & Partial<Omit<ParameterNode, 'kind' | 'name' | 'in' | 'schema'>>
42
42
 
43
43
  /**
44
- * Definition for the {@link ParameterNode}. `required` defaults to `false` and the
45
- * schema's `optional`/`nullish` flags are kept in sync with it.
44
+ * Definition for the {@link ParameterNode}. `required` defaults to `false`. When a `dialect` is
45
+ * passed to `create`, the schema's `optional`/`nullish` flags are derived through its
46
+ * `optionality`; without one, the schema is left as-is.
46
47
  */
47
48
  export const parameterDef = defineNode<ParameterNode, UserParameterNode>({
48
49
  kind: 'Parameter',
49
- build: (props) => {
50
+ build: (props, dialect) => {
50
51
  const required = props.required ?? false
51
- return { ...props, required, schema: syncOptionality(props.schema, required) }
52
+ return { ...props, required, schema: dialect ? dialect.schema.optionality(props.schema, required) : props.schema }
52
53
  },
53
54
  children: ['schema'],
54
55
  visitorKey: 'parameter',
55
- rebuild: true,
56
56
  })
57
57
 
58
58
  /**
@@ -1,4 +1,4 @@
1
- import { defineNode, syncOptionality } from '../node.ts'
1
+ import { defineNode } from '../defineNode.ts'
2
2
  import type { BaseNode } from './base.ts'
3
3
  import type { SchemaNode } from './schema.ts'
4
4
 
@@ -37,18 +37,18 @@ export type PropertyNode = BaseNode & {
37
37
  export type UserPropertyNode = Pick<PropertyNode, 'name' | 'schema'> & Partial<Omit<PropertyNode, 'kind' | 'name' | 'schema'>>
38
38
 
39
39
  /**
40
- * Definition for the {@link PropertyNode}. `required` defaults to `false` and the
41
- * schema's `optional`/`nullish` flags are kept in sync with it.
40
+ * Definition for the {@link PropertyNode}. `required` defaults to `false`. When a `dialect` is
41
+ * passed to `create`, the schema's `optional`/`nullish` flags are derived through its
42
+ * `optionality`; without one, the schema is left as-is.
42
43
  */
43
44
  export const propertyDef = defineNode<PropertyNode, UserPropertyNode>({
44
45
  kind: 'Property',
45
- build: (props) => {
46
+ build: (props, dialect) => {
46
47
  const required = props.required ?? false
47
- return { ...props, required, schema: syncOptionality(props.schema, required) }
48
+ return { ...props, required, schema: dialect ? dialect.schema.optionality(props.schema, required) : props.schema }
48
49
  },
49
50
  children: ['schema'],
50
51
  visitorKey: 'property',
51
- rebuild: true,
52
52
  })
53
53
 
54
54
  /**