@kubb/parser-ts 5.0.0-beta.11 → 5.0.0-beta.110
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/LICENSE +17 -10
- package/README.md +57 -49
- package/dist/index.cjs +269 -153
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +63 -56
- package/dist/index.js +270 -149
- package/dist/index.js.map +1 -1
- package/package.json +6 -10
- package/extension.yaml +0 -100
- package/src/constants.ts +0 -47
- package/src/index.ts +0 -2
- package/src/parserTs.ts +0 -60
- package/src/parserTsx.ts +0 -20
- package/src/utils.ts +0 -459
- /package/dist/{chunk--u3MIqq1.js → rolldown-runtime-C0LytTxp.js} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -16,19 +16,38 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
}
|
|
17
17
|
return to;
|
|
18
18
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
20
20
|
value: mod,
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
-
let
|
|
24
|
+
let _kubb_kit = require("@kubb/kit");
|
|
25
25
|
let node_path = require("node:path");
|
|
26
26
|
let typescript = require("typescript");
|
|
27
27
|
typescript = __toESM(typescript, 1);
|
|
28
|
-
//#region src/
|
|
28
|
+
//#region ../../internals/utils/src/fs.ts
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* Strips the file extension from a path or file name.
|
|
31
|
+
* Only removes the last `.ext` segment when the dot is not part of a directory name.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* trimExtName('petStore.ts') // 'petStore'
|
|
35
|
+
* trimExtName('/src/models/pet.ts') // '/src/models/pet'
|
|
36
|
+
* trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'
|
|
37
|
+
* trimExtName('noExtension') // 'noExtension'
|
|
38
|
+
*/
|
|
39
|
+
function trimExtName(text) {
|
|
40
|
+
const dotIndex = text.lastIndexOf(".");
|
|
41
|
+
if (dotIndex > 0 && !text.includes("/", dotIndex)) return text.slice(0, dotIndex);
|
|
42
|
+
return text;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Indentation unit prepended once per nesting level when pretty-printing.
|
|
46
|
+
*/
|
|
47
|
+
const INDENT = " ".repeat(2);
|
|
48
|
+
/**
|
|
49
|
+
* Matches only the final `.<ext>` of a path, so a name like `foo.bar.ts` keeps
|
|
50
|
+
* `foo.bar` and loses just `.ts`.
|
|
32
51
|
*/
|
|
33
52
|
const FILE_EXTENSION_PATTERN = /\.[^/.]+$/;
|
|
34
53
|
/**
|
|
@@ -36,48 +55,36 @@ const FILE_EXTENSION_PATTERN = /\.[^/.]+$/;
|
|
|
36
55
|
*/
|
|
37
56
|
const WINDOWS_PATH_SEPARATOR = /\\/g;
|
|
38
57
|
/**
|
|
39
|
-
* Matches `*\/` in free-form text so JSDoc bodies can
|
|
58
|
+
* Matches `*\/` in free-form text so JSDoc bodies can neutralize premature
|
|
40
59
|
* comment terminators (`*\/` → `* /`).
|
|
41
60
|
*/
|
|
42
61
|
const JSDOC_TERMINATOR_PATTERN = /\*\//g;
|
|
43
62
|
/**
|
|
44
|
-
* Matches carriage returns for
|
|
63
|
+
* Matches carriage returns for normalizing CRLF/CR line endings to LF.
|
|
45
64
|
*/
|
|
46
65
|
const CARRIAGE_RETURN_PATTERN = /\r/g;
|
|
47
66
|
/**
|
|
48
|
-
* Matches CRLF sequences used when
|
|
67
|
+
* Matches CRLF sequences used when normalizing TypeScript printer output.
|
|
49
68
|
*/
|
|
50
69
|
const CRLF_PATTERN = /\r\n/g;
|
|
51
70
|
/**
|
|
52
|
-
* Matches an identifier that starts with a digit
|
|
53
|
-
* so the printer
|
|
71
|
+
* Matches an identifier that starts with a digit. JavaScript disallows this,
|
|
72
|
+
* so the printer replaces the leading digit with `_`.
|
|
54
73
|
*/
|
|
55
74
|
const LEADING_DIGIT_PATTERN = /^\d/;
|
|
56
75
|
//#endregion
|
|
57
76
|
//#region src/utils.ts
|
|
58
77
|
const { factory } = typescript.default;
|
|
59
78
|
/**
|
|
60
|
-
* Normalises a file-system path to POSIX separators and strips any leading `../` segment.
|
|
61
|
-
*/
|
|
62
|
-
function slash(path) {
|
|
63
|
-
return (0, node_path.normalize)(path).replaceAll(WINDOWS_PATH_SEPARATOR, "/").replace("../", "");
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
79
|
* Resolves `filePath` relative to `rootDir` and returns a POSIX-style path
|
|
67
80
|
* prefixed with `./` when the target sits inside the root, or `../` when it escapes it.
|
|
68
81
|
*/
|
|
69
82
|
function getRelativePath(rootDir, filePath) {
|
|
70
|
-
const
|
|
83
|
+
const rel = (0, node_path.relative)(rootDir, filePath);
|
|
84
|
+
const slashed = (0, node_path.normalize)(rel).replaceAll(WINDOWS_PATH_SEPARATOR, "/").replace("../", "");
|
|
71
85
|
return slashed.startsWith("../") ? slashed : `./${slashed}`;
|
|
72
86
|
}
|
|
73
87
|
/**
|
|
74
|
-
* Strips the trailing file extension (for example `.ts`) from a path.
|
|
75
|
-
* Preserves intermediate dots like `foo.bar.ts` → `foo.bar`.
|
|
76
|
-
*/
|
|
77
|
-
function trimExtName(text) {
|
|
78
|
-
return text.replace(FILE_EXTENSION_PATTERN, "");
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
88
|
* Rewrites an import/export path so its extension matches the caller-supplied
|
|
82
89
|
* `options.extname`. When the source path has no extension the original is kept,
|
|
83
90
|
* so virtual/module-only paths flow through unchanged.
|
|
@@ -88,25 +95,64 @@ function resolveOutputPath(path, options, rootAware) {
|
|
|
88
95
|
return rootAware ? trimExtName(path) : path;
|
|
89
96
|
}
|
|
90
97
|
/**
|
|
91
|
-
* Serializes
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* Elements are joined with `\n`.
|
|
98
|
+
* Serializes a `nodes` array into source text. Each entry is rendered via {@link printCodeNode}
|
|
99
|
+
* and joined with a single newline. A `Break` node (`<br/>`) inserts one blank line between
|
|
100
|
+
* statements. Consecutive breaks, and breaks at the very start or end, are folded into the
|
|
101
|
+
* separator, so a double `<br/>` never emits more than one blank line.
|
|
96
102
|
*/
|
|
97
103
|
function printNodes(nodes) {
|
|
98
104
|
if (!nodes || nodes.length === 0) return "";
|
|
99
|
-
|
|
105
|
+
let result = "";
|
|
106
|
+
let hasContent = false;
|
|
107
|
+
let pendingBreak = false;
|
|
108
|
+
for (const node of nodes) {
|
|
109
|
+
if (node.kind === "Break") {
|
|
110
|
+
if (hasContent) pendingBreak = true;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const text = printCodeNode(node);
|
|
114
|
+
if (!text) continue;
|
|
115
|
+
if (hasContent) result += pendingBreak ? "\n\n" : "\n";
|
|
116
|
+
result += text;
|
|
117
|
+
hasContent = true;
|
|
118
|
+
pendingBreak = false;
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
100
121
|
}
|
|
101
122
|
/**
|
|
102
|
-
* Indents every non-empty line of `text` by
|
|
123
|
+
* Indents every non-empty line of `text` by one indent unit. Pass a number to repeat
|
|
124
|
+
* {@link INDENT_CHAR} that many times, or a string to use as the indent verbatim.
|
|
103
125
|
*/
|
|
104
|
-
function indentLines(text,
|
|
126
|
+
function indentLines(text, indent = INDENT) {
|
|
105
127
|
if (!text) return "";
|
|
106
|
-
const pad = " ".repeat(
|
|
128
|
+
const pad = typeof indent === "string" ? indent : " ".repeat(indent);
|
|
107
129
|
return text.split("\n").map((line) => line.trim() ? `${pad}${line}` : "").join("\n");
|
|
108
130
|
}
|
|
109
131
|
/**
|
|
132
|
+
* Removes the common leading whitespace shared by every non-blank line and trims
|
|
133
|
+
* surrounding blank lines, so multi-line content authored inside an indented template
|
|
134
|
+
* literal lines up at a column-zero baseline. Leading whitespace is counted by
|
|
135
|
+
* character, so N tabs and N spaces are treated as the same depth.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* dedent('\n foo\n bar\n ')
|
|
140
|
+
* // 'foo\n bar'
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
function dedent(text) {
|
|
144
|
+
if (!text) return "";
|
|
145
|
+
const lines = text.split("\n");
|
|
146
|
+
const isBlank = (line) => line.trim() === "";
|
|
147
|
+
const start = lines.findIndex((line) => !isBlank(line));
|
|
148
|
+
if (start === -1) return "";
|
|
149
|
+
const end = lines.findLastIndex((line) => !isBlank(line));
|
|
150
|
+
const trimmed = lines.slice(start, end + 1);
|
|
151
|
+
const indents = trimmed.filter((line) => !isBlank(line)).map((line) => line.match(/^\s*/)?.[0].length ?? 0);
|
|
152
|
+
const min = indents.length ? Math.min(...indents) : 0;
|
|
153
|
+
return trimmed.map((line) => isBlank(line) ? "" : line.slice(min)).join("\n");
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
110
156
|
* Renders the generic clause (`<T, U>`) shared by function and arrow-function nodes.
|
|
111
157
|
* Accepts either a raw string (rendered verbatim) or an array of type-parameter names.
|
|
112
158
|
*/
|
|
@@ -123,37 +169,31 @@ function formatReturnType(returnType, isAsync) {
|
|
|
123
169
|
return isAsync ? `: Promise<${returnType}>` : `: ${returnType}`;
|
|
124
170
|
}
|
|
125
171
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* TypeScript printer to crash.
|
|
172
|
+
* Module-scoped TypeScript printer instance. A printer does not mutate the source file, so one
|
|
173
|
+
* instance is reused across every `print()` call instead of constructing a new printer each time.
|
|
129
174
|
*/
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
175
|
+
const TS_PRINTER = typescript.default.createPrinter({
|
|
176
|
+
omitTrailingSemicolon: true,
|
|
177
|
+
newLine: typescript.default.NewLineKind.LineFeed,
|
|
178
|
+
removeComments: false,
|
|
179
|
+
noEmitHelpers: true
|
|
180
|
+
});
|
|
136
181
|
/**
|
|
137
|
-
*
|
|
182
|
+
* Module-scoped source file used as the print target. `printList` only reads the source
|
|
183
|
+
* file's compiler options / language version. It never mutates it.
|
|
138
184
|
*/
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return typescript.default.createPrinter({
|
|
142
|
-
omitTrailingSemicolon: true,
|
|
143
|
-
newLine: typescript.default.NewLineKind.LineFeed,
|
|
144
|
-
removeComments: false,
|
|
145
|
-
noEmitHelpers: true
|
|
146
|
-
}).printList(typescript.default.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile).replace(CRLF_PATTERN, "\n");
|
|
147
|
-
}
|
|
185
|
+
const PRINT_SOURCE_FILE = typescript.default.createSourceFile("print.tsx", "", typescript.default.ScriptTarget.ES2022, true, typescript.default.ScriptKind.TSX);
|
|
186
|
+
TS_PRINTER.printList(typescript.default.ListFormat.MultiLine, factory.createNodeArray([]), PRINT_SOURCE_FILE);
|
|
148
187
|
/**
|
|
149
|
-
*
|
|
188
|
+
* Converts TypeScript/TSX AST nodes to a string using the TypeScript printer.
|
|
150
189
|
*/
|
|
151
|
-
function
|
|
152
|
-
|
|
153
|
-
|
|
190
|
+
function print(...elements) {
|
|
191
|
+
const filtered = elements.filter(Boolean);
|
|
192
|
+
if (filtered.length === 0) return "";
|
|
193
|
+
return TS_PRINTER.printList(typescript.default.ListFormat.MultiLine, factory.createNodeArray(filtered), PRINT_SOURCE_FILE).replace(CRLF_PATTERN, "\n");
|
|
154
194
|
}
|
|
155
195
|
/**
|
|
156
|
-
* Converts a {@link JSDocNode} to a JSDoc comment block string.
|
|
196
|
+
* Converts a {@link ast.JSDocNode} to a JSDoc comment block string.
|
|
157
197
|
*
|
|
158
198
|
* @example
|
|
159
199
|
* ```ts
|
|
@@ -176,19 +216,19 @@ function printJSDoc(jsDoc) {
|
|
|
176
216
|
].join("\n");
|
|
177
217
|
}
|
|
178
218
|
/**
|
|
179
|
-
* Converts a {@link ConstNode} to a TypeScript `const` declaration string.
|
|
219
|
+
* Converts a {@link ast.ConstNode} to a TypeScript `const` declaration string.
|
|
180
220
|
*
|
|
181
221
|
* Mirrors the `Const` component from `@kubb/renderer-jsx`.
|
|
182
222
|
*
|
|
183
223
|
* @example
|
|
184
224
|
* ```ts
|
|
185
|
-
* printConst(createConst({ name: 'pet', export: true, nodes: ['{}'] }))
|
|
225
|
+
* printConst(factory.createConst({ name: 'pet', export: true, nodes: ['{}'] }))
|
|
186
226
|
* // 'export const pet = {}'
|
|
187
227
|
* ```
|
|
188
228
|
*
|
|
189
229
|
* @example With type and `as const`
|
|
190
230
|
* ```ts
|
|
191
|
-
* printConst(createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true, nodes: ['[]'] }))
|
|
231
|
+
* printConst(factory.createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true, nodes: ['[]'] }))
|
|
192
232
|
* // 'export const pets: Pet[] = [] as const'
|
|
193
233
|
* ```
|
|
194
234
|
*/
|
|
@@ -207,13 +247,13 @@ function printConst(node) {
|
|
|
207
247
|
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
208
248
|
}
|
|
209
249
|
/**
|
|
210
|
-
* Converts a {@link TypeNode} to a TypeScript `type` alias declaration string.
|
|
250
|
+
* Converts a {@link ast.TypeNode} to a TypeScript `type` alias declaration string.
|
|
211
251
|
*
|
|
212
252
|
* Mirrors the `Type` component from `@kubb/renderer-jsx`.
|
|
213
253
|
*
|
|
214
254
|
* @example
|
|
215
255
|
* ```ts
|
|
216
|
-
* printType(createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))
|
|
256
|
+
* printType(factory.createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))
|
|
217
257
|
* // 'export type Pet = { id: number }'
|
|
218
258
|
* ```
|
|
219
259
|
*/
|
|
@@ -230,19 +270,19 @@ function printType(node) {
|
|
|
230
270
|
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
231
271
|
}
|
|
232
272
|
/**
|
|
233
|
-
* Converts a {@link FunctionNode} to a TypeScript `function` declaration string.
|
|
273
|
+
* Converts a {@link ast.FunctionNode} to a TypeScript `function` declaration string.
|
|
234
274
|
*
|
|
235
275
|
* Mirrors the `Function` component from `@kubb/renderer-jsx`.
|
|
236
276
|
*
|
|
237
277
|
* @example
|
|
238
278
|
* ```ts
|
|
239
|
-
* printFunction(createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))
|
|
279
|
+
* printFunction(factory.createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))
|
|
240
280
|
* // 'export function getPet(id: string): Pet {\n return fetch(id)\n}'
|
|
241
281
|
* ```
|
|
242
282
|
*
|
|
243
283
|
* @example Async with generics
|
|
244
284
|
* ```ts
|
|
245
|
-
* printFunction(createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))
|
|
285
|
+
* printFunction(factory.createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))
|
|
246
286
|
* // 'export async function fetchPet<T>(id: string): Promise<T> {\n}'
|
|
247
287
|
* ```
|
|
248
288
|
*/
|
|
@@ -266,19 +306,19 @@ function printFunction(node) {
|
|
|
266
306
|
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
267
307
|
}
|
|
268
308
|
/**
|
|
269
|
-
* Converts an {@link ArrowFunctionNode} to a TypeScript arrow function declaration string.
|
|
309
|
+
* Converts an {@link ast.ArrowFunctionNode} to a TypeScript arrow function declaration string.
|
|
270
310
|
*
|
|
271
311
|
* Mirrors the `Function.Arrow` component from `@kubb/renderer-jsx`.
|
|
272
312
|
*
|
|
273
313
|
* @example Multi-line arrow function
|
|
274
314
|
* ```ts
|
|
275
|
-
* printArrowFunction(createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))
|
|
315
|
+
* printArrowFunction(factory.createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))
|
|
276
316
|
* // 'export const getPet = (id: string) => {\n return fetch(id)\n}'
|
|
277
317
|
* ```
|
|
278
318
|
*
|
|
279
319
|
* @example Single-line arrow function
|
|
280
320
|
* ```ts
|
|
281
|
-
* printArrowFunction(createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))
|
|
321
|
+
* printArrowFunction(factory.createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))
|
|
282
322
|
* // 'const double = (n: number) => n * 2'
|
|
283
323
|
* ```
|
|
284
324
|
*/
|
|
@@ -301,134 +341,210 @@ function printArrowFunction(node) {
|
|
|
301
341
|
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
302
342
|
}
|
|
303
343
|
/**
|
|
304
|
-
* Converts a {@link CodeNode} to its TypeScript string representation.
|
|
344
|
+
* Converts a {@link ast.CodeNode} to its TypeScript string representation.
|
|
305
345
|
*
|
|
306
346
|
* Dispatches to the appropriate printer based on the node's `kind`.
|
|
307
347
|
*
|
|
308
348
|
* @example
|
|
309
349
|
* ```ts
|
|
310
|
-
* printCodeNode(createConst({ name: 'x', nodes: ['1'] }))
|
|
350
|
+
* printCodeNode(factory.createConst({ name: 'x', nodes: ['1'] }))
|
|
311
351
|
* // 'const x = 1'
|
|
312
352
|
* ```
|
|
313
353
|
*/
|
|
314
354
|
function printCodeNode(node) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
355
|
+
if (node.kind === "Break") return "";
|
|
356
|
+
if (node.kind === "Text") return dedent(node.value);
|
|
357
|
+
if (node.kind === "Jsx") return dedent(node.value);
|
|
358
|
+
if (node.kind === "Const") return printConst(node);
|
|
359
|
+
if (node.kind === "Type") return printType(node);
|
|
360
|
+
if (node.kind === "Function") return printFunction(node);
|
|
361
|
+
if (node.kind === "ArrowFunction") return printArrowFunction(node);
|
|
362
|
+
return "";
|
|
324
363
|
}
|
|
325
364
|
/**
|
|
326
|
-
* Converts a {@link SourceNode} to its TypeScript string representation.
|
|
365
|
+
* Converts a {@link ast.SourceNode} to its TypeScript string representation.
|
|
327
366
|
*
|
|
328
|
-
* Iterates `nodes` in DOM order, rendering each {@link CodeNode} via
|
|
367
|
+
* Iterates `nodes` in DOM order, rendering each {@link ast.CodeNode} via
|
|
329
368
|
* {@link printCodeNode}.
|
|
330
369
|
*
|
|
370
|
+
* Top-level declarations are separated by a blank line so the source reads
|
|
371
|
+
* cleanly without an external formatter.
|
|
372
|
+
*
|
|
331
373
|
* @example From nodes
|
|
332
374
|
* ```ts
|
|
333
|
-
* printSource({ kind: 'Source', nodes: [createConst({ name: 'x', nodes: [createText('1')] }), createText('x.toString()')] })
|
|
334
|
-
* // 'const x = 1\nx.toString()'
|
|
375
|
+
* printSource({ kind: 'Source', nodes: [factory.createConst({ name: 'x', nodes: [factory.createText('1')] }), factory.createText('x.toString()')] })
|
|
376
|
+
* // 'const x = 1\n\nx.toString()'
|
|
335
377
|
* ```
|
|
336
378
|
*/
|
|
337
379
|
function printSource(node) {
|
|
338
|
-
|
|
339
|
-
return "";
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
return factory.createImportDeclaration(void 0, factory.createImportClause(isTypeOnly, factory.createIdentifier(name), void 0), factory.createStringLiteral(resolvePath), void 0);
|
|
380
|
+
const nodes = node.nodes;
|
|
381
|
+
if (!nodes || nodes.length === 0) return "";
|
|
382
|
+
let result = "";
|
|
383
|
+
for (const child of nodes) {
|
|
384
|
+
const text = printCodeNode(child);
|
|
385
|
+
if (!text) continue;
|
|
386
|
+
result = result ? `${result}\n\n${text}` : text;
|
|
346
387
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
return
|
|
388
|
+
return result;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Wraps a module specifier in single quotes, escaping any embedded backslash or quote so the emitted
|
|
392
|
+
* statement stays valid even for unusual paths.
|
|
393
|
+
*/
|
|
394
|
+
function quoteModulePath(path) {
|
|
395
|
+
return `'${path.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
355
396
|
}
|
|
356
|
-
|
|
357
|
-
|
|
397
|
+
/**
|
|
398
|
+
* Renders an import declaration string in the repo style (single quotes, no semicolons), covering
|
|
399
|
+
* default, namespace (`* as`), and named imports with `{ a as b }` aliases, each optionally
|
|
400
|
+
* `type`-only. `path` is used verbatim, so resolve it first.
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```ts
|
|
404
|
+
* printImport({ name: ['z'], path: './zod.ts' })
|
|
405
|
+
* // "import { z } from './zod.ts'"
|
|
406
|
+
* ```
|
|
407
|
+
*/
|
|
408
|
+
function printImport({ name, path, isTypeOnly = false, isNameSpace = false }) {
|
|
409
|
+
const typePrefix = isTypeOnly ? "type " : "";
|
|
410
|
+
const from = quoteModulePath(path);
|
|
358
411
|
if (!Array.isArray(name)) {
|
|
359
|
-
|
|
360
|
-
return
|
|
412
|
+
if (isNameSpace) return `import ${typePrefix}* as ${name} from ${from}`;
|
|
413
|
+
return `import ${typePrefix}${name} from ${from}`;
|
|
361
414
|
}
|
|
362
|
-
return
|
|
415
|
+
return `import ${typePrefix}{ ${name.map((item) => {
|
|
416
|
+
if (typeof item === "object") return item.name ? `${item.propertyName} as ${item.name}` : item.propertyName;
|
|
417
|
+
return item;
|
|
418
|
+
}).join(", ")} } from ${from}`;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Renders an export declaration string in the repo style (single quotes, no semicolons), covering
|
|
422
|
+
* named re-exports, namespace alias (`* as name`), and wildcard, each optionally `type`-only.
|
|
423
|
+
* `path` is used verbatim, so resolve it first.
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* ```ts
|
|
427
|
+
* printExport({ name: ['Pet', 'Order'], path: './models.ts' })
|
|
428
|
+
* // "export { Pet, Order } from './models.ts'"
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
function printExport({ path, name, isTypeOnly = false, asAlias = false }) {
|
|
432
|
+
const typePrefix = isTypeOnly ? "type " : "";
|
|
433
|
+
const from = quoteModulePath(path);
|
|
434
|
+
if (Array.isArray(name)) return `export ${typePrefix}{ ${name.map((item) => typeof item === "string" ? item : item.text).join(", ")} } from ${from}`;
|
|
435
|
+
if (asAlias && name) return `export ${typePrefix}* as ${LEADING_DIGIT_PATTERN.test(name) ? `_${name.slice(1)}` : name} from ${from}`;
|
|
436
|
+
if (name) return `export ${typePrefix}{ ${name} } from ${from}`;
|
|
437
|
+
return `export ${typePrefix}* from ${from}`;
|
|
363
438
|
}
|
|
364
439
|
//#endregion
|
|
365
440
|
//#region src/parserTs.ts
|
|
441
|
+
const DEFAULT_EXTENSION = { ".ts": "" };
|
|
366
442
|
/**
|
|
367
|
-
*
|
|
368
|
-
*
|
|
443
|
+
* Default Kubb parser for `.ts` and `.js` files. Takes the universal AST
|
|
444
|
+
* produced by an adapter and prints it as TypeScript source using the official
|
|
445
|
+
* TypeScript compiler. Imports and exports are rewritten based on each file's
|
|
446
|
+
* metadata and the `extension` option.
|
|
447
|
+
*
|
|
448
|
+
* Used automatically when no `parsers` option is set on `defineConfig`. Use
|
|
449
|
+
* `parserTsx` instead for React projects that emit JSX.
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```ts
|
|
453
|
+
* import { defineConfig } from 'kubb'
|
|
454
|
+
* import { adapterOas } from '@kubb/adapter-oas'
|
|
455
|
+
* import { parserTs } from '@kubb/parser-ts'
|
|
369
456
|
*
|
|
370
|
-
*
|
|
457
|
+
* export default defineConfig({
|
|
458
|
+
* input: './petStore.yaml',
|
|
459
|
+
* output: { path: './src/gen' },
|
|
460
|
+
* adapter: adapterOas(),
|
|
461
|
+
* parsers: [parserTs()],
|
|
462
|
+
* plugins: [],
|
|
463
|
+
* })
|
|
464
|
+
* ```
|
|
371
465
|
*/
|
|
372
|
-
const parserTs = (0,
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
466
|
+
const parserTs = (0, _kubb_kit.defineParser)(({ extension = DEFAULT_EXTENSION } = {}) => {
|
|
467
|
+
return {
|
|
468
|
+
name: "typescript",
|
|
469
|
+
extNames: [".ts", ".js"],
|
|
470
|
+
print(...nodes) {
|
|
471
|
+
return print(...nodes);
|
|
472
|
+
},
|
|
473
|
+
parse(file) {
|
|
474
|
+
const extname = extension[file.extname] || void 0;
|
|
475
|
+
const sourceParts = [];
|
|
476
|
+
for (const item of file.sources) {
|
|
477
|
+
const sourceStr = printSource(item);
|
|
478
|
+
if (sourceStr) sourceParts.push(sourceStr.trimEnd());
|
|
479
|
+
}
|
|
480
|
+
const source = sourceParts.join("\n\n");
|
|
481
|
+
const importLines = [];
|
|
482
|
+
for (const item of file.imports) {
|
|
483
|
+
const importPath = item.root ? getRelativePath(item.root, item.path) : item.path;
|
|
484
|
+
importLines.push(printImport({
|
|
485
|
+
name: item.name,
|
|
486
|
+
path: resolveOutputPath(importPath, { extname }, Boolean(item.root)),
|
|
487
|
+
isTypeOnly: item.isTypeOnly,
|
|
488
|
+
isNameSpace: item.isNameSpace
|
|
489
|
+
}));
|
|
490
|
+
}
|
|
491
|
+
const exportLines = [];
|
|
492
|
+
for (const item of file.exports) exportLines.push(printExport({
|
|
386
493
|
name: item.name,
|
|
387
|
-
path: resolveOutputPath(
|
|
494
|
+
path: resolveOutputPath(item.path, { extname }, true),
|
|
388
495
|
isTypeOnly: item.isTypeOnly,
|
|
389
|
-
|
|
496
|
+
asAlias: item.asAlias
|
|
390
497
|
}));
|
|
498
|
+
const importExportBlock = [...importLines, ...exportLines].join("\n");
|
|
499
|
+
return [
|
|
500
|
+
file.banner,
|
|
501
|
+
importExportBlock,
|
|
502
|
+
source,
|
|
503
|
+
file.footer
|
|
504
|
+
].filter((segment) => Boolean(segment)).map((s) => s.trimEnd()).join("\n\n");
|
|
391
505
|
}
|
|
392
|
-
|
|
393
|
-
for (const item of file.exports) exportNodes.push(createExport({
|
|
394
|
-
name: item.name,
|
|
395
|
-
path: resolveOutputPath(item.path, options, true),
|
|
396
|
-
isTypeOnly: item.isTypeOnly,
|
|
397
|
-
asAlias: item.asAlias
|
|
398
|
-
}));
|
|
399
|
-
return [
|
|
400
|
-
file.banner,
|
|
401
|
-
print(...importNodes, ...exportNodes),
|
|
402
|
-
source,
|
|
403
|
-
file.footer
|
|
404
|
-
].filter((segment) => Boolean(segment)).map((s) => s.trimEnd()).join("\n\n");
|
|
405
|
-
}
|
|
506
|
+
};
|
|
406
507
|
});
|
|
407
508
|
//#endregion
|
|
408
509
|
//#region src/parserTsx.ts
|
|
409
510
|
/**
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
511
|
+
* Kubb parser for `.tsx` and `.jsx` files. Delegates to `parserTs` because the
|
|
512
|
+
* TypeScript compiler handles JSX natively via `ScriptKind.TSX`, so it shares the
|
|
513
|
+
* same `extension` option.
|
|
413
514
|
*
|
|
414
|
-
* Add
|
|
515
|
+
* Add to the `parsers` array on `defineConfig` when generating components for
|
|
516
|
+
* React (or any framework that emits JSX).
|
|
415
517
|
*
|
|
416
|
-
* @
|
|
518
|
+
* @example
|
|
519
|
+
* ```ts
|
|
520
|
+
* import { defineConfig } from 'kubb'
|
|
521
|
+
* import { adapterOas } from '@kubb/adapter-oas'
|
|
522
|
+
* import { parserTsx } from '@kubb/parser-ts'
|
|
523
|
+
*
|
|
524
|
+
* export default defineConfig({
|
|
525
|
+
* input: './petStore.yaml',
|
|
526
|
+
* output: { path: './src/gen' },
|
|
527
|
+
* adapter: adapterOas(),
|
|
528
|
+
* parsers: [parserTsx()],
|
|
529
|
+
* plugins: [],
|
|
530
|
+
* })
|
|
531
|
+
* ```
|
|
417
532
|
*/
|
|
418
|
-
const parserTsx = (0,
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
533
|
+
const parserTsx = (0, _kubb_kit.defineParser)((options = {}) => {
|
|
534
|
+
const parser = parserTs(options);
|
|
535
|
+
return {
|
|
536
|
+
name: "tsx",
|
|
537
|
+
extNames: [".tsx", ".jsx"],
|
|
538
|
+
print(...nodes) {
|
|
539
|
+
return print(...nodes);
|
|
540
|
+
},
|
|
541
|
+
parse(file) {
|
|
542
|
+
return parser.parse(file);
|
|
543
|
+
}
|
|
544
|
+
};
|
|
424
545
|
});
|
|
425
546
|
//#endregion
|
|
426
|
-
exports.createExport = createExport;
|
|
427
|
-
exports.createImport = createImport;
|
|
428
547
|
exports.parserTs = parserTs;
|
|
429
548
|
exports.parserTsx = parserTsx;
|
|
430
|
-
exports.print = print;
|
|
431
|
-
exports.safePrint = safePrint;
|
|
432
|
-
exports.validateNodes = validateNodes;
|
|
433
549
|
|
|
434
550
|
//# sourceMappingURL=index.cjs.map
|