@kubb/parser-ts 5.0.0-beta.89 → 5.0.0-beta.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,20 +42,30 @@ npm install @kubb/parser-ts
42
42
  import { defineConfig } from 'kubb'
43
43
  import { parserTs, parserTsx } from '@kubb/parser-ts'
44
44
 
45
+ export default defineConfig({
46
+ input: './petstore.yaml',
47
+ output: { path: './src/gen' },
48
+ parsers: [parserTs(), parserTsx()],
49
+ })
50
+ ```
51
+
52
+ Pass an `extension` map to rewrite the extensions emitted in `import`/`export` statements. Keys are the source extension, values the output, and an empty string drops it. Use `{ '.ts': '.js' }` for ESM when the consumer transpiles to JavaScript:
53
+
54
+ ```typescript
45
55
  export default defineConfig({
46
56
  input: { path: './petstore.yaml' },
47
57
  output: { path: './src/gen' },
48
- parsers: [parserTs, parserTsx],
58
+ parsers: [parserTs({ extension: { '.ts': '.js' } }), parserTsx()],
49
59
  })
50
60
  ```
51
61
 
52
- To render compiler AST nodes to source text from inside a plugin, call `print` on the parser instance:
62
+ To render compiler AST nodes to source text from inside a plugin, call `print` on a parser instance:
53
63
 
54
64
  ```typescript
55
65
  import { parserTs } from '@kubb/parser-ts'
56
66
  import ts from 'typescript'
57
67
 
58
- const source = parserTs.print(
68
+ const source = parserTs().print(
59
69
  ts.factory.createVariableStatement(
60
70
  [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
61
71
  ts.factory.createVariableDeclarationList(
@@ -69,16 +79,15 @@ const source = parserTs.print(
69
79
 
70
80
  ## API
71
81
 
72
- ### `parserTs`
82
+ ### `parserTs(options?)`
73
83
 
74
- Parser instance for `.ts` and `.js` files. Pass to `defineConfig({ parsers: [...] })` to emit TypeScript source files.
84
+ Factory returning a parser instance for `.ts` and `.js` files. Pass to `defineConfig({ parsers: [...] })` to emit TypeScript source files. The optional `extension` map rewrites the extensions written in `import`/`export` statements and defaults to `{ '.ts': '.ts' }`.
75
85
 
76
- - `parserTs.parse(file, options?)` serialize a `FileNode` to TypeScript source.
77
- - `parserTs.print(...nodes)` — convert TypeScript compiler `Node` instances to a formatted source string.
86
+ The returned instance exposes `parse(file)` to serialize a `FileNode` to TypeScript source and `print(...nodes)` to convert TypeScript compiler `Node` instances to a formatted source string.
78
87
 
79
- ### `parserTsx`
88
+ ### `parserTsx(options?)`
80
89
 
81
- Parser instance for `.tsx` and `.jsx` files. Same API as `parserTs` with JSX support.
90
+ Factory returning a parser instance for `.tsx` and `.jsx` files. Same API and `extension` option as `parserTs`, with JSX support.
82
91
 
83
92
  ## Supporting Kubb
84
93
 
package/dist/index.cjs CHANGED
@@ -76,17 +76,11 @@ const LEADING_DIGIT_PATTERN = /^\d/;
76
76
  //#region src/utils.ts
77
77
  const { factory } = typescript.default;
78
78
  /**
79
- * Normalizes a file-system path to POSIX separators and strips any leading `../` segment.
80
- */
81
- function slash(path) {
82
- return (0, node_path.normalize)(path).replaceAll(WINDOWS_PATH_SEPARATOR, "/").replace("../", "");
83
- }
84
- /**
85
79
  * Resolves `filePath` relative to `rootDir` and returns a POSIX-style path
86
80
  * prefixed with `./` when the target sits inside the root, or `../` when it escapes it.
87
81
  */
88
82
  function getRelativePath(rootDir, filePath) {
89
- const slashed = slash((0, node_path.relative)(rootDir, filePath));
83
+ const slashed = (0, node_path.normalize)((0, node_path.relative)(rootDir, filePath)).replaceAll(WINDOWS_PATH_SEPARATOR, "/").replace("../", "");
90
84
  return slashed.startsWith("../") ? slashed : `./${slashed}`;
91
85
  }
92
86
  /**
@@ -443,11 +437,12 @@ function printExport({ path, name, isTypeOnly = false, asAlias = false }) {
443
437
  }
444
438
  //#endregion
445
439
  //#region src/parserTs.ts
440
+ const DEFAULT_EXTENSION = { ".ts": ".ts" };
446
441
  /**
447
442
  * Default Kubb parser for `.ts` and `.js` files. Takes the universal AST
448
443
  * produced by an adapter and prints it as TypeScript source using the official
449
444
  * TypeScript compiler. Imports and exports are rewritten based on each file's
450
- * metadata.
445
+ * metadata and the `extension` option.
451
446
  *
452
447
  * Used automatically when no `parsers` option is set on `defineConfig`. Use
453
448
  * `parserTsx` instead for React projects that emit JSX.
@@ -459,58 +454,62 @@ function printExport({ path, name, isTypeOnly = false, asAlias = false }) {
459
454
  * import { parserTs } from '@kubb/parser-ts'
460
455
  *
461
456
  * export default defineConfig({
462
- * input: { path: './petStore.yaml' },
457
+ * input: './petStore.yaml',
463
458
  * output: { path: './src/gen' },
464
459
  * adapter: adapterOas(),
465
- * parsers: [parserTs],
460
+ * parsers: [parserTs()],
466
461
  * plugins: [],
467
462
  * })
468
463
  * ```
469
464
  */
470
- const parserTs = (0, _kubb_core.defineParser)({
471
- name: "typescript",
472
- extNames: [".ts", ".js"],
473
- print(...nodes) {
474
- return print(...nodes);
475
- },
476
- parse(file, options = { extname: ".ts" }) {
477
- const sourceParts = [];
478
- for (const item of file.sources) {
479
- const sourceStr = printSource(item);
480
- if (sourceStr) sourceParts.push(sourceStr.trimEnd());
481
- }
482
- const source = sourceParts.join("\n\n");
483
- const importLines = [];
484
- for (const item of file.imports) {
485
- const importPath = item.root ? getRelativePath(item.root, item.path) : item.path;
486
- importLines.push(printImport({
465
+ const parserTs = (0, _kubb_core.defineParser)(({ extension = DEFAULT_EXTENSION } = {}) => {
466
+ return {
467
+ name: "typescript",
468
+ extNames: [".ts", ".js"],
469
+ print(...nodes) {
470
+ return print(...nodes);
471
+ },
472
+ parse(file) {
473
+ const extname = extension[file.extname] || void 0;
474
+ const sourceParts = [];
475
+ for (const item of file.sources) {
476
+ const sourceStr = printSource(item);
477
+ if (sourceStr) sourceParts.push(sourceStr.trimEnd());
478
+ }
479
+ const source = sourceParts.join("\n\n");
480
+ const importLines = [];
481
+ for (const item of file.imports) {
482
+ const importPath = item.root ? getRelativePath(item.root, item.path) : item.path;
483
+ importLines.push(printImport({
484
+ name: item.name,
485
+ path: resolveOutputPath(importPath, { extname }, Boolean(item.root)),
486
+ isTypeOnly: item.isTypeOnly,
487
+ isNameSpace: item.isNameSpace
488
+ }));
489
+ }
490
+ const exportLines = [];
491
+ for (const item of file.exports) exportLines.push(printExport({
487
492
  name: item.name,
488
- path: resolveOutputPath(importPath, options, Boolean(item.root)),
493
+ path: resolveOutputPath(item.path, { extname }, true),
489
494
  isTypeOnly: item.isTypeOnly,
490
- isNameSpace: item.isNameSpace
495
+ asAlias: item.asAlias
491
496
  }));
497
+ const importExportBlock = [...importLines, ...exportLines].join("\n");
498
+ return [
499
+ file.banner,
500
+ importExportBlock,
501
+ source,
502
+ file.footer
503
+ ].filter((segment) => Boolean(segment)).map((s) => s.trimEnd()).join("\n\n");
492
504
  }
493
- const exportLines = [];
494
- for (const item of file.exports) exportLines.push(printExport({
495
- name: item.name,
496
- path: resolveOutputPath(item.path, options, true),
497
- isTypeOnly: item.isTypeOnly,
498
- asAlias: item.asAlias
499
- }));
500
- const importExportBlock = [...importLines, ...exportLines].join("\n");
501
- return [
502
- file.banner,
503
- importExportBlock,
504
- source,
505
- file.footer
506
- ].filter((segment) => Boolean(segment)).map((s) => s.trimEnd()).join("\n\n");
507
- }
505
+ };
508
506
  });
509
507
  //#endregion
510
508
  //#region src/parserTsx.ts
511
509
  /**
512
510
  * Kubb parser for `.tsx` and `.jsx` files. Delegates to `parserTs` because the
513
- * TypeScript compiler handles JSX natively via `ScriptKind.TSX`.
511
+ * TypeScript compiler handles JSX natively via `ScriptKind.TSX`, so it shares the
512
+ * same `extension` option.
514
513
  *
515
514
  * Add to the `parsers` array on `defineConfig` when generating components for
516
515
  * React (or any framework that emits JSX).
@@ -522,23 +521,26 @@ const parserTs = (0, _kubb_core.defineParser)({
522
521
  * import { parserTsx } from '@kubb/parser-ts'
523
522
  *
524
523
  * export default defineConfig({
525
- * input: { path: './petStore.yaml' },
524
+ * input: './petStore.yaml',
526
525
  * output: { path: './src/gen' },
527
526
  * adapter: adapterOas(),
528
- * parsers: [parserTsx],
527
+ * parsers: [parserTsx()],
529
528
  * plugins: [],
530
529
  * })
531
530
  * ```
532
531
  */
533
- const parserTsx = (0, _kubb_core.defineParser)({
534
- name: "tsx",
535
- extNames: [".tsx", ".jsx"],
536
- print(...nodes) {
537
- return print(...nodes);
538
- },
539
- parse(file, options = { extname: ".tsx" }) {
540
- return parserTs.parse(file, options);
541
- }
532
+ const parserTsx = (0, _kubb_core.defineParser)((options = {}) => {
533
+ const parser = parserTs(options);
534
+ return {
535
+ name: "tsx",
536
+ extNames: [".tsx", ".jsx"],
537
+ print(...nodes) {
538
+ return print(...nodes);
539
+ },
540
+ parse(file) {
541
+ return parser.parse(file);
542
+ }
543
+ };
542
544
  });
543
545
  //#endregion
544
546
  exports.parserTs = parserTs;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ts"],"sources":["../../../internals/utils/src/fs.ts","../src/constants.ts","../src/utils.ts","../src/parserTs.ts","../src/parserTsx.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, join, posix, resolve } from 'node:path'\nimport { camelCase } from './casing.ts'\nimport { runtime } from './runtime.ts'\n\n/**\n * Walks up the directory tree from `cwd` (defaults to `process.cwd()`) and\n * returns the absolute path of the nearest `package.json`, or `null` when none\n * is found before reaching the filesystem root.\n *\n * @example\n * ```ts\n * const pkgPath = findPackageJSON('/home/user/project/src') // '/home/user/project/package.json'\n * ```\n */\nexport function findPackageJSON(cwd?: string): string | null {\n let dir = cwd ? resolve(cwd) : process.cwd()\n while (true) {\n const pkgPath = join(dir, 'package.json')\n if (existsSync(pkgPath)) return pkgPath\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\n/**\n * Converts all backslashes to forward slashes.\n * Extended-length Windows paths (`\\\\?\\...`) are left unchanged.\n */\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Resolves to `true` when the file or directory at `path` exists.\n * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.\n *\n * @example\n * ```ts\n * if (await exists('./kubb.config.ts')) {\n * const content = await read('./kubb.config.ts')\n * }\n * ```\n */\nexport async function exists(path: string): Promise<boolean> {\n if (runtime.isBun) {\n return Bun.file(path).exists()\n }\n return access(path).then(\n () => true,\n () => false,\n )\n}\n\n/**\n * Reads the file at `path` as a UTF-8 string.\n * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.\n *\n * @example\n * ```ts\n * const source = await read('./src/Pet.ts')\n * ```\n */\nexport async function read(path: string): Promise<string> {\n if (runtime.isBun) {\n return Bun.file(path).text()\n }\n return readFile(path, { encoding: 'utf8' })\n}\n\ntype WriteOptions = {\n /**\n * When `true`, re-reads the file immediately after writing and throws if the\n * content does not match — useful for catching write failures on unreliable file systems.\n */\n sanity?: boolean\n}\n\n/**\n * Writes `data` to `path`, trimming leading/trailing whitespace before saving.\n * Skips the write when the trimmed content is empty or identical to what is already on disk.\n * Creates any missing parent directories automatically.\n * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.\n *\n * @example\n * ```ts\n * await write('./src/Pet.ts', source) // writes and returns trimmed content\n * await write('./src/Pet.ts', source) // null — file unchanged\n * await write('./src/Pet.ts', ' ') // null — empty content skipped\n * ```\n */\nexport async function write(path: string, data: string, options: WriteOptions = {}): Promise<string | null> {\n const trimmed = data.trim()\n if (trimmed === '') return null\n\n const resolved = resolve(path)\n\n if (runtime.isBun) {\n const file = Bun.file(resolved)\n const oldContent = (await file.exists()) ? await file.text() : null\n if (oldContent === trimmed) return null\n await Bun.write(resolved, trimmed)\n return trimmed\n }\n\n try {\n const oldContent = await readFile(resolved, { encoding: 'utf-8' })\n if (oldContent === trimmed) return null\n } catch {\n /* file doesn't exist yet */\n }\n\n await mkdir(dirname(resolved), { recursive: true })\n await writeFile(resolved, trimmed, { encoding: 'utf-8' })\n\n if (options.sanity) {\n const savedData = await readFile(resolved, { encoding: 'utf-8' })\n if (savedData !== trimmed) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n return savedData\n }\n\n return trimmed\n}\n\n/**\n * Recursively removes `path`. Silently succeeds when `path` does not exist.\n *\n * @example\n * ```ts\n * await clean('./dist')\n * ```\n */\nexport async function clean(path: string): Promise<void> {\n return rm(path, { recursive: true, force: true })\n}\n\n/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","/**\n * Character used for a single indent step. Set to `'\\t'` to emit tab-indented output.\n */\nexport const INDENT_CHAR = ' '\n\n/**\n * Indentation unit prepended once per nesting level when pretty-printing.\n */\nexport const INDENT = INDENT_CHAR.repeat(2)\n\n/**\n * Matches only the final `.<ext>` of a path, so a name like `foo.bar.ts` keeps\n * `foo.bar` and loses just `.ts`.\n */\nexport const FILE_EXTENSION_PATTERN = /\\.[^/.]+$/\n\n/**\n * Matches Windows-style backslash path separators.\n */\nexport const WINDOWS_PATH_SEPARATOR = /\\\\/g\n\n/**\n * Matches `*\\/` in free-form text so JSDoc bodies can neutralize premature\n * comment terminators (`*\\/` → `* /`).\n */\nexport const JSDOC_TERMINATOR_PATTERN = /\\*\\//g\n\n/**\n * Matches carriage returns for normalizing CRLF/CR line endings to LF.\n */\nexport const CARRIAGE_RETURN_PATTERN = /\\r/g\n\n/**\n * Matches CRLF sequences used when normalizing TypeScript printer output.\n */\nexport const CRLF_PATTERN = /\\r\\n/g\n\n/**\n * Matches an identifier that starts with a digit. JavaScript disallows this,\n * so the printer replaces the leading digit with `_`.\n */\nexport const LEADING_DIGIT_PATTERN = /^\\d/\n\n/**\n * Relative path prefix used to detect traversal segments (`../`).\n */\nexport const PARENT_DIRECTORY_PREFIX = '../' as const\n\n/**\n * Relative path prefix used when resolving imports within the output root.\n */\nexport const CURRENT_DIRECTORY_PREFIX = './' as const\n","import { normalize, relative } from 'node:path'\nimport { trimExtName } from '@internals/utils'\nimport type { ArrowFunctionNode, CodeNode, ConstNode, FunctionNode, JSDocNode, JsxNode, SourceNode, TextNode, TypeNode } from '@kubb/ast'\nimport ts from 'typescript'\nimport {\n CARRIAGE_RETURN_PATTERN,\n CRLF_PATTERN,\n CURRENT_DIRECTORY_PREFIX,\n FILE_EXTENSION_PATTERN,\n INDENT,\n INDENT_CHAR,\n JSDOC_TERMINATOR_PATTERN,\n LEADING_DIGIT_PATTERN,\n PARENT_DIRECTORY_PREFIX,\n WINDOWS_PATH_SEPARATOR,\n} from './constants.ts'\n\nconst { factory } = ts\n\n/**\n * Normalizes a file-system path to POSIX separators and strips any leading `../` segment.\n */\nexport function slash(path: string): string {\n return normalize(path).replaceAll(WINDOWS_PATH_SEPARATOR, '/').replace(PARENT_DIRECTORY_PREFIX, '')\n}\n\n/**\n * Resolves `filePath` relative to `rootDir` and returns a POSIX-style path\n * prefixed with `./` when the target sits inside the root, or `../` when it escapes it.\n */\nexport function getRelativePath(rootDir: string, filePath: string): string {\n const rel = relative(rootDir, filePath)\n const slashed = slash(rel)\n return slashed.startsWith(PARENT_DIRECTORY_PREFIX) ? slashed : `${CURRENT_DIRECTORY_PREFIX}${slashed}`\n}\n\n/**\n * Rewrites an import/export path so its extension matches the caller-supplied\n * `options.extname`. When the source path has no extension the original is kept,\n * so virtual/module-only paths flow through unchanged.\n */\nexport function resolveOutputPath(path: string, options: { extname?: string } | undefined, rootAware: boolean): string {\n const hasExtname = FILE_EXTENSION_PATTERN.test(path)\n if (options?.extname && hasExtname) {\n return `${trimExtName(path)}${options.extname}`\n }\n return rootAware ? trimExtName(path) : path\n}\n\n/**\n * Serializes a `nodes` array into source text. Each entry is rendered via {@link printCodeNode}\n * and joined with a single newline. A `Break` node (`<br/>`) inserts one blank line between\n * statements. Consecutive breaks, and breaks at the very start or end, are folded into the\n * separator, so a double `<br/>` never emits more than one blank line.\n */\nexport function printNodes(nodes: Array<CodeNode> | undefined): string {\n if (!nodes || nodes.length === 0) return ''\n\n let result = ''\n let hasContent = false\n let pendingBreak = false\n\n for (const node of nodes) {\n if (node.kind === 'Break') {\n if (hasContent) pendingBreak = true\n continue\n }\n\n const text = printCodeNode(node)\n if (!text) continue\n\n if (hasContent) result += pendingBreak ? '\\n\\n' : '\\n'\n result += text\n hasContent = true\n pendingBreak = false\n }\n\n return result\n}\n\n/**\n * Indents every non-empty line of `text` by one indent unit. Pass a number to repeat\n * {@link INDENT_CHAR} that many times, or a string to use as the indent verbatim.\n */\nexport function indentLines(text: string, indent: number | string = INDENT): string {\n if (!text) return ''\n const pad = typeof indent === 'string' ? indent : INDENT_CHAR.repeat(indent)\n return text\n .split('\\n')\n .map((line) => (line.trim() ? `${pad}${line}` : ''))\n .join('\\n')\n}\n\n/**\n * Removes the common leading whitespace shared by every non-blank line and trims\n * surrounding blank lines, so multi-line content authored inside an indented template\n * literal lines up at a column-zero baseline. Leading whitespace is counted by\n * character, so N tabs and N spaces are treated as the same depth.\n *\n * @example\n * ```ts\n * dedent('\\n foo\\n bar\\n ')\n * // 'foo\\n bar'\n * ```\n */\nexport function dedent(text: string): string {\n if (!text) return ''\n\n const lines = text.split('\\n')\n const isBlank = (line: string) => line.trim() === ''\n\n const start = lines.findIndex((line) => !isBlank(line))\n if (start === -1) return ''\n const end = lines.findLastIndex((line) => !isBlank(line))\n\n const trimmed = lines.slice(start, end + 1)\n const indents = trimmed.filter((line) => !isBlank(line)).map((line) => line.match(/^\\s*/)?.[0].length ?? 0)\n const min = indents.length ? Math.min(...indents) : 0\n\n return trimmed.map((line) => (isBlank(line) ? '' : line.slice(min))).join('\\n')\n}\n\n/**\n * Renders the generic clause (`<T, U>`) shared by function and arrow-function nodes.\n * Accepts either a raw string (rendered verbatim) or an array of type-parameter names.\n */\nexport function formatGenerics(generics: FunctionNode['generics'] | ArrowFunctionNode['generics']): string {\n if (!generics) return ''\n return `<${Array.isArray(generics) ? generics.join(', ') : generics}>`\n}\n\n/**\n * Renders the return-type suffix (`: T` or `: Promise<T>` when `isAsync` is true).\n * Returns an empty string when no return type is provided.\n */\nexport function formatReturnType(returnType: string | null | undefined, isAsync: boolean | null | undefined): string {\n if (!returnType) return ''\n return isAsync ? `: Promise<${returnType}>` : `: ${returnType}`\n}\n\n/**\n * Module-scoped TypeScript printer instance. A printer does not mutate the source file, so one\n * instance is reused across every `print()` call instead of constructing a new printer each time.\n */\nconst TS_PRINTER = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n})\n\n/**\n * Module-scoped source file used as the print target. `printList` only reads the source\n * file's compiler options / language version. It never mutates it.\n */\nconst PRINT_SOURCE_FILE = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n// Pre-warm the printer at module load. The first `printList` call lazily initializes\n// the printer's internal string-builder and identifier tables. Doing it once at import\n// time keeps that cost off the critical path for short-lived CLI builds.\nTS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray([]), PRINT_SOURCE_FILE)\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 filtered = elements.filter(Boolean)\n if (filtered.length === 0) return ''\n\n const output = TS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray(filtered), PRINT_SOURCE_FILE)\n\n return output.replace(CRLF_PATTERN, '\\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(JSDOC_TERMINATOR_PATTERN, '* /').replace(CARRIAGE_RETURN_PATTERN, ''))\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 * Converts a {@link ConstNode} to a TypeScript `const` declaration string.\n *\n * Mirrors the `Const` component from `@kubb/renderer-jsx`.\n *\n * @example\n * ```ts\n * printConst(factory.createConst({ name: 'pet', export: true, nodes: ['{}'] }))\n * // 'export const pet = {}'\n * ```\n *\n * @example With type and `as const`\n * ```ts\n * printConst(factory.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: Array<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/renderer-jsx`.\n *\n * @example\n * ```ts\n * printType(factory.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: Array<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/renderer-jsx`.\n *\n * @example\n * ```ts\n * printFunction(factory.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(factory.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 const body = printNodes(nodes)\n const indented = body ? indentLines(body) : ''\n\n const parts: Array<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(formatGenerics(generics))\n parts.push(`(${params ?? ''})`)\n parts.push(formatReturnType(returnType, isAsync))\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/renderer-jsx`.\n *\n * @example Multi-line arrow function\n * ```ts\n * printArrowFunction(factory.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(factory.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 const body = printNodes(nodes)\n const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\\n${indentLines(body)}\\n}` : ' => {}'\n\n const parts: Array<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(formatGenerics(generics))\n parts.push(`(${params ?? ''})`)\n parts.push(formatReturnType(returnType, isAsync))\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(factory.createConst({ name: 'x', nodes: ['1'] }))\n * // 'const x = 1'\n * ```\n */\nexport function printCodeNode(node: CodeNode): string {\n if (node.kind === 'Break') return ''\n if (node.kind === 'Text') return dedent((node as TextNode).value)\n if (node.kind === 'Jsx') return dedent((node as JsxNode).value)\n if (node.kind === 'Const') return printConst(node)\n if (node.kind === 'Type') return printType(node)\n if (node.kind === 'Function') return printFunction(node)\n if (node.kind === 'ArrowFunction') return printArrowFunction(node)\n return ''\n}\n\n/**\n * Converts a {@link SourceNode} to its TypeScript string representation.\n *\n * Iterates `nodes` in DOM order, rendering each {@link CodeNode} via\n * {@link printCodeNode}.\n *\n * Top-level declarations are separated by a blank line so the source reads\n * cleanly without an external formatter.\n *\n * @example From nodes\n * ```ts\n * printSource({ kind: 'Source', nodes: [factory.createConst({ name: 'x', nodes: [factory.createText('1')] }), factory.createText('x.toString()')] })\n * // 'const x = 1\\n\\nx.toString()'\n * ```\n */\nexport function printSource(node: SourceNode): string {\n const nodes = node.nodes\n\n if (!nodes || nodes.length === 0) return ''\n\n // Imperative join. `map().filter().join()` allocated a closure and two arrays per source, and\n // this runs once per source fragment during printing, so it surfaced in the deopt churn trace.\n let result = ''\n for (const child of nodes) {\n const text = printCodeNode(child as CodeNode)\n if (!text) continue\n result = result ? `${result}\\n\\n${text}` : text\n }\n\n return result\n}\n\n/**\n * Wraps a module specifier in single quotes, escaping any embedded backslash or quote so the emitted\n * statement stays valid even for unusual paths.\n */\nfunction quoteModulePath(path: string): string {\n return `'${path.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`\n}\n\n/**\n * Renders an import declaration string in the repo style (single quotes, no semicolons), covering\n * default, namespace (`* as`), and named imports with `{ a as b }` aliases, each optionally\n * `type`-only. `path` is used verbatim, so resolve it first.\n *\n * @example\n * ```ts\n * printImport({ name: ['z'], path: './zod.ts' })\n * // \"import { z } from './zod.ts'\"\n * ```\n */\nexport function printImport({\n name,\n path,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n isTypeOnly?: boolean | null\n isNameSpace?: boolean | null\n}): string {\n const typePrefix = isTypeOnly ? 'type ' : ''\n const from = quoteModulePath(path)\n\n if (!Array.isArray(name)) {\n if (isNameSpace) return `import ${typePrefix}* as ${name} from ${from}`\n return `import ${typePrefix}${name} from ${from}`\n }\n\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n return item.name ? `${item.propertyName} as ${item.name}` : item.propertyName\n }\n return item\n })\n\n return `import ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`\n}\n\n/**\n * Renders an export declaration string in the repo style (single quotes, no semicolons), covering\n * named re-exports, namespace alias (`* as name`), and wildcard, each optionally `type`-only.\n * `path` is used verbatim, so resolve it first.\n *\n * @example\n * ```ts\n * printExport({ name: ['Pet', 'Order'], path: './models.ts' })\n * // \"export { Pet, Order } from './models.ts'\"\n * ```\n */\nexport function printExport({\n path,\n name,\n isTypeOnly = false,\n asAlias = false,\n}: {\n path: string\n name?: string | Array<ts.Identifier | string> | null\n isTypeOnly?: boolean | null\n asAlias?: boolean | null\n}): string {\n const typePrefix = isTypeOnly ? 'type ' : ''\n const from = quoteModulePath(path)\n\n if (Array.isArray(name)) {\n const specifiers = name.map((item) => (typeof item === 'string' ? item : item.text))\n return `export ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`\n }\n\n if (asAlias && name) {\n const parsedName = LEADING_DIGIT_PATTERN.test(name) ? `_${name.slice(1)}` : name\n return `export ${typePrefix}* as ${parsedName} from ${from}`\n }\n\n if (name) {\n console.warn(`When using name as string, asAlias should be true: ${name}`)\n }\n\n return `export ${typePrefix}* from ${from}`\n}\n","import type { FileNode, SourceNode } from '@kubb/ast'\nimport { defineParser } from '@kubb/core'\nimport type * as ts from 'typescript'\nimport { getRelativePath, print, printExport, printImport, printSource, resolveOutputPath } from './utils.ts'\n\n/**\n * Default Kubb parser for `.ts` and `.js` files. Takes the universal AST\n * produced by an adapter and prints it as TypeScript source using the official\n * TypeScript compiler. Imports and exports are rewritten based on each file's\n * metadata.\n *\n * Used automatically when no `parsers` option is set on `defineConfig`. Use\n * `parserTsx` instead for React projects that emit JSX.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { parserTs } from '@kubb/parser-ts'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * parsers: [parserTs],\n * plugins: [],\n * })\n * ```\n */\nexport const parserTs = defineParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n print(...nodes: Array<ts.Node>) {\n return print(...nodes)\n },\n 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.trimEnd())\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importLines: Array<string> = []\n for (const item of (file as FileNode).imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n importLines.push(\n printImport({\n name: item.name as string | Array<string | { propertyName: string; name?: string }>,\n path: resolveOutputPath(importPath, options, Boolean(item.root)),\n isTypeOnly: item.isTypeOnly,\n isNameSpace: item.isNameSpace,\n }),\n )\n }\n\n const exportLines: Array<string> = []\n for (const item of (file as FileNode).exports) {\n exportLines.push(\n printExport({\n name: item.name as string | Array<ts.Identifier | string> | null | undefined,\n path: resolveOutputPath(item.path, options, true),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const importExportBlock = [...importLines, ...exportLines].join('\\n')\n\n const parts = [file.banner, importExportBlock, source, file.footer].filter((segment): segment is string => Boolean(segment)).map((s) => s.trimEnd())\n\n return parts.join('\\n\\n')\n },\n})\n","import { defineParser } from '@kubb/core'\nimport type * as ts from 'typescript'\nimport { parserTs } from './parserTs.ts'\nimport { print } from './utils.ts'\n\n/**\n * Kubb parser for `.tsx` and `.jsx` files. Delegates to `parserTs` because the\n * TypeScript compiler handles JSX natively via `ScriptKind.TSX`.\n *\n * Add to the `parsers` array on `defineConfig` when generating components for\n * React (or any framework that emits JSX).\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { parserTsx } from '@kubb/parser-ts'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * parsers: [parserTsx],\n * plugins: [],\n * })\n * ```\n */\nexport const parserTsx = defineParser({\n name: 'tsx',\n extNames: ['.tsx', '.jsx'],\n print(...nodes: Array<ts.Node>) {\n return print(...nodes)\n },\n 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":["../../../internals/utils/src/fs.ts","../src/constants.ts","../src/utils.ts","../src/parserTs.ts","../src/parserTsx.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, join, posix, resolve } from 'node:path'\nimport { camelCase } from './casing.ts'\nimport { runtime } from './runtime.ts'\n\n/**\n * Walks up the directory tree from `cwd` (defaults to `process.cwd()`) and\n * returns the absolute path of the nearest `package.json`, or `null` when none\n * is found before reaching the filesystem root.\n *\n * @example\n * ```ts\n * const pkgPath = findPackageJSON('/home/user/project/src') // '/home/user/project/package.json'\n * ```\n */\nexport function findPackageJSON(cwd?: string): string | null {\n let dir = cwd ? resolve(cwd) : process.cwd()\n while (true) {\n const pkgPath = join(dir, 'package.json')\n if (existsSync(pkgPath)) return pkgPath\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\n/**\n * Converts all backslashes to forward slashes.\n * Extended-length Windows paths (`\\\\?\\...`) are left unchanged.\n */\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Resolves to `true` when the file or directory at `path` exists.\n * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.\n *\n * @example\n * ```ts\n * if (await exists('./kubb.config.ts')) {\n * const content = await read('./kubb.config.ts')\n * }\n * ```\n */\nexport async function exists(path: string): Promise<boolean> {\n if (runtime.isBun) {\n return Bun.file(path).exists()\n }\n return access(path).then(\n () => true,\n () => false,\n )\n}\n\n/**\n * Reads the file at `path` as a UTF-8 string.\n * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.\n *\n * @example\n * ```ts\n * const source = await read('./src/Pet.ts')\n * ```\n */\nexport async function read(path: string): Promise<string> {\n if (runtime.isBun) {\n return Bun.file(path).text()\n }\n return readFile(path, { encoding: 'utf8' })\n}\n\ntype WriteOptions = {\n /**\n * When `true`, re-reads the file immediately after writing and throws if the\n * content does not match — useful for catching write failures on unreliable file systems.\n */\n sanity?: boolean\n}\n\n/**\n * Writes `data` to `path`, trimming leading/trailing whitespace before saving.\n * Skips the write when the trimmed content is empty or identical to what is already on disk.\n * Creates any missing parent directories automatically.\n * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.\n *\n * @example\n * ```ts\n * await write('./src/Pet.ts', source) // writes and returns trimmed content\n * await write('./src/Pet.ts', source) // null — file unchanged\n * await write('./src/Pet.ts', ' ') // null — empty content skipped\n * ```\n */\nexport async function write(path: string, data: string, options: WriteOptions = {}): Promise<string | null> {\n const trimmed = data.trim()\n if (trimmed === '') return null\n\n const resolved = resolve(path)\n\n if (runtime.isBun) {\n const file = Bun.file(resolved)\n const oldContent = (await file.exists()) ? await file.text() : null\n if (oldContent === trimmed) return null\n await Bun.write(resolved, trimmed)\n return trimmed\n }\n\n try {\n const oldContent = await readFile(resolved, { encoding: 'utf-8' })\n if (oldContent === trimmed) return null\n } catch {\n /* file doesn't exist yet */\n }\n\n await mkdir(dirname(resolved), { recursive: true })\n await writeFile(resolved, trimmed, { encoding: 'utf-8' })\n\n if (options.sanity) {\n const savedData = await readFile(resolved, { encoding: 'utf-8' })\n if (savedData !== trimmed) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n return savedData\n }\n\n return trimmed\n}\n\n/**\n * Recursively removes `path`. Silently succeeds when `path` does not exist.\n *\n * @example\n * ```ts\n * await clean('./dist')\n * ```\n */\nexport async function clean(path: string): Promise<void> {\n return rm(path, { recursive: true, force: true })\n}\n\n/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","/**\n * Character used for a single indent step. Set to `'\\t'` to emit tab-indented output.\n */\nexport const INDENT_CHAR = ' '\n\n/**\n * Indentation unit prepended once per nesting level when pretty-printing.\n */\nexport const INDENT = INDENT_CHAR.repeat(2)\n\n/**\n * Matches only the final `.<ext>` of a path, so a name like `foo.bar.ts` keeps\n * `foo.bar` and loses just `.ts`.\n */\nexport const FILE_EXTENSION_PATTERN = /\\.[^/.]+$/\n\n/**\n * Matches Windows-style backslash path separators.\n */\nexport const WINDOWS_PATH_SEPARATOR = /\\\\/g\n\n/**\n * Matches `*\\/` in free-form text so JSDoc bodies can neutralize premature\n * comment terminators (`*\\/` → `* /`).\n */\nexport const JSDOC_TERMINATOR_PATTERN = /\\*\\//g\n\n/**\n * Matches carriage returns for normalizing CRLF/CR line endings to LF.\n */\nexport const CARRIAGE_RETURN_PATTERN = /\\r/g\n\n/**\n * Matches CRLF sequences used when normalizing TypeScript printer output.\n */\nexport const CRLF_PATTERN = /\\r\\n/g\n\n/**\n * Matches an identifier that starts with a digit. JavaScript disallows this,\n * so the printer replaces the leading digit with `_`.\n */\nexport const LEADING_DIGIT_PATTERN = /^\\d/\n\n/**\n * Relative path prefix used to detect traversal segments (`../`).\n */\nexport const PARENT_DIRECTORY_PREFIX = '../' as const\n\n/**\n * Relative path prefix used when resolving imports within the output root.\n */\nexport const CURRENT_DIRECTORY_PREFIX = './' as const\n","import { normalize, relative } from 'node:path'\nimport { trimExtName } from '@internals/utils'\nimport type { ArrowFunctionNode, CodeNode, ConstNode, FunctionNode, JSDocNode, JsxNode, SourceNode, TextNode, TypeNode } from '@kubb/ast'\nimport ts from 'typescript'\nimport {\n CARRIAGE_RETURN_PATTERN,\n CRLF_PATTERN,\n CURRENT_DIRECTORY_PREFIX,\n FILE_EXTENSION_PATTERN,\n INDENT,\n INDENT_CHAR,\n JSDOC_TERMINATOR_PATTERN,\n LEADING_DIGIT_PATTERN,\n PARENT_DIRECTORY_PREFIX,\n WINDOWS_PATH_SEPARATOR,\n} from './constants.ts'\n\nconst { factory } = ts\n\n/**\n * Resolves `filePath` relative to `rootDir` and returns a POSIX-style path\n * prefixed with `./` when the target sits inside the root, or `../` when it escapes it.\n */\nexport function getRelativePath(rootDir: string, filePath: string): string {\n const rel = relative(rootDir, filePath)\n const slashed = normalize(rel).replaceAll(WINDOWS_PATH_SEPARATOR, '/').replace(PARENT_DIRECTORY_PREFIX, '')\n return slashed.startsWith(PARENT_DIRECTORY_PREFIX) ? slashed : `${CURRENT_DIRECTORY_PREFIX}${slashed}`\n}\n\n/**\n * Rewrites an import/export path so its extension matches the caller-supplied\n * `options.extname`. When the source path has no extension the original is kept,\n * so virtual/module-only paths flow through unchanged.\n */\nexport function resolveOutputPath(path: string, options: { extname?: string } | undefined, rootAware: boolean): string {\n const hasExtname = FILE_EXTENSION_PATTERN.test(path)\n if (options?.extname && hasExtname) {\n return `${trimExtName(path)}${options.extname}`\n }\n return rootAware ? trimExtName(path) : path\n}\n\n/**\n * Serializes a `nodes` array into source text. Each entry is rendered via {@link printCodeNode}\n * and joined with a single newline. A `Break` node (`<br/>`) inserts one blank line between\n * statements. Consecutive breaks, and breaks at the very start or end, are folded into the\n * separator, so a double `<br/>` never emits more than one blank line.\n */\nexport function printNodes(nodes: Array<CodeNode> | undefined): string {\n if (!nodes || nodes.length === 0) return ''\n\n let result = ''\n let hasContent = false\n let pendingBreak = false\n\n for (const node of nodes) {\n if (node.kind === 'Break') {\n if (hasContent) pendingBreak = true\n continue\n }\n\n const text = printCodeNode(node)\n if (!text) continue\n\n if (hasContent) result += pendingBreak ? '\\n\\n' : '\\n'\n result += text\n hasContent = true\n pendingBreak = false\n }\n\n return result\n}\n\n/**\n * Indents every non-empty line of `text` by one indent unit. Pass a number to repeat\n * {@link INDENT_CHAR} that many times, or a string to use as the indent verbatim.\n */\nexport function indentLines(text: string, indent: number | string = INDENT): string {\n if (!text) return ''\n const pad = typeof indent === 'string' ? indent : INDENT_CHAR.repeat(indent)\n return text\n .split('\\n')\n .map((line) => (line.trim() ? `${pad}${line}` : ''))\n .join('\\n')\n}\n\n/**\n * Removes the common leading whitespace shared by every non-blank line and trims\n * surrounding blank lines, so multi-line content authored inside an indented template\n * literal lines up at a column-zero baseline. Leading whitespace is counted by\n * character, so N tabs and N spaces are treated as the same depth.\n *\n * @example\n * ```ts\n * dedent('\\n foo\\n bar\\n ')\n * // 'foo\\n bar'\n * ```\n */\nexport function dedent(text: string): string {\n if (!text) return ''\n\n const lines = text.split('\\n')\n const isBlank = (line: string) => line.trim() === ''\n\n const start = lines.findIndex((line) => !isBlank(line))\n if (start === -1) return ''\n const end = lines.findLastIndex((line) => !isBlank(line))\n\n const trimmed = lines.slice(start, end + 1)\n const indents = trimmed.filter((line) => !isBlank(line)).map((line) => line.match(/^\\s*/)?.[0].length ?? 0)\n const min = indents.length ? Math.min(...indents) : 0\n\n return trimmed.map((line) => (isBlank(line) ? '' : line.slice(min))).join('\\n')\n}\n\n/**\n * Renders the generic clause (`<T, U>`) shared by function and arrow-function nodes.\n * Accepts either a raw string (rendered verbatim) or an array of type-parameter names.\n */\nexport function formatGenerics(generics: FunctionNode['generics'] | ArrowFunctionNode['generics']): string {\n if (!generics) return ''\n return `<${Array.isArray(generics) ? generics.join(', ') : generics}>`\n}\n\n/**\n * Renders the return-type suffix (`: T` or `: Promise<T>` when `isAsync` is true).\n * Returns an empty string when no return type is provided.\n */\nexport function formatReturnType(returnType: string | null | undefined, isAsync: boolean | null | undefined): string {\n if (!returnType) return ''\n return isAsync ? `: Promise<${returnType}>` : `: ${returnType}`\n}\n\n/**\n * Module-scoped TypeScript printer instance. A printer does not mutate the source file, so one\n * instance is reused across every `print()` call instead of constructing a new printer each time.\n */\nconst TS_PRINTER = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n})\n\n/**\n * Module-scoped source file used as the print target. `printList` only reads the source\n * file's compiler options / language version. It never mutates it.\n */\nconst PRINT_SOURCE_FILE = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n// Pre-warm the printer at module load. The first `printList` call lazily initializes\n// the printer's internal string-builder and identifier tables. Doing it once at import\n// time keeps that cost off the critical path for short-lived CLI builds.\nTS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray([]), PRINT_SOURCE_FILE)\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 filtered = elements.filter(Boolean)\n if (filtered.length === 0) return ''\n\n const output = TS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray(filtered), PRINT_SOURCE_FILE)\n\n return output.replace(CRLF_PATTERN, '\\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(JSDOC_TERMINATOR_PATTERN, '* /').replace(CARRIAGE_RETURN_PATTERN, ''))\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 * Converts a {@link ConstNode} to a TypeScript `const` declaration string.\n *\n * Mirrors the `Const` component from `@kubb/renderer-jsx`.\n *\n * @example\n * ```ts\n * printConst(factory.createConst({ name: 'pet', export: true, nodes: ['{}'] }))\n * // 'export const pet = {}'\n * ```\n *\n * @example With type and `as const`\n * ```ts\n * printConst(factory.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: Array<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/renderer-jsx`.\n *\n * @example\n * ```ts\n * printType(factory.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: Array<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/renderer-jsx`.\n *\n * @example\n * ```ts\n * printFunction(factory.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(factory.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 const body = printNodes(nodes)\n const indented = body ? indentLines(body) : ''\n\n const parts: Array<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(formatGenerics(generics))\n parts.push(`(${params ?? ''})`)\n parts.push(formatReturnType(returnType, isAsync))\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/renderer-jsx`.\n *\n * @example Multi-line arrow function\n * ```ts\n * printArrowFunction(factory.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(factory.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 const body = printNodes(nodes)\n const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\\n${indentLines(body)}\\n}` : ' => {}'\n\n const parts: Array<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(formatGenerics(generics))\n parts.push(`(${params ?? ''})`)\n parts.push(formatReturnType(returnType, isAsync))\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(factory.createConst({ name: 'x', nodes: ['1'] }))\n * // 'const x = 1'\n * ```\n */\nexport function printCodeNode(node: CodeNode): string {\n if (node.kind === 'Break') return ''\n if (node.kind === 'Text') return dedent((node as TextNode).value)\n if (node.kind === 'Jsx') return dedent((node as JsxNode).value)\n if (node.kind === 'Const') return printConst(node)\n if (node.kind === 'Type') return printType(node)\n if (node.kind === 'Function') return printFunction(node)\n if (node.kind === 'ArrowFunction') return printArrowFunction(node)\n return ''\n}\n\n/**\n * Converts a {@link SourceNode} to its TypeScript string representation.\n *\n * Iterates `nodes` in DOM order, rendering each {@link CodeNode} via\n * {@link printCodeNode}.\n *\n * Top-level declarations are separated by a blank line so the source reads\n * cleanly without an external formatter.\n *\n * @example From nodes\n * ```ts\n * printSource({ kind: 'Source', nodes: [factory.createConst({ name: 'x', nodes: [factory.createText('1')] }), factory.createText('x.toString()')] })\n * // 'const x = 1\\n\\nx.toString()'\n * ```\n */\nexport function printSource(node: SourceNode): string {\n const nodes = node.nodes\n\n if (!nodes || nodes.length === 0) return ''\n\n // Imperative join. `map().filter().join()` allocated a closure and two arrays per source, and\n // this runs once per source fragment during printing, so it surfaced in the deopt churn trace.\n let result = ''\n for (const child of nodes) {\n const text = printCodeNode(child as CodeNode)\n if (!text) continue\n result = result ? `${result}\\n\\n${text}` : text\n }\n\n return result\n}\n\n/**\n * Wraps a module specifier in single quotes, escaping any embedded backslash or quote so the emitted\n * statement stays valid even for unusual paths.\n */\nfunction quoteModulePath(path: string): string {\n return `'${path.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`\n}\n\n/**\n * Renders an import declaration string in the repo style (single quotes, no semicolons), covering\n * default, namespace (`* as`), and named imports with `{ a as b }` aliases, each optionally\n * `type`-only. `path` is used verbatim, so resolve it first.\n *\n * @example\n * ```ts\n * printImport({ name: ['z'], path: './zod.ts' })\n * // \"import { z } from './zod.ts'\"\n * ```\n */\nexport function printImport({\n name,\n path,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n isTypeOnly?: boolean | null\n isNameSpace?: boolean | null\n}): string {\n const typePrefix = isTypeOnly ? 'type ' : ''\n const from = quoteModulePath(path)\n\n if (!Array.isArray(name)) {\n if (isNameSpace) return `import ${typePrefix}* as ${name} from ${from}`\n return `import ${typePrefix}${name} from ${from}`\n }\n\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n return item.name ? `${item.propertyName} as ${item.name}` : item.propertyName\n }\n return item\n })\n\n return `import ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`\n}\n\n/**\n * Renders an export declaration string in the repo style (single quotes, no semicolons), covering\n * named re-exports, namespace alias (`* as name`), and wildcard, each optionally `type`-only.\n * `path` is used verbatim, so resolve it first.\n *\n * @example\n * ```ts\n * printExport({ name: ['Pet', 'Order'], path: './models.ts' })\n * // \"export { Pet, Order } from './models.ts'\"\n * ```\n */\nexport function printExport({\n path,\n name,\n isTypeOnly = false,\n asAlias = false,\n}: {\n path: string\n name?: string | Array<ts.Identifier | string> | null\n isTypeOnly?: boolean | null\n asAlias?: boolean | null\n}): string {\n const typePrefix = isTypeOnly ? 'type ' : ''\n const from = quoteModulePath(path)\n\n if (Array.isArray(name)) {\n const specifiers = name.map((item) => (typeof item === 'string' ? item : item.text))\n return `export ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`\n }\n\n if (asAlias && name) {\n const parsedName = LEADING_DIGIT_PATTERN.test(name) ? `_${name.slice(1)}` : name\n return `export ${typePrefix}* as ${parsedName} from ${from}`\n }\n\n if (name) {\n console.warn(`When using name as string, asAlias should be true: ${name}`)\n }\n\n return `export ${typePrefix}* from ${from}`\n}\n","import type { FileNode, SourceNode } from '@kubb/ast'\nimport { defineParser } from '@kubb/core'\nimport type * as ts from 'typescript'\nimport { getRelativePath, print, printExport, printImport, printSource, resolveOutputPath } from './utils.ts'\n\nconst DEFAULT_EXTENSION: Record<FileNode['extname'], FileNode['extname'] | ''> = { '.ts': '.ts' }\n\n/**\n * Options accepted by `parserTs` and `parserTsx`.\n */\nexport type ParserTsOptions = {\n /**\n * Rewrite the extensions emitted in `import`/`export` statements, e.g. emit `.js` imports from\n * `.ts` sources for ESM dual packages. Keys are the source extension, values the output, and `''`\n * drops it. Only the module-specifier string changes, never the on-disk filename.\n *\n * @default { '.ts': '.ts' }\n * @example\n * ```ts\n * parserTs({ extension: { '.ts': '.js' } }) // import './api.js' instead of './api.ts'\n * parserTs({ extension: { '.ts': '', '.tsx': '.jsx' } })\n * ```\n */\n extension?: Record<FileNode['extname'], FileNode['extname'] | ''>\n}\n\n/**\n * Default Kubb parser for `.ts` and `.js` files. Takes the universal AST\n * produced by an adapter and prints it as TypeScript source using the official\n * TypeScript compiler. Imports and exports are rewritten based on each file's\n * metadata and the `extension` option.\n *\n * Used automatically when no `parsers` option is set on `defineConfig`. Use\n * `parserTsx` instead for React projects that emit JSX.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { parserTs } from '@kubb/parser-ts'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * parsers: [parserTs()],\n * plugins: [],\n * })\n * ```\n */\nexport const parserTs = defineParser<ParserTsOptions>(({ extension = DEFAULT_EXTENSION } = {}) => {\n return {\n name: 'typescript',\n extNames: ['.ts', '.js'],\n print(...nodes: Array<ts.Node>) {\n return print(...nodes)\n },\n parse(file) {\n const extname = extension[file.extname] || undefined\n\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.trimEnd())\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importLines: Array<string> = []\n for (const item of (file as FileNode).imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n importLines.push(\n printImport({\n name: item.name as string | Array<string | { propertyName: string; name?: string }>,\n path: resolveOutputPath(importPath, { extname }, Boolean(item.root)),\n isTypeOnly: item.isTypeOnly,\n isNameSpace: item.isNameSpace,\n }),\n )\n }\n\n const exportLines: Array<string> = []\n for (const item of (file as FileNode).exports) {\n exportLines.push(\n printExport({\n name: item.name as string | Array<ts.Identifier | string> | null | undefined,\n path: resolveOutputPath(item.path, { extname }, true),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const importExportBlock = [...importLines, ...exportLines].join('\\n')\n\n const parts = [file.banner, importExportBlock, source, file.footer].filter((segment): segment is string => Boolean(segment)).map((s) => s.trimEnd())\n\n return parts.join('\\n\\n')\n },\n }\n})\n","import { defineParser } from '@kubb/core'\nimport type * as ts from 'typescript'\nimport { parserTs, type ParserTsOptions } from './parserTs.ts'\nimport { print } from './utils.ts'\n\n/**\n * Kubb parser for `.tsx` and `.jsx` files. Delegates to `parserTs` because the\n * TypeScript compiler handles JSX natively via `ScriptKind.TSX`, so it shares the\n * same `extension` option.\n *\n * Add to the `parsers` array on `defineConfig` when generating components for\n * React (or any framework that emits JSX).\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { parserTsx } from '@kubb/parser-ts'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * parsers: [parserTsx()],\n * plugins: [],\n * })\n * ```\n */\nexport const parserTsx = defineParser<ParserTsOptions>((options = {}) => {\n const parser = parserTs(options)\n\n return {\n name: 'tsx',\n extNames: ['.tsx', '.jsx'],\n print(...nodes: Array<ts.Node>) {\n return print(...nodes)\n },\n parse(file) {\n return parser.parse(file)\n },\n }\n})\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,13 +1,30 @@
1
1
  import { t as __name } from "./rolldown-runtime-C0LytTxp.js";
2
- import * as ts$1 from "typescript";
3
2
  import { FileNode } from "@kubb/ast";
4
3
 
5
4
  //#region src/parserTs.d.ts
5
+ /**
6
+ * Options accepted by `parserTs` and `parserTsx`.
7
+ */
8
+ type ParserTsOptions = {
9
+ /**
10
+ * Rewrite the extensions emitted in `import`/`export` statements, e.g. emit `.js` imports from
11
+ * `.ts` sources for ESM dual packages. Keys are the source extension, values the output, and `''`
12
+ * drops it. Only the module-specifier string changes, never the on-disk filename.
13
+ *
14
+ * @default { '.ts': '.ts' }
15
+ * @example
16
+ * ```ts
17
+ * parserTs({ extension: { '.ts': '.js' } }) // import './api.js' instead of './api.ts'
18
+ * parserTs({ extension: { '.ts': '', '.tsx': '.jsx' } })
19
+ * ```
20
+ */
21
+ extension?: Record<FileNode['extname'], FileNode['extname'] | ''>;
22
+ };
6
23
  /**
7
24
  * Default Kubb parser for `.ts` and `.js` files. Takes the universal AST
8
25
  * produced by an adapter and prints it as TypeScript source using the official
9
26
  * TypeScript compiler. Imports and exports are rewritten based on each file's
10
- * metadata.
27
+ * metadata and the `extension` option.
11
28
  *
12
29
  * Used automatically when no `parsers` option is set on `defineConfig`. Use
13
30
  * `parserTsx` instead for React projects that emit JSX.
@@ -19,27 +36,21 @@ import { FileNode } from "@kubb/ast";
19
36
  * import { parserTs } from '@kubb/parser-ts'
20
37
  *
21
38
  * export default defineConfig({
22
- * input: { path: './petStore.yaml' },
39
+ * input: './petStore.yaml',
23
40
  * output: { path: './src/gen' },
24
41
  * adapter: adapterOas(),
25
- * parsers: [parserTs],
42
+ * parsers: [parserTs()],
26
43
  * plugins: [],
27
44
  * })
28
45
  * ```
29
46
  */
30
- declare const parserTs: {
31
- name: string;
32
- extNames: (".ts" | ".js")[];
33
- print(...nodes: Array<ts$1.Node>): string;
34
- parse(file: FileNode<object>, options?: {
35
- extname?: FileNode["extname"];
36
- } | undefined): string;
37
- };
47
+ declare const parserTs: (options?: ParserTsOptions | undefined) => import("@kubb/core").Parser<object, unknown>;
38
48
  //#endregion
39
49
  //#region src/parserTsx.d.ts
40
50
  /**
41
51
  * Kubb parser for `.tsx` and `.jsx` files. Delegates to `parserTs` because the
42
- * TypeScript compiler handles JSX natively via `ScriptKind.TSX`.
52
+ * TypeScript compiler handles JSX natively via `ScriptKind.TSX`, so it shares the
53
+ * same `extension` option.
43
54
  *
44
55
  * Add to the `parsers` array on `defineConfig` when generating components for
45
56
  * React (or any framework that emits JSX).
@@ -51,22 +62,15 @@ declare const parserTs: {
51
62
  * import { parserTsx } from '@kubb/parser-ts'
52
63
  *
53
64
  * export default defineConfig({
54
- * input: { path: './petStore.yaml' },
65
+ * input: './petStore.yaml',
55
66
  * output: { path: './src/gen' },
56
67
  * adapter: adapterOas(),
57
- * parsers: [parserTsx],
68
+ * parsers: [parserTsx()],
58
69
  * plugins: [],
59
70
  * })
60
71
  * ```
61
72
  */
62
- declare const parserTsx: {
63
- name: string;
64
- extNames: (".tsx" | ".jsx")[];
65
- print(...nodes: Array<ts$1.Node>): string;
66
- parse(file: import("@kubb/ast").FileNode<object>, options?: {
67
- extname?: import("@kubb/ast").FileNode["extname"];
68
- } | undefined): string;
69
- };
73
+ declare const parserTsx: (options?: ParserTsOptions | undefined) => import("@kubb/core").Parser<object, unknown>;
70
74
  //#endregion
71
- export { parserTs, parserTsx };
75
+ export { type ParserTsOptions, parserTs, parserTsx };
72
76
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -53,17 +53,11 @@ const LEADING_DIGIT_PATTERN = /^\d/;
53
53
  //#region src/utils.ts
54
54
  const { factory } = ts;
55
55
  /**
56
- * Normalizes a file-system path to POSIX separators and strips any leading `../` segment.
57
- */
58
- function slash(path) {
59
- return normalize(path).replaceAll(WINDOWS_PATH_SEPARATOR, "/").replace("../", "");
60
- }
61
- /**
62
56
  * Resolves `filePath` relative to `rootDir` and returns a POSIX-style path
63
57
  * prefixed with `./` when the target sits inside the root, or `../` when it escapes it.
64
58
  */
65
59
  function getRelativePath(rootDir, filePath) {
66
- const slashed = slash(relative(rootDir, filePath));
60
+ const slashed = normalize(relative(rootDir, filePath)).replaceAll(WINDOWS_PATH_SEPARATOR, "/").replace("../", "");
67
61
  return slashed.startsWith("../") ? slashed : `./${slashed}`;
68
62
  }
69
63
  /**
@@ -420,11 +414,12 @@ function printExport({ path, name, isTypeOnly = false, asAlias = false }) {
420
414
  }
421
415
  //#endregion
422
416
  //#region src/parserTs.ts
417
+ const DEFAULT_EXTENSION = { ".ts": ".ts" };
423
418
  /**
424
419
  * Default Kubb parser for `.ts` and `.js` files. Takes the universal AST
425
420
  * produced by an adapter and prints it as TypeScript source using the official
426
421
  * TypeScript compiler. Imports and exports are rewritten based on each file's
427
- * metadata.
422
+ * metadata and the `extension` option.
428
423
  *
429
424
  * Used automatically when no `parsers` option is set on `defineConfig`. Use
430
425
  * `parserTsx` instead for React projects that emit JSX.
@@ -436,58 +431,62 @@ function printExport({ path, name, isTypeOnly = false, asAlias = false }) {
436
431
  * import { parserTs } from '@kubb/parser-ts'
437
432
  *
438
433
  * export default defineConfig({
439
- * input: { path: './petStore.yaml' },
434
+ * input: './petStore.yaml',
440
435
  * output: { path: './src/gen' },
441
436
  * adapter: adapterOas(),
442
- * parsers: [parserTs],
437
+ * parsers: [parserTs()],
443
438
  * plugins: [],
444
439
  * })
445
440
  * ```
446
441
  */
447
- const parserTs = defineParser({
448
- name: "typescript",
449
- extNames: [".ts", ".js"],
450
- print(...nodes) {
451
- return print(...nodes);
452
- },
453
- parse(file, options = { extname: ".ts" }) {
454
- const sourceParts = [];
455
- for (const item of file.sources) {
456
- const sourceStr = printSource(item);
457
- if (sourceStr) sourceParts.push(sourceStr.trimEnd());
458
- }
459
- const source = sourceParts.join("\n\n");
460
- const importLines = [];
461
- for (const item of file.imports) {
462
- const importPath = item.root ? getRelativePath(item.root, item.path) : item.path;
463
- importLines.push(printImport({
442
+ const parserTs = defineParser(({ extension = DEFAULT_EXTENSION } = {}) => {
443
+ return {
444
+ name: "typescript",
445
+ extNames: [".ts", ".js"],
446
+ print(...nodes) {
447
+ return print(...nodes);
448
+ },
449
+ parse(file) {
450
+ const extname = extension[file.extname] || void 0;
451
+ const sourceParts = [];
452
+ for (const item of file.sources) {
453
+ const sourceStr = printSource(item);
454
+ if (sourceStr) sourceParts.push(sourceStr.trimEnd());
455
+ }
456
+ const source = sourceParts.join("\n\n");
457
+ const importLines = [];
458
+ for (const item of file.imports) {
459
+ const importPath = item.root ? getRelativePath(item.root, item.path) : item.path;
460
+ importLines.push(printImport({
461
+ name: item.name,
462
+ path: resolveOutputPath(importPath, { extname }, Boolean(item.root)),
463
+ isTypeOnly: item.isTypeOnly,
464
+ isNameSpace: item.isNameSpace
465
+ }));
466
+ }
467
+ const exportLines = [];
468
+ for (const item of file.exports) exportLines.push(printExport({
464
469
  name: item.name,
465
- path: resolveOutputPath(importPath, options, Boolean(item.root)),
470
+ path: resolveOutputPath(item.path, { extname }, true),
466
471
  isTypeOnly: item.isTypeOnly,
467
- isNameSpace: item.isNameSpace
472
+ asAlias: item.asAlias
468
473
  }));
474
+ const importExportBlock = [...importLines, ...exportLines].join("\n");
475
+ return [
476
+ file.banner,
477
+ importExportBlock,
478
+ source,
479
+ file.footer
480
+ ].filter((segment) => Boolean(segment)).map((s) => s.trimEnd()).join("\n\n");
469
481
  }
470
- const exportLines = [];
471
- for (const item of file.exports) exportLines.push(printExport({
472
- name: item.name,
473
- path: resolveOutputPath(item.path, options, true),
474
- isTypeOnly: item.isTypeOnly,
475
- asAlias: item.asAlias
476
- }));
477
- const importExportBlock = [...importLines, ...exportLines].join("\n");
478
- return [
479
- file.banner,
480
- importExportBlock,
481
- source,
482
- file.footer
483
- ].filter((segment) => Boolean(segment)).map((s) => s.trimEnd()).join("\n\n");
484
- }
482
+ };
485
483
  });
486
484
  //#endregion
487
485
  //#region src/parserTsx.ts
488
486
  /**
489
487
  * Kubb parser for `.tsx` and `.jsx` files. Delegates to `parserTs` because the
490
- * TypeScript compiler handles JSX natively via `ScriptKind.TSX`.
488
+ * TypeScript compiler handles JSX natively via `ScriptKind.TSX`, so it shares the
489
+ * same `extension` option.
491
490
  *
492
491
  * Add to the `parsers` array on `defineConfig` when generating components for
493
492
  * React (or any framework that emits JSX).
@@ -499,23 +498,26 @@ const parserTs = defineParser({
499
498
  * import { parserTsx } from '@kubb/parser-ts'
500
499
  *
501
500
  * export default defineConfig({
502
- * input: { path: './petStore.yaml' },
501
+ * input: './petStore.yaml',
503
502
  * output: { path: './src/gen' },
504
503
  * adapter: adapterOas(),
505
- * parsers: [parserTsx],
504
+ * parsers: [parserTsx()],
506
505
  * plugins: [],
507
506
  * })
508
507
  * ```
509
508
  */
510
- const parserTsx = defineParser({
511
- name: "tsx",
512
- extNames: [".tsx", ".jsx"],
513
- print(...nodes) {
514
- return print(...nodes);
515
- },
516
- parse(file, options = { extname: ".tsx" }) {
517
- return parserTs.parse(file, options);
518
- }
509
+ const parserTsx = defineParser((options = {}) => {
510
+ const parser = parserTs(options);
511
+ return {
512
+ name: "tsx",
513
+ extNames: [".tsx", ".jsx"],
514
+ print(...nodes) {
515
+ return print(...nodes);
516
+ },
517
+ parse(file) {
518
+ return parser.parse(file);
519
+ }
520
+ };
519
521
  });
520
522
  //#endregion
521
523
  export { parserTs, parserTsx };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../internals/utils/src/fs.ts","../src/constants.ts","../src/utils.ts","../src/parserTs.ts","../src/parserTsx.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, join, posix, resolve } from 'node:path'\nimport { camelCase } from './casing.ts'\nimport { runtime } from './runtime.ts'\n\n/**\n * Walks up the directory tree from `cwd` (defaults to `process.cwd()`) and\n * returns the absolute path of the nearest `package.json`, or `null` when none\n * is found before reaching the filesystem root.\n *\n * @example\n * ```ts\n * const pkgPath = findPackageJSON('/home/user/project/src') // '/home/user/project/package.json'\n * ```\n */\nexport function findPackageJSON(cwd?: string): string | null {\n let dir = cwd ? resolve(cwd) : process.cwd()\n while (true) {\n const pkgPath = join(dir, 'package.json')\n if (existsSync(pkgPath)) return pkgPath\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\n/**\n * Converts all backslashes to forward slashes.\n * Extended-length Windows paths (`\\\\?\\...`) are left unchanged.\n */\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Resolves to `true` when the file or directory at `path` exists.\n * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.\n *\n * @example\n * ```ts\n * if (await exists('./kubb.config.ts')) {\n * const content = await read('./kubb.config.ts')\n * }\n * ```\n */\nexport async function exists(path: string): Promise<boolean> {\n if (runtime.isBun) {\n return Bun.file(path).exists()\n }\n return access(path).then(\n () => true,\n () => false,\n )\n}\n\n/**\n * Reads the file at `path` as a UTF-8 string.\n * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.\n *\n * @example\n * ```ts\n * const source = await read('./src/Pet.ts')\n * ```\n */\nexport async function read(path: string): Promise<string> {\n if (runtime.isBun) {\n return Bun.file(path).text()\n }\n return readFile(path, { encoding: 'utf8' })\n}\n\ntype WriteOptions = {\n /**\n * When `true`, re-reads the file immediately after writing and throws if the\n * content does not match — useful for catching write failures on unreliable file systems.\n */\n sanity?: boolean\n}\n\n/**\n * Writes `data` to `path`, trimming leading/trailing whitespace before saving.\n * Skips the write when the trimmed content is empty or identical to what is already on disk.\n * Creates any missing parent directories automatically.\n * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.\n *\n * @example\n * ```ts\n * await write('./src/Pet.ts', source) // writes and returns trimmed content\n * await write('./src/Pet.ts', source) // null — file unchanged\n * await write('./src/Pet.ts', ' ') // null — empty content skipped\n * ```\n */\nexport async function write(path: string, data: string, options: WriteOptions = {}): Promise<string | null> {\n const trimmed = data.trim()\n if (trimmed === '') return null\n\n const resolved = resolve(path)\n\n if (runtime.isBun) {\n const file = Bun.file(resolved)\n const oldContent = (await file.exists()) ? await file.text() : null\n if (oldContent === trimmed) return null\n await Bun.write(resolved, trimmed)\n return trimmed\n }\n\n try {\n const oldContent = await readFile(resolved, { encoding: 'utf-8' })\n if (oldContent === trimmed) return null\n } catch {\n /* file doesn't exist yet */\n }\n\n await mkdir(dirname(resolved), { recursive: true })\n await writeFile(resolved, trimmed, { encoding: 'utf-8' })\n\n if (options.sanity) {\n const savedData = await readFile(resolved, { encoding: 'utf-8' })\n if (savedData !== trimmed) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n return savedData\n }\n\n return trimmed\n}\n\n/**\n * Recursively removes `path`. Silently succeeds when `path` does not exist.\n *\n * @example\n * ```ts\n * await clean('./dist')\n * ```\n */\nexport async function clean(path: string): Promise<void> {\n return rm(path, { recursive: true, force: true })\n}\n\n/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","/**\n * Character used for a single indent step. Set to `'\\t'` to emit tab-indented output.\n */\nexport const INDENT_CHAR = ' '\n\n/**\n * Indentation unit prepended once per nesting level when pretty-printing.\n */\nexport const INDENT = INDENT_CHAR.repeat(2)\n\n/**\n * Matches only the final `.<ext>` of a path, so a name like `foo.bar.ts` keeps\n * `foo.bar` and loses just `.ts`.\n */\nexport const FILE_EXTENSION_PATTERN = /\\.[^/.]+$/\n\n/**\n * Matches Windows-style backslash path separators.\n */\nexport const WINDOWS_PATH_SEPARATOR = /\\\\/g\n\n/**\n * Matches `*\\/` in free-form text so JSDoc bodies can neutralize premature\n * comment terminators (`*\\/` → `* /`).\n */\nexport const JSDOC_TERMINATOR_PATTERN = /\\*\\//g\n\n/**\n * Matches carriage returns for normalizing CRLF/CR line endings to LF.\n */\nexport const CARRIAGE_RETURN_PATTERN = /\\r/g\n\n/**\n * Matches CRLF sequences used when normalizing TypeScript printer output.\n */\nexport const CRLF_PATTERN = /\\r\\n/g\n\n/**\n * Matches an identifier that starts with a digit. JavaScript disallows this,\n * so the printer replaces the leading digit with `_`.\n */\nexport const LEADING_DIGIT_PATTERN = /^\\d/\n\n/**\n * Relative path prefix used to detect traversal segments (`../`).\n */\nexport const PARENT_DIRECTORY_PREFIX = '../' as const\n\n/**\n * Relative path prefix used when resolving imports within the output root.\n */\nexport const CURRENT_DIRECTORY_PREFIX = './' as const\n","import { normalize, relative } from 'node:path'\nimport { trimExtName } from '@internals/utils'\nimport type { ArrowFunctionNode, CodeNode, ConstNode, FunctionNode, JSDocNode, JsxNode, SourceNode, TextNode, TypeNode } from '@kubb/ast'\nimport ts from 'typescript'\nimport {\n CARRIAGE_RETURN_PATTERN,\n CRLF_PATTERN,\n CURRENT_DIRECTORY_PREFIX,\n FILE_EXTENSION_PATTERN,\n INDENT,\n INDENT_CHAR,\n JSDOC_TERMINATOR_PATTERN,\n LEADING_DIGIT_PATTERN,\n PARENT_DIRECTORY_PREFIX,\n WINDOWS_PATH_SEPARATOR,\n} from './constants.ts'\n\nconst { factory } = ts\n\n/**\n * Normalizes a file-system path to POSIX separators and strips any leading `../` segment.\n */\nexport function slash(path: string): string {\n return normalize(path).replaceAll(WINDOWS_PATH_SEPARATOR, '/').replace(PARENT_DIRECTORY_PREFIX, '')\n}\n\n/**\n * Resolves `filePath` relative to `rootDir` and returns a POSIX-style path\n * prefixed with `./` when the target sits inside the root, or `../` when it escapes it.\n */\nexport function getRelativePath(rootDir: string, filePath: string): string {\n const rel = relative(rootDir, filePath)\n const slashed = slash(rel)\n return slashed.startsWith(PARENT_DIRECTORY_PREFIX) ? slashed : `${CURRENT_DIRECTORY_PREFIX}${slashed}`\n}\n\n/**\n * Rewrites an import/export path so its extension matches the caller-supplied\n * `options.extname`. When the source path has no extension the original is kept,\n * so virtual/module-only paths flow through unchanged.\n */\nexport function resolveOutputPath(path: string, options: { extname?: string } | undefined, rootAware: boolean): string {\n const hasExtname = FILE_EXTENSION_PATTERN.test(path)\n if (options?.extname && hasExtname) {\n return `${trimExtName(path)}${options.extname}`\n }\n return rootAware ? trimExtName(path) : path\n}\n\n/**\n * Serializes a `nodes` array into source text. Each entry is rendered via {@link printCodeNode}\n * and joined with a single newline. A `Break` node (`<br/>`) inserts one blank line between\n * statements. Consecutive breaks, and breaks at the very start or end, are folded into the\n * separator, so a double `<br/>` never emits more than one blank line.\n */\nexport function printNodes(nodes: Array<CodeNode> | undefined): string {\n if (!nodes || nodes.length === 0) return ''\n\n let result = ''\n let hasContent = false\n let pendingBreak = false\n\n for (const node of nodes) {\n if (node.kind === 'Break') {\n if (hasContent) pendingBreak = true\n continue\n }\n\n const text = printCodeNode(node)\n if (!text) continue\n\n if (hasContent) result += pendingBreak ? '\\n\\n' : '\\n'\n result += text\n hasContent = true\n pendingBreak = false\n }\n\n return result\n}\n\n/**\n * Indents every non-empty line of `text` by one indent unit. Pass a number to repeat\n * {@link INDENT_CHAR} that many times, or a string to use as the indent verbatim.\n */\nexport function indentLines(text: string, indent: number | string = INDENT): string {\n if (!text) return ''\n const pad = typeof indent === 'string' ? indent : INDENT_CHAR.repeat(indent)\n return text\n .split('\\n')\n .map((line) => (line.trim() ? `${pad}${line}` : ''))\n .join('\\n')\n}\n\n/**\n * Removes the common leading whitespace shared by every non-blank line and trims\n * surrounding blank lines, so multi-line content authored inside an indented template\n * literal lines up at a column-zero baseline. Leading whitespace is counted by\n * character, so N tabs and N spaces are treated as the same depth.\n *\n * @example\n * ```ts\n * dedent('\\n foo\\n bar\\n ')\n * // 'foo\\n bar'\n * ```\n */\nexport function dedent(text: string): string {\n if (!text) return ''\n\n const lines = text.split('\\n')\n const isBlank = (line: string) => line.trim() === ''\n\n const start = lines.findIndex((line) => !isBlank(line))\n if (start === -1) return ''\n const end = lines.findLastIndex((line) => !isBlank(line))\n\n const trimmed = lines.slice(start, end + 1)\n const indents = trimmed.filter((line) => !isBlank(line)).map((line) => line.match(/^\\s*/)?.[0].length ?? 0)\n const min = indents.length ? Math.min(...indents) : 0\n\n return trimmed.map((line) => (isBlank(line) ? '' : line.slice(min))).join('\\n')\n}\n\n/**\n * Renders the generic clause (`<T, U>`) shared by function and arrow-function nodes.\n * Accepts either a raw string (rendered verbatim) or an array of type-parameter names.\n */\nexport function formatGenerics(generics: FunctionNode['generics'] | ArrowFunctionNode['generics']): string {\n if (!generics) return ''\n return `<${Array.isArray(generics) ? generics.join(', ') : generics}>`\n}\n\n/**\n * Renders the return-type suffix (`: T` or `: Promise<T>` when `isAsync` is true).\n * Returns an empty string when no return type is provided.\n */\nexport function formatReturnType(returnType: string | null | undefined, isAsync: boolean | null | undefined): string {\n if (!returnType) return ''\n return isAsync ? `: Promise<${returnType}>` : `: ${returnType}`\n}\n\n/**\n * Module-scoped TypeScript printer instance. A printer does not mutate the source file, so one\n * instance is reused across every `print()` call instead of constructing a new printer each time.\n */\nconst TS_PRINTER = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n})\n\n/**\n * Module-scoped source file used as the print target. `printList` only reads the source\n * file's compiler options / language version. It never mutates it.\n */\nconst PRINT_SOURCE_FILE = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n// Pre-warm the printer at module load. The first `printList` call lazily initializes\n// the printer's internal string-builder and identifier tables. Doing it once at import\n// time keeps that cost off the critical path for short-lived CLI builds.\nTS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray([]), PRINT_SOURCE_FILE)\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 filtered = elements.filter(Boolean)\n if (filtered.length === 0) return ''\n\n const output = TS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray(filtered), PRINT_SOURCE_FILE)\n\n return output.replace(CRLF_PATTERN, '\\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(JSDOC_TERMINATOR_PATTERN, '* /').replace(CARRIAGE_RETURN_PATTERN, ''))\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 * Converts a {@link ConstNode} to a TypeScript `const` declaration string.\n *\n * Mirrors the `Const` component from `@kubb/renderer-jsx`.\n *\n * @example\n * ```ts\n * printConst(factory.createConst({ name: 'pet', export: true, nodes: ['{}'] }))\n * // 'export const pet = {}'\n * ```\n *\n * @example With type and `as const`\n * ```ts\n * printConst(factory.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: Array<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/renderer-jsx`.\n *\n * @example\n * ```ts\n * printType(factory.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: Array<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/renderer-jsx`.\n *\n * @example\n * ```ts\n * printFunction(factory.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(factory.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 const body = printNodes(nodes)\n const indented = body ? indentLines(body) : ''\n\n const parts: Array<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(formatGenerics(generics))\n parts.push(`(${params ?? ''})`)\n parts.push(formatReturnType(returnType, isAsync))\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/renderer-jsx`.\n *\n * @example Multi-line arrow function\n * ```ts\n * printArrowFunction(factory.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(factory.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 const body = printNodes(nodes)\n const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\\n${indentLines(body)}\\n}` : ' => {}'\n\n const parts: Array<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(formatGenerics(generics))\n parts.push(`(${params ?? ''})`)\n parts.push(formatReturnType(returnType, isAsync))\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(factory.createConst({ name: 'x', nodes: ['1'] }))\n * // 'const x = 1'\n * ```\n */\nexport function printCodeNode(node: CodeNode): string {\n if (node.kind === 'Break') return ''\n if (node.kind === 'Text') return dedent((node as TextNode).value)\n if (node.kind === 'Jsx') return dedent((node as JsxNode).value)\n if (node.kind === 'Const') return printConst(node)\n if (node.kind === 'Type') return printType(node)\n if (node.kind === 'Function') return printFunction(node)\n if (node.kind === 'ArrowFunction') return printArrowFunction(node)\n return ''\n}\n\n/**\n * Converts a {@link SourceNode} to its TypeScript string representation.\n *\n * Iterates `nodes` in DOM order, rendering each {@link CodeNode} via\n * {@link printCodeNode}.\n *\n * Top-level declarations are separated by a blank line so the source reads\n * cleanly without an external formatter.\n *\n * @example From nodes\n * ```ts\n * printSource({ kind: 'Source', nodes: [factory.createConst({ name: 'x', nodes: [factory.createText('1')] }), factory.createText('x.toString()')] })\n * // 'const x = 1\\n\\nx.toString()'\n * ```\n */\nexport function printSource(node: SourceNode): string {\n const nodes = node.nodes\n\n if (!nodes || nodes.length === 0) return ''\n\n // Imperative join. `map().filter().join()` allocated a closure and two arrays per source, and\n // this runs once per source fragment during printing, so it surfaced in the deopt churn trace.\n let result = ''\n for (const child of nodes) {\n const text = printCodeNode(child as CodeNode)\n if (!text) continue\n result = result ? `${result}\\n\\n${text}` : text\n }\n\n return result\n}\n\n/**\n * Wraps a module specifier in single quotes, escaping any embedded backslash or quote so the emitted\n * statement stays valid even for unusual paths.\n */\nfunction quoteModulePath(path: string): string {\n return `'${path.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`\n}\n\n/**\n * Renders an import declaration string in the repo style (single quotes, no semicolons), covering\n * default, namespace (`* as`), and named imports with `{ a as b }` aliases, each optionally\n * `type`-only. `path` is used verbatim, so resolve it first.\n *\n * @example\n * ```ts\n * printImport({ name: ['z'], path: './zod.ts' })\n * // \"import { z } from './zod.ts'\"\n * ```\n */\nexport function printImport({\n name,\n path,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n isTypeOnly?: boolean | null\n isNameSpace?: boolean | null\n}): string {\n const typePrefix = isTypeOnly ? 'type ' : ''\n const from = quoteModulePath(path)\n\n if (!Array.isArray(name)) {\n if (isNameSpace) return `import ${typePrefix}* as ${name} from ${from}`\n return `import ${typePrefix}${name} from ${from}`\n }\n\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n return item.name ? `${item.propertyName} as ${item.name}` : item.propertyName\n }\n return item\n })\n\n return `import ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`\n}\n\n/**\n * Renders an export declaration string in the repo style (single quotes, no semicolons), covering\n * named re-exports, namespace alias (`* as name`), and wildcard, each optionally `type`-only.\n * `path` is used verbatim, so resolve it first.\n *\n * @example\n * ```ts\n * printExport({ name: ['Pet', 'Order'], path: './models.ts' })\n * // \"export { Pet, Order } from './models.ts'\"\n * ```\n */\nexport function printExport({\n path,\n name,\n isTypeOnly = false,\n asAlias = false,\n}: {\n path: string\n name?: string | Array<ts.Identifier | string> | null\n isTypeOnly?: boolean | null\n asAlias?: boolean | null\n}): string {\n const typePrefix = isTypeOnly ? 'type ' : ''\n const from = quoteModulePath(path)\n\n if (Array.isArray(name)) {\n const specifiers = name.map((item) => (typeof item === 'string' ? item : item.text))\n return `export ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`\n }\n\n if (asAlias && name) {\n const parsedName = LEADING_DIGIT_PATTERN.test(name) ? `_${name.slice(1)}` : name\n return `export ${typePrefix}* as ${parsedName} from ${from}`\n }\n\n if (name) {\n console.warn(`When using name as string, asAlias should be true: ${name}`)\n }\n\n return `export ${typePrefix}* from ${from}`\n}\n","import type { FileNode, SourceNode } from '@kubb/ast'\nimport { defineParser } from '@kubb/core'\nimport type * as ts from 'typescript'\nimport { getRelativePath, print, printExport, printImport, printSource, resolveOutputPath } from './utils.ts'\n\n/**\n * Default Kubb parser for `.ts` and `.js` files. Takes the universal AST\n * produced by an adapter and prints it as TypeScript source using the official\n * TypeScript compiler. Imports and exports are rewritten based on each file's\n * metadata.\n *\n * Used automatically when no `parsers` option is set on `defineConfig`. Use\n * `parserTsx` instead for React projects that emit JSX.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { parserTs } from '@kubb/parser-ts'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * parsers: [parserTs],\n * plugins: [],\n * })\n * ```\n */\nexport const parserTs = defineParser({\n name: 'typescript',\n extNames: ['.ts', '.js'],\n print(...nodes: Array<ts.Node>) {\n return print(...nodes)\n },\n 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.trimEnd())\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importLines: Array<string> = []\n for (const item of (file as FileNode).imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n importLines.push(\n printImport({\n name: item.name as string | Array<string | { propertyName: string; name?: string }>,\n path: resolveOutputPath(importPath, options, Boolean(item.root)),\n isTypeOnly: item.isTypeOnly,\n isNameSpace: item.isNameSpace,\n }),\n )\n }\n\n const exportLines: Array<string> = []\n for (const item of (file as FileNode).exports) {\n exportLines.push(\n printExport({\n name: item.name as string | Array<ts.Identifier | string> | null | undefined,\n path: resolveOutputPath(item.path, options, true),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const importExportBlock = [...importLines, ...exportLines].join('\\n')\n\n const parts = [file.banner, importExportBlock, source, file.footer].filter((segment): segment is string => Boolean(segment)).map((s) => s.trimEnd())\n\n return parts.join('\\n\\n')\n },\n})\n","import { defineParser } from '@kubb/core'\nimport type * as ts from 'typescript'\nimport { parserTs } from './parserTs.ts'\nimport { print } from './utils.ts'\n\n/**\n * Kubb parser for `.tsx` and `.jsx` files. Delegates to `parserTs` because the\n * TypeScript compiler handles JSX natively via `ScriptKind.TSX`.\n *\n * Add to the `parsers` array on `defineConfig` when generating components for\n * React (or any framework that emits JSX).\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { parserTsx } from '@kubb/parser-ts'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * parsers: [parserTsx],\n * plugins: [],\n * })\n * ```\n */\nexport const parserTsx = defineParser({\n name: 'tsx',\n extNames: ['.tsx', '.jsx'],\n print(...nodes: Array<ts.Node>) {\n return print(...nodes)\n },\n parse(file, options = { extname: '.tsx' }) {\n return parserTs.parse(file, options)\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../internals/utils/src/fs.ts","../src/constants.ts","../src/utils.ts","../src/parserTs.ts","../src/parserTsx.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { access, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, join, posix, resolve } from 'node:path'\nimport { camelCase } from './casing.ts'\nimport { runtime } from './runtime.ts'\n\n/**\n * Walks up the directory tree from `cwd` (defaults to `process.cwd()`) and\n * returns the absolute path of the nearest `package.json`, or `null` when none\n * is found before reaching the filesystem root.\n *\n * @example\n * ```ts\n * const pkgPath = findPackageJSON('/home/user/project/src') // '/home/user/project/package.json'\n * ```\n */\nexport function findPackageJSON(cwd?: string): string | null {\n let dir = cwd ? resolve(cwd) : process.cwd()\n while (true) {\n const pkgPath = join(dir, 'package.json')\n if (existsSync(pkgPath)) return pkgPath\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n}\n\n/**\n * Converts all backslashes to forward slashes.\n * Extended-length Windows paths (`\\\\?\\...`) are left unchanged.\n */\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Resolves to `true` when the file or directory at `path` exists.\n * Uses `Bun.file().exists()` when running under Bun, `fs.access` otherwise.\n *\n * @example\n * ```ts\n * if (await exists('./kubb.config.ts')) {\n * const content = await read('./kubb.config.ts')\n * }\n * ```\n */\nexport async function exists(path: string): Promise<boolean> {\n if (runtime.isBun) {\n return Bun.file(path).exists()\n }\n return access(path).then(\n () => true,\n () => false,\n )\n}\n\n/**\n * Reads the file at `path` as a UTF-8 string.\n * Uses `Bun.file().text()` when running under Bun, `fs.readFile` otherwise.\n *\n * @example\n * ```ts\n * const source = await read('./src/Pet.ts')\n * ```\n */\nexport async function read(path: string): Promise<string> {\n if (runtime.isBun) {\n return Bun.file(path).text()\n }\n return readFile(path, { encoding: 'utf8' })\n}\n\ntype WriteOptions = {\n /**\n * When `true`, re-reads the file immediately after writing and throws if the\n * content does not match — useful for catching write failures on unreliable file systems.\n */\n sanity?: boolean\n}\n\n/**\n * Writes `data` to `path`, trimming leading/trailing whitespace before saving.\n * Skips the write when the trimmed content is empty or identical to what is already on disk.\n * Creates any missing parent directories automatically.\n * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.\n *\n * @example\n * ```ts\n * await write('./src/Pet.ts', source) // writes and returns trimmed content\n * await write('./src/Pet.ts', source) // null — file unchanged\n * await write('./src/Pet.ts', ' ') // null — empty content skipped\n * ```\n */\nexport async function write(path: string, data: string, options: WriteOptions = {}): Promise<string | null> {\n const trimmed = data.trim()\n if (trimmed === '') return null\n\n const resolved = resolve(path)\n\n if (runtime.isBun) {\n const file = Bun.file(resolved)\n const oldContent = (await file.exists()) ? await file.text() : null\n if (oldContent === trimmed) return null\n await Bun.write(resolved, trimmed)\n return trimmed\n }\n\n try {\n const oldContent = await readFile(resolved, { encoding: 'utf-8' })\n if (oldContent === trimmed) return null\n } catch {\n /* file doesn't exist yet */\n }\n\n await mkdir(dirname(resolved), { recursive: true })\n await writeFile(resolved, trimmed, { encoding: 'utf-8' })\n\n if (options.sanity) {\n const savedData = await readFile(resolved, { encoding: 'utf-8' })\n if (savedData !== trimmed) {\n throw new Error(`Sanity check failed for ${path}\\n\\nData[${data.length}]:\\n${data}\\n\\nSaved[${savedData.length}]:\\n${savedData}\\n`)\n }\n return savedData\n }\n\n return trimmed\n}\n\n/**\n * Recursively removes `path`. Silently succeeds when `path` does not exist.\n *\n * @example\n * ```ts\n * await clean('./dist')\n * ```\n */\nexport async function clean(path: string): Promise<void> {\n return rm(path, { recursive: true, force: true })\n}\n\n/**\n * Converts a filesystem path to use POSIX (`/`) separators.\n *\n * Most of the codebase compares and composes paths as strings (prefix matching, joining for\n * import specifiers, splitting on `/`). On POSIX `path.resolve` already returns `/`-separated\n * paths, but on Windows it returns `\\`-separated paths, which breaks every such comparison.\n *\n * Routing every path that crosses a module boundary through `toPosixPath` keeps the rest of the\n * code platform-agnostic. The conversion runs unconditionally so Windows-specific behavior is\n * exercisable from POSIX CI.\n *\n * @example\n * toPosixPath('C:\\\\repo\\\\src\\\\pet.ts') // 'C:/repo/src/pet.ts'\n */\nexport function toPosixPath(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","/**\n * Character used for a single indent step. Set to `'\\t'` to emit tab-indented output.\n */\nexport const INDENT_CHAR = ' '\n\n/**\n * Indentation unit prepended once per nesting level when pretty-printing.\n */\nexport const INDENT = INDENT_CHAR.repeat(2)\n\n/**\n * Matches only the final `.<ext>` of a path, so a name like `foo.bar.ts` keeps\n * `foo.bar` and loses just `.ts`.\n */\nexport const FILE_EXTENSION_PATTERN = /\\.[^/.]+$/\n\n/**\n * Matches Windows-style backslash path separators.\n */\nexport const WINDOWS_PATH_SEPARATOR = /\\\\/g\n\n/**\n * Matches `*\\/` in free-form text so JSDoc bodies can neutralize premature\n * comment terminators (`*\\/` → `* /`).\n */\nexport const JSDOC_TERMINATOR_PATTERN = /\\*\\//g\n\n/**\n * Matches carriage returns for normalizing CRLF/CR line endings to LF.\n */\nexport const CARRIAGE_RETURN_PATTERN = /\\r/g\n\n/**\n * Matches CRLF sequences used when normalizing TypeScript printer output.\n */\nexport const CRLF_PATTERN = /\\r\\n/g\n\n/**\n * Matches an identifier that starts with a digit. JavaScript disallows this,\n * so the printer replaces the leading digit with `_`.\n */\nexport const LEADING_DIGIT_PATTERN = /^\\d/\n\n/**\n * Relative path prefix used to detect traversal segments (`../`).\n */\nexport const PARENT_DIRECTORY_PREFIX = '../' as const\n\n/**\n * Relative path prefix used when resolving imports within the output root.\n */\nexport const CURRENT_DIRECTORY_PREFIX = './' as const\n","import { normalize, relative } from 'node:path'\nimport { trimExtName } from '@internals/utils'\nimport type { ArrowFunctionNode, CodeNode, ConstNode, FunctionNode, JSDocNode, JsxNode, SourceNode, TextNode, TypeNode } from '@kubb/ast'\nimport ts from 'typescript'\nimport {\n CARRIAGE_RETURN_PATTERN,\n CRLF_PATTERN,\n CURRENT_DIRECTORY_PREFIX,\n FILE_EXTENSION_PATTERN,\n INDENT,\n INDENT_CHAR,\n JSDOC_TERMINATOR_PATTERN,\n LEADING_DIGIT_PATTERN,\n PARENT_DIRECTORY_PREFIX,\n WINDOWS_PATH_SEPARATOR,\n} from './constants.ts'\n\nconst { factory } = ts\n\n/**\n * Resolves `filePath` relative to `rootDir` and returns a POSIX-style path\n * prefixed with `./` when the target sits inside the root, or `../` when it escapes it.\n */\nexport function getRelativePath(rootDir: string, filePath: string): string {\n const rel = relative(rootDir, filePath)\n const slashed = normalize(rel).replaceAll(WINDOWS_PATH_SEPARATOR, '/').replace(PARENT_DIRECTORY_PREFIX, '')\n return slashed.startsWith(PARENT_DIRECTORY_PREFIX) ? slashed : `${CURRENT_DIRECTORY_PREFIX}${slashed}`\n}\n\n/**\n * Rewrites an import/export path so its extension matches the caller-supplied\n * `options.extname`. When the source path has no extension the original is kept,\n * so virtual/module-only paths flow through unchanged.\n */\nexport function resolveOutputPath(path: string, options: { extname?: string } | undefined, rootAware: boolean): string {\n const hasExtname = FILE_EXTENSION_PATTERN.test(path)\n if (options?.extname && hasExtname) {\n return `${trimExtName(path)}${options.extname}`\n }\n return rootAware ? trimExtName(path) : path\n}\n\n/**\n * Serializes a `nodes` array into source text. Each entry is rendered via {@link printCodeNode}\n * and joined with a single newline. A `Break` node (`<br/>`) inserts one blank line between\n * statements. Consecutive breaks, and breaks at the very start or end, are folded into the\n * separator, so a double `<br/>` never emits more than one blank line.\n */\nexport function printNodes(nodes: Array<CodeNode> | undefined): string {\n if (!nodes || nodes.length === 0) return ''\n\n let result = ''\n let hasContent = false\n let pendingBreak = false\n\n for (const node of nodes) {\n if (node.kind === 'Break') {\n if (hasContent) pendingBreak = true\n continue\n }\n\n const text = printCodeNode(node)\n if (!text) continue\n\n if (hasContent) result += pendingBreak ? '\\n\\n' : '\\n'\n result += text\n hasContent = true\n pendingBreak = false\n }\n\n return result\n}\n\n/**\n * Indents every non-empty line of `text` by one indent unit. Pass a number to repeat\n * {@link INDENT_CHAR} that many times, or a string to use as the indent verbatim.\n */\nexport function indentLines(text: string, indent: number | string = INDENT): string {\n if (!text) return ''\n const pad = typeof indent === 'string' ? indent : INDENT_CHAR.repeat(indent)\n return text\n .split('\\n')\n .map((line) => (line.trim() ? `${pad}${line}` : ''))\n .join('\\n')\n}\n\n/**\n * Removes the common leading whitespace shared by every non-blank line and trims\n * surrounding blank lines, so multi-line content authored inside an indented template\n * literal lines up at a column-zero baseline. Leading whitespace is counted by\n * character, so N tabs and N spaces are treated as the same depth.\n *\n * @example\n * ```ts\n * dedent('\\n foo\\n bar\\n ')\n * // 'foo\\n bar'\n * ```\n */\nexport function dedent(text: string): string {\n if (!text) return ''\n\n const lines = text.split('\\n')\n const isBlank = (line: string) => line.trim() === ''\n\n const start = lines.findIndex((line) => !isBlank(line))\n if (start === -1) return ''\n const end = lines.findLastIndex((line) => !isBlank(line))\n\n const trimmed = lines.slice(start, end + 1)\n const indents = trimmed.filter((line) => !isBlank(line)).map((line) => line.match(/^\\s*/)?.[0].length ?? 0)\n const min = indents.length ? Math.min(...indents) : 0\n\n return trimmed.map((line) => (isBlank(line) ? '' : line.slice(min))).join('\\n')\n}\n\n/**\n * Renders the generic clause (`<T, U>`) shared by function and arrow-function nodes.\n * Accepts either a raw string (rendered verbatim) or an array of type-parameter names.\n */\nexport function formatGenerics(generics: FunctionNode['generics'] | ArrowFunctionNode['generics']): string {\n if (!generics) return ''\n return `<${Array.isArray(generics) ? generics.join(', ') : generics}>`\n}\n\n/**\n * Renders the return-type suffix (`: T` or `: Promise<T>` when `isAsync` is true).\n * Returns an empty string when no return type is provided.\n */\nexport function formatReturnType(returnType: string | null | undefined, isAsync: boolean | null | undefined): string {\n if (!returnType) return ''\n return isAsync ? `: Promise<${returnType}>` : `: ${returnType}`\n}\n\n/**\n * Module-scoped TypeScript printer instance. A printer does not mutate the source file, so one\n * instance is reused across every `print()` call instead of constructing a new printer each time.\n */\nconst TS_PRINTER = ts.createPrinter({\n omitTrailingSemicolon: true,\n newLine: ts.NewLineKind.LineFeed,\n removeComments: false,\n noEmitHelpers: true,\n})\n\n/**\n * Module-scoped source file used as the print target. `printList` only reads the source\n * file's compiler options / language version. It never mutates it.\n */\nconst PRINT_SOURCE_FILE = ts.createSourceFile('print.tsx', '', ts.ScriptTarget.ES2022, true, ts.ScriptKind.TSX)\n\n// Pre-warm the printer at module load. The first `printList` call lazily initializes\n// the printer's internal string-builder and identifier tables. Doing it once at import\n// time keeps that cost off the critical path for short-lived CLI builds.\nTS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray([]), PRINT_SOURCE_FILE)\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 filtered = elements.filter(Boolean)\n if (filtered.length === 0) return ''\n\n const output = TS_PRINTER.printList(ts.ListFormat.MultiLine, factory.createNodeArray(filtered), PRINT_SOURCE_FILE)\n\n return output.replace(CRLF_PATTERN, '\\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(JSDOC_TERMINATOR_PATTERN, '* /').replace(CARRIAGE_RETURN_PATTERN, ''))\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 * Converts a {@link ConstNode} to a TypeScript `const` declaration string.\n *\n * Mirrors the `Const` component from `@kubb/renderer-jsx`.\n *\n * @example\n * ```ts\n * printConst(factory.createConst({ name: 'pet', export: true, nodes: ['{}'] }))\n * // 'export const pet = {}'\n * ```\n *\n * @example With type and `as const`\n * ```ts\n * printConst(factory.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: Array<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/renderer-jsx`.\n *\n * @example\n * ```ts\n * printType(factory.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: Array<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/renderer-jsx`.\n *\n * @example\n * ```ts\n * printFunction(factory.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(factory.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 const body = printNodes(nodes)\n const indented = body ? indentLines(body) : ''\n\n const parts: Array<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(formatGenerics(generics))\n parts.push(`(${params ?? ''})`)\n parts.push(formatReturnType(returnType, isAsync))\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/renderer-jsx`.\n *\n * @example Multi-line arrow function\n * ```ts\n * printArrowFunction(factory.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(factory.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 const body = printNodes(nodes)\n const arrowBody = singleLine ? ` => ${body}` : body ? ` => {\\n${indentLines(body)}\\n}` : ' => {}'\n\n const parts: Array<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(formatGenerics(generics))\n parts.push(`(${params ?? ''})`)\n parts.push(formatReturnType(returnType, isAsync))\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(factory.createConst({ name: 'x', nodes: ['1'] }))\n * // 'const x = 1'\n * ```\n */\nexport function printCodeNode(node: CodeNode): string {\n if (node.kind === 'Break') return ''\n if (node.kind === 'Text') return dedent((node as TextNode).value)\n if (node.kind === 'Jsx') return dedent((node as JsxNode).value)\n if (node.kind === 'Const') return printConst(node)\n if (node.kind === 'Type') return printType(node)\n if (node.kind === 'Function') return printFunction(node)\n if (node.kind === 'ArrowFunction') return printArrowFunction(node)\n return ''\n}\n\n/**\n * Converts a {@link SourceNode} to its TypeScript string representation.\n *\n * Iterates `nodes` in DOM order, rendering each {@link CodeNode} via\n * {@link printCodeNode}.\n *\n * Top-level declarations are separated by a blank line so the source reads\n * cleanly without an external formatter.\n *\n * @example From nodes\n * ```ts\n * printSource({ kind: 'Source', nodes: [factory.createConst({ name: 'x', nodes: [factory.createText('1')] }), factory.createText('x.toString()')] })\n * // 'const x = 1\\n\\nx.toString()'\n * ```\n */\nexport function printSource(node: SourceNode): string {\n const nodes = node.nodes\n\n if (!nodes || nodes.length === 0) return ''\n\n // Imperative join. `map().filter().join()` allocated a closure and two arrays per source, and\n // this runs once per source fragment during printing, so it surfaced in the deopt churn trace.\n let result = ''\n for (const child of nodes) {\n const text = printCodeNode(child as CodeNode)\n if (!text) continue\n result = result ? `${result}\\n\\n${text}` : text\n }\n\n return result\n}\n\n/**\n * Wraps a module specifier in single quotes, escaping any embedded backslash or quote so the emitted\n * statement stays valid even for unusual paths.\n */\nfunction quoteModulePath(path: string): string {\n return `'${path.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`\n}\n\n/**\n * Renders an import declaration string in the repo style (single quotes, no semicolons), covering\n * default, namespace (`* as`), and named imports with `{ a as b }` aliases, each optionally\n * `type`-only. `path` is used verbatim, so resolve it first.\n *\n * @example\n * ```ts\n * printImport({ name: ['z'], path: './zod.ts' })\n * // \"import { z } from './zod.ts'\"\n * ```\n */\nexport function printImport({\n name,\n path,\n isTypeOnly = false,\n isNameSpace = false,\n}: {\n name: string | Array<string | { propertyName: string; name?: string }>\n path: string\n isTypeOnly?: boolean | null\n isNameSpace?: boolean | null\n}): string {\n const typePrefix = isTypeOnly ? 'type ' : ''\n const from = quoteModulePath(path)\n\n if (!Array.isArray(name)) {\n if (isNameSpace) return `import ${typePrefix}* as ${name} from ${from}`\n return `import ${typePrefix}${name} from ${from}`\n }\n\n const specifiers = name.map((item) => {\n if (typeof item === 'object') {\n return item.name ? `${item.propertyName} as ${item.name}` : item.propertyName\n }\n return item\n })\n\n return `import ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`\n}\n\n/**\n * Renders an export declaration string in the repo style (single quotes, no semicolons), covering\n * named re-exports, namespace alias (`* as name`), and wildcard, each optionally `type`-only.\n * `path` is used verbatim, so resolve it first.\n *\n * @example\n * ```ts\n * printExport({ name: ['Pet', 'Order'], path: './models.ts' })\n * // \"export { Pet, Order } from './models.ts'\"\n * ```\n */\nexport function printExport({\n path,\n name,\n isTypeOnly = false,\n asAlias = false,\n}: {\n path: string\n name?: string | Array<ts.Identifier | string> | null\n isTypeOnly?: boolean | null\n asAlias?: boolean | null\n}): string {\n const typePrefix = isTypeOnly ? 'type ' : ''\n const from = quoteModulePath(path)\n\n if (Array.isArray(name)) {\n const specifiers = name.map((item) => (typeof item === 'string' ? item : item.text))\n return `export ${typePrefix}{ ${specifiers.join(', ')} } from ${from}`\n }\n\n if (asAlias && name) {\n const parsedName = LEADING_DIGIT_PATTERN.test(name) ? `_${name.slice(1)}` : name\n return `export ${typePrefix}* as ${parsedName} from ${from}`\n }\n\n if (name) {\n console.warn(`When using name as string, asAlias should be true: ${name}`)\n }\n\n return `export ${typePrefix}* from ${from}`\n}\n","import type { FileNode, SourceNode } from '@kubb/ast'\nimport { defineParser } from '@kubb/core'\nimport type * as ts from 'typescript'\nimport { getRelativePath, print, printExport, printImport, printSource, resolveOutputPath } from './utils.ts'\n\nconst DEFAULT_EXTENSION: Record<FileNode['extname'], FileNode['extname'] | ''> = { '.ts': '.ts' }\n\n/**\n * Options accepted by `parserTs` and `parserTsx`.\n */\nexport type ParserTsOptions = {\n /**\n * Rewrite the extensions emitted in `import`/`export` statements, e.g. emit `.js` imports from\n * `.ts` sources for ESM dual packages. Keys are the source extension, values the output, and `''`\n * drops it. Only the module-specifier string changes, never the on-disk filename.\n *\n * @default { '.ts': '.ts' }\n * @example\n * ```ts\n * parserTs({ extension: { '.ts': '.js' } }) // import './api.js' instead of './api.ts'\n * parserTs({ extension: { '.ts': '', '.tsx': '.jsx' } })\n * ```\n */\n extension?: Record<FileNode['extname'], FileNode['extname'] | ''>\n}\n\n/**\n * Default Kubb parser for `.ts` and `.js` files. Takes the universal AST\n * produced by an adapter and prints it as TypeScript source using the official\n * TypeScript compiler. Imports and exports are rewritten based on each file's\n * metadata and the `extension` option.\n *\n * Used automatically when no `parsers` option is set on `defineConfig`. Use\n * `parserTsx` instead for React projects that emit JSX.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { parserTs } from '@kubb/parser-ts'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * parsers: [parserTs()],\n * plugins: [],\n * })\n * ```\n */\nexport const parserTs = defineParser<ParserTsOptions>(({ extension = DEFAULT_EXTENSION } = {}) => {\n return {\n name: 'typescript',\n extNames: ['.ts', '.js'],\n print(...nodes: Array<ts.Node>) {\n return print(...nodes)\n },\n parse(file) {\n const extname = extension[file.extname] || undefined\n\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.trimEnd())\n }\n }\n const source = sourceParts.join('\\n\\n')\n\n const importLines: Array<string> = []\n for (const item of (file as FileNode).imports) {\n const importPath = item.root ? getRelativePath(item.root, item.path) : item.path\n importLines.push(\n printImport({\n name: item.name as string | Array<string | { propertyName: string; name?: string }>,\n path: resolveOutputPath(importPath, { extname }, Boolean(item.root)),\n isTypeOnly: item.isTypeOnly,\n isNameSpace: item.isNameSpace,\n }),\n )\n }\n\n const exportLines: Array<string> = []\n for (const item of (file as FileNode).exports) {\n exportLines.push(\n printExport({\n name: item.name as string | Array<ts.Identifier | string> | null | undefined,\n path: resolveOutputPath(item.path, { extname }, true),\n isTypeOnly: item.isTypeOnly,\n asAlias: item.asAlias,\n }),\n )\n }\n\n const importExportBlock = [...importLines, ...exportLines].join('\\n')\n\n const parts = [file.banner, importExportBlock, source, file.footer].filter((segment): segment is string => Boolean(segment)).map((s) => s.trimEnd())\n\n return parts.join('\\n\\n')\n },\n }\n})\n","import { defineParser } from '@kubb/core'\nimport type * as ts from 'typescript'\nimport { parserTs, type ParserTsOptions } from './parserTs.ts'\nimport { print } from './utils.ts'\n\n/**\n * Kubb parser for `.tsx` and `.jsx` files. Delegates to `parserTs` because the\n * TypeScript compiler handles JSX natively via `ScriptKind.TSX`, so it shares the\n * same `extension` option.\n *\n * Add to the `parsers` array on `defineConfig` when generating components for\n * React (or any framework that emits JSX).\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { adapterOas } from '@kubb/adapter-oas'\n * import { parserTsx } from '@kubb/parser-ts'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * adapter: adapterOas(),\n * parsers: [parserTsx()],\n * plugins: [],\n * })\n * ```\n */\nexport const parserTsx = defineParser<ParserTsOptions>((options = {}) => {\n const parser = parserTs(options)\n\n return {\n name: 'tsx',\n extNames: ['.tsx', '.jsx'],\n print(...nodes: Array<ts.Node>) {\n return print(...nodes)\n },\n parse(file) {\n return parser.parse(file)\n },\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-beta.89",
3
+ "version": "5.0.0-beta.91",
4
4
  "description": "TypeScript and TSX source file parser for Kubb. Converts AST nodes into formatted source strings using the TypeScript compiler API.",
5
5
  "keywords": [
6
6
  "codegen",
@@ -41,11 +41,11 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "typescript": "^6.0.3",
44
- "@kubb/core": "5.0.0-beta.89"
44
+ "@kubb/core": "5.0.0-beta.91"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@internals/utils": "0.0.0",
48
- "@kubb/ast": "5.0.0-beta.89"
48
+ "@kubb/ast": "5.0.0-beta.91"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=22"