@kubb/ast 5.0.0-beta.61 → 5.0.0-beta.63
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/{defineMacro-BLIR6k-j.d.ts → defineMacro-BATi7xoC.d.ts} +11 -20
- package/dist/{defineMacro-Bv9R_9a2.cjs → defineMacro-CEZHaCXE.cjs} +13 -21
- package/dist/defineMacro-CEZHaCXE.cjs.map +1 -0
- package/dist/{defineMacro-BTXvS8nI.js → defineMacro-Shz8f6SG.js} +12 -19
- package/dist/defineMacro-Shz8f6SG.js.map +1 -0
- package/dist/factory.cjs +88 -28
- package/dist/factory.cjs.map +1 -0
- package/dist/factory.d.ts +6 -41
- package/dist/factory.js +58 -3
- package/dist/factory.js.map +1 -0
- package/dist/{index-BzjwdK2M.d.ts → index-B9cc8MBS.d.ts} +164 -194
- package/dist/index.cjs +144 -274
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +43 -37
- package/dist/index.js +109 -235
- package/dist/index.js.map +1 -1
- package/dist/macros.cjs +41 -28
- package/dist/macros.cjs.map +1 -1
- package/dist/macros.d.ts +14 -12
- package/dist/macros.js +34 -21
- package/dist/macros.js.map +1 -1
- package/dist/{operationParams-BZ07xDm0.d.ts → operationParams-k5CKwSWZ.d.ts} +9 -2
- package/dist/{visitor-DJ6ZEJvq.js → refs-BjNDuCBD.js} +116 -159
- package/dist/refs-BjNDuCBD.js.map +1 -0
- package/dist/{visitor-DpKZ9Tk0.cjs → refs-u5SDdyV7.cjs} +140 -195
- package/dist/refs-u5SDdyV7.cjs.map +1 -0
- package/dist/{response-hnSw2NKE.cjs → schema-BkvrrOAr.cjs} +496 -231
- package/dist/schema-BkvrrOAr.cjs.map +1 -0
- package/dist/{response-KUdWiDWw.js → schema-Cbnxmz4b.js} +472 -220
- package/dist/schema-Cbnxmz4b.js.map +1 -0
- package/dist/{types-DyDzizSf.d.ts → types-BB_xgRJ3.d.ts} +49 -123
- package/dist/types.d.ts +5 -6
- package/dist/{utils-BLJwyza-.cjs → utils-CEepwqmb.cjs} +76 -69
- package/dist/utils-CEepwqmb.cjs.map +1 -0
- package/dist/{utils-CF_-Pn_c.js → utils-DaXkewb1.js} +58 -51
- package/dist/utils-DaXkewb1.js.map +1 -0
- package/dist/utils.cjs +11 -11
- package/dist/utils.d.ts +53 -30
- package/dist/utils.js +3 -3
- package/package.json +1 -1
- package/src/constants.ts +3 -36
- package/src/defineMacro.ts +20 -13
- package/src/{node.ts → defineNode.ts} +12 -38
- package/src/{printer.ts → definePrinter.ts} +5 -3
- package/src/dialect.ts +52 -19
- package/src/factory.ts +7 -94
- package/src/index.ts +7 -9
- package/src/infer.ts +1 -1
- package/src/macros/macroDiscriminatorEnum.ts +7 -1
- package/src/macros/macroEnumName.ts +10 -2
- package/src/macros/macroSimplifyUnion.ts +29 -19
- package/src/nodes/code.ts +40 -80
- package/src/nodes/content.ts +2 -7
- package/src/nodes/file.ts +107 -18
- package/src/nodes/function.ts +46 -46
- package/src/nodes/index.ts +2 -3
- package/src/nodes/input.ts +13 -9
- package/src/nodes/operation.ts +8 -5
- package/src/nodes/output.ts +1 -1
- package/src/nodes/parameter.ts +5 -5
- package/src/nodes/property.ts +5 -5
- package/src/nodes/requestBody.ts +6 -13
- package/src/nodes/response.ts +93 -8
- package/src/nodes/schema.ts +5 -5
- package/src/optionality.ts +15 -0
- package/src/registry.ts +1 -1
- package/src/types.ts +4 -6
- package/src/utils/codegen.ts +6 -7
- package/src/utils/extractStringsFromNodes.ts +1 -0
- package/src/utils/fileMerge.ts +7 -8
- package/src/utils/operationParams.ts +9 -9
- package/src/utils/refs.ts +14 -18
- package/src/utils/schemaGraph.ts +41 -33
- package/src/utils/schemaMerge.ts +2 -2
- package/src/visitor.ts +3 -14
- package/dist/defineMacro-BTXvS8nI.js.map +0 -1
- package/dist/defineMacro-Bv9R_9a2.cjs.map +0 -1
- package/dist/extractStringsFromNodes-Cja-xxx5.js +0 -29
- package/dist/extractStringsFromNodes-Cja-xxx5.js.map +0 -1
- package/dist/extractStringsFromNodes-DKgDjFO0.cjs +0 -34
- package/dist/extractStringsFromNodes-DKgDjFO0.cjs.map +0 -1
- package/dist/extractStringsFromNodes-p4mX1TQD.d.ts +0 -14
- package/dist/factory-CZNOGI-N.js +0 -283
- package/dist/factory-CZNOGI-N.js.map +0 -1
- package/dist/factory-DG1CVkEb.cjs +0 -300
- package/dist/factory-DG1CVkEb.cjs.map +0 -1
- package/dist/response-KUdWiDWw.js.map +0 -1
- package/dist/response-hnSw2NKE.cjs.map +0 -1
- package/dist/utils-BLJwyza-.cjs.map +0 -1
- package/dist/utils-CF_-Pn_c.js.map +0 -1
- package/dist/visitor-DJ6ZEJvq.js.map +0 -1
- package/dist/visitor-DpKZ9Tk0.cjs.map +0 -1
- package/src/dedupe.ts +0 -239
- package/src/mocks.ts +0 -56
- package/src/nodes/http.ts +0 -85
package/src/nodes/file.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
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
|
|
|
@@ -192,13 +197,14 @@ export type FileNode<TMeta extends object = object> = BaseNode & {
|
|
|
192
197
|
id: string
|
|
193
198
|
/**
|
|
194
199
|
* File name without extension, derived from `baseName`.
|
|
195
|
-
*
|
|
200
|
+
*
|
|
201
|
+
* @see https://nodejs.org/api/path.html#pathformatpathobject
|
|
196
202
|
*/
|
|
197
203
|
name: string
|
|
198
204
|
/**
|
|
199
|
-
* File base name, including extension
|
|
200
|
-
*
|
|
201
|
-
* @
|
|
205
|
+
* File base name, including extension, shaped like `${name}${extname}`.
|
|
206
|
+
*
|
|
207
|
+
* @see https://nodejs.org/api/path.html#pathbasenamepath-suffix
|
|
202
208
|
*/
|
|
203
209
|
baseName: `${string}.${string}`
|
|
204
210
|
/**
|
|
@@ -242,6 +248,22 @@ export type FileNode<TMeta extends object = object> = BaseNode & {
|
|
|
242
248
|
*/
|
|
243
249
|
export const importDef = defineNode<ImportNode>({ kind: 'Import' })
|
|
244
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Definition for the {@link ExportNode}.
|
|
253
|
+
*/
|
|
254
|
+
export const exportDef = defineNode<ExportNode>({ kind: 'Export' })
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Definition for the {@link SourceNode}.
|
|
258
|
+
*/
|
|
259
|
+
export const sourceDef = defineNode<SourceNode>({ kind: 'Source' })
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Definition for the {@link FileNode}. The fully resolved builder lives in
|
|
263
|
+
* `createFile`, so this definition only supplies the guard.
|
|
264
|
+
*/
|
|
265
|
+
export const fileDef = defineNode<FileNode>({ kind: 'File' })
|
|
266
|
+
|
|
245
267
|
/**
|
|
246
268
|
* Creates an `ImportNode` representing a language-agnostic import/dependency declaration.
|
|
247
269
|
*
|
|
@@ -253,11 +275,6 @@ export const importDef = defineNode<ImportNode>({ kind: 'Import' })
|
|
|
253
275
|
*/
|
|
254
276
|
export const createImport = importDef.create
|
|
255
277
|
|
|
256
|
-
/**
|
|
257
|
-
* Definition for the {@link ExportNode}.
|
|
258
|
-
*/
|
|
259
|
-
export const exportDef = defineNode<ExportNode>({ kind: 'Export' })
|
|
260
|
-
|
|
261
278
|
/**
|
|
262
279
|
* Creates an `ExportNode` representing a language-agnostic export/public API declaration.
|
|
263
280
|
*
|
|
@@ -269,11 +286,6 @@ export const exportDef = defineNode<ExportNode>({ kind: 'Export' })
|
|
|
269
286
|
*/
|
|
270
287
|
export const createExport = exportDef.create
|
|
271
288
|
|
|
272
|
-
/**
|
|
273
|
-
* Definition for the {@link SourceNode}.
|
|
274
|
-
*/
|
|
275
|
-
export const sourceDef = defineNode<SourceNode>({ kind: 'Source' })
|
|
276
|
-
|
|
277
289
|
/**
|
|
278
290
|
* Creates a `SourceNode` representing a fragment of source code within a file.
|
|
279
291
|
*
|
|
@@ -285,7 +297,84 @@ export const sourceDef = defineNode<SourceNode>({ kind: 'Source' })
|
|
|
285
297
|
export const createSource = sourceDef.create
|
|
286
298
|
|
|
287
299
|
/**
|
|
288
|
-
*
|
|
289
|
-
* `
|
|
300
|
+
* Input descriptor for {@link createFile}, before `id`, `name`, and `extname` are computed
|
|
301
|
+
* and `imports`/`exports`/`sources` are deduplicated.
|
|
290
302
|
*/
|
|
291
|
-
export
|
|
303
|
+
export type UserFileNode<TMeta extends object = object> = Omit<FileNode<TMeta>, 'kind' | 'id' | 'name' | 'extname' | 'imports' | 'exports' | 'sources'> &
|
|
304
|
+
Pick<Partial<FileNode<TMeta>>, 'imports' | 'exports' | 'sources'>
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Creates a fully resolved `FileNode` from a file input descriptor.
|
|
308
|
+
*
|
|
309
|
+
* Computes:
|
|
310
|
+
* - `id` SHA256 hash of the file path
|
|
311
|
+
* - `name` `baseName` without extension
|
|
312
|
+
* - `extname` extension extracted from `baseName`
|
|
313
|
+
*
|
|
314
|
+
* Deduplicates:
|
|
315
|
+
* - `sources` via `combineSources`
|
|
316
|
+
* - `exports` via `combineExports`
|
|
317
|
+
* - `imports` via `combineImports` (also filters unused imports)
|
|
318
|
+
*
|
|
319
|
+
* @throws {Error} when `baseName` has no extension.
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* ```ts
|
|
323
|
+
* const file = createFile({
|
|
324
|
+
* baseName: 'petStore.ts',
|
|
325
|
+
* path: 'src/models/petStore.ts',
|
|
326
|
+
* sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')] })],
|
|
327
|
+
* imports: [createImport({ name: ['z'], path: 'zod' })],
|
|
328
|
+
* exports: [createExport({ name: ['Pet'], path: './petStore' })],
|
|
329
|
+
* })
|
|
330
|
+
* // file.id = SHA256 hash of 'src/models/petStore.ts'
|
|
331
|
+
* // file.name = 'petStore'
|
|
332
|
+
* // file.extname = '.ts'
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
export function createFile<TMeta extends object = object>(input: UserFileNode<TMeta>): FileNode<TMeta> {
|
|
336
|
+
const rawExtname = path.extname(input.baseName)
|
|
337
|
+
// Handle dotfile basename like '.ts' where path.extname returns ''
|
|
338
|
+
const extname = (rawExtname || (input.baseName.startsWith('.') ? input.baseName : '')) as `.${string}`
|
|
339
|
+
if (!extname) {
|
|
340
|
+
throw new Error(`No extname found for ${input.baseName}`)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const source = (input.sources ?? [])
|
|
344
|
+
.flatMap((item) => item.nodes ?? [])
|
|
345
|
+
.map((node) => extractStringsFromNodes([node]))
|
|
346
|
+
.filter(Boolean)
|
|
347
|
+
.join('\n\n')
|
|
348
|
+
const resolvedExports = input.exports?.length ? combineExports(input.exports) : []
|
|
349
|
+
const combinedImports = input.imports?.length ? combineImports(input.imports, resolvedExports, source || undefined) : []
|
|
350
|
+
const localNames = new Set((input.sources ?? []).map((item) => item.name).filter((name): name is string => Boolean(name)))
|
|
351
|
+
const nameOf = (item: string | { propertyName: string; name?: string }): string => (typeof item === 'string' ? item : (item.name ?? item.propertyName))
|
|
352
|
+
// Drop self-imports. Consolidating output (`mode: 'file'`) can place a symbol's
|
|
353
|
+
// definition and a cross-file import of it in the same file. The first pass catches imports that
|
|
354
|
+
// resolve to this file's own path. The second drops imports of names the file already defines,
|
|
355
|
+
// the case consolidation produces when the import path no longer matches `input.path`. Sources
|
|
356
|
+
// stay intact, so the local definition remains. Bare specifiers like `'zod'` never match a path.
|
|
357
|
+
const resolvedImports = combinedImports
|
|
358
|
+
.filter((imp) => imp.path !== input.path)
|
|
359
|
+
.flatMap((imp) => {
|
|
360
|
+
if (!Array.isArray(imp.name)) {
|
|
361
|
+
return typeof imp.name === 'string' && localNames.has(imp.name) ? [] : [imp]
|
|
362
|
+
}
|
|
363
|
+
const kept = imp.name.filter((item) => !localNames.has(nameOf(item)))
|
|
364
|
+
if (!kept.length) return []
|
|
365
|
+
return [kept.length === imp.name.length ? imp : { ...imp, name: kept }]
|
|
366
|
+
})
|
|
367
|
+
const resolvedSources = input.sources?.length ? combineSources(input.sources) : []
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
kind: 'File',
|
|
371
|
+
...input,
|
|
372
|
+
id: hash('sha256', input.path, 'hex'),
|
|
373
|
+
name: trimExtName(input.baseName),
|
|
374
|
+
extname,
|
|
375
|
+
imports: resolvedImports,
|
|
376
|
+
exports: resolvedExports,
|
|
377
|
+
sources: resolvedSources,
|
|
378
|
+
meta: input.meta ?? ({} as TMeta),
|
|
379
|
+
}
|
|
380
|
+
}
|
package/src/nodes/function.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineNode } from '../
|
|
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 `
|
|
46
|
+
* TypeScript renders as `target['key']`.
|
|
47
47
|
*
|
|
48
48
|
* @example
|
|
49
49
|
* ```ts
|
|
50
|
-
* createIndexedAccessType({
|
|
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
|
-
|
|
59
|
+
target: string
|
|
60
60
|
/**
|
|
61
61
|
* Field key to access, e.g. `'petId'`.
|
|
62
62
|
*/
|
|
63
|
-
|
|
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
|
*
|
package/src/nodes/index.ts
CHANGED
|
@@ -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,
|
package/src/nodes/input.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Streamable } from '@internals/utils'
|
|
2
|
-
import { defineNode } from '../
|
|
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
|
|
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
|
-
|
|
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
|
|
119
|
-
*
|
|
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
|
|
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
|
}
|
package/src/nodes/operation.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { defineNode } from '../
|
|
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
|
|
4
|
+
import { createRequestBody, type RequestBodyNode } from './requestBody.ts'
|
|
5
5
|
import type { ResponseNode } from './response.ts'
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* HTTP method an operation responds to.
|
|
9
|
+
*/
|
|
7
10
|
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'TRACE'
|
|
8
11
|
|
|
9
12
|
/**
|
|
@@ -111,7 +114,7 @@ type OperationInput = {
|
|
|
111
114
|
operationId: string
|
|
112
115
|
method?: HttpOperationNode['method']
|
|
113
116
|
path?: HttpOperationNode['path']
|
|
114
|
-
requestBody?:
|
|
117
|
+
requestBody?: Omit<RequestBodyNode, 'kind'>
|
|
115
118
|
[key: string]: unknown
|
|
116
119
|
}
|
|
117
120
|
|
|
@@ -151,13 +154,13 @@ export const operationDef = defineNode<OperationNode, OperationInput>({
|
|
|
151
154
|
export function createOperation(
|
|
152
155
|
props: Pick<HttpOperationNode, 'operationId' | 'method' | 'path'> &
|
|
153
156
|
Partial<Omit<HttpOperationNode, 'kind' | 'operationId' | 'method' | 'path' | 'requestBody'>> & {
|
|
154
|
-
requestBody?:
|
|
157
|
+
requestBody?: Omit<RequestBodyNode, 'kind'>
|
|
155
158
|
},
|
|
156
159
|
): HttpOperationNode
|
|
157
160
|
export function createOperation(
|
|
158
161
|
props: Pick<GenericOperationNode, 'operationId'> &
|
|
159
162
|
Partial<Omit<GenericOperationNode, 'kind' | 'operationId' | 'requestBody'>> & {
|
|
160
|
-
requestBody?:
|
|
163
|
+
requestBody?: Omit<RequestBodyNode, 'kind'>
|
|
161
164
|
},
|
|
162
165
|
): GenericOperationNode
|
|
163
166
|
export function createOperation(props: OperationInput): OperationNode {
|
package/src/nodes/output.ts
CHANGED
package/src/nodes/parameter.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineNode
|
|
1
|
+
import { defineNode } from '../defineNode.ts'
|
|
2
|
+
import { optionality } from '../optionality.ts'
|
|
2
3
|
import type { BaseNode } from './base.ts'
|
|
3
4
|
import type { SchemaNode } from './schema.ts'
|
|
4
5
|
|
|
@@ -41,18 +42,17 @@ export type ParameterNode = BaseNode & {
|
|
|
41
42
|
type UserParameterNode = Pick<ParameterNode, 'name' | 'in' | 'schema'> & Partial<Omit<ParameterNode, 'kind' | 'name' | 'in' | 'schema'>>
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
|
-
* Definition for the {@link ParameterNode}. `required` defaults to `false
|
|
45
|
-
*
|
|
45
|
+
* Definition for the {@link ParameterNode}. `required` defaults to `false`, and the schema's
|
|
46
|
+
* `optional`/`nullish` flags are derived from it through {@link optionality}.
|
|
46
47
|
*/
|
|
47
48
|
export const parameterDef = defineNode<ParameterNode, UserParameterNode>({
|
|
48
49
|
kind: 'Parameter',
|
|
49
50
|
build: (props) => {
|
|
50
51
|
const required = props.required ?? false
|
|
51
|
-
return { ...props, required, schema:
|
|
52
|
+
return { ...props, required, schema: optionality(props.schema, required) }
|
|
52
53
|
},
|
|
53
54
|
children: ['schema'],
|
|
54
55
|
visitorKey: 'parameter',
|
|
55
|
-
rebuild: true,
|
|
56
56
|
})
|
|
57
57
|
|
|
58
58
|
/**
|
package/src/nodes/property.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineNode
|
|
1
|
+
import { defineNode } from '../defineNode.ts'
|
|
2
|
+
import { optionality } from '../optionality.ts'
|
|
2
3
|
import type { BaseNode } from './base.ts'
|
|
3
4
|
import type { SchemaNode } from './schema.ts'
|
|
4
5
|
|
|
@@ -37,18 +38,17 @@ export type PropertyNode = BaseNode & {
|
|
|
37
38
|
export type UserPropertyNode = Pick<PropertyNode, 'name' | 'schema'> & Partial<Omit<PropertyNode, 'kind' | 'name' | 'schema'>>
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
|
-
* Definition for the {@link PropertyNode}. `required` defaults to `false
|
|
41
|
-
*
|
|
41
|
+
* Definition for the {@link PropertyNode}. `required` defaults to `false`, and the schema's
|
|
42
|
+
* `optional`/`nullish` flags are derived from it through {@link optionality}.
|
|
42
43
|
*/
|
|
43
44
|
export const propertyDef = defineNode<PropertyNode, UserPropertyNode>({
|
|
44
45
|
kind: 'Property',
|
|
45
46
|
build: (props) => {
|
|
46
47
|
const required = props.required ?? false
|
|
47
|
-
return { ...props, required, schema:
|
|
48
|
+
return { ...props, required, schema: optionality(props.schema, required) }
|
|
48
49
|
},
|
|
49
50
|
children: ['schema'],
|
|
50
51
|
visitorKey: 'property',
|
|
51
|
-
rebuild: true,
|
|
52
52
|
})
|
|
53
53
|
|
|
54
54
|
/**
|
package/src/nodes/requestBody.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defineNode } from '../
|
|
1
|
+
import { defineNode } from '../defineNode.ts'
|
|
2
2
|
import type { BaseNode } from './base.ts'
|
|
3
|
-
import {
|
|
3
|
+
import type { ContentNode } from './content.ts'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* AST node representing an operation request body.
|
|
@@ -40,22 +40,15 @@ export type RequestBodyNode = BaseNode & {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
43
|
+
* Definition for the {@link RequestBodyNode}. Content entries are built upfront with
|
|
44
|
+
* {@link createContent}, mirroring how `parameters` and `responses` take prebuilt nodes.
|
|
44
45
|
*/
|
|
45
|
-
export
|
|
46
|
-
content?: Array<UserContent>
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Definition for the {@link RequestBodyNode}, normalizing each content entry into a `ContentNode`.
|
|
51
|
-
*/
|
|
52
|
-
export const requestBodyDef = defineNode<RequestBodyNode, UserRequestBody>({
|
|
46
|
+
export const requestBodyDef = defineNode<RequestBodyNode>({
|
|
53
47
|
kind: 'RequestBody',
|
|
54
|
-
build: (props) => ({ ...props, content: props.content?.map(createContent) }),
|
|
55
48
|
children: ['content'],
|
|
56
49
|
})
|
|
57
50
|
|
|
58
51
|
/**
|
|
59
|
-
* Creates a `RequestBodyNode
|
|
52
|
+
* Creates a `RequestBodyNode`.
|
|
60
53
|
*/
|
|
61
54
|
export const createRequestBody = requestBodyDef.create
|
package/src/nodes/response.ts
CHANGED
|
@@ -1,9 +1,94 @@
|
|
|
1
|
-
import { defineNode } from '../
|
|
1
|
+
import { defineNode } from '../defineNode.ts'
|
|
2
2
|
import type { BaseNode } from './base.ts'
|
|
3
|
-
import { type ContentNode, createContent
|
|
4
|
-
import type { StatusCode } from './http.ts'
|
|
3
|
+
import { type ContentNode, createContent } from './content.ts'
|
|
5
4
|
import type { SchemaNode } from './schema.ts'
|
|
6
5
|
|
|
6
|
+
/**
|
|
7
|
+
* All supported HTTP status code literals as strings, as used in API specs
|
|
8
|
+
* (for example, `"200"` and `"404"`).
|
|
9
|
+
*/
|
|
10
|
+
type HttpStatusCode =
|
|
11
|
+
// 1xx Informational
|
|
12
|
+
| '100'
|
|
13
|
+
| '101'
|
|
14
|
+
| '102'
|
|
15
|
+
| '103'
|
|
16
|
+
// 2xx Success
|
|
17
|
+
| '200'
|
|
18
|
+
| '201'
|
|
19
|
+
| '202'
|
|
20
|
+
| '203'
|
|
21
|
+
| '204'
|
|
22
|
+
| '205'
|
|
23
|
+
| '206'
|
|
24
|
+
| '207'
|
|
25
|
+
| '208'
|
|
26
|
+
| '226'
|
|
27
|
+
// 3xx Redirection
|
|
28
|
+
| '300'
|
|
29
|
+
| '301'
|
|
30
|
+
| '302'
|
|
31
|
+
| '303'
|
|
32
|
+
| '304'
|
|
33
|
+
| '305'
|
|
34
|
+
| '307'
|
|
35
|
+
| '308'
|
|
36
|
+
// 4xx Client Error
|
|
37
|
+
| '400'
|
|
38
|
+
| '401'
|
|
39
|
+
| '402'
|
|
40
|
+
| '403'
|
|
41
|
+
| '404'
|
|
42
|
+
| '405'
|
|
43
|
+
| '406'
|
|
44
|
+
| '407'
|
|
45
|
+
| '408'
|
|
46
|
+
| '409'
|
|
47
|
+
| '410'
|
|
48
|
+
| '411'
|
|
49
|
+
| '412'
|
|
50
|
+
| '413'
|
|
51
|
+
| '414'
|
|
52
|
+
| '415'
|
|
53
|
+
| '416'
|
|
54
|
+
| '417'
|
|
55
|
+
| '418'
|
|
56
|
+
| '421'
|
|
57
|
+
| '422'
|
|
58
|
+
| '423'
|
|
59
|
+
| '424'
|
|
60
|
+
| '425'
|
|
61
|
+
| '426'
|
|
62
|
+
| '428'
|
|
63
|
+
| '429'
|
|
64
|
+
| '431'
|
|
65
|
+
| '451'
|
|
66
|
+
// 5xx Server Error
|
|
67
|
+
| '500'
|
|
68
|
+
| '501'
|
|
69
|
+
| '502'
|
|
70
|
+
| '503'
|
|
71
|
+
| '504'
|
|
72
|
+
| '505'
|
|
73
|
+
| '506'
|
|
74
|
+
| '507'
|
|
75
|
+
| '508'
|
|
76
|
+
| '510'
|
|
77
|
+
| '511'
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Response status code literal used by operations.
|
|
81
|
+
*
|
|
82
|
+
* Includes specific HTTP status code strings and `"default"` for catch-all responses.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const status: StatusCode = '200'
|
|
87
|
+
* const fallback: StatusCode = 'default'
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export type StatusCode = HttpStatusCode | 'default'
|
|
91
|
+
|
|
7
92
|
/**
|
|
8
93
|
* AST node representing one operation response variant.
|
|
9
94
|
*
|
|
@@ -16,7 +101,7 @@ import type { SchemaNode } from './schema.ts'
|
|
|
16
101
|
* const response: ResponseNode = {
|
|
17
102
|
* kind: 'Response',
|
|
18
103
|
* statusCode: '200',
|
|
19
|
-
* content: [{ contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
|
|
104
|
+
* content: [{ kind: 'Content', contentType: 'application/json', schema: createSchema({ type: 'string' }) }],
|
|
20
105
|
* }
|
|
21
106
|
* ```
|
|
22
107
|
*/
|
|
@@ -53,7 +138,7 @@ export type ResponseNode = BaseNode & {
|
|
|
53
138
|
|
|
54
139
|
type ResponseInput = Pick<ResponseNode, 'statusCode'> &
|
|
55
140
|
Partial<Omit<ResponseNode, 'kind' | 'statusCode' | 'content'>> & {
|
|
56
|
-
content?: Array<
|
|
141
|
+
content?: Array<ContentNode>
|
|
57
142
|
schema?: SchemaNode
|
|
58
143
|
mediaType?: string | null
|
|
59
144
|
keysToOmit?: Array<string> | null
|
|
@@ -67,8 +152,8 @@ export const responseDef = defineNode<ResponseNode, ResponseInput>({
|
|
|
67
152
|
kind: 'Response',
|
|
68
153
|
build: (props) => {
|
|
69
154
|
const { schema, mediaType, keysToOmit, content, ...rest } = props
|
|
70
|
-
const entries = content ?? (schema ? [{ contentType: mediaType ?? 'application/json', schema, keysToOmit: keysToOmit ?? null }] : undefined)
|
|
71
|
-
return { ...rest, content: entries
|
|
155
|
+
const entries = content ?? (schema ? [createContent({ contentType: mediaType ?? 'application/json', schema, keysToOmit: keysToOmit ?? null })] : undefined)
|
|
156
|
+
return { ...rest, content: entries }
|
|
72
157
|
},
|
|
73
158
|
children: ['content'],
|
|
74
159
|
visitorKey: 'response',
|
|
@@ -81,7 +166,7 @@ export const responseDef = defineNode<ResponseNode, ResponseInput>({
|
|
|
81
166
|
* ```ts
|
|
82
167
|
* const response = createResponse({
|
|
83
168
|
* statusCode: '200',
|
|
84
|
-
* content: [{ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) }],
|
|
169
|
+
* content: [createContent({ contentType: 'application/json', schema: createSchema({ type: 'object', properties: [] }) })],
|
|
85
170
|
* })
|
|
86
171
|
* ```
|
|
87
172
|
*/
|