@kubb/parser-ts 5.0.0-beta.6 → 5.0.0-beta.61

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/src/utils.ts ADDED
@@ -0,0 +1,488 @@
1
+ import { normalize, relative } from 'node:path'
2
+ import { trimExtName } from '@internals/utils'
3
+ import type { ArrowFunctionNode, CodeNode, ConstNode, FunctionNode, JSDocNode, JsxNode, SourceNode, TextNode, TypeNode } from '@kubb/ast'
4
+ import ts from 'typescript'
5
+ import {
6
+ CARRIAGE_RETURN_PATTERN,
7
+ CRLF_PATTERN,
8
+ CURRENT_DIRECTORY_PREFIX,
9
+ FILE_EXTENSION_PATTERN,
10
+ INDENT,
11
+ INDENT_CHAR,
12
+ JSDOC_TERMINATOR_PATTERN,
13
+ LEADING_DIGIT_PATTERN,
14
+ PARENT_DIRECTORY_PREFIX,
15
+ WINDOWS_PATH_SEPARATOR,
16
+ } from './constants.ts'
17
+
18
+ const { factory } = ts
19
+
20
+ /**
21
+ * Normalizes a file-system path to POSIX separators and strips any leading `../` segment.
22
+ */
23
+ export function slash(path: string): string {
24
+ return normalize(path).replaceAll(WINDOWS_PATH_SEPARATOR, '/').replace(PARENT_DIRECTORY_PREFIX, '')
25
+ }
26
+
27
+ /**
28
+ * Resolves `filePath` relative to `rootDir` and returns a POSIX-style path
29
+ * prefixed with `./` when the target sits inside the root, or `../` when it escapes it.
30
+ */
31
+ export function getRelativePath(rootDir: string, filePath: string): string {
32
+ const rel = relative(rootDir, filePath)
33
+ const slashed = slash(rel)
34
+ return slashed.startsWith(PARENT_DIRECTORY_PREFIX) ? slashed : `${CURRENT_DIRECTORY_PREFIX}${slashed}`
35
+ }
36
+
37
+ /**
38
+ * Rewrites an import/export path so its extension matches the caller-supplied
39
+ * `options.extname`. When the source path has no extension the original is kept,
40
+ * so virtual/module-only paths flow through unchanged.
41
+ */
42
+ export function resolveOutputPath(path: string, options: { extname?: string } | undefined, rootAware: boolean): string {
43
+ const hasExtname = FILE_EXTENSION_PATTERN.test(path)
44
+ if (options?.extname && hasExtname) {
45
+ return `${trimExtName(path)}${options.extname}`
46
+ }
47
+ return rootAware ? trimExtName(path) : path
48
+ }
49
+
50
+ /**
51
+ * Serializes a `nodes` array into source text. Each entry is rendered via {@link printCodeNode}
52
+ * and joined with a single newline. A `Break` node (`<br/>`) inserts one blank line between
53
+ * statements. Consecutive breaks, and breaks at the very start or end, are folded into the
54
+ * separator, so a double `<br/>` never emits more than one blank line.
55
+ */
56
+ export function printNodes(nodes: Array<CodeNode> | undefined): string {
57
+ if (!nodes || nodes.length === 0) return ''
58
+
59
+ let result = ''
60
+ let hasContent = false
61
+ let pendingBreak = false
62
+
63
+ for (const node of nodes) {
64
+ if (node.kind === 'Break') {
65
+ if (hasContent) pendingBreak = true
66
+ continue
67
+ }
68
+
69
+ const text = printCodeNode(node)
70
+ if (!text) continue
71
+
72
+ if (hasContent) result += pendingBreak ? '\n\n' : '\n'
73
+ result += text
74
+ hasContent = true
75
+ pendingBreak = false
76
+ }
77
+
78
+ return result
79
+ }
80
+
81
+ /**
82
+ * Indents every non-empty line of `text` by one indent unit. Pass a number to repeat
83
+ * {@link INDENT_CHAR} that many times, or a string to use as the indent verbatim.
84
+ */
85
+ export function indentLines(text: string, indent: number | string = INDENT): string {
86
+ if (!text) return ''
87
+ const pad = typeof indent === 'string' ? indent : INDENT_CHAR.repeat(indent)
88
+ return text
89
+ .split('\n')
90
+ .map((line) => (line.trim() ? `${pad}${line}` : ''))
91
+ .join('\n')
92
+ }
93
+
94
+ /**
95
+ * Removes the common leading whitespace shared by every non-blank line and trims
96
+ * surrounding blank lines, so multi-line content authored inside an indented template
97
+ * literal lines up at a column-zero baseline. Leading whitespace is counted by
98
+ * character, so N tabs and N spaces are treated as the same depth.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * dedent('\n foo\n bar\n ')
103
+ * // 'foo\n bar'
104
+ * ```
105
+ */
106
+ export function dedent(text: string): string {
107
+ if (!text) return ''
108
+
109
+ const lines = text.split('\n')
110
+ const isBlank = (line: string) => line.trim() === ''
111
+
112
+ const start = lines.findIndex((line) => !isBlank(line))
113
+ if (start === -1) return ''
114
+ const end = lines.findLastIndex((line) => !isBlank(line))
115
+
116
+ const trimmed = lines.slice(start, end + 1)
117
+ const indents = trimmed.filter((line) => !isBlank(line)).map((line) => line.match(/^\s*/)?.[0].length ?? 0)
118
+ const min = indents.length ? Math.min(...indents) : 0
119
+
120
+ return trimmed.map((line) => (isBlank(line) ? '' : line.slice(min))).join('\n')
121
+ }
122
+
123
+ /**
124
+ * Renders the generic clause (`<T, U>`) shared by function and arrow-function nodes.
125
+ * Accepts either a raw string (rendered verbatim) or an array of type-parameter names.
126
+ */
127
+ export function formatGenerics(generics: FunctionNode['generics'] | ArrowFunctionNode['generics']): string {
128
+ if (!generics) return ''
129
+ return `<${Array.isArray(generics) ? generics.join(', ') : generics}>`
130
+ }
131
+
132
+ /**
133
+ * Renders the return-type suffix (`: T` or `: Promise<T>` when `isAsync` is true).
134
+ * Returns an empty string when no return type is provided.
135
+ */
136
+ export function formatReturnType(returnType: string | null | undefined, isAsync: boolean | null | undefined): string {
137
+ if (!returnType) return ''
138
+ return isAsync ? `: Promise<${returnType}>` : `: ${returnType}`
139
+ }
140
+
141
+ /**
142
+ * Module-scoped TypeScript printer instance. `ts.createPrinter()` is stateless across calls
143
+ * (it does not mutate the source file) so a single instance can be safely reused for every
144
+ * `print()` call. Hoisting it out of `print()` avoids re-running the printer initialization
145
+ * for each file's import/export section.
146
+ */
147
+ const TS_PRINTER = ts.createPrinter({
148
+ omitTrailingSemicolon: true,
149
+ newLine: ts.NewLineKind.LineFeed,
150
+ removeComments: false,
151
+ noEmitHelpers: true,
152
+ })
153
+
154
+ /**
155
+ * Module-scoped source file used as the print target. `printList` only reads the source
156
+ * file's compiler options / language version. It never mutates it.
157
+ */
158
+ const PRINT_SOURCE_FILE = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)
159
+
160
+ // Pre-warm the printer at module load. The first `printList` call lazily initializes
161
+ // the printer's internal string-builder and identifier tables. Doing it once at import
162
+ // time keeps that cost off the critical path for short-lived CLI builds.
163
+ TS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray([]), PRINT_SOURCE_FILE)
164
+
165
+ /**
166
+ * Converts TypeScript/TSX AST nodes to a string using the TypeScript printer.
167
+ */
168
+ export function print(...elements: Array<ts.Node>): string {
169
+ const filtered = elements.filter(Boolean)
170
+ if (filtered.length === 0) return ''
171
+
172
+ const output = TS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray(filtered), PRINT_SOURCE_FILE)
173
+
174
+ return output.replace(CRLF_PATTERN, '\n')
175
+ }
176
+
177
+ /**
178
+ * Converts a {@link JSDocNode} to a JSDoc comment block string.
179
+ *
180
+ * @example
181
+ * ```ts
182
+ * printJSDoc({ comments: ['@description A pet', '@deprecated'] })
183
+ * // /**
184
+ * // * @description A pet
185
+ * // * @deprecated
186
+ * // *\/
187
+ * ```
188
+ */
189
+ export function printJSDoc(jsDoc: JSDocNode): string {
190
+ const comments = (jsDoc.comments ?? []).filter((c) => c != null)
191
+ if (comments.length === 0) return ''
192
+
193
+ const lines = comments
194
+ .flatMap((c) => c.split(/\r?\n/))
195
+ .map((l) => l.replace(JSDOC_TERMINATOR_PATTERN, '* /').replace(CARRIAGE_RETURN_PATTERN, ''))
196
+ .filter((l) => l.trim().length > 0)
197
+
198
+ if (lines.length === 0) return ''
199
+
200
+ return ['/**', ...lines.map((l) => ` * ${l}`), ' */'].join('\n')
201
+ }
202
+
203
+ /**
204
+ * Converts a {@link ConstNode} to a TypeScript `const` declaration string.
205
+ *
206
+ * Mirrors the `Const` component from `@kubb/renderer-jsx`.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * printConst(factory.createConst({ name: 'pet', export: true, nodes: ['{}'] }))
211
+ * // 'export const pet = {}'
212
+ * ```
213
+ *
214
+ * @example With type and `as const`
215
+ * ```ts
216
+ * printConst(factory.createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true, nodes: ['[]'] }))
217
+ * // 'export const pets: Pet[] = [] as const'
218
+ * ```
219
+ */
220
+ export function printConst(node: ConstNode): string {
221
+ const { name, export: canExport, type, JSDoc, asConst, nodes } = node
222
+
223
+ const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
224
+ const body = printNodes(nodes)
225
+
226
+ const parts: Array<string> = []
227
+ if (canExport) parts.push('export ')
228
+ parts.push('const ')
229
+ parts.push(name)
230
+ if (type) {
231
+ parts.push(`: ${type}`)
232
+ }
233
+ parts.push(' = ')
234
+ parts.push(body)
235
+ if (asConst) parts.push(' as const')
236
+
237
+ const declaration = parts.join('')
238
+ return [jsDocStr, declaration].filter(Boolean).join('\n')
239
+ }
240
+
241
+ /**
242
+ * Converts a {@link TypeNode} to a TypeScript `type` alias declaration string.
243
+ *
244
+ * Mirrors the `Type` component from `@kubb/renderer-jsx`.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * printType(factory.createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))
249
+ * // 'export type Pet = { id: number }'
250
+ * ```
251
+ */
252
+ export function printType(node: TypeNode): string {
253
+ const { name, export: canExport, JSDoc, nodes } = node
254
+
255
+ const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
256
+ const body = printNodes(nodes)
257
+
258
+ const parts: Array<string> = []
259
+ if (canExport) parts.push('export ')
260
+ parts.push('type ')
261
+ parts.push(name)
262
+ parts.push(' = ')
263
+ parts.push(body)
264
+
265
+ const declaration = parts.join('')
266
+ return [jsDocStr, declaration].filter(Boolean).join('\n')
267
+ }
268
+
269
+ /**
270
+ * Converts a {@link FunctionNode} to a TypeScript `function` declaration string.
271
+ *
272
+ * Mirrors the `Function` component from `@kubb/renderer-jsx`.
273
+ *
274
+ * @example
275
+ * ```ts
276
+ * printFunction(factory.createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))
277
+ * // 'export function getPet(id: string): Pet {\n return fetch(id)\n}'
278
+ * ```
279
+ *
280
+ * @example Async with generics
281
+ * ```ts
282
+ * printFunction(factory.createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))
283
+ * // 'export async function fetchPet<T>(id: string): Promise<T> {\n}'
284
+ * ```
285
+ */
286
+ export function printFunction(node: FunctionNode): string {
287
+ const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes } = node
288
+
289
+ const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
290
+ const body = printNodes(nodes)
291
+ const indented = body ? indentLines(body) : ''
292
+
293
+ const parts: Array<string> = []
294
+ if (canExport) parts.push('export ')
295
+ if (isDefault) parts.push('default ')
296
+ if (isAsync) parts.push('async ')
297
+ parts.push('function ')
298
+ parts.push(name)
299
+ parts.push(formatGenerics(generics))
300
+ parts.push(`(${params ?? ''})`)
301
+ parts.push(formatReturnType(returnType, isAsync))
302
+ parts.push(' {')
303
+ if (indented) {
304
+ parts.push(`\n${indented}\n`)
305
+ }
306
+ parts.push('}')
307
+
308
+ const declaration = parts.join('')
309
+ return [jsDocStr, declaration].filter(Boolean).join('\n')
310
+ }
311
+
312
+ /**
313
+ * Converts an {@link ArrowFunctionNode} to a TypeScript arrow function declaration string.
314
+ *
315
+ * Mirrors the `Function.Arrow` component from `@kubb/renderer-jsx`.
316
+ *
317
+ * @example Multi-line arrow function
318
+ * ```ts
319
+ * printArrowFunction(factory.createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))
320
+ * // 'export const getPet = (id: string) => {\n return fetch(id)\n}'
321
+ * ```
322
+ *
323
+ * @example Single-line arrow function
324
+ * ```ts
325
+ * printArrowFunction(factory.createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))
326
+ * // 'const double = (n: number) => n * 2'
327
+ * ```
328
+ */
329
+ export function printArrowFunction(node: ArrowFunctionNode): string {
330
+ const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes, singleLine } = node
331
+
332
+ const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
333
+ const body = printNodes(nodes)
334
+ const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\n${indentLines(body)}\n}` : ' => {}'
335
+
336
+ const parts: Array<string> = []
337
+ if (canExport) parts.push('export ')
338
+ if (isDefault) parts.push('default ')
339
+ parts.push('const ')
340
+ parts.push(name)
341
+ parts.push(' = ')
342
+ if (isAsync) parts.push('async ')
343
+ parts.push(formatGenerics(generics))
344
+ parts.push(`(${params ?? ''})`)
345
+ parts.push(formatReturnType(returnType, isAsync))
346
+ parts.push(arrowBody)
347
+
348
+ const declaration = parts.join('')
349
+ return [jsDocStr, declaration].filter(Boolean).join('\n')
350
+ }
351
+
352
+ /**
353
+ * Converts a {@link CodeNode} to its TypeScript string representation.
354
+ *
355
+ * Dispatches to the appropriate printer based on the node's `kind`.
356
+ *
357
+ * @example
358
+ * ```ts
359
+ * printCodeNode(factory.createConst({ name: 'x', nodes: ['1'] }))
360
+ * // 'const x = 1'
361
+ * ```
362
+ */
363
+ export function printCodeNode(node: CodeNode): string {
364
+ if (node.kind === 'Break') return ''
365
+ if (node.kind === 'Text') return dedent((node as TextNode).value)
366
+ if (node.kind === 'Jsx') return dedent((node as JsxNode).value)
367
+ if (node.kind === 'Const') return printConst(node)
368
+ if (node.kind === 'Type') return printType(node)
369
+ if (node.kind === 'Function') return printFunction(node)
370
+ if (node.kind === 'ArrowFunction') return printArrowFunction(node)
371
+ return ''
372
+ }
373
+
374
+ /**
375
+ * Converts a {@link SourceNode} to its TypeScript string representation.
376
+ *
377
+ * Iterates `nodes` in DOM order, rendering each {@link CodeNode} via
378
+ * {@link printCodeNode}.
379
+ *
380
+ * Top-level declarations are separated by a blank line so the source reads
381
+ * cleanly without an external formatter.
382
+ *
383
+ * @example From nodes
384
+ * ```ts
385
+ * printSource({ kind: 'Source', nodes: [factory.createConst({ name: 'x', nodes: [factory.createText('1')] }), factory.createText('x.toString()')] })
386
+ * // 'const x = 1\n\nx.toString()'
387
+ * ```
388
+ */
389
+ export function printSource(node: SourceNode): string {
390
+ const nodes = node.nodes
391
+
392
+ if (!nodes || nodes.length === 0) return ''
393
+
394
+ return nodes
395
+ .map((child) => printCodeNode(child as CodeNode))
396
+ .filter(Boolean)
397
+ .join('\n\n')
398
+ }
399
+
400
+ /**
401
+ * Wraps a module specifier in single quotes, escaping any embedded backslash or quote so the emitted
402
+ * statement stays valid even for unusual paths.
403
+ */
404
+ function quoteModulePath(path: string): string {
405
+ return `'${path.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`
406
+ }
407
+
408
+ /**
409
+ * Renders an import declaration string in the repo style (single quotes, no semicolons), covering
410
+ * default, namespace (`* as`), and named imports with `{ a as b }` aliases, each optionally
411
+ * `type`-only. `path` is used verbatim, so resolve it first.
412
+ *
413
+ * @example
414
+ * ```ts
415
+ * printImport({ name: ['z'], path: './zod.ts' })
416
+ * // "import { z } from './zod.ts'"
417
+ * ```
418
+ */
419
+ export function printImport({
420
+ name,
421
+ path,
422
+ isTypeOnly = false,
423
+ isNameSpace = false,
424
+ }: {
425
+ name: string | Array<string | { propertyName: string; name?: string }>
426
+ path: string
427
+ isTypeOnly?: boolean | null
428
+ isNameSpace?: boolean | null
429
+ }): string {
430
+ const typePrefix = isTypeOnly ? 'type ' : ''
431
+ const from = quoteModulePath(path)
432
+
433
+ if (!Array.isArray(name)) {
434
+ if (isNameSpace) return `import ${typePrefix}* as ${name} from ${from}`
435
+ return `import ${typePrefix}${name} from ${from}`
436
+ }
437
+
438
+ const specifiers = name.map((item) => {
439
+ if (typeof item === 'object') {
440
+ return item.name ? `${item.propertyName} as ${item.name}` : item.propertyName
441
+ }
442
+ return item
443
+ })
444
+
445
+ return `import ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`
446
+ }
447
+
448
+ /**
449
+ * Renders an export declaration string in the repo style (single quotes, no semicolons), covering
450
+ * named re-exports, namespace alias (`* as name`), and wildcard, each optionally `type`-only.
451
+ * `path` is used verbatim, so resolve it first.
452
+ *
453
+ * @example
454
+ * ```ts
455
+ * printExport({ name: ['Pet', 'Order'], path: './models.ts' })
456
+ * // "export { Pet, Order } from './models.ts'"
457
+ * ```
458
+ */
459
+ export function printExport({
460
+ path,
461
+ name,
462
+ isTypeOnly = false,
463
+ asAlias = false,
464
+ }: {
465
+ path: string
466
+ name?: string | Array<ts.Identifier | string> | null
467
+ isTypeOnly?: boolean | null
468
+ asAlias?: boolean | null
469
+ }): string {
470
+ const typePrefix = isTypeOnly ? 'type ' : ''
471
+ const from = quoteModulePath(path)
472
+
473
+ if (Array.isArray(name)) {
474
+ const specifiers = name.map((item) => (typeof item === 'string' ? item : item.text))
475
+ return `export ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`
476
+ }
477
+
478
+ if (asAlias && name) {
479
+ const parsedName = LEADING_DIGIT_PATTERN.test(name) ? `_${name.slice(1)}` : name
480
+ return `export ${typePrefix}* as ${parsedName} from ${from}`
481
+ }
482
+
483
+ if (name) {
484
+ console.warn(`When using name as string, asAlias should be true: ${name}`)
485
+ }
486
+
487
+ return `export ${typePrefix}* from ${from}`
488
+ }
package/extension.yaml DELETED
@@ -1,100 +0,0 @@
1
- $schema: https://kubb.dev/schemas/extension.json
2
- kind: parser
3
- id: parser-ts
4
- name: TypeScript
5
- description: TypeScript and TSX file parser for Kubb. Converts the universal AST to `.ts`/`.tsx` source code using the official TypeScript compiler.
6
- category: typescript
7
- type: official
8
- npmPackage: '@kubb/parser-ts'
9
- docsPath: /parsers/parser-ts
10
- repo: https://github.com/kubb-labs/kubb
11
- maintainers:
12
- - name: Stijn Van Hulle
13
- github: stijnvanhulle
14
- compatibility:
15
- kubb: '>=5.0.0'
16
- node: '>=22'
17
- tags:
18
- - typescript
19
- - tsx
20
- - parser
21
- - printer
22
- - ast
23
- resources:
24
- documentation: https://kubb.dev/parsers/parser-ts
25
- repository: https://github.com/kubb-labs/kubb
26
- issues: https://github.com/kubb-labs/kubb/issues
27
- changelog: https://github.com/kubb-labs/kubb/blob/main/packages/parser-ts/CHANGELOG.md
28
- featured: true
29
- icon:
30
- light: https://kubb.dev/feature/typescript.svg
31
- intro: |-
32
- The TypeScript parser is the default file parser used by Kubb when no `parsers` option is set in `defineConfig`. It converts Kubb's universal AST into `.ts` and `.tsx` source code using the official [TypeScript compiler](https://www.typescriptlang.org/).
33
-
34
- Two parser instances are exported:
35
-
36
- - `parserTs` — handles `.ts` and `.js` files
37
- - `parserTsx` — handles `.tsx` and `.jsx` files
38
-
39
- Both are configured globally in `defineConfig` and apply to every file produced by every plugin.
40
- options:
41
- - name: extname
42
- type: "'.ts' | '.js' | '.tsx' | '.jsx' | string"
43
- required: false
44
- default: "'.ts'"
45
- description: |-
46
- File extension used when rewriting relative import paths. Set to `.js` for ESM-friendly emit, `.tsx` for React projects, or leave unset to keep TypeScript's default behaviour.
47
-
48
- Extension rewriting is configured via `output.extension` in `defineConfig`, not as a parser argument.
49
- codeBlock:
50
- lang: typescript
51
- title: kubb.config.ts
52
- twoslash: false
53
- code: |-
54
- import { defineConfig } from 'kubb'
55
- import { adapterOas } from '@kubb/adapter-oas'
56
- import { parserTs } from '@kubb/parser-ts'
57
-
58
- export default defineConfig({
59
- input: { path: './petstore.yaml' },
60
- output: { path: './src/gen', extension: { '.ts': '.js' } },
61
- adapter: adapterOas(),
62
- parsers: [parserTs],
63
- })
64
- examples:
65
- - name: TypeScript (default)
66
- files:
67
- - name: kubb.config.ts
68
- lang: typescript
69
- twoslash: false
70
- code: |-
71
- import { defineConfig } from 'kubb'
72
- import { adapterOas } from '@kubb/adapter-oas'
73
- import { parserTs } from '@kubb/parser-ts'
74
-
75
- export default defineConfig({
76
- input: { path: './petstore.yaml' },
77
- output: { path: './src/gen' },
78
- adapter: adapterOas(),
79
- parsers: [parserTs],
80
- })
81
- - name: TSX (React)
82
- files:
83
- - name: kubb.config.ts
84
- lang: typescript
85
- twoslash: false
86
- code: |-
87
- import { defineConfig } from 'kubb'
88
- import { adapterOas } from '@kubb/adapter-oas'
89
- import { parserTsx } from '@kubb/parser-ts'
90
-
91
- export default defineConfig({
92
- input: { path: './petstore.yaml' },
93
- output: { path: './src/gen' },
94
- adapter: adapterOas(),
95
- parsers: [parserTsx],
96
- })
97
- notes:
98
- - type: tip
99
- body: |-
100
- `parser-ts` is bundled with Kubb and used automatically when no `parsers` option is provided. You only need to install it explicitly when combining it with other parsers or providing a fully custom parsers list.
File without changes