@kubb/parser-ts 5.0.0-alpha.31 → 5.0.0-alpha.32
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/index.cjs +217 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +217 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/parserTs.ts +267 -5
package/dist/index.cjs
CHANGED
|
@@ -91,6 +91,219 @@ function createExport({ path, asAlias, isTypeOnly = false, name }) {
|
|
|
91
91
|
return factory.createExportDeclaration(void 0, isTypeOnly, factory.createNamedExports(name.map((propertyName) => factory.createExportSpecifier(false, void 0, typeof propertyName === "string" ? factory.createIdentifier(propertyName) : propertyName))), factory.createStringLiteral(path), void 0);
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
|
+
* Converts a {@link JSDocNode} to a JSDoc comment block string.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* printJSDoc({ comments: ['@description A pet', '@deprecated'] })
|
|
99
|
+
* // /**
|
|
100
|
+
* // * @description A pet
|
|
101
|
+
* // * @deprecated
|
|
102
|
+
* // *\/
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
function printJSDoc(jsDoc) {
|
|
106
|
+
const comments = (jsDoc.comments ?? []).filter((c) => c != null);
|
|
107
|
+
if (comments.length === 0) return "";
|
|
108
|
+
const lines = comments.flatMap((c) => c.split(/\r?\n/)).map((l) => l.replace(/\*\//g, "* /").replace(/\r/g, "")).filter((l) => l.trim().length > 0);
|
|
109
|
+
if (lines.length === 0) return "";
|
|
110
|
+
return [
|
|
111
|
+
"/**",
|
|
112
|
+
...lines.map((l) => ` * ${l}`),
|
|
113
|
+
" */"
|
|
114
|
+
].join("\n");
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Serialises the body / value content from a `nodes` array.
|
|
118
|
+
*
|
|
119
|
+
* Each element is either a raw string or a structured {@link CodeNode}
|
|
120
|
+
* (recursively converted via {@link printCodeNode}).
|
|
121
|
+
* Elements are joined with `\n`.
|
|
122
|
+
*/
|
|
123
|
+
function printNodes(nodes) {
|
|
124
|
+
if (!nodes || nodes.length === 0) return "";
|
|
125
|
+
return nodes.map((n) => typeof n === "string" ? n : printCodeNode(n)).join("\n");
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Indents every non-empty line of `text` by `spaces` spaces.
|
|
129
|
+
*/
|
|
130
|
+
function indentLines(text, spaces = 2) {
|
|
131
|
+
if (!text) return "";
|
|
132
|
+
const pad = " ".repeat(spaces);
|
|
133
|
+
return text.split("\n").map((line) => line.trim() ? `${pad}${line}` : "").join("\n");
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Converts a {@link ConstNode} to a TypeScript `const` declaration string.
|
|
137
|
+
*
|
|
138
|
+
* Mirrors the `Const` component from `@kubb/react-fabric`.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* printConst(createConst({ name: 'pet', export: true, nodes: ['{}'] }))
|
|
143
|
+
* // 'export const pet = {}'
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @example With type and `as const`
|
|
147
|
+
* ```ts
|
|
148
|
+
* printConst(createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true, nodes: ['[]'] }))
|
|
149
|
+
* // 'export const pets: Pet[] = [] as const'
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
function printConst(node) {
|
|
153
|
+
const { name, export: canExport, type, JSDoc, asConst, nodes } = node;
|
|
154
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : "";
|
|
155
|
+
const body = printNodes(nodes);
|
|
156
|
+
const parts = [];
|
|
157
|
+
if (canExport) parts.push("export ");
|
|
158
|
+
parts.push("const ");
|
|
159
|
+
parts.push(name);
|
|
160
|
+
if (type) parts.push(`: ${type}`);
|
|
161
|
+
parts.push(" = ");
|
|
162
|
+
parts.push(body);
|
|
163
|
+
if (asConst) parts.push(" as const");
|
|
164
|
+
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Converts a {@link TypeNode} to a TypeScript `type` alias declaration string.
|
|
168
|
+
*
|
|
169
|
+
* Mirrors the `Type` component from `@kubb/react-fabric`.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* printType(createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))
|
|
174
|
+
* // 'export type Pet = { id: number }'
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
function printType(node) {
|
|
178
|
+
const { name, export: canExport, JSDoc, nodes } = node;
|
|
179
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : "";
|
|
180
|
+
const body = printNodes(nodes);
|
|
181
|
+
const parts = [];
|
|
182
|
+
if (canExport) parts.push("export ");
|
|
183
|
+
parts.push("type ");
|
|
184
|
+
parts.push(name);
|
|
185
|
+
parts.push(" = ");
|
|
186
|
+
parts.push(body);
|
|
187
|
+
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Converts a {@link FunctionNode} to a TypeScript `function` declaration string.
|
|
191
|
+
*
|
|
192
|
+
* Mirrors the `Function` component from `@kubb/react-fabric`.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* printFunction(createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))
|
|
197
|
+
* // 'export function getPet(id: string): Pet {\n return fetch(id)\n}'
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* @example Async with generics
|
|
201
|
+
* ```ts
|
|
202
|
+
* printFunction(createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))
|
|
203
|
+
* // 'export async function fetchPet<T>(id: string): Promise<T> {\n}'
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
function printFunction(node) {
|
|
207
|
+
const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes } = node;
|
|
208
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : "";
|
|
209
|
+
const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(", ") : generics}>` : "";
|
|
210
|
+
const returnTypeStr = returnType ? isAsync ? `: Promise<${returnType}>` : `: ${returnType}` : "";
|
|
211
|
+
const body = printNodes(nodes);
|
|
212
|
+
const indented = body ? indentLines(body) : "";
|
|
213
|
+
const parts = [];
|
|
214
|
+
if (canExport) parts.push("export ");
|
|
215
|
+
if (isDefault) parts.push("default ");
|
|
216
|
+
if (isAsync) parts.push("async ");
|
|
217
|
+
parts.push("function ");
|
|
218
|
+
parts.push(name);
|
|
219
|
+
parts.push(genericsStr);
|
|
220
|
+
parts.push(`(${params ?? ""})`);
|
|
221
|
+
parts.push(returnTypeStr);
|
|
222
|
+
parts.push(" {");
|
|
223
|
+
if (indented) parts.push(`\n${indented}\n`);
|
|
224
|
+
parts.push("}");
|
|
225
|
+
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Converts an {@link ArrowFunctionNode} to a TypeScript arrow function declaration string.
|
|
229
|
+
*
|
|
230
|
+
* Mirrors the `Function.Arrow` component from `@kubb/react-fabric`.
|
|
231
|
+
*
|
|
232
|
+
* @example Multi-line arrow function
|
|
233
|
+
* ```ts
|
|
234
|
+
* printArrowFunction(createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))
|
|
235
|
+
* // 'export const getPet = (id: string) => {\n return fetch(id)\n}'
|
|
236
|
+
* ```
|
|
237
|
+
*
|
|
238
|
+
* @example Single-line arrow function
|
|
239
|
+
* ```ts
|
|
240
|
+
* printArrowFunction(createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))
|
|
241
|
+
* // 'const double = (n: number) => n * 2'
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
function printArrowFunction(node) {
|
|
245
|
+
const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes, singleLine } = node;
|
|
246
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : "";
|
|
247
|
+
const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(", ") : generics}>` : "";
|
|
248
|
+
const returnTypeStr = returnType ? isAsync ? `: Promise<${returnType}>` : `: ${returnType}` : "";
|
|
249
|
+
const body = printNodes(nodes);
|
|
250
|
+
const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\n${indentLines(body)}\n}` : " => {}";
|
|
251
|
+
const parts = [];
|
|
252
|
+
if (canExport) parts.push("export ");
|
|
253
|
+
if (isDefault) parts.push("default ");
|
|
254
|
+
parts.push("const ");
|
|
255
|
+
parts.push(name);
|
|
256
|
+
parts.push(" = ");
|
|
257
|
+
if (isAsync) parts.push("async ");
|
|
258
|
+
parts.push(genericsStr);
|
|
259
|
+
parts.push(`(${params ?? ""})`);
|
|
260
|
+
parts.push(returnTypeStr);
|
|
261
|
+
parts.push(arrowBody);
|
|
262
|
+
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Converts a {@link CodeNode} to its TypeScript string representation.
|
|
266
|
+
*
|
|
267
|
+
* Dispatches to the appropriate printer based on the node's `kind`.
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```ts
|
|
271
|
+
* printCodeNode(createConst({ name: 'x', nodes: ['1'] }))
|
|
272
|
+
* // 'const x = 1'
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
function printCodeNode(node) {
|
|
276
|
+
switch (node.kind) {
|
|
277
|
+
case "Const": return printConst(node);
|
|
278
|
+
case "Type": return printType(node);
|
|
279
|
+
case "Function": return printFunction(node);
|
|
280
|
+
case "ArrowFunction": return printArrowFunction(node);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Converts a {@link SourceNode} to its TypeScript string representation.
|
|
285
|
+
*
|
|
286
|
+
* Uses `value` if present; otherwise converts the structured `nodes` array
|
|
287
|
+
* via {@link printCodeNode}.
|
|
288
|
+
*
|
|
289
|
+
* @example From value
|
|
290
|
+
* ```ts
|
|
291
|
+
* printSource({ kind: 'Source', value: 'const x = 1' })
|
|
292
|
+
* // 'const x = 1'
|
|
293
|
+
* ```
|
|
294
|
+
*
|
|
295
|
+
* @example From nodes
|
|
296
|
+
* ```ts
|
|
297
|
+
* printSource({ kind: 'Source', nodes: [createConst({ name: 'x', nodes: ['1'] })] })
|
|
298
|
+
* // 'const x = 1'
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
function printSource(node) {
|
|
302
|
+
if (node.value) return node.value;
|
|
303
|
+
if (node.nodes && node.nodes.length > 0) return node.nodes.map(printCodeNode).join("\n");
|
|
304
|
+
return "";
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
94
307
|
* Parser that converts `.ts` and `.js` files to strings using the TypeScript
|
|
95
308
|
* compiler. Handles import/export statement generation from file metadata.
|
|
96
309
|
*
|
|
@@ -101,7 +314,10 @@ const parserTs = (0, _kubb_core.defineParser)({
|
|
|
101
314
|
extNames: [".ts", ".js"],
|
|
102
315
|
async parse(file, options = { extname: ".ts" }) {
|
|
103
316
|
const sourceParts = [];
|
|
104
|
-
for (const item of file.sources)
|
|
317
|
+
for (const item of file.sources) {
|
|
318
|
+
const sourceStr = printSource(item);
|
|
319
|
+
if (sourceStr) sourceParts.push(sourceStr);
|
|
320
|
+
}
|
|
105
321
|
const source = sourceParts.join("\n\n");
|
|
106
322
|
const importNodes = [];
|
|
107
323
|
for (const item of file.imports) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["ts"],"sources":["../src/parserTs.ts","../src/parserTsx.ts"],"sourcesContent":["import { normalize, relative } from 'node:path'\nimport type { KubbFile, Parser } from '@kubb/core'\nimport { defineParser } from '@kubb/core'\nimport ts from 'typescript'\n\nconst { factory } = ts\n\nfunction slash(path: string): string {\n return normalize(path).replaceAll(/\\\\/g, '/').replace('../', '')\n}\n\nfunction getRelativePath(rootDir: string, filePath: string): string {\n const rel = relative(rootDir, filePath)\n const slashed = slash(rel)\n return slashed.startsWith('../') ? slashed : `./${slashed}`\n}\n\nfunction trimExtName(text: string): string {\n return text.replace(/\\.[^/.]+$/, '')\n}\n\n/**\n * Validates TypeScript AST nodes before printing.\n * Throws an error if any node has SyntaxKind.Unknown which would cause the\n * TypeScript printer to crash.\n */\nexport function validateNodes(...nodes: ts.Node[]): void {\n for (const node of nodes) {\n if (!node) {\n throw new Error('Attempted to print undefined or null TypeScript node')\n }\n if (node.kind === ts.SyntaxKind.Unknown) {\n throw new Error(\n 'Invalid TypeScript AST node detected with SyntaxKind.Unknown. ' +\n 'This typically indicates a schema pattern that could not be properly converted to TypeScript. ' +\n `Node: ${JSON.stringify(node, null, 2)}`,\n )\n }\n }\n}\n\n/**\n * Converts TypeScript/TSX AST nodes to a string using the TypeScript printer.\n */\nexport function print(...elements: Array<ts.Node>): string {\n const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n const printer = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n })\n\n const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)\n\n return output.replace(/\\r\\n/g, '\\n')\n}\n\n/**\n * Like `print` but validates nodes first to surface issues early.\n */\nexport function safePrint(...elements: Array<ts.Node>): string {\n validateNodes(...elements)\n return print(...elements)\n}\n\nexport function createImport({\n name,\n path,\n root,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n root?: string\n /** @default false */\n isTypeOnly?: boolean\n /** @default false */\n isNameSpace?: boolean\n}): ts.ImportDeclaration {\n const resolvePath = root ? getRelativePath(root, path) : path\n\n if (!Array.isArray(name)) {\n if (isNameSpace) {\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n const { propertyName, name: alias } = item\n return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))\n }\n return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n })\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n}\n\nexport function createExport({\n path,\n asAlias,\n isTypeOnly = false,\n name,\n}: {\n path: string\n /** @default false */\n asAlias?: boolean\n /** @default false */\n isTypeOnly?: boolean\n name?: string | Array<ts.Identifier | string>\n}): ts.ExportDeclaration {\n if (name && !Array.isArray(name) && !asAlias) {\n console.warn(`When using name as string, asAlias should be true: ${name}`)\n }\n\n if (!Array.isArray(name)) {\n const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n factory.createStringLiteral(path),\n undefined,\n )\n }\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n factory.createNamedExports(\n name.map((propertyName) =>\n factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName),\n ),\n ),\n factory.createStringLiteral(path),\n undefined,\n )\n}\n\n/**\n * Parser that converts `.ts` and `.js` files to strings using the TypeScript\n * compiler. Handles import/export statement generation from file metadata.\n *\n * @default Used automatically when no `parsers` option is set in `defineConfig`.\n */\nexport const parserTs: Parser = defineParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n async parse(file, options = { extname: '.ts' }) {\n const sourceParts: Array<string> = []\n for (const item of file.sources) {\n if (item.value) {\n sourceParts.push(item.value)\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importNodes: Array<ts.ImportDeclaration> = []\n for (const item of (file as KubbFile.ResolvedFile).imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n const hasExtname = !!/\\.[^/.]+$/.exec(importPath)\n\n importNodes.push(\n createImport({\n name: item.name as string | Array<string | { propertyName: string; name?: string }>,\n path: options?.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,\n isTypeOnly: item.isTypeOnly,\n isNameSpace: item.isNameSpace,\n }),\n )\n }\n\n const exportNodes: Array<ts.ExportDeclaration> = []\n for (const item of (file as KubbFile.ResolvedFile).exports) {\n const exportPath = item.path\n const hasExtname = !!/\\.[^/.]+$/.exec(exportPath)\n\n exportNodes.push(\n createExport({\n name: item.name as string | Array<ts.Identifier | string> | undefined,\n path: options?.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter((segment): segment is string => segment != null)\n return parts.join('\\n')\n },\n})\n","import type { Parser } from '@kubb/core'\nimport { defineParser } from '@kubb/core'\nimport { parserTs } from './parserTs.ts'\n\n/**\n * Parser that converts `.tsx` and `.jsx` files to strings.\n * Delegates to `typescriptParser` since the TypeScript compiler natively\n * supports JSX/TSX syntax via `ScriptKind.TSX`.\n *\n * Add this parser to the `parsers` option in `defineConfig` when generating `.tsx`/`.jsx` files.\n *\n * @default extname '.tsx'\n */\nexport const parserTsx: Parser = defineParser({\n name: 'tsx',\n extNames: ['.tsx', '.jsx'],\n async parse(file, options = { extname: '.tsx' }) {\n return parserTs.parse(file, options)\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["ts"],"sources":["../src/parserTs.ts","../src/parserTsx.ts"],"sourcesContent":["import { normalize, relative } from 'node:path'\nimport type { ArrowFunctionNode, CodeNode, ConstNode, FileNode, FunctionNode, JSDocNode, SourceNode, TypeNode } from '@kubb/ast/types'\nimport type { Parser } from '@kubb/core'\nimport { defineParser } from '@kubb/core'\nimport ts from 'typescript'\n\nconst { factory } = ts\n\nfunction slash(path: string): string {\n return normalize(path).replaceAll(/\\\\/g, '/').replace('../', '')\n}\n\nfunction getRelativePath(rootDir: string, filePath: string): string {\n const rel = relative(rootDir, filePath)\n const slashed = slash(rel)\n return slashed.startsWith('../') ? slashed : `./${slashed}`\n}\n\nfunction trimExtName(text: string): string {\n return text.replace(/\\.[^/.]+$/, '')\n}\n\n/**\n * Validates TypeScript AST nodes before printing.\n * Throws an error if any node has SyntaxKind.Unknown which would cause the\n * TypeScript printer to crash.\n */\nexport function validateNodes(...nodes: ts.Node[]): void {\n for (const node of nodes) {\n if (!node) {\n throw new Error('Attempted to print undefined or null TypeScript node')\n }\n if (node.kind === ts.SyntaxKind.Unknown) {\n throw new Error(\n 'Invalid TypeScript AST node detected with SyntaxKind.Unknown. ' +\n 'This typically indicates a schema pattern that could not be properly converted to TypeScript. ' +\n `Node: ${JSON.stringify(node, null, 2)}`,\n )\n }\n }\n}\n\n/**\n * Converts TypeScript/TSX AST nodes to a string using the TypeScript printer.\n */\nexport function print(...elements: Array<ts.Node>): string {\n const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n const printer = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n })\n\n const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)\n\n return output.replace(/\\r\\n/g, '\\n')\n}\n\n/**\n * Like `print` but validates nodes first to surface issues early.\n */\nexport function safePrint(...elements: Array<ts.Node>): string {\n validateNodes(...elements)\n return print(...elements)\n}\n\nexport function createImport({\n name,\n path,\n root,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n root?: string\n /** @default false */\n isTypeOnly?: boolean\n /** @default false */\n isNameSpace?: boolean\n}): ts.ImportDeclaration {\n const resolvePath = root ? getRelativePath(root, path) : path\n\n if (!Array.isArray(name)) {\n if (isNameSpace) {\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n const { propertyName, name: alias } = item\n return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))\n }\n return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n })\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n}\n\nexport function createExport({\n path,\n asAlias,\n isTypeOnly = false,\n name,\n}: {\n path: string\n /** @default false */\n asAlias?: boolean\n /** @default false */\n isTypeOnly?: boolean\n name?: string | Array<ts.Identifier | string>\n}): ts.ExportDeclaration {\n if (name && !Array.isArray(name) && !asAlias) {\n console.warn(`When using name as string, asAlias should be true: ${name}`)\n }\n\n if (!Array.isArray(name)) {\n const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n factory.createStringLiteral(path),\n undefined,\n )\n }\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n factory.createNamedExports(\n name.map((propertyName) =>\n factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName),\n ),\n ),\n factory.createStringLiteral(path),\n undefined,\n )\n}\n\n/**\n * Converts a {@link JSDocNode} to a JSDoc comment block string.\n *\n * @example\n * ```ts\n * printJSDoc({ comments: ['@description A pet', '@deprecated'] })\n * // /**\n * // * @description A pet\n * // * @deprecated\n * // *\\/\n * ```\n */\nexport function printJSDoc(jsDoc: JSDocNode): string {\n const comments = (jsDoc.comments ?? []).filter((c) => c != null)\n if (comments.length === 0) return ''\n\n const lines = comments\n .flatMap((c) => c.split(/\\r?\\n/))\n .map((l) => l.replace(/\\*\\//g, '* /').replace(/\\r/g, ''))\n .filter((l) => l.trim().length > 0)\n\n if (lines.length === 0) return ''\n\n return ['/**', ...lines.map((l) => ` * ${l}`), ' */'].join('\\n')\n}\n\n/**\n * Serialises the body / value content from a `nodes` array.\n *\n * Each element is either a raw string or a structured {@link CodeNode}\n * (recursively converted via {@link printCodeNode}).\n * Elements are joined with `\\n`.\n */\nfunction printNodes(nodes: Array<CodeNode | string> | undefined): string {\n if (!nodes || nodes.length === 0) return ''\n return nodes.map((n) => (typeof n === 'string' ? n : printCodeNode(n))).join('\\n')\n}\n\n/**\n * Indents every non-empty line of `text` by `spaces` spaces.\n */\nfunction indentLines(text: string, spaces = 2): string {\n if (!text) return ''\n const pad = ' '.repeat(spaces)\n return text\n .split('\\n')\n .map((line) => (line.trim() ? `${pad}${line}` : ''))\n .join('\\n')\n}\n\n/**\n * Converts a {@link ConstNode} to a TypeScript `const` declaration string.\n *\n * Mirrors the `Const` component from `@kubb/react-fabric`.\n *\n * @example\n * ```ts\n * printConst(createConst({ name: 'pet', export: true, nodes: ['{}'] }))\n * // 'export const pet = {}'\n * ```\n *\n * @example With type and `as const`\n * ```ts\n * printConst(createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true, nodes: ['[]'] }))\n * // 'export const pets: Pet[] = [] as const'\n * ```\n */\nexport function printConst(node: ConstNode): string {\n const { name, export: canExport, type, JSDoc, asConst, nodes } = node\n\n const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''\n const body = printNodes(nodes)\n\n const parts: string[] = []\n if (canExport) parts.push('export ')\n parts.push('const ')\n parts.push(name)\n if (type) {\n parts.push(`: ${type}`)\n }\n parts.push(' = ')\n parts.push(body)\n if (asConst) parts.push(' as const')\n\n const declaration = parts.join('')\n return [jsDocStr, declaration].filter(Boolean).join('\\n')\n}\n\n/**\n * Converts a {@link TypeNode} to a TypeScript `type` alias declaration string.\n *\n * Mirrors the `Type` component from `@kubb/react-fabric`.\n *\n * @example\n * ```ts\n * printType(createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))\n * // 'export type Pet = { id: number }'\n * ```\n */\nexport function printType(node: TypeNode): string {\n const { name, export: canExport, JSDoc, nodes } = node\n\n const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''\n const body = printNodes(nodes)\n\n const parts: string[] = []\n if (canExport) parts.push('export ')\n parts.push('type ')\n parts.push(name)\n parts.push(' = ')\n parts.push(body)\n\n const declaration = parts.join('')\n return [jsDocStr, declaration].filter(Boolean).join('\\n')\n}\n\n/**\n * Converts a {@link FunctionNode} to a TypeScript `function` declaration string.\n *\n * Mirrors the `Function` component from `@kubb/react-fabric`.\n *\n * @example\n * ```ts\n * printFunction(createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))\n * // 'export function getPet(id: string): Pet {\\n return fetch(id)\\n}'\n * ```\n *\n * @example Async with generics\n * ```ts\n * printFunction(createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))\n * // 'export async function fetchPet<T>(id: string): Promise<T> {\\n}'\n * ```\n */\nexport function printFunction(node: FunctionNode): string {\n const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes } = node\n\n const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''\n\n const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(', ') : generics}>` : ''\n\n const returnTypeStr = returnType ? (isAsync ? `: Promise<${returnType}>` : `: ${returnType}`) : ''\n\n const body = printNodes(nodes)\n const indented = body ? indentLines(body) : ''\n\n const parts: string[] = []\n if (canExport) parts.push('export ')\n if (isDefault) parts.push('default ')\n if (isAsync) parts.push('async ')\n parts.push('function ')\n parts.push(name)\n parts.push(genericsStr)\n parts.push(`(${params ?? ''})`)\n parts.push(returnTypeStr)\n parts.push(' {')\n if (indented) {\n parts.push(`\\n${indented}\\n`)\n }\n parts.push('}')\n\n const declaration = parts.join('')\n return [jsDocStr, declaration].filter(Boolean).join('\\n')\n}\n\n/**\n * Converts an {@link ArrowFunctionNode} to a TypeScript arrow function declaration string.\n *\n * Mirrors the `Function.Arrow` component from `@kubb/react-fabric`.\n *\n * @example Multi-line arrow function\n * ```ts\n * printArrowFunction(createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))\n * // 'export const getPet = (id: string) => {\\n return fetch(id)\\n}'\n * ```\n *\n * @example Single-line arrow function\n * ```ts\n * printArrowFunction(createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))\n * // 'const double = (n: number) => n * 2'\n * ```\n */\nexport function printArrowFunction(node: ArrowFunctionNode): string {\n const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes, singleLine } = node\n\n const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''\n\n const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(', ') : generics}>` : ''\n\n const returnTypeStr = returnType ? (isAsync ? `: Promise<${returnType}>` : `: ${returnType}`) : ''\n\n const body = printNodes(nodes)\n\n const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\\n${indentLines(body)}\\n}` : ' => {}'\n\n const parts: string[] = []\n if (canExport) parts.push('export ')\n if (isDefault) parts.push('default ')\n parts.push('const ')\n parts.push(name)\n parts.push(' = ')\n if (isAsync) parts.push('async ')\n parts.push(genericsStr)\n parts.push(`(${params ?? ''})`)\n parts.push(returnTypeStr)\n parts.push(arrowBody)\n\n const declaration = parts.join('')\n return [jsDocStr, declaration].filter(Boolean).join('\\n')\n}\n\n/**\n * Converts a {@link CodeNode} to its TypeScript string representation.\n *\n * Dispatches to the appropriate printer based on the node's `kind`.\n *\n * @example\n * ```ts\n * printCodeNode(createConst({ name: 'x', nodes: ['1'] }))\n * // 'const x = 1'\n * ```\n */\nexport function printCodeNode(node: CodeNode): string {\n switch (node.kind) {\n case 'Const':\n return printConst(node)\n case 'Type':\n return printType(node)\n case 'Function':\n return printFunction(node)\n case 'ArrowFunction':\n return printArrowFunction(node)\n }\n}\n\n/**\n * Converts a {@link SourceNode} to its TypeScript string representation.\n *\n * Uses `value` if present; otherwise converts the structured `nodes` array\n * via {@link printCodeNode}.\n *\n * @example From value\n * ```ts\n * printSource({ kind: 'Source', value: 'const x = 1' })\n * // 'const x = 1'\n * ```\n *\n * @example From nodes\n * ```ts\n * printSource({ kind: 'Source', nodes: [createConst({ name: 'x', nodes: ['1'] })] })\n * // 'const x = 1'\n * ```\n */\nexport function printSource(node: SourceNode): string {\n if (node.value) return node.value\n if (node.nodes && node.nodes.length > 0) {\n return node.nodes.map(printCodeNode).join('\\n')\n }\n return ''\n}\n\n/**\n * Parser that converts `.ts` and `.js` files to strings using the TypeScript\n * compiler. Handles import/export statement generation from file metadata.\n *\n * @default Used automatically when no `parsers` option is set in `defineConfig`.\n */\nexport const parserTs: Parser = defineParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n async parse(file, options = { extname: '.ts' }) {\n const sourceParts: Array<string> = []\n for (const item of file.sources) {\n const sourceStr = printSource(item as SourceNode)\n if (sourceStr) {\n sourceParts.push(sourceStr)\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importNodes: Array<ts.ImportDeclaration> = []\n for (const item of (file as FileNode).imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n const hasExtname = !!/\\.[^/.]+$/.exec(importPath)\n\n importNodes.push(\n createImport({\n name: item.name as string | Array<string | { propertyName: string; name?: string }>,\n path: options?.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,\n isTypeOnly: item.isTypeOnly,\n isNameSpace: item.isNameSpace,\n }),\n )\n }\n\n const exportNodes: Array<ts.ExportDeclaration> = []\n for (const item of (file as FileNode).exports) {\n const exportPath = item.path\n const hasExtname = !!/\\.[^/.]+$/.exec(exportPath)\n\n exportNodes.push(\n createExport({\n name: item.name as string | Array<ts.Identifier | string> | undefined,\n path: options?.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter((segment): segment is string => segment != null)\n return parts.join('\\n')\n },\n})\n","import type { Parser } from '@kubb/core'\nimport { defineParser } from '@kubb/core'\nimport { parserTs } from './parserTs.ts'\n\n/**\n * Parser that converts `.tsx` and `.jsx` files to strings.\n * Delegates to `typescriptParser` since the TypeScript compiler natively\n * supports JSX/TSX syntax via `ScriptKind.TSX`.\n *\n * Add this parser to the `parsers` option in `defineConfig` when generating `.tsx`/`.jsx` files.\n *\n * @default extname '.tsx'\n */\nexport const parserTsx: Parser = defineParser({\n name: 'tsx',\n extNames: ['.tsx', '.jsx'],\n async parse(file, options = { extname: '.tsx' }) {\n return parserTs.parse(file, options)\n },\n})\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -68,6 +68,219 @@ function createExport({ path, asAlias, isTypeOnly = false, name }) {
|
|
|
68
68
|
return factory.createExportDeclaration(void 0, isTypeOnly, factory.createNamedExports(name.map((propertyName) => factory.createExportSpecifier(false, void 0, typeof propertyName === "string" ? factory.createIdentifier(propertyName) : propertyName))), factory.createStringLiteral(path), void 0);
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
|
+
* Converts a {@link JSDocNode} to a JSDoc comment block string.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* printJSDoc({ comments: ['@description A pet', '@deprecated'] })
|
|
76
|
+
* // /**
|
|
77
|
+
* // * @description A pet
|
|
78
|
+
* // * @deprecated
|
|
79
|
+
* // *\/
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
function printJSDoc(jsDoc) {
|
|
83
|
+
const comments = (jsDoc.comments ?? []).filter((c) => c != null);
|
|
84
|
+
if (comments.length === 0) return "";
|
|
85
|
+
const lines = comments.flatMap((c) => c.split(/\r?\n/)).map((l) => l.replace(/\*\//g, "* /").replace(/\r/g, "")).filter((l) => l.trim().length > 0);
|
|
86
|
+
if (lines.length === 0) return "";
|
|
87
|
+
return [
|
|
88
|
+
"/**",
|
|
89
|
+
...lines.map((l) => ` * ${l}`),
|
|
90
|
+
" */"
|
|
91
|
+
].join("\n");
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Serialises the body / value content from a `nodes` array.
|
|
95
|
+
*
|
|
96
|
+
* Each element is either a raw string or a structured {@link CodeNode}
|
|
97
|
+
* (recursively converted via {@link printCodeNode}).
|
|
98
|
+
* Elements are joined with `\n`.
|
|
99
|
+
*/
|
|
100
|
+
function printNodes(nodes) {
|
|
101
|
+
if (!nodes || nodes.length === 0) return "";
|
|
102
|
+
return nodes.map((n) => typeof n === "string" ? n : printCodeNode(n)).join("\n");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Indents every non-empty line of `text` by `spaces` spaces.
|
|
106
|
+
*/
|
|
107
|
+
function indentLines(text, spaces = 2) {
|
|
108
|
+
if (!text) return "";
|
|
109
|
+
const pad = " ".repeat(spaces);
|
|
110
|
+
return text.split("\n").map((line) => line.trim() ? `${pad}${line}` : "").join("\n");
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Converts a {@link ConstNode} to a TypeScript `const` declaration string.
|
|
114
|
+
*
|
|
115
|
+
* Mirrors the `Const` component from `@kubb/react-fabric`.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* printConst(createConst({ name: 'pet', export: true, nodes: ['{}'] }))
|
|
120
|
+
* // 'export const pet = {}'
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* @example With type and `as const`
|
|
124
|
+
* ```ts
|
|
125
|
+
* printConst(createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true, nodes: ['[]'] }))
|
|
126
|
+
* // 'export const pets: Pet[] = [] as const'
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
function printConst(node) {
|
|
130
|
+
const { name, export: canExport, type, JSDoc, asConst, nodes } = node;
|
|
131
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : "";
|
|
132
|
+
const body = printNodes(nodes);
|
|
133
|
+
const parts = [];
|
|
134
|
+
if (canExport) parts.push("export ");
|
|
135
|
+
parts.push("const ");
|
|
136
|
+
parts.push(name);
|
|
137
|
+
if (type) parts.push(`: ${type}`);
|
|
138
|
+
parts.push(" = ");
|
|
139
|
+
parts.push(body);
|
|
140
|
+
if (asConst) parts.push(" as const");
|
|
141
|
+
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Converts a {@link TypeNode} to a TypeScript `type` alias declaration string.
|
|
145
|
+
*
|
|
146
|
+
* Mirrors the `Type` component from `@kubb/react-fabric`.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* printType(createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))
|
|
151
|
+
* // 'export type Pet = { id: number }'
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
function printType(node) {
|
|
155
|
+
const { name, export: canExport, JSDoc, nodes } = node;
|
|
156
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : "";
|
|
157
|
+
const body = printNodes(nodes);
|
|
158
|
+
const parts = [];
|
|
159
|
+
if (canExport) parts.push("export ");
|
|
160
|
+
parts.push("type ");
|
|
161
|
+
parts.push(name);
|
|
162
|
+
parts.push(" = ");
|
|
163
|
+
parts.push(body);
|
|
164
|
+
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Converts a {@link FunctionNode} to a TypeScript `function` declaration string.
|
|
168
|
+
*
|
|
169
|
+
* Mirrors the `Function` component from `@kubb/react-fabric`.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* printFunction(createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))
|
|
174
|
+
* // 'export function getPet(id: string): Pet {\n return fetch(id)\n}'
|
|
175
|
+
* ```
|
|
176
|
+
*
|
|
177
|
+
* @example Async with generics
|
|
178
|
+
* ```ts
|
|
179
|
+
* printFunction(createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))
|
|
180
|
+
* // 'export async function fetchPet<T>(id: string): Promise<T> {\n}'
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
function printFunction(node) {
|
|
184
|
+
const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes } = node;
|
|
185
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : "";
|
|
186
|
+
const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(", ") : generics}>` : "";
|
|
187
|
+
const returnTypeStr = returnType ? isAsync ? `: Promise<${returnType}>` : `: ${returnType}` : "";
|
|
188
|
+
const body = printNodes(nodes);
|
|
189
|
+
const indented = body ? indentLines(body) : "";
|
|
190
|
+
const parts = [];
|
|
191
|
+
if (canExport) parts.push("export ");
|
|
192
|
+
if (isDefault) parts.push("default ");
|
|
193
|
+
if (isAsync) parts.push("async ");
|
|
194
|
+
parts.push("function ");
|
|
195
|
+
parts.push(name);
|
|
196
|
+
parts.push(genericsStr);
|
|
197
|
+
parts.push(`(${params ?? ""})`);
|
|
198
|
+
parts.push(returnTypeStr);
|
|
199
|
+
parts.push(" {");
|
|
200
|
+
if (indented) parts.push(`\n${indented}\n`);
|
|
201
|
+
parts.push("}");
|
|
202
|
+
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Converts an {@link ArrowFunctionNode} to a TypeScript arrow function declaration string.
|
|
206
|
+
*
|
|
207
|
+
* Mirrors the `Function.Arrow` component from `@kubb/react-fabric`.
|
|
208
|
+
*
|
|
209
|
+
* @example Multi-line arrow function
|
|
210
|
+
* ```ts
|
|
211
|
+
* printArrowFunction(createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))
|
|
212
|
+
* // 'export const getPet = (id: string) => {\n return fetch(id)\n}'
|
|
213
|
+
* ```
|
|
214
|
+
*
|
|
215
|
+
* @example Single-line arrow function
|
|
216
|
+
* ```ts
|
|
217
|
+
* printArrowFunction(createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))
|
|
218
|
+
* // 'const double = (n: number) => n * 2'
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
function printArrowFunction(node) {
|
|
222
|
+
const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes, singleLine } = node;
|
|
223
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : "";
|
|
224
|
+
const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(", ") : generics}>` : "";
|
|
225
|
+
const returnTypeStr = returnType ? isAsync ? `: Promise<${returnType}>` : `: ${returnType}` : "";
|
|
226
|
+
const body = printNodes(nodes);
|
|
227
|
+
const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\n${indentLines(body)}\n}` : " => {}";
|
|
228
|
+
const parts = [];
|
|
229
|
+
if (canExport) parts.push("export ");
|
|
230
|
+
if (isDefault) parts.push("default ");
|
|
231
|
+
parts.push("const ");
|
|
232
|
+
parts.push(name);
|
|
233
|
+
parts.push(" = ");
|
|
234
|
+
if (isAsync) parts.push("async ");
|
|
235
|
+
parts.push(genericsStr);
|
|
236
|
+
parts.push(`(${params ?? ""})`);
|
|
237
|
+
parts.push(returnTypeStr);
|
|
238
|
+
parts.push(arrowBody);
|
|
239
|
+
return [jsDocStr, parts.join("")].filter(Boolean).join("\n");
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Converts a {@link CodeNode} to its TypeScript string representation.
|
|
243
|
+
*
|
|
244
|
+
* Dispatches to the appropriate printer based on the node's `kind`.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* printCodeNode(createConst({ name: 'x', nodes: ['1'] }))
|
|
249
|
+
* // 'const x = 1'
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
function printCodeNode(node) {
|
|
253
|
+
switch (node.kind) {
|
|
254
|
+
case "Const": return printConst(node);
|
|
255
|
+
case "Type": return printType(node);
|
|
256
|
+
case "Function": return printFunction(node);
|
|
257
|
+
case "ArrowFunction": return printArrowFunction(node);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Converts a {@link SourceNode} to its TypeScript string representation.
|
|
262
|
+
*
|
|
263
|
+
* Uses `value` if present; otherwise converts the structured `nodes` array
|
|
264
|
+
* via {@link printCodeNode}.
|
|
265
|
+
*
|
|
266
|
+
* @example From value
|
|
267
|
+
* ```ts
|
|
268
|
+
* printSource({ kind: 'Source', value: 'const x = 1' })
|
|
269
|
+
* // 'const x = 1'
|
|
270
|
+
* ```
|
|
271
|
+
*
|
|
272
|
+
* @example From nodes
|
|
273
|
+
* ```ts
|
|
274
|
+
* printSource({ kind: 'Source', nodes: [createConst({ name: 'x', nodes: ['1'] })] })
|
|
275
|
+
* // 'const x = 1'
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
function printSource(node) {
|
|
279
|
+
if (node.value) return node.value;
|
|
280
|
+
if (node.nodes && node.nodes.length > 0) return node.nodes.map(printCodeNode).join("\n");
|
|
281
|
+
return "";
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
71
284
|
* Parser that converts `.ts` and `.js` files to strings using the TypeScript
|
|
72
285
|
* compiler. Handles import/export statement generation from file metadata.
|
|
73
286
|
*
|
|
@@ -78,7 +291,10 @@ const parserTs = defineParser({
|
|
|
78
291
|
extNames: [".ts", ".js"],
|
|
79
292
|
async parse(file, options = { extname: ".ts" }) {
|
|
80
293
|
const sourceParts = [];
|
|
81
|
-
for (const item of file.sources)
|
|
294
|
+
for (const item of file.sources) {
|
|
295
|
+
const sourceStr = printSource(item);
|
|
296
|
+
if (sourceStr) sourceParts.push(sourceStr);
|
|
297
|
+
}
|
|
82
298
|
const source = sourceParts.join("\n\n");
|
|
83
299
|
const importNodes = [];
|
|
84
300
|
for (const item of file.imports) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/parserTs.ts","../src/parserTsx.ts"],"sourcesContent":["import { normalize, relative } from 'node:path'\nimport type { KubbFile, Parser } from '@kubb/core'\nimport { defineParser } from '@kubb/core'\nimport ts from 'typescript'\n\nconst { factory } = ts\n\nfunction slash(path: string): string {\n return normalize(path).replaceAll(/\\\\/g, '/').replace('../', '')\n}\n\nfunction getRelativePath(rootDir: string, filePath: string): string {\n const rel = relative(rootDir, filePath)\n const slashed = slash(rel)\n return slashed.startsWith('../') ? slashed : `./${slashed}`\n}\n\nfunction trimExtName(text: string): string {\n return text.replace(/\\.[^/.]+$/, '')\n}\n\n/**\n * Validates TypeScript AST nodes before printing.\n * Throws an error if any node has SyntaxKind.Unknown which would cause the\n * TypeScript printer to crash.\n */\nexport function validateNodes(...nodes: ts.Node[]): void {\n for (const node of nodes) {\n if (!node) {\n throw new Error('Attempted to print undefined or null TypeScript node')\n }\n if (node.kind === ts.SyntaxKind.Unknown) {\n throw new Error(\n 'Invalid TypeScript AST node detected with SyntaxKind.Unknown. ' +\n 'This typically indicates a schema pattern that could not be properly converted to TypeScript. ' +\n `Node: ${JSON.stringify(node, null, 2)}`,\n )\n }\n }\n}\n\n/**\n * Converts TypeScript/TSX AST nodes to a string using the TypeScript printer.\n */\nexport function print(...elements: Array<ts.Node>): string {\n const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n const printer = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n })\n\n const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)\n\n return output.replace(/\\r\\n/g, '\\n')\n}\n\n/**\n * Like `print` but validates nodes first to surface issues early.\n */\nexport function safePrint(...elements: Array<ts.Node>): string {\n validateNodes(...elements)\n return print(...elements)\n}\n\nexport function createImport({\n name,\n path,\n root,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n root?: string\n /** @default false */\n isTypeOnly?: boolean\n /** @default false */\n isNameSpace?: boolean\n}): ts.ImportDeclaration {\n const resolvePath = root ? getRelativePath(root, path) : path\n\n if (!Array.isArray(name)) {\n if (isNameSpace) {\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n const { propertyName, name: alias } = item\n return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))\n }\n return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n })\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n}\n\nexport function createExport({\n path,\n asAlias,\n isTypeOnly = false,\n name,\n}: {\n path: string\n /** @default false */\n asAlias?: boolean\n /** @default false */\n isTypeOnly?: boolean\n name?: string | Array<ts.Identifier | string>\n}): ts.ExportDeclaration {\n if (name && !Array.isArray(name) && !asAlias) {\n console.warn(`When using name as string, asAlias should be true: ${name}`)\n }\n\n if (!Array.isArray(name)) {\n const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n factory.createStringLiteral(path),\n undefined,\n )\n }\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n factory.createNamedExports(\n name.map((propertyName) =>\n factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName),\n ),\n ),\n factory.createStringLiteral(path),\n undefined,\n )\n}\n\n/**\n * Parser that converts `.ts` and `.js` files to strings using the TypeScript\n * compiler. Handles import/export statement generation from file metadata.\n *\n * @default Used automatically when no `parsers` option is set in `defineConfig`.\n */\nexport const parserTs: Parser = defineParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n async parse(file, options = { extname: '.ts' }) {\n const sourceParts: Array<string> = []\n for (const item of file.sources) {\n if (item.value) {\n sourceParts.push(item.value)\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importNodes: Array<ts.ImportDeclaration> = []\n for (const item of (file as KubbFile.ResolvedFile).imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n const hasExtname = !!/\\.[^/.]+$/.exec(importPath)\n\n importNodes.push(\n createImport({\n name: item.name as string | Array<string | { propertyName: string; name?: string }>,\n path: options?.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,\n isTypeOnly: item.isTypeOnly,\n isNameSpace: item.isNameSpace,\n }),\n )\n }\n\n const exportNodes: Array<ts.ExportDeclaration> = []\n for (const item of (file as KubbFile.ResolvedFile).exports) {\n const exportPath = item.path\n const hasExtname = !!/\\.[^/.]+$/.exec(exportPath)\n\n exportNodes.push(\n createExport({\n name: item.name as string | Array<ts.Identifier | string> | undefined,\n path: options?.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter((segment): segment is string => segment != null)\n return parts.join('\\n')\n },\n})\n","import type { Parser } from '@kubb/core'\nimport { defineParser } from '@kubb/core'\nimport { parserTs } from './parserTs.ts'\n\n/**\n * Parser that converts `.tsx` and `.jsx` files to strings.\n * Delegates to `typescriptParser` since the TypeScript compiler natively\n * supports JSX/TSX syntax via `ScriptKind.TSX`.\n *\n * Add this parser to the `parsers` option in `defineConfig` when generating `.tsx`/`.jsx` files.\n *\n * @default extname '.tsx'\n */\nexport const parserTsx: Parser = defineParser({\n name: 'tsx',\n extNames: ['.tsx', '.jsx'],\n async parse(file, options = { extname: '.tsx' }) {\n return parserTs.parse(file, options)\n },\n})\n"],"mappings":";;;;;AAKA,MAAM,EAAE,YAAY;AAEpB,SAAS,MAAM,MAAsB;AACnC,QAAO,UAAU,KAAK,CAAC,WAAW,OAAO,IAAI,CAAC,QAAQ,OAAO,GAAG;;AAGlE,SAAS,gBAAgB,SAAiB,UAA0B;CAElE,MAAM,UAAU,MADJ,SAAS,SAAS,SAAS,CACb;AAC1B,QAAO,QAAQ,WAAW,MAAM,GAAG,UAAU,KAAK;;AAGpD,SAAS,YAAY,MAAsB;AACzC,QAAO,KAAK,QAAQ,aAAa,GAAG;;;;;;;AAQtC,SAAgB,cAAc,GAAG,OAAwB;AACvD,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,uDAAuD;AAEzE,MAAI,KAAK,SAAS,GAAG,WAAW,QAC9B,OAAM,IAAI,MACR,qKAEW,KAAK,UAAU,MAAM,MAAM,EAAE,GACzC;;;;;;AAQP,SAAgB,MAAM,GAAG,UAAkC;CACzD,MAAM,aAAa,GAAG,iBAAiB,aAAa,IAAI,GAAG,aAAa,QAAQ,MAAM,GAAG,WAAW,IAAI;AAWxG,QATgB,GAAG,cAAc;EAC/B,uBAAuB;EACvB,SAAS,GAAG,YAAY;EACxB,gBAAgB;EAChB,eAAe;EAChB,CAAC,CAEqB,UAAU,GAAG,WAAW,WAAW,QAAQ,gBAAgB,SAAS,OAAO,QAAQ,CAAC,EAAE,WAAW,CAE1G,QAAQ,SAAS,KAAK;;;;;AAMtC,SAAgB,UAAU,GAAG,UAAkC;AAC7D,eAAc,GAAG,SAAS;AAC1B,QAAO,MAAM,GAAG,SAAS;;AAG3B,SAAgB,aAAa,EAC3B,MACA,MACA,MACA,aAAa,OACb,cAAc,SASS;CACvB,MAAM,cAAc,OAAO,gBAAgB,MAAM,KAAK,GAAG;AAEzD,KAAI,CAAC,MAAM,QAAQ,KAAK,EAAE;AACxB,MAAI,YACF,QAAO,QAAQ,wBACb,KAAA,GACA,QAAQ,mBAAmB,YAAY,KAAA,GAAW,QAAQ,sBAAsB,QAAQ,iBAAiB,KAAK,CAAC,CAAC,EAChH,QAAQ,oBAAoB,YAAY,EACxC,KAAA,EACD;AAGH,SAAO,QAAQ,wBACb,KAAA,GACA,QAAQ,mBAAmB,YAAY,QAAQ,iBAAiB,KAAK,EAAE,KAAA,EAAU,EACjF,QAAQ,oBAAoB,YAAY,EACxC,KAAA,EACD;;CAGH,MAAM,aAAa,KAAK,KAAK,SAAS;AACpC,MAAI,OAAO,SAAS,UAAU;GAC5B,MAAM,EAAE,cAAc,MAAM,UAAU;AACtC,UAAO,QAAQ,sBAAsB,OAAO,QAAQ,QAAQ,iBAAiB,aAAa,GAAG,KAAA,GAAW,QAAQ,iBAAiB,SAAS,aAAa,CAAC;;AAE1J,SAAO,QAAQ,sBAAsB,OAAO,KAAA,GAAW,QAAQ,iBAAiB,KAAK,CAAC;GACtF;AAEF,QAAO,QAAQ,wBACb,KAAA,GACA,QAAQ,mBAAmB,YAAY,KAAA,GAAW,QAAQ,mBAAmB,WAAW,CAAC,EACzF,QAAQ,oBAAoB,YAAY,EACxC,KAAA,EACD;;AAGH,SAAgB,aAAa,EAC3B,MACA,SACA,aAAa,OACb,QAQuB;AACvB,KAAI,QAAQ,CAAC,MAAM,QAAQ,KAAK,IAAI,CAAC,QACnC,SAAQ,KAAK,sDAAsD,OAAO;AAG5E,KAAI,CAAC,MAAM,QAAQ,KAAK,EAAE;EACxB,MAAM,aAAa,MAAM,MAAM,MAAM,GAAG,IAAI,MAAM,MAAM,EAAE,KAAK;AAE/D,SAAO,QAAQ,wBACb,KAAA,GACA,YACA,WAAW,aAAa,QAAQ,sBAAsB,QAAQ,iBAAiB,WAAW,CAAC,GAAG,KAAA,GAC9F,QAAQ,oBAAoB,KAAK,EACjC,KAAA,EACD;;AAGH,QAAO,QAAQ,wBACb,KAAA,GACA,YACA,QAAQ,mBACN,KAAK,KAAK,iBACR,QAAQ,sBAAsB,OAAO,KAAA,GAAW,OAAO,iBAAiB,WAAW,QAAQ,iBAAiB,aAAa,GAAG,aAAa,CAC1I,CACF,EACD,QAAQ,oBAAoB,KAAK,EACjC,KAAA,EACD;;;;;;;;AASH,MAAa,WAAmB,aAAa;CAC3C,MAAM;CACN,UAAU,CAAC,OAAO,MAAM;CACxB,MAAM,MAAM,MAAM,UAAU,EAAE,SAAS,OAAO,EAAE;EAC9C,MAAM,cAA6B,EAAE;AACrC,OAAK,MAAM,QAAQ,KAAK,QACtB,KAAI,KAAK,MACP,aAAY,KAAK,KAAK,MAAM;EAGhC,MAAM,SAAS,YAAY,KAAK,OAAO;EAEvC,MAAM,cAA2C,EAAE;AACnD,OAAK,MAAM,QAAS,KAA+B,SAAS;GAC1D,MAAM,aAAa,KAAK,OAAO,gBAAgB,KAAK,MAAM,KAAK,KAAK,GAAG,KAAK;GAC5E,MAAM,aAAa,CAAC,CAAC,YAAY,KAAK,WAAW;AAEjD,eAAY,KACV,aAAa;IACX,MAAM,KAAK;IACX,MAAM,SAAS,WAAW,aAAa,GAAG,YAAY,WAAW,GAAG,QAAQ,YAAY,KAAK,OAAO,YAAY,WAAW,GAAG;IAC9H,YAAY,KAAK;IACjB,aAAa,KAAK;IACnB,CAAC,CACH;;EAGH,MAAM,cAA2C,EAAE;AACnD,OAAK,MAAM,QAAS,KAA+B,SAAS;GAC1D,MAAM,aAAa,KAAK;GACxB,MAAM,aAAa,CAAC,CAAC,YAAY,KAAK,WAAW;AAEjD,eAAY,KACV,aAAa;IACX,MAAM,KAAK;IACX,MAAM,SAAS,WAAW,aAAa,GAAG,YAAY,KAAK,KAAK,GAAG,QAAQ,YAAY,YAAY,KAAK,KAAK;IAC7G,YAAY,KAAK;IACjB,SAAS,KAAK;IACf,CAAC,CACH;;AAIH,SADc;GAAC,KAAK;GAAQ,MAAM,GAAG,aAAa,GAAG,YAAY;GAAE;GAAQ,KAAK;GAAO,CAAC,QAAQ,YAA+B,WAAW,KAAK,CAClI,KAAK,KAAK;;CAE1B,CAAC;;;;;;;;;;;;ACtMF,MAAa,YAAoB,aAAa;CAC5C,MAAM;CACN,UAAU,CAAC,QAAQ,OAAO;CAC1B,MAAM,MAAM,MAAM,UAAU,EAAE,SAAS,QAAQ,EAAE;AAC/C,SAAO,SAAS,MAAM,MAAM,QAAQ;;CAEvC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/parserTs.ts","../src/parserTsx.ts"],"sourcesContent":["import { normalize, relative } from 'node:path'\nimport type { ArrowFunctionNode, CodeNode, ConstNode, FileNode, FunctionNode, JSDocNode, SourceNode, TypeNode } from '@kubb/ast/types'\nimport type { Parser } from '@kubb/core'\nimport { defineParser } from '@kubb/core'\nimport ts from 'typescript'\n\nconst { factory } = ts\n\nfunction slash(path: string): string {\n return normalize(path).replaceAll(/\\\\/g, '/').replace('../', '')\n}\n\nfunction getRelativePath(rootDir: string, filePath: string): string {\n const rel = relative(rootDir, filePath)\n const slashed = slash(rel)\n return slashed.startsWith('../') ? slashed : `./${slashed}`\n}\n\nfunction trimExtName(text: string): string {\n return text.replace(/\\.[^/.]+$/, '')\n}\n\n/**\n * Validates TypeScript AST nodes before printing.\n * Throws an error if any node has SyntaxKind.Unknown which would cause the\n * TypeScript printer to crash.\n */\nexport function validateNodes(...nodes: ts.Node[]): void {\n for (const node of nodes) {\n if (!node) {\n throw new Error('Attempted to print undefined or null TypeScript node')\n }\n if (node.kind === ts.SyntaxKind.Unknown) {\n throw new Error(\n 'Invalid TypeScript AST node detected with SyntaxKind.Unknown. ' +\n 'This typically indicates a schema pattern that could not be properly converted to TypeScript. ' +\n `Node: ${JSON.stringify(node, null, 2)}`,\n )\n }\n }\n}\n\n/**\n * Converts TypeScript/TSX AST nodes to a string using the TypeScript printer.\n */\nexport function print(...elements: Array<ts.Node>): string {\n const sourceFile = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n const printer = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n })\n\n const output = printer.printList(ts.ListFormat.MultiLine, factory.createNodeArray(elements.filter(Boolean)), sourceFile)\n\n return output.replace(/\\r\\n/g, '\\n')\n}\n\n/**\n * Like `print` but validates nodes first to surface issues early.\n */\nexport function safePrint(...elements: Array<ts.Node>): string {\n validateNodes(...elements)\n return print(...elements)\n}\n\nexport function createImport({\n name,\n path,\n root,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n root?: string\n /** @default false */\n isTypeOnly?: boolean\n /** @default false */\n isNameSpace?: boolean\n}): ts.ImportDeclaration {\n const resolvePath = root ? getRelativePath(root, path) : path\n\n if (!Array.isArray(name)) {\n if (isNameSpace) {\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamespaceImport(factory.createIdentifier(name))),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, factory.createIdentifier(name), undefined),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n }\n\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n const { propertyName, name: alias } = item\n return factory.createImportSpecifier(false, alias ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(alias ?? propertyName))\n }\n return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n })\n\n return factory.createImportDeclaration(\n undefined,\n factory.createImportClause(isTypeOnly, undefined, factory.createNamedImports(specifiers)),\n factory.createStringLiteral(resolvePath),\n undefined,\n )\n}\n\nexport function createExport({\n path,\n asAlias,\n isTypeOnly = false,\n name,\n}: {\n path: string\n /** @default false */\n asAlias?: boolean\n /** @default false */\n isTypeOnly?: boolean\n name?: string | Array<ts.Identifier | string>\n}): ts.ExportDeclaration {\n if (name && !Array.isArray(name) && !asAlias) {\n console.warn(`When using name as string, asAlias should be true: ${name}`)\n }\n\n if (!Array.isArray(name)) {\n const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n factory.createStringLiteral(path),\n undefined,\n )\n }\n\n return factory.createExportDeclaration(\n undefined,\n isTypeOnly,\n factory.createNamedExports(\n name.map((propertyName) =>\n factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName),\n ),\n ),\n factory.createStringLiteral(path),\n undefined,\n )\n}\n\n/**\n * Converts a {@link JSDocNode} to a JSDoc comment block string.\n *\n * @example\n * ```ts\n * printJSDoc({ comments: ['@description A pet', '@deprecated'] })\n * // /**\n * // * @description A pet\n * // * @deprecated\n * // *\\/\n * ```\n */\nexport function printJSDoc(jsDoc: JSDocNode): string {\n const comments = (jsDoc.comments ?? []).filter((c) => c != null)\n if (comments.length === 0) return ''\n\n const lines = comments\n .flatMap((c) => c.split(/\\r?\\n/))\n .map((l) => l.replace(/\\*\\//g, '* /').replace(/\\r/g, ''))\n .filter((l) => l.trim().length > 0)\n\n if (lines.length === 0) return ''\n\n return ['/**', ...lines.map((l) => ` * ${l}`), ' */'].join('\\n')\n}\n\n/**\n * Serialises the body / value content from a `nodes` array.\n *\n * Each element is either a raw string or a structured {@link CodeNode}\n * (recursively converted via {@link printCodeNode}).\n * Elements are joined with `\\n`.\n */\nfunction printNodes(nodes: Array<CodeNode | string> | undefined): string {\n if (!nodes || nodes.length === 0) return ''\n return nodes.map((n) => (typeof n === 'string' ? n : printCodeNode(n))).join('\\n')\n}\n\n/**\n * Indents every non-empty line of `text` by `spaces` spaces.\n */\nfunction indentLines(text: string, spaces = 2): string {\n if (!text) return ''\n const pad = ' '.repeat(spaces)\n return text\n .split('\\n')\n .map((line) => (line.trim() ? `${pad}${line}` : ''))\n .join('\\n')\n}\n\n/**\n * Converts a {@link ConstNode} to a TypeScript `const` declaration string.\n *\n * Mirrors the `Const` component from `@kubb/react-fabric`.\n *\n * @example\n * ```ts\n * printConst(createConst({ name: 'pet', export: true, nodes: ['{}'] }))\n * // 'export const pet = {}'\n * ```\n *\n * @example With type and `as const`\n * ```ts\n * printConst(createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true, nodes: ['[]'] }))\n * // 'export const pets: Pet[] = [] as const'\n * ```\n */\nexport function printConst(node: ConstNode): string {\n const { name, export: canExport, type, JSDoc, asConst, nodes } = node\n\n const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''\n const body = printNodes(nodes)\n\n const parts: string[] = []\n if (canExport) parts.push('export ')\n parts.push('const ')\n parts.push(name)\n if (type) {\n parts.push(`: ${type}`)\n }\n parts.push(' = ')\n parts.push(body)\n if (asConst) parts.push(' as const')\n\n const declaration = parts.join('')\n return [jsDocStr, declaration].filter(Boolean).join('\\n')\n}\n\n/**\n * Converts a {@link TypeNode} to a TypeScript `type` alias declaration string.\n *\n * Mirrors the `Type` component from `@kubb/react-fabric`.\n *\n * @example\n * ```ts\n * printType(createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))\n * // 'export type Pet = { id: number }'\n * ```\n */\nexport function printType(node: TypeNode): string {\n const { name, export: canExport, JSDoc, nodes } = node\n\n const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''\n const body = printNodes(nodes)\n\n const parts: string[] = []\n if (canExport) parts.push('export ')\n parts.push('type ')\n parts.push(name)\n parts.push(' = ')\n parts.push(body)\n\n const declaration = parts.join('')\n return [jsDocStr, declaration].filter(Boolean).join('\\n')\n}\n\n/**\n * Converts a {@link FunctionNode} to a TypeScript `function` declaration string.\n *\n * Mirrors the `Function` component from `@kubb/react-fabric`.\n *\n * @example\n * ```ts\n * printFunction(createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))\n * // 'export function getPet(id: string): Pet {\\n return fetch(id)\\n}'\n * ```\n *\n * @example Async with generics\n * ```ts\n * printFunction(createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))\n * // 'export async function fetchPet<T>(id: string): Promise<T> {\\n}'\n * ```\n */\nexport function printFunction(node: FunctionNode): string {\n const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes } = node\n\n const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''\n\n const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(', ') : generics}>` : ''\n\n const returnTypeStr = returnType ? (isAsync ? `: Promise<${returnType}>` : `: ${returnType}`) : ''\n\n const body = printNodes(nodes)\n const indented = body ? indentLines(body) : ''\n\n const parts: string[] = []\n if (canExport) parts.push('export ')\n if (isDefault) parts.push('default ')\n if (isAsync) parts.push('async ')\n parts.push('function ')\n parts.push(name)\n parts.push(genericsStr)\n parts.push(`(${params ?? ''})`)\n parts.push(returnTypeStr)\n parts.push(' {')\n if (indented) {\n parts.push(`\\n${indented}\\n`)\n }\n parts.push('}')\n\n const declaration = parts.join('')\n return [jsDocStr, declaration].filter(Boolean).join('\\n')\n}\n\n/**\n * Converts an {@link ArrowFunctionNode} to a TypeScript arrow function declaration string.\n *\n * Mirrors the `Function.Arrow` component from `@kubb/react-fabric`.\n *\n * @example Multi-line arrow function\n * ```ts\n * printArrowFunction(createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))\n * // 'export const getPet = (id: string) => {\\n return fetch(id)\\n}'\n * ```\n *\n * @example Single-line arrow function\n * ```ts\n * printArrowFunction(createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))\n * // 'const double = (n: number) => n * 2'\n * ```\n */\nexport function printArrowFunction(node: ArrowFunctionNode): string {\n const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes, singleLine } = node\n\n const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''\n\n const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(', ') : generics}>` : ''\n\n const returnTypeStr = returnType ? (isAsync ? `: Promise<${returnType}>` : `: ${returnType}`) : ''\n\n const body = printNodes(nodes)\n\n const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\\n${indentLines(body)}\\n}` : ' => {}'\n\n const parts: string[] = []\n if (canExport) parts.push('export ')\n if (isDefault) parts.push('default ')\n parts.push('const ')\n parts.push(name)\n parts.push(' = ')\n if (isAsync) parts.push('async ')\n parts.push(genericsStr)\n parts.push(`(${params ?? ''})`)\n parts.push(returnTypeStr)\n parts.push(arrowBody)\n\n const declaration = parts.join('')\n return [jsDocStr, declaration].filter(Boolean).join('\\n')\n}\n\n/**\n * Converts a {@link CodeNode} to its TypeScript string representation.\n *\n * Dispatches to the appropriate printer based on the node's `kind`.\n *\n * @example\n * ```ts\n * printCodeNode(createConst({ name: 'x', nodes: ['1'] }))\n * // 'const x = 1'\n * ```\n */\nexport function printCodeNode(node: CodeNode): string {\n switch (node.kind) {\n case 'Const':\n return printConst(node)\n case 'Type':\n return printType(node)\n case 'Function':\n return printFunction(node)\n case 'ArrowFunction':\n return printArrowFunction(node)\n }\n}\n\n/**\n * Converts a {@link SourceNode} to its TypeScript string representation.\n *\n * Uses `value` if present; otherwise converts the structured `nodes` array\n * via {@link printCodeNode}.\n *\n * @example From value\n * ```ts\n * printSource({ kind: 'Source', value: 'const x = 1' })\n * // 'const x = 1'\n * ```\n *\n * @example From nodes\n * ```ts\n * printSource({ kind: 'Source', nodes: [createConst({ name: 'x', nodes: ['1'] })] })\n * // 'const x = 1'\n * ```\n */\nexport function printSource(node: SourceNode): string {\n if (node.value) return node.value\n if (node.nodes && node.nodes.length > 0) {\n return node.nodes.map(printCodeNode).join('\\n')\n }\n return ''\n}\n\n/**\n * Parser that converts `.ts` and `.js` files to strings using the TypeScript\n * compiler. Handles import/export statement generation from file metadata.\n *\n * @default Used automatically when no `parsers` option is set in `defineConfig`.\n */\nexport const parserTs: Parser = defineParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n async parse(file, options = { extname: '.ts' }) {\n const sourceParts: Array<string> = []\n for (const item of file.sources) {\n const sourceStr = printSource(item as SourceNode)\n if (sourceStr) {\n sourceParts.push(sourceStr)\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importNodes: Array<ts.ImportDeclaration> = []\n for (const item of (file as FileNode).imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n const hasExtname = !!/\\.[^/.]+$/.exec(importPath)\n\n importNodes.push(\n createImport({\n name: item.name as string | Array<string | { propertyName: string; name?: string }>,\n path: options?.extname && hasExtname ? `${trimExtName(importPath)}${options.extname}` : item.root ? trimExtName(importPath) : importPath,\n isTypeOnly: item.isTypeOnly,\n isNameSpace: item.isNameSpace,\n }),\n )\n }\n\n const exportNodes: Array<ts.ExportDeclaration> = []\n for (const item of (file as FileNode).exports) {\n const exportPath = item.path\n const hasExtname = !!/\\.[^/.]+$/.exec(exportPath)\n\n exportNodes.push(\n createExport({\n name: item.name as string | Array<ts.Identifier | string> | undefined,\n path: options?.extname && hasExtname ? `${trimExtName(item.path)}${options.extname}` : trimExtName(item.path),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const parts = [file.banner, print(...importNodes, ...exportNodes), source, file.footer].filter((segment): segment is string => segment != null)\n return parts.join('\\n')\n },\n})\n","import type { Parser } from '@kubb/core'\nimport { defineParser } from '@kubb/core'\nimport { parserTs } from './parserTs.ts'\n\n/**\n * Parser that converts `.tsx` and `.jsx` files to strings.\n * Delegates to `typescriptParser` since the TypeScript compiler natively\n * supports JSX/TSX syntax via `ScriptKind.TSX`.\n *\n * Add this parser to the `parsers` option in `defineConfig` when generating `.tsx`/`.jsx` files.\n *\n * @default extname '.tsx'\n */\nexport const parserTsx: Parser = defineParser({\n name: 'tsx',\n extNames: ['.tsx', '.jsx'],\n async parse(file, options = { extname: '.tsx' }) {\n return parserTs.parse(file, options)\n },\n})\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/parser-ts",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.32",
|
|
4
4
|
"description": "TypeScript and TSX file parser for Kubb, converting generated files to strings using the TypeScript compiler.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -36,10 +36,11 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"typescript": "^6.0.2",
|
|
39
|
-
"@kubb/core": "5.0.0-alpha.
|
|
39
|
+
"@kubb/core": "5.0.0-alpha.32"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@internals/utils": "0.0.0"
|
|
42
|
+
"@internals/utils": "0.0.0",
|
|
43
|
+
"@kubb/ast": "5.0.0-alpha.32"
|
|
43
44
|
},
|
|
44
45
|
"engines": {
|
|
45
46
|
"node": ">=22"
|
package/src/parserTs.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { normalize, relative } from 'node:path'
|
|
2
|
-
import type {
|
|
2
|
+
import type { ArrowFunctionNode, CodeNode, ConstNode, FileNode, FunctionNode, JSDocNode, SourceNode, TypeNode } from '@kubb/ast/types'
|
|
3
|
+
import type { Parser } from '@kubb/core'
|
|
3
4
|
import { defineParser } from '@kubb/core'
|
|
4
5
|
import ts from 'typescript'
|
|
5
6
|
|
|
@@ -158,6 +159,266 @@ export function createExport({
|
|
|
158
159
|
)
|
|
159
160
|
}
|
|
160
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Converts a {@link JSDocNode} to a JSDoc comment block string.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* printJSDoc({ comments: ['@description A pet', '@deprecated'] })
|
|
168
|
+
* // /**
|
|
169
|
+
* // * @description A pet
|
|
170
|
+
* // * @deprecated
|
|
171
|
+
* // *\/
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
export function printJSDoc(jsDoc: JSDocNode): string {
|
|
175
|
+
const comments = (jsDoc.comments ?? []).filter((c) => c != null)
|
|
176
|
+
if (comments.length === 0) return ''
|
|
177
|
+
|
|
178
|
+
const lines = comments
|
|
179
|
+
.flatMap((c) => c.split(/\r?\n/))
|
|
180
|
+
.map((l) => l.replace(/\*\//g, '* /').replace(/\r/g, ''))
|
|
181
|
+
.filter((l) => l.trim().length > 0)
|
|
182
|
+
|
|
183
|
+
if (lines.length === 0) return ''
|
|
184
|
+
|
|
185
|
+
return ['/**', ...lines.map((l) => ` * ${l}`), ' */'].join('\n')
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Serialises the body / value content from a `nodes` array.
|
|
190
|
+
*
|
|
191
|
+
* Each element is either a raw string or a structured {@link CodeNode}
|
|
192
|
+
* (recursively converted via {@link printCodeNode}).
|
|
193
|
+
* Elements are joined with `\n`.
|
|
194
|
+
*/
|
|
195
|
+
function printNodes(nodes: Array<CodeNode | string> | undefined): string {
|
|
196
|
+
if (!nodes || nodes.length === 0) return ''
|
|
197
|
+
return nodes.map((n) => (typeof n === 'string' ? n : printCodeNode(n))).join('\n')
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Indents every non-empty line of `text` by `spaces` spaces.
|
|
202
|
+
*/
|
|
203
|
+
function indentLines(text: string, spaces = 2): string {
|
|
204
|
+
if (!text) return ''
|
|
205
|
+
const pad = ' '.repeat(spaces)
|
|
206
|
+
return text
|
|
207
|
+
.split('\n')
|
|
208
|
+
.map((line) => (line.trim() ? `${pad}${line}` : ''))
|
|
209
|
+
.join('\n')
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Converts a {@link ConstNode} to a TypeScript `const` declaration string.
|
|
214
|
+
*
|
|
215
|
+
* Mirrors the `Const` component from `@kubb/react-fabric`.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* ```ts
|
|
219
|
+
* printConst(createConst({ name: 'pet', export: true, nodes: ['{}'] }))
|
|
220
|
+
* // 'export const pet = {}'
|
|
221
|
+
* ```
|
|
222
|
+
*
|
|
223
|
+
* @example With type and `as const`
|
|
224
|
+
* ```ts
|
|
225
|
+
* printConst(createConst({ name: 'pets', export: true, type: 'Pet[]', asConst: true, nodes: ['[]'] }))
|
|
226
|
+
* // 'export const pets: Pet[] = [] as const'
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
export function printConst(node: ConstNode): string {
|
|
230
|
+
const { name, export: canExport, type, JSDoc, asConst, nodes } = node
|
|
231
|
+
|
|
232
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
|
|
233
|
+
const body = printNodes(nodes)
|
|
234
|
+
|
|
235
|
+
const parts: string[] = []
|
|
236
|
+
if (canExport) parts.push('export ')
|
|
237
|
+
parts.push('const ')
|
|
238
|
+
parts.push(name)
|
|
239
|
+
if (type) {
|
|
240
|
+
parts.push(`: ${type}`)
|
|
241
|
+
}
|
|
242
|
+
parts.push(' = ')
|
|
243
|
+
parts.push(body)
|
|
244
|
+
if (asConst) parts.push(' as const')
|
|
245
|
+
|
|
246
|
+
const declaration = parts.join('')
|
|
247
|
+
return [jsDocStr, declaration].filter(Boolean).join('\n')
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Converts a {@link TypeNode} to a TypeScript `type` alias declaration string.
|
|
252
|
+
*
|
|
253
|
+
* Mirrors the `Type` component from `@kubb/react-fabric`.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* printType(createType({ name: 'Pet', export: true, nodes: ['{ id: number }'] }))
|
|
258
|
+
* // 'export type Pet = { id: number }'
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
export function printType(node: TypeNode): string {
|
|
262
|
+
const { name, export: canExport, JSDoc, nodes } = node
|
|
263
|
+
|
|
264
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
|
|
265
|
+
const body = printNodes(nodes)
|
|
266
|
+
|
|
267
|
+
const parts: string[] = []
|
|
268
|
+
if (canExport) parts.push('export ')
|
|
269
|
+
parts.push('type ')
|
|
270
|
+
parts.push(name)
|
|
271
|
+
parts.push(' = ')
|
|
272
|
+
parts.push(body)
|
|
273
|
+
|
|
274
|
+
const declaration = parts.join('')
|
|
275
|
+
return [jsDocStr, declaration].filter(Boolean).join('\n')
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Converts a {@link FunctionNode} to a TypeScript `function` declaration string.
|
|
280
|
+
*
|
|
281
|
+
* Mirrors the `Function` component from `@kubb/react-fabric`.
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```ts
|
|
285
|
+
* printFunction(createFunction({ name: 'getPet', export: true, params: 'id: string', returnType: 'Pet', nodes: ['return fetch(id)'] }))
|
|
286
|
+
* // 'export function getPet(id: string): Pet {\n return fetch(id)\n}'
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* @example Async with generics
|
|
290
|
+
* ```ts
|
|
291
|
+
* printFunction(createFunction({ name: 'fetchPet', export: true, async: true, generics: ['T'], params: 'id: string', returnType: 'T' }))
|
|
292
|
+
* // 'export async function fetchPet<T>(id: string): Promise<T> {\n}'
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
export function printFunction(node: FunctionNode): string {
|
|
296
|
+
const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes } = node
|
|
297
|
+
|
|
298
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
|
|
299
|
+
|
|
300
|
+
const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(', ') : generics}>` : ''
|
|
301
|
+
|
|
302
|
+
const returnTypeStr = returnType ? (isAsync ? `: Promise<${returnType}>` : `: ${returnType}`) : ''
|
|
303
|
+
|
|
304
|
+
const body = printNodes(nodes)
|
|
305
|
+
const indented = body ? indentLines(body) : ''
|
|
306
|
+
|
|
307
|
+
const parts: string[] = []
|
|
308
|
+
if (canExport) parts.push('export ')
|
|
309
|
+
if (isDefault) parts.push('default ')
|
|
310
|
+
if (isAsync) parts.push('async ')
|
|
311
|
+
parts.push('function ')
|
|
312
|
+
parts.push(name)
|
|
313
|
+
parts.push(genericsStr)
|
|
314
|
+
parts.push(`(${params ?? ''})`)
|
|
315
|
+
parts.push(returnTypeStr)
|
|
316
|
+
parts.push(' {')
|
|
317
|
+
if (indented) {
|
|
318
|
+
parts.push(`\n${indented}\n`)
|
|
319
|
+
}
|
|
320
|
+
parts.push('}')
|
|
321
|
+
|
|
322
|
+
const declaration = parts.join('')
|
|
323
|
+
return [jsDocStr, declaration].filter(Boolean).join('\n')
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Converts an {@link ArrowFunctionNode} to a TypeScript arrow function declaration string.
|
|
328
|
+
*
|
|
329
|
+
* Mirrors the `Function.Arrow` component from `@kubb/react-fabric`.
|
|
330
|
+
*
|
|
331
|
+
* @example Multi-line arrow function
|
|
332
|
+
* ```ts
|
|
333
|
+
* printArrowFunction(createArrowFunction({ name: 'getPet', export: true, params: 'id: string', nodes: ['return fetch(id)'] }))
|
|
334
|
+
* // 'export const getPet = (id: string) => {\n return fetch(id)\n}'
|
|
335
|
+
* ```
|
|
336
|
+
*
|
|
337
|
+
* @example Single-line arrow function
|
|
338
|
+
* ```ts
|
|
339
|
+
* printArrowFunction(createArrowFunction({ name: 'double', params: 'n: number', singleLine: true, nodes: ['n * 2'] }))
|
|
340
|
+
* // 'const double = (n: number) => n * 2'
|
|
341
|
+
* ```
|
|
342
|
+
*/
|
|
343
|
+
export function printArrowFunction(node: ArrowFunctionNode): string {
|
|
344
|
+
const { name, default: isDefault, export: canExport, async: isAsync, generics, params, returnType, JSDoc, nodes, singleLine } = node
|
|
345
|
+
|
|
346
|
+
const jsDocStr = JSDoc ? printJSDoc(JSDoc) : ''
|
|
347
|
+
|
|
348
|
+
const genericsStr = generics ? `<${Array.isArray(generics) ? generics.join(', ') : generics}>` : ''
|
|
349
|
+
|
|
350
|
+
const returnTypeStr = returnType ? (isAsync ? `: Promise<${returnType}>` : `: ${returnType}`) : ''
|
|
351
|
+
|
|
352
|
+
const body = printNodes(nodes)
|
|
353
|
+
|
|
354
|
+
const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\n${indentLines(body)}\n}` : ' => {}'
|
|
355
|
+
|
|
356
|
+
const parts: string[] = []
|
|
357
|
+
if (canExport) parts.push('export ')
|
|
358
|
+
if (isDefault) parts.push('default ')
|
|
359
|
+
parts.push('const ')
|
|
360
|
+
parts.push(name)
|
|
361
|
+
parts.push(' = ')
|
|
362
|
+
if (isAsync) parts.push('async ')
|
|
363
|
+
parts.push(genericsStr)
|
|
364
|
+
parts.push(`(${params ?? ''})`)
|
|
365
|
+
parts.push(returnTypeStr)
|
|
366
|
+
parts.push(arrowBody)
|
|
367
|
+
|
|
368
|
+
const declaration = parts.join('')
|
|
369
|
+
return [jsDocStr, declaration].filter(Boolean).join('\n')
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Converts a {@link CodeNode} to its TypeScript string representation.
|
|
374
|
+
*
|
|
375
|
+
* Dispatches to the appropriate printer based on the node's `kind`.
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* ```ts
|
|
379
|
+
* printCodeNode(createConst({ name: 'x', nodes: ['1'] }))
|
|
380
|
+
* // 'const x = 1'
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
export function printCodeNode(node: CodeNode): string {
|
|
384
|
+
switch (node.kind) {
|
|
385
|
+
case 'Const':
|
|
386
|
+
return printConst(node)
|
|
387
|
+
case 'Type':
|
|
388
|
+
return printType(node)
|
|
389
|
+
case 'Function':
|
|
390
|
+
return printFunction(node)
|
|
391
|
+
case 'ArrowFunction':
|
|
392
|
+
return printArrowFunction(node)
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Converts a {@link SourceNode} to its TypeScript string representation.
|
|
398
|
+
*
|
|
399
|
+
* Uses `value` if present; otherwise converts the structured `nodes` array
|
|
400
|
+
* via {@link printCodeNode}.
|
|
401
|
+
*
|
|
402
|
+
* @example From value
|
|
403
|
+
* ```ts
|
|
404
|
+
* printSource({ kind: 'Source', value: 'const x = 1' })
|
|
405
|
+
* // 'const x = 1'
|
|
406
|
+
* ```
|
|
407
|
+
*
|
|
408
|
+
* @example From nodes
|
|
409
|
+
* ```ts
|
|
410
|
+
* printSource({ kind: 'Source', nodes: [createConst({ name: 'x', nodes: ['1'] })] })
|
|
411
|
+
* // 'const x = 1'
|
|
412
|
+
* ```
|
|
413
|
+
*/
|
|
414
|
+
export function printSource(node: SourceNode): string {
|
|
415
|
+
if (node.value) return node.value
|
|
416
|
+
if (node.nodes && node.nodes.length > 0) {
|
|
417
|
+
return node.nodes.map(printCodeNode).join('\n')
|
|
418
|
+
}
|
|
419
|
+
return ''
|
|
420
|
+
}
|
|
421
|
+
|
|
161
422
|
/**
|
|
162
423
|
* Parser that converts `.ts` and `.js` files to strings using the TypeScript
|
|
163
424
|
* compiler. Handles import/export statement generation from file metadata.
|
|
@@ -170,14 +431,15 @@ export const parserTs: Parser = defineParser({
|
|
|
170
431
|
async parse(file, options = { extname: '.ts' }) {
|
|
171
432
|
const sourceParts: Array<string> = []
|
|
172
433
|
for (const item of file.sources) {
|
|
173
|
-
|
|
174
|
-
|
|
434
|
+
const sourceStr = printSource(item as SourceNode)
|
|
435
|
+
if (sourceStr) {
|
|
436
|
+
sourceParts.push(sourceStr)
|
|
175
437
|
}
|
|
176
438
|
}
|
|
177
439
|
const source = sourceParts.join('\n\n')
|
|
178
440
|
|
|
179
441
|
const importNodes: Array<ts.ImportDeclaration> = []
|
|
180
|
-
for (const item of (file as
|
|
442
|
+
for (const item of (file as FileNode).imports) {
|
|
181
443
|
const importPath = item.root ? getRelativePath(item.root, item.path) : item.path
|
|
182
444
|
const hasExtname = !!/\.[^/.]+$/.exec(importPath)
|
|
183
445
|
|
|
@@ -192,7 +454,7 @@ export const parserTs: Parser = defineParser({
|
|
|
192
454
|
}
|
|
193
455
|
|
|
194
456
|
const exportNodes: Array<ts.ExportDeclaration> = []
|
|
195
|
-
for (const item of (file as
|
|
457
|
+
for (const item of (file as FileNode).exports) {
|
|
196
458
|
const exportPath = item.path
|
|
197
459
|
const hasExtname = !!/\.[^/.]+$/.exec(exportPath)
|
|
198
460
|
|