@kubb/parser-ts 5.0.0-beta.4 → 5.0.0-beta.40
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/README.md +111 -0
- package/dist/index.cjs +150 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +60 -55
- package/dist/index.js +152 -106
- package/dist/index.js.map +1 -1
- package/extension.yaml +14 -13
- package/package.json +5 -5
- package/src/constants.ts +4 -4
- package/src/index.ts +1 -1
- package/src/parserTs.ts +26 -459
- package/src/parserTsx.ts +25 -8
- package/src/utils.ts +458 -0
- /package/dist/{chunk--u3MIqq1.js → chunk-C0LytTxp.js} +0 -0
package/extension.yaml
CHANGED
|
@@ -2,7 +2,7 @@ $schema: https://kubb.dev/schemas/extension.json
|
|
|
2
2
|
kind: parser
|
|
3
3
|
id: parser-ts
|
|
4
4
|
name: TypeScript
|
|
5
|
-
description:
|
|
5
|
+
description: Default file parser for Kubb. Converts the universal AST to `.ts`/`.tsx` source using the official TypeScript compiler.
|
|
6
6
|
category: typescript
|
|
7
7
|
type: official
|
|
8
8
|
npmPackage: '@kubb/parser-ts'
|
|
@@ -29,23 +29,21 @@ featured: true
|
|
|
29
29
|
icon:
|
|
30
30
|
light: https://kubb.dev/feature/typescript.svg
|
|
31
31
|
intro: |-
|
|
32
|
-
|
|
32
|
+
`@kubb/parser-ts` takes the `FileNode` staged by your plugins and prints it as TypeScript source using the official [TypeScript compiler](https://www.typescriptlang.org/). It resolves import paths, deduplicates declarations, prints JSDoc, and rewrites extensions based on `output.extension`.
|
|
33
33
|
|
|
34
|
-
Two
|
|
34
|
+
Two parsers are exported:
|
|
35
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.
|
|
36
|
+
- `parserTs` — handles `.ts` and `.js` files.
|
|
37
|
+
- `parserTsx` — handles `.tsx` and `.jsx` files. Use this for React projects so JSX in generated components is preserved.
|
|
40
38
|
options:
|
|
41
39
|
- name: extname
|
|
42
40
|
type: "'.ts' | '.js' | '.tsx' | '.jsx' | string"
|
|
43
41
|
required: false
|
|
44
42
|
default: "'.ts'"
|
|
45
43
|
description: |-
|
|
46
|
-
|
|
44
|
+
Controls which extension is written into the generated import specifiers. Set `.js` for ESM-compatible output, `.tsx` for React projects. Leave unset for the TypeScript default.
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
To rewrite extensions in the generated source (e.g. `./foo` → `./foo.js`), use `output.extension` in `defineConfig`, not this option.
|
|
49
47
|
codeBlock:
|
|
50
48
|
lang: typescript
|
|
51
49
|
title: kubb.config.ts
|
|
@@ -56,10 +54,11 @@ options:
|
|
|
56
54
|
import { parserTs } from '@kubb/parser-ts'
|
|
57
55
|
|
|
58
56
|
export default defineConfig({
|
|
59
|
-
input: { path: './
|
|
57
|
+
input: { path: './petStore.yaml' },
|
|
60
58
|
output: { path: './src/gen', extension: { '.ts': '.js' } },
|
|
61
59
|
adapter: adapterOas(),
|
|
62
60
|
parsers: [parserTs],
|
|
61
|
+
plugins: [],
|
|
63
62
|
})
|
|
64
63
|
examples:
|
|
65
64
|
- name: TypeScript (default)
|
|
@@ -73,10 +72,11 @@ examples:
|
|
|
73
72
|
import { parserTs } from '@kubb/parser-ts'
|
|
74
73
|
|
|
75
74
|
export default defineConfig({
|
|
76
|
-
input: { path: './
|
|
75
|
+
input: { path: './petStore.yaml' },
|
|
77
76
|
output: { path: './src/gen' },
|
|
78
77
|
adapter: adapterOas(),
|
|
79
78
|
parsers: [parserTs],
|
|
79
|
+
plugins: [],
|
|
80
80
|
})
|
|
81
81
|
- name: TSX (React)
|
|
82
82
|
files:
|
|
@@ -89,12 +89,13 @@ examples:
|
|
|
89
89
|
import { parserTsx } from '@kubb/parser-ts'
|
|
90
90
|
|
|
91
91
|
export default defineConfig({
|
|
92
|
-
input: { path: './
|
|
92
|
+
input: { path: './petStore.yaml' },
|
|
93
93
|
output: { path: './src/gen' },
|
|
94
94
|
adapter: adapterOas(),
|
|
95
95
|
parsers: [parserTsx],
|
|
96
|
+
plugins: [],
|
|
96
97
|
})
|
|
97
98
|
notes:
|
|
98
99
|
- type: tip
|
|
99
100
|
body: |-
|
|
100
|
-
|
|
101
|
+
`@kubb/parser-ts` is bundled with Kubb and used automatically when no `parsers` option is set. Install it explicitly only when combining it with other parsers or providing a fully custom parser list.
|
package/package.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/parser-ts",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
4
|
-
"description": "TypeScript and TSX file parser for Kubb
|
|
3
|
+
"version": "5.0.0-beta.40",
|
|
4
|
+
"description": "TypeScript and TSX source file parser for Kubb. Converts AST nodes and raw TypeScript code into formatted source strings using the TypeScript compiler API.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"code-generator",
|
|
7
6
|
"codegen",
|
|
8
7
|
"kubb",
|
|
9
8
|
"parser",
|
|
@@ -43,11 +42,11 @@
|
|
|
43
42
|
},
|
|
44
43
|
"dependencies": {
|
|
45
44
|
"typescript": "^6.0.3",
|
|
46
|
-
"@kubb/core": "5.0.0-beta.
|
|
45
|
+
"@kubb/core": "5.0.0-beta.40"
|
|
47
46
|
},
|
|
48
47
|
"devDependencies": {
|
|
49
48
|
"@internals/utils": "0.0.0",
|
|
50
|
-
"@kubb/ast": "5.0.0-beta.
|
|
49
|
+
"@kubb/ast": "5.0.0-beta.40"
|
|
51
50
|
},
|
|
52
51
|
"engines": {
|
|
53
52
|
"node": ">=22"
|
|
@@ -59,6 +58,7 @@
|
|
|
59
58
|
"lint:fix": "oxlint --fix .",
|
|
60
59
|
"release": "pnpm publish --no-git-check",
|
|
61
60
|
"release:canary": "bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check",
|
|
61
|
+
"release:stage": "pnpm stage publish --no-git-check",
|
|
62
62
|
"start": "tsdown --watch",
|
|
63
63
|
"test": "vitest --passWithNoTests",
|
|
64
64
|
"typecheck": "tsc -p ./tsconfig.json --noEmit --emitDeclarationOnly false"
|
package/src/constants.ts
CHANGED
|
@@ -15,23 +15,23 @@ export const FILE_EXTENSION_PATTERN = /\.[^/.]+$/
|
|
|
15
15
|
export const WINDOWS_PATH_SEPARATOR = /\\/g
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Matches `*\/` in free-form text so JSDoc bodies can
|
|
18
|
+
* Matches `*\/` in free-form text so JSDoc bodies can neutralize premature
|
|
19
19
|
* comment terminators (`*\/` → `* /`).
|
|
20
20
|
*/
|
|
21
21
|
export const JSDOC_TERMINATOR_PATTERN = /\*\//g
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* Matches carriage returns for
|
|
24
|
+
* Matches carriage returns for normalizing CRLF/CR line endings to LF.
|
|
25
25
|
*/
|
|
26
26
|
export const CARRIAGE_RETURN_PATTERN = /\r/g
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
* Matches CRLF sequences used when
|
|
29
|
+
* Matches CRLF sequences used when normalizing TypeScript printer output.
|
|
30
30
|
*/
|
|
31
31
|
export const CRLF_PATTERN = /\r\n/g
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* Matches an identifier that starts with a digit
|
|
34
|
+
* Matches an identifier that starts with a digit. JavaScript disallows this,
|
|
35
35
|
* so the printer prefixes such names with `_`.
|
|
36
36
|
*/
|
|
37
37
|
export const LEADING_DIGIT_PATTERN = /^\d/
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { parserTs } from './parserTs.ts'
|
|
2
2
|
export { parserTsx } from './parserTsx.ts'
|
package/src/parserTs.ts
CHANGED
|
@@ -1,472 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { ArrowFunctionNode, CodeNode, ConstNode, FileNode, FunctionNode, JSDocNode, JsxNode, SourceNode, TextNode, TypeNode } from '@kubb/ast'
|
|
3
|
-
import type { Parser } from '@kubb/core'
|
|
1
|
+
import type { FileNode, SourceNode } from '@kubb/ast'
|
|
4
2
|
import { defineParser } from '@kubb/core'
|
|
5
|
-
import ts from 'typescript'
|
|
6
|
-
import {
|
|
7
|
-
CARRIAGE_RETURN_PATTERN,
|
|
8
|
-
CRLF_PATTERN,
|
|
9
|
-
CURRENT_DIRECTORY_PREFIX,
|
|
10
|
-
FILE_EXTENSION_PATTERN,
|
|
11
|
-
INDENT_SIZE,
|
|
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
|
-
function slash(path: string): string {
|
|
21
|
-
return normalize(path).replaceAll(WINDOWS_PATH_SEPARATOR, '/').replace(PARENT_DIRECTORY_PREFIX, '')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Resolves `filePath` relative to `rootDir` and returns a POSIX-style path
|
|
26
|
-
* prefixed with `./` when the target sits inside the root, or `../` when it escapes it.
|
|
27
|
-
*/
|
|
28
|
-
function getRelativePath(rootDir: string, filePath: string): string {
|
|
29
|
-
const rel = relative(rootDir, filePath)
|
|
30
|
-
const slashed = slash(rel)
|
|
31
|
-
return slashed.startsWith(PARENT_DIRECTORY_PREFIX) ? slashed : `${CURRENT_DIRECTORY_PREFIX}${slashed}`
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Strips the trailing file extension (for example `.ts`) from a path.
|
|
36
|
-
* Preserves intermediate dots like `foo.bar.ts` → `foo.bar`.
|
|
37
|
-
*/
|
|
38
|
-
function trimExtName(text: string): string {
|
|
39
|
-
return text.replace(FILE_EXTENSION_PATTERN, '')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Rewrites an import/export path so its extension matches the caller-supplied
|
|
44
|
-
* `options.extname`. When the source path has no extension the original is kept,
|
|
45
|
-
* so virtual/module-only paths flow through unchanged.
|
|
46
|
-
*/
|
|
47
|
-
function resolveOutputPath(path: string, options: { extname?: string } | undefined, rootAware: boolean): string {
|
|
48
|
-
const hasExtname = FILE_EXTENSION_PATTERN.test(path)
|
|
49
|
-
if (options?.extname && hasExtname) {
|
|
50
|
-
return `${trimExtName(path)}${options.extname}`
|
|
51
|
-
}
|
|
52
|
-
return rootAware ? trimExtName(path) : path
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Validates TypeScript AST nodes before printing.
|
|
57
|
-
* Throws an error if any node has SyntaxKind.Unknown which would cause the
|
|
58
|
-
* TypeScript printer to crash.
|
|
59
|
-
*/
|
|
60
|
-
export function validateNodes(...nodes: ts.Node[]): void {
|
|
61
|
-
for (const node of nodes) {
|
|
62
|
-
if (!node) {
|
|
63
|
-
throw new Error('Attempted to print undefined or null TypeScript node')
|
|
64
|
-
}
|
|
65
|
-
if (node.kind === ts.SyntaxKind.Unknown) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
'Invalid TypeScript AST node detected with SyntaxKind.Unknown. ' +
|
|
68
|
-
'This typically indicates a schema pattern that could not be properly converted to TypeScript. ' +
|
|
69
|
-
`Node: ${JSON.stringify(node, null, 2)}`,
|
|
70
|
-
)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Converts TypeScript/TSX AST nodes to a string using the TypeScript printer.
|
|
77
|
-
*/
|
|
78
|
-
export function print(...elements: Array<ts.Node>): string {
|
|
79
|
-
const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)
|
|
80
|
-
|
|
81
|
-
const printer = ts.createPrinter({
|
|
82
|
-
omitTrailingSemicolon: true,
|
|
83
|
-
newLine: ts.NewLineKind.LineFeed,
|
|
84
|
-
removeComments: false,
|
|
85
|
-
noEmitHelpers: true,
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)
|
|
89
|
-
|
|
90
|
-
return output.replace(CRLF_PATTERN, '\n')
|
|
91
|
-
}
|
|
3
|
+
import type * as ts from 'typescript'
|
|
4
|
+
import { createExport, createImport, getRelativePath, print, printSource, resolveOutputPath } from './utils.ts'
|
|
92
5
|
|
|
93
6
|
/**
|
|
94
|
-
*
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return print(...elements)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function createImport({
|
|
102
|
-
name,
|
|
103
|
-
path,
|
|
104
|
-
root,
|
|
105
|
-
isTypeOnly = false,
|
|
106
|
-
isNameSpace = false,
|
|
107
|
-
}: {
|
|
108
|
-
name: string | Array<string | { propertyName: string; name?: string }>
|
|
109
|
-
path: string
|
|
110
|
-
root?: string
|
|
111
|
-
/** @default false */
|
|
112
|
-
isTypeOnly?: boolean
|
|
113
|
-
/** @default false */
|
|
114
|
-
isNameSpace?: boolean
|
|
115
|
-
}): ts.ImportDeclaration {
|
|
116
|
-
const resolvePath = root ? getRelativePath(root, path) : path
|
|
117
|
-
|
|
118
|
-
if (!Array.isArray(name)) {
|
|
119
|
-
if (isNameSpace) {
|
|
120
|
-
return factory.createImportDeclaration(
|
|
121
|
-
undefined,
|
|
122
|
-
factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),
|
|
123
|
-
factory.createStringLiteral(resolvePath),
|
|
124
|
-
undefined,
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return factory.createImportDeclaration(
|
|
129
|
-
undefined,
|
|
130
|
-
factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),
|
|
131
|
-
factory.createStringLiteral(resolvePath),
|
|
132
|
-
undefined,
|
|
133
|
-
)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const specifiers = name.map((item) => {
|
|
137
|
-
if (typeof item === 'object') {
|
|
138
|
-
const { propertyName, name: alias } = item
|
|
139
|
-
return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))
|
|
140
|
-
}
|
|
141
|
-
return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
return factory.createImportDeclaration(
|
|
145
|
-
undefined,
|
|
146
|
-
factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),
|
|
147
|
-
factory.createStringLiteral(resolvePath),
|
|
148
|
-
undefined,
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function createExport({
|
|
153
|
-
path,
|
|
154
|
-
asAlias,
|
|
155
|
-
isTypeOnly = false,
|
|
156
|
-
name,
|
|
157
|
-
}: {
|
|
158
|
-
path: string
|
|
159
|
-
/** @default false */
|
|
160
|
-
asAlias?: boolean
|
|
161
|
-
/** @default false */
|
|
162
|
-
isTypeOnly?: boolean
|
|
163
|
-
name?: string | Array<ts.Identifier | string>
|
|
164
|
-
}): ts.ExportDeclaration {
|
|
165
|
-
if (name && !Array.isArray(name) && !asAlias) {
|
|
166
|
-
console.warn(`When using name as string, asAlias should be true: ${name}`)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (!Array.isArray(name)) {
|
|
170
|
-
const parsedName = name && LEADING_DIGIT_PATTERN.test(name) ? `_${name.slice(1)}` : name
|
|
171
|
-
|
|
172
|
-
return factory.createExportDeclaration(
|
|
173
|
-
undefined,
|
|
174
|
-
isTypeOnly,
|
|
175
|
-
asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,
|
|
176
|
-
factory.createStringLiteral(path),
|
|
177
|
-
undefined,
|
|
178
|
-
)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return factory.createExportDeclaration(
|
|
182
|
-
undefined,
|
|
183
|
-
isTypeOnly,
|
|
184
|
-
factory.createNamedExports(
|
|
185
|
-
name.map((propertyName) =>
|
|
186
|
-
factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName),
|
|
187
|
-
),
|
|
188
|
-
),
|
|
189
|
-
factory.createStringLiteral(path),
|
|
190
|
-
undefined,
|
|
191
|
-
)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Converts a {@link JSDocNode} to a JSDoc comment block string.
|
|
7
|
+
* Default Kubb parser for `.ts` and `.js` files. Takes the universal AST
|
|
8
|
+
* produced by an adapter and prints it as TypeScript source using the official
|
|
9
|
+
* TypeScript compiler. Imports and exports are rewritten based on each file's
|
|
10
|
+
* metadata.
|
|
196
11
|
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* printJSDoc({ comments: ['@description A pet', '@deprecated'] })
|
|
200
|
-
* // /**
|
|
201
|
-
* // * @description A pet
|
|
202
|
-
* // * @deprecated
|
|
203
|
-
* // *\/
|
|
204
|
-
* ```
|
|
205
|
-
*/
|
|
206
|
-
export function printJSDoc(jsDoc: JSDocNode): string {
|
|
207
|
-
const comments = (jsDoc.comments ?? []).filter((c) => c != null)
|
|
208
|
-
if (comments.length === 0) return ''
|
|
209
|
-
|
|
210
|
-
const lines = comments
|
|
211
|
-
.flatMap((c) => c.split(/\r?\n/))
|
|
212
|
-
.map((l) => l.replace(JSDOC_TERMINATOR_PATTERN, '* /').replace(CARRIAGE_RETURN_PATTERN, ''))
|
|
213
|
-
.filter((l) => l.trim().length > 0)
|
|
214
|
-
|
|
215
|
-
if (lines.length === 0) return ''
|
|
216
|
-
|
|
217
|
-
return ['/**', ...lines.map((l) => ` * ${l}`), ' */'].join('\n')
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Serializes the body / value content from a `nodes` array.
|
|
222
|
-
*
|
|
223
|
-
* Each element is either a raw string or a structured {@link CodeNode}
|
|
224
|
-
* (recursively converted via {@link printCodeNode}).
|
|
225
|
-
* Elements are joined with `\n`.
|
|
226
|
-
*/
|
|
227
|
-
function printNodes(nodes: Array<CodeNode> | undefined): string {
|
|
228
|
-
if (!nodes || nodes.length === 0) return ''
|
|
229
|
-
return nodes.map(printCodeNode).join('\n')
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Indents every non-empty line of `text` by `spaces` spaces.
|
|
234
|
-
*/
|
|
235
|
-
function indentLines(text: string, spaces: number = INDENT_SIZE): string {
|
|
236
|
-
if (!text) return ''
|
|
237
|
-
const pad = ' '.repeat(spaces)
|
|
238
|
-
return text
|
|
239
|
-
.split('\n')
|
|
240
|
-
.map((line) => (line.trim() ? `${pad}${line}` : ''))
|
|
241
|
-
.join('\n')
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Renders the generic clause (`<T, U>`) shared by function and arrow-function nodes.
|
|
246
|
-
* Accepts either a raw string (rendered verbatim) or an array of type-parameter names.
|
|
247
|
-
*/
|
|
248
|
-
function formatGenerics(generics: FunctionNode['generics'] | ArrowFunctionNode['generics']): string {
|
|
249
|
-
if (!generics) return ''
|
|
250
|
-
return `<${Array.isArray(generics) ? generics.join(', ') : generics}>`
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Renders the return-type suffix (`: T` or `: Promise<T>` when `isAsync` is true).
|
|
255
|
-
* Returns an empty string when no return type is provided.
|
|
256
|
-
*/
|
|
257
|
-
function formatReturnType(returnType: string | undefined, isAsync: boolean | undefined): string {
|
|
258
|
-
if (!returnType) return ''
|
|
259
|
-
return isAsync ? `: Promise<${returnType}>` : `: ${returnType}`
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Converts a {@link ConstNode} to a TypeScript `const` declaration string.
|
|
264
|
-
*
|
|
265
|
-
* Mirrors the `Const` component from `@kubb/renderer-jsx`.
|
|
12
|
+
* Used automatically when no `parsers` option is set on `defineConfig`. Use
|
|
13
|
+
* `parserTsx` instead for React projects that emit JSX.
|
|
266
14
|
*
|
|
267
15
|
* @example
|
|
268
16
|
* ```ts
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const { name, export: canExport, type, JSDoc, asConst, nodes } = node
|
|
281
|
-
|
|
282
|
-
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
|
|
283
|
-
const body = printNodes(nodes)
|
|
284
|
-
|
|
285
|
-
const parts: string[] = []
|
|
286
|
-
if (canExport) parts.push('export ')
|
|
287
|
-
parts.push('const ')
|
|
288
|
-
parts.push(name)
|
|
289
|
-
if (type) {
|
|
290
|
-
parts.push(`: ${type}`)
|
|
291
|
-
}
|
|
292
|
-
parts.push(' = ')
|
|
293
|
-
parts.push(body)
|
|
294
|
-
if (asConst) parts.push(' as const')
|
|
295
|
-
|
|
296
|
-
const declaration = parts.join('')
|
|
297
|
-
return [jsDocStr, declaration].filter(Boolean).join('\n')
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Converts a {@link TypeNode} to a TypeScript `type` alias declaration string.
|
|
302
|
-
*
|
|
303
|
-
* Mirrors the `Type` component from `@kubb/renderer-jsx`.
|
|
304
|
-
*
|
|
305
|
-
* @example
|
|
306
|
-
* ```ts
|
|
307
|
-
* printType(createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))
|
|
308
|
-
* // 'export type Pet = { id: number }'
|
|
309
|
-
* ```
|
|
310
|
-
*/
|
|
311
|
-
export function printType(node: TypeNode): string {
|
|
312
|
-
const { name, export: canExport, JSDoc, nodes } = node
|
|
313
|
-
|
|
314
|
-
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
|
|
315
|
-
const body = printNodes(nodes)
|
|
316
|
-
|
|
317
|
-
const parts: string[] = []
|
|
318
|
-
if (canExport) parts.push('export ')
|
|
319
|
-
parts.push('type ')
|
|
320
|
-
parts.push(name)
|
|
321
|
-
parts.push(' = ')
|
|
322
|
-
parts.push(body)
|
|
323
|
-
|
|
324
|
-
const declaration = parts.join('')
|
|
325
|
-
return [jsDocStr, declaration].filter(Boolean).join('\n')
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Converts a {@link FunctionNode} to a TypeScript `function` declaration string.
|
|
330
|
-
*
|
|
331
|
-
* Mirrors the `Function` component from `@kubb/renderer-jsx`.
|
|
332
|
-
*
|
|
333
|
-
* @example
|
|
334
|
-
* ```ts
|
|
335
|
-
* printFunction(createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))
|
|
336
|
-
* // 'export function getPet(id: string): Pet {\n return fetch(id)\n}'
|
|
337
|
-
* ```
|
|
338
|
-
*
|
|
339
|
-
* @example Async with generics
|
|
340
|
-
* ```ts
|
|
341
|
-
* printFunction(createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))
|
|
342
|
-
* // 'export async function fetchPet<T>(id: string): Promise<T> {\n}'
|
|
343
|
-
* ```
|
|
344
|
-
*/
|
|
345
|
-
export function printFunction(node: FunctionNode): string {
|
|
346
|
-
const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes } = node
|
|
347
|
-
|
|
348
|
-
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
|
|
349
|
-
const body = printNodes(nodes)
|
|
350
|
-
const indented = body ? indentLines(body) : ''
|
|
351
|
-
|
|
352
|
-
const parts: string[] = []
|
|
353
|
-
if (canExport) parts.push('export ')
|
|
354
|
-
if (isDefault) parts.push('default ')
|
|
355
|
-
if (isAsync) parts.push('async ')
|
|
356
|
-
parts.push('function ')
|
|
357
|
-
parts.push(name)
|
|
358
|
-
parts.push(formatGenerics(generics))
|
|
359
|
-
parts.push(`(${params ?? ''})`)
|
|
360
|
-
parts.push(formatReturnType(returnType, isAsync))
|
|
361
|
-
parts.push(' {')
|
|
362
|
-
if (indented) {
|
|
363
|
-
parts.push(`\n${indented}\n`)
|
|
364
|
-
}
|
|
365
|
-
parts.push('}')
|
|
366
|
-
|
|
367
|
-
const declaration = parts.join('')
|
|
368
|
-
return [jsDocStr, declaration].filter(Boolean).join('\n')
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* Converts an {@link ArrowFunctionNode} to a TypeScript arrow function declaration string.
|
|
373
|
-
*
|
|
374
|
-
* Mirrors the `Function.Arrow` component from `@kubb/renderer-jsx`.
|
|
375
|
-
*
|
|
376
|
-
* @example Multi-line arrow function
|
|
377
|
-
* ```ts
|
|
378
|
-
* printArrowFunction(createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))
|
|
379
|
-
* // 'export const getPet = (id: string) => {\n return fetch(id)\n}'
|
|
380
|
-
* ```
|
|
381
|
-
*
|
|
382
|
-
* @example Single-line arrow function
|
|
383
|
-
* ```ts
|
|
384
|
-
* printArrowFunction(createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))
|
|
385
|
-
* // 'const double = (n: number) => n * 2'
|
|
17
|
+
* import { defineConfig } from 'kubb'
|
|
18
|
+
* import { adapterOas } from '@kubb/adapter-oas'
|
|
19
|
+
* import { parserTs } from '@kubb/parser-ts'
|
|
20
|
+
*
|
|
21
|
+
* export default defineConfig({
|
|
22
|
+
* input: { path: './petStore.yaml' },
|
|
23
|
+
* output: { path: './src/gen' },
|
|
24
|
+
* adapter: adapterOas(),
|
|
25
|
+
* parsers: [parserTs],
|
|
26
|
+
* plugins: [],
|
|
27
|
+
* })
|
|
386
28
|
* ```
|
|
387
29
|
*/
|
|
388
|
-
export
|
|
389
|
-
const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes, singleLine } = node
|
|
390
|
-
|
|
391
|
-
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
|
|
392
|
-
const body = printNodes(nodes)
|
|
393
|
-
const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\n${indentLines(body)}\n}` : ' => {}'
|
|
394
|
-
|
|
395
|
-
const parts: string[] = []
|
|
396
|
-
if (canExport) parts.push('export ')
|
|
397
|
-
if (isDefault) parts.push('default ')
|
|
398
|
-
parts.push('const ')
|
|
399
|
-
parts.push(name)
|
|
400
|
-
parts.push(' = ')
|
|
401
|
-
if (isAsync) parts.push('async ')
|
|
402
|
-
parts.push(formatGenerics(generics))
|
|
403
|
-
parts.push(`(${params ?? ''})`)
|
|
404
|
-
parts.push(formatReturnType(returnType, isAsync))
|
|
405
|
-
parts.push(arrowBody)
|
|
406
|
-
|
|
407
|
-
const declaration = parts.join('')
|
|
408
|
-
return [jsDocStr, declaration].filter(Boolean).join('\n')
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* Converts a {@link CodeNode} to its TypeScript string representation.
|
|
413
|
-
*
|
|
414
|
-
* Dispatches to the appropriate printer based on the node's `kind`.
|
|
415
|
-
*
|
|
416
|
-
* @example
|
|
417
|
-
* ```ts
|
|
418
|
-
* printCodeNode(createConst({ name: 'x', nodes: ['1'] }))
|
|
419
|
-
* // 'const x = 1'
|
|
420
|
-
* ```
|
|
421
|
-
*/
|
|
422
|
-
export function printCodeNode(node: CodeNode): string {
|
|
423
|
-
switch (node.kind) {
|
|
424
|
-
case 'Break':
|
|
425
|
-
return ''
|
|
426
|
-
case 'Text':
|
|
427
|
-
return (node as TextNode).value
|
|
428
|
-
case 'Jsx':
|
|
429
|
-
return (node as JsxNode).value
|
|
430
|
-
case 'Const':
|
|
431
|
-
return printConst(node)
|
|
432
|
-
case 'Type':
|
|
433
|
-
return printType(node)
|
|
434
|
-
case 'Function':
|
|
435
|
-
return printFunction(node)
|
|
436
|
-
case 'ArrowFunction':
|
|
437
|
-
return printArrowFunction(node)
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/**
|
|
442
|
-
* Converts a {@link SourceNode} to its TypeScript string representation.
|
|
443
|
-
*
|
|
444
|
-
* Iterates `nodes` in DOM order, rendering each {@link CodeNode} via
|
|
445
|
-
* {@link printCodeNode}.
|
|
446
|
-
*
|
|
447
|
-
* @example From nodes
|
|
448
|
-
* ```ts
|
|
449
|
-
* printSource({ kind: 'Source', nodes: [createConst({ name: 'x', nodes: [createText('1')] }), createText('x.toString()')] })
|
|
450
|
-
* // 'const x = 1\nx.toString()'
|
|
451
|
-
* ```
|
|
452
|
-
*/
|
|
453
|
-
export function printSource(node: SourceNode): string {
|
|
454
|
-
if (node.nodes && node.nodes.length > 0) {
|
|
455
|
-
return node.nodes.map(printCodeNode).join('\n')
|
|
456
|
-
}
|
|
457
|
-
return ''
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Parser that converts `.ts` and `.js` files to strings using the TypeScript
|
|
462
|
-
* compiler. Handles import/export statement generation from file metadata.
|
|
463
|
-
*
|
|
464
|
-
* @default Used automatically when no `parsers` option is set in `defineConfig`.
|
|
465
|
-
*/
|
|
466
|
-
export const parserTs: Parser = defineParser({
|
|
30
|
+
export const parserTs = defineParser({
|
|
467
31
|
name: 'typescript',
|
|
468
32
|
extNames: ['.ts', '.js'],
|
|
469
|
-
|
|
33
|
+
print(...nodes: Array<ts.Node>) {
|
|
34
|
+
return print(...nodes)
|
|
35
|
+
},
|
|
36
|
+
parse(file, options = { extname: '.ts' }) {
|
|
470
37
|
const sourceParts: Array<string> = []
|
|
471
38
|
for (const item of file.sources) {
|
|
472
39
|
const sourceStr = printSource(item as SourceNode)
|
|
@@ -493,7 +60,7 @@ export const parserTs: Parser = defineParser({
|
|
|
493
60
|
for (const item of (file as FileNode).exports) {
|
|
494
61
|
exportNodes.push(
|
|
495
62
|
createExport({
|
|
496
|
-
name: item.name as string | Array<ts.Identifier | string> | undefined,
|
|
63
|
+
name: item.name as string | Array<ts.Identifier | string> | null | undefined,
|
|
497
64
|
path: resolveOutputPath(item.path, options, true),
|
|
498
65
|
isTypeOnly: item.isTypeOnly,
|
|
499
66
|
asAlias: item.asAlias,
|