@hey-api/codegen-core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Hey API
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ <div align="center">
2
+ <img alt="Three people building a brick structure" height="214" src="https://heyapi.dev/images/bricks-640w.png" width="320">
3
+ <h1 align="center"><b>Codegen Core</b></h1>
4
+ <p align="center">🧱 TypeScript framework for generating structured, multi-file source code from abstract syntax trees.</p>
5
+ </div>
6
+
7
+ <br/>
8
+
9
+ <p align="center">
10
+ <a href="https://opensource.org/license/mit" rel="nofollow"><img src="https://img.shields.io/github/license/hey-api/openapi-ts" alt="MIT License"></a>
11
+ <a href="https://github.com/hey-api/openapi-ts/actions?query=branch%3Amain"><img src="https://github.com/hey-api/openapi-ts/actions/workflows/ci.yml/badge.svg?event=push&branch=main" alt="CI status" /></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://github.com/hey-api/openapi-ts/issues">Issues</a>
16
+ <span>&nbsp;•&nbsp;</span>
17
+ <a href="https://heyapi.dev/openapi-ts/community/contributing">Contribute</a>
18
+ <span>&nbsp;•&nbsp;</span>
19
+ <a href="https://heyapi.dev/openapi-ts/community/spotlight#core-team">Join Core Team</a>
20
+ </p>
21
+
22
+ <br/>
23
+
24
+ ## Dashboard
25
+
26
+ Hey API is an ecosystem of products helping you build better APIs. Superpower your codegen and APIs with Hey API Platform.
27
+
28
+ [Sign In](https://app.heyapi.dev) to Hey API Platform.
29
+
30
+ ## Contributing
31
+
32
+ Want to see your code in products used by millions?
33
+
34
+ Start with our [Contributing](https://heyapi.dev/openapi-ts/community/contributing) guide and release your first feature.
35
+
36
+ ## Sponsors
37
+
38
+ Help Hey API stay around for the long haul by becoming a [sponsor](https://github.com/sponsors/hey-api).
39
+
40
+ <h3 align="center">Gold</h3>
41
+
42
+ <table align="center" style="justify-content: center;align-items: center;display: flex;">
43
+ <tbody>
44
+ <tr>
45
+ <td align="center">
46
+ <p></p>
47
+ <p>
48
+ <a href="https://kutt.it/pkEZyc" target="_blank">
49
+ <picture height="50px">
50
+ <source media="(prefers-color-scheme: dark)" srcset="https://heyapi.dev/images/stainless-logo-wordmark-480w.jpeg">
51
+ <img alt="Stainless logo" height="50px" src="https://heyapi.dev/images/stainless-logo-wordmark-480w.jpeg">
52
+ </picture>
53
+ </a>
54
+ <br/>
55
+ Best-in-class SDKs and MCP for your API.
56
+ <br/>
57
+ <a href="https://kutt.it/pkEZyc" style="text-decoration:none;" target="_blank">
58
+ stainless.com
59
+ </a>
60
+ </p>
61
+ <p></p>
62
+ </td>
63
+ </tr>
64
+ </tbody>
65
+ </table>
66
+
67
+ <h3 align="center">Silver</h3>
68
+
69
+ <table align="center" style="justify-content: center;align-items: center;display: flex;">
70
+ <tbody>
71
+ <tr>
72
+ <td align="center">
73
+ <a href="https://kutt.it/skQUVd" target="_blank">
74
+ <picture height="40px">
75
+ <source media="(prefers-color-scheme: dark)" srcset="https://heyapi.dev/images/scalar-logo-wordmark-480w.jpeg">
76
+ <img alt="Scalar logo" height="40px" src="https://heyapi.dev/scalar-logo-wordmark.svg">
77
+ </picture>
78
+ </a>
79
+ <br/>
80
+ <a href="https://kutt.it/skQUVd" style="text-decoration:none;" target="_blank">
81
+ scalar.com
82
+ </a>
83
+ </td>
84
+ <td align="center">
85
+ <a href="https://kutt.it/Dr9GuW" target="_blank">
86
+ <picture height="40px">
87
+ <img alt="FastAPI logo" height="40px" src="https://heyapi.dev/fastapi-logo-wordmark.svg">
88
+ </picture>
89
+ </a>
90
+ <br/>
91
+ <a href="https://kutt.it/Dr9GuW" style="text-decoration:none;" target="_blank">
92
+ fastapi.tiangolo.com
93
+ </a>
94
+ </td>
95
+ </tr>
96
+ </tbody>
97
+ </table>
98
+
99
+ <h3 align="center">Bronze</h3>
100
+
101
+ <table align="center" style="justify-content: center;align-items: center;display: flex;">
102
+ <tbody>
103
+ <tr>
104
+ <td align="center">
105
+ <a href="https://kutt.it/YpaKsX" target="_blank">
106
+ <picture height="34px">
107
+ <source media="(prefers-color-scheme: dark)" srcset="https://heyapi.dev/images/kinde-logo-wordmark-dark-480w.webp">
108
+ <img alt="Kinde logo" height="34px" src="https://heyapi.dev/images/kinde-logo-wordmark-480w.jpeg">
109
+ </picture>
110
+ </a>
111
+ </td>
112
+ <td align="center">
113
+ <a href="https://kutt.it/KkqSaw" target="_blank">
114
+ <picture height="34px">
115
+ <source media="(prefers-color-scheme: dark)" srcset="https://heyapi.dev/images/cella-logo-wordmark-480w.webp">
116
+ <img alt="Cella logo" height="34px" src="https://heyapi.dev/cella-logo-wordmark.svg">
117
+ </picture>
118
+ </a>
119
+ </td>
120
+ </tr>
121
+ </tbody>
122
+ </table>
123
+
124
+ ## License
125
+
126
+ Released under the [MIT License](https://github.com/hey-api/openapi-ts/blob/main/LICENSE.md).
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var s=require('path');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var s__default=/*#__PURE__*/_interopDefault(s);var i=class d{constructor(e,t={}){this.path=e;this.meta=t;let r=d.pathToFilePath(e);t.path&&(typeof t.path=="function"?r=t.path(r):r=t.path.replace("{{path}}",r)),this.path=r;}cache={};state={exports:new Map,imports:new Map,symbols:new Map};addExport(e){return this.addImportExport(e,"exports")}addImport(e){return this.addImportExport(e,"imports")}addImportExport(e,t){let r=typeof e.from=="string"?e.from:e.from.path,o=this.state[t].get(r);o?(this.mergeImportExportValues(o,e),this.state[t].set(r,o)):this.state[t].set(r,{...e}),this.cache[t]=void 0;}addSymbol(e){let t=e.name,r=this.state.symbols.get(t);r?(r.value=e.value,this.state.symbols.set(t,r)):this.state.symbols.set(t,{...e}),this.cache.symbols=void 0;}get exports(){return this.cache.exports||(this.cache.exports=Array.from(this.state.exports.values())),this.cache.exports}getAllSymbols(){return [...this.symbols,...this.imports.flatMap(e=>(e.names??[]).map(t=>({name:e.aliases?.[t]??t}))),...this.exports.flatMap(e=>(e.names??[]).map(t=>({name:e.aliases?.[t]??t})))]}hasContent(){return this.state.symbols.size>0||this.state.exports.size>0}hasSymbol(e){return this.state.symbols.has(e)}get imports(){return this.cache.imports||(this.cache.imports=Array.from(this.state.imports.values())),this.cache.imports}mergeImportExportValues(e,t){e.aliases={...e.aliases,...t.aliases},t.defaultImport!==void 0&&(e.defaultImport=t.defaultImport),e.names=[...new Set([...e.names??[],...t.names??[]])],t.namespaceImport!==void 0&&(e.namespaceImport=t.namespaceImport),t.typeDefaultImport!==void 0&&(e.typeDefaultImport=t.typeDefaultImport),e.typeNames=[...new Set([...e.typeNames??[],...t.typeNames??[]])],t.typeNamespaceImport!==void 0&&(e.typeNamespaceImport=t.typeNamespaceImport);}static pathToFilePath(e){return e.includes("/")?e.split("/").filter(Boolean).join(s__default.default.sep):e.includes("\\")?e.split("\\").filter(Boolean).join(s__default.default.sep):e.split(s__default.default.sep).filter(Boolean).join(s__default.default.sep)}relativePathFromFile(e){let t=s__default.default.posix.relative(s__default.default.posix.dirname(e.path),this.path);return t.startsWith(".")||(t=`./${t}`),t}relativePathToFile(e){let t=s__default.default.posix.relative(s__default.default.posix.dirname(this.path),e.path);return t.startsWith(".")||(t=`./${t}`),t}get symbols(){return this.cache.symbols||(this.cache.symbols=Array.from(this.state.symbols.values())),this.cache.symbols}};var a=class{filesMap=new Map;filesOrder=[];renderers=new Map;addExportToFile(e,t){this.ensureFile(e).addExport(t);}addImportToFile(e,t){this.ensureFile(e).addImport(t);}addSymbolToFile(e,t){this.ensureFile(e).addSymbol(t);}createFile(e,t={}){let{renderer:r,...o}=t;r&&this.ensureRenderer(r);let n=this.getFileByPath(e);if(n)return r?.id&&r.id!==n.meta.renderer&&(n.meta.renderer=r.id),n;let p=new i(e,{...o,renderer:r?.id});return this.filesOrder.push(p),this.filesMap.set(e,p),p}ensureFile(e){if(typeof e!="string")return e;let t=this.getFileByPath(e);return t||this.createFile(e)}ensureRenderer(e){return this.renderers.has(e.id)||this.renderers.set(e.id,e),this.renderers.get(e.id)}get files(){return [...this.filesOrder]}getAllSymbols(){return this.filesOrder.flatMap(e=>e.getAllSymbols())}getFileByPath(e){return this.filesMap.get(e)}render(e){let t=[];for(let r of this.filesOrder){if(!r.meta.renderer)continue;let o=this.renderers.get(r.meta.renderer);o&&t.push(o.render(r,e));}return t}};exports.CodegenFile=i;exports.CodegenProject=a;//# sourceMappingURL=index.cjs.map
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/files/file.ts","../src/project/project.ts"],"names":["CodegenFile","_CodegenFile","path","meta","filePath","exp","imp","value","field","key","existing","symbol","name","target","source","file","relativePath","CodegenProject","fileOrPath","renderer","metadata","existingFile","results"],"mappings":"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","file":"index.cjs","sourcesContent":["import path from 'node:path';\n\nimport type { ICodegenImport } from '../imports/types';\nimport type { ICodegenSymbol } from '../symbols/types';\nimport type { ICodegenFile } from './types';\n\nexport class CodegenFile implements ICodegenFile {\n private cache: {\n exports?: ReadonlyArray<ICodegenImport>;\n imports?: ReadonlyArray<ICodegenImport>;\n symbols?: ReadonlyArray<ICodegenSymbol>;\n } = {};\n\n private state: {\n exports: Map<string, ICodegenImport>;\n imports: Map<string, ICodegenImport>;\n symbols: Map<string, ICodegenSymbol>;\n } = {\n exports: new Map(),\n imports: new Map(),\n symbols: new Map(),\n };\n\n constructor(\n public path: string,\n public meta: ICodegenFile['meta'] = {},\n ) {\n let filePath = CodegenFile.pathToFilePath(path);\n if (meta.path) {\n if (typeof meta.path === 'function') {\n filePath = meta.path(filePath);\n } else {\n filePath = meta.path.replace('{{path}}', filePath);\n }\n }\n this.path = filePath;\n }\n\n addExport(exp: ICodegenImport): void {\n return this.addImportExport(exp, 'exports');\n }\n\n addImport(imp: ICodegenImport): void {\n return this.addImportExport(imp, 'imports');\n }\n\n private addImportExport(\n value: ICodegenImport,\n field: 'exports' | 'imports',\n ): void {\n const key = typeof value.from === 'string' ? value.from : value.from.path;\n const existing = this.state[field].get(key);\n if (existing) {\n this.mergeImportExportValues(existing, value);\n this.state[field].set(key, existing);\n } else {\n this.state[field].set(key, { ...value }); // clone to avoid mutation\n }\n this.cache[field] = undefined;\n }\n\n addSymbol(symbol: ICodegenSymbol): void {\n const key = symbol.name;\n const existing = this.state.symbols.get(key);\n if (existing) {\n existing.value = symbol.value;\n this.state.symbols.set(key, existing);\n } else {\n this.state.symbols.set(key, { ...symbol }); // clone to avoid mutation\n }\n this.cache.symbols = undefined;\n }\n\n get exports(): ReadonlyArray<ICodegenImport> {\n if (!this.cache.exports) {\n this.cache.exports = Array.from(this.state.exports.values());\n }\n return this.cache.exports;\n }\n\n getAllSymbols(): ReadonlyArray<ICodegenSymbol> {\n return [\n ...this.symbols,\n ...this.imports.flatMap((imp) =>\n (imp.names ?? []).map((name) => ({\n name: imp.aliases?.[name] ?? name,\n })),\n ),\n ...this.exports.flatMap((imp) =>\n (imp.names ?? []).map((name) => ({\n name: imp.aliases?.[name] ?? name,\n })),\n ),\n ];\n }\n\n hasContent(): boolean {\n return this.state.symbols.size > 0 || this.state.exports.size > 0;\n }\n\n hasSymbol(name: string): boolean {\n return this.state.symbols.has(name);\n }\n\n get imports(): ReadonlyArray<ICodegenImport> {\n if (!this.cache.imports) {\n this.cache.imports = Array.from(this.state.imports.values());\n }\n return this.cache.imports;\n }\n\n private mergeImportExportValues(\n target: ICodegenImport,\n source: ICodegenImport,\n ): void {\n target.aliases = { ...target.aliases, ...source.aliases };\n if (source.defaultImport !== undefined) {\n target.defaultImport = source.defaultImport;\n }\n target.names = [\n ...new Set([...(target.names ?? []), ...(source.names ?? [])]),\n ];\n if (source.namespaceImport !== undefined) {\n target.namespaceImport = source.namespaceImport;\n }\n if (source.typeDefaultImport !== undefined) {\n target.typeDefaultImport = source.typeDefaultImport;\n }\n target.typeNames = [\n ...new Set([...(target.typeNames ?? []), ...(source.typeNames ?? [])]),\n ];\n if (source.typeNamespaceImport !== undefined) {\n target.typeNamespaceImport = source.typeNamespaceImport;\n }\n }\n\n static pathToFilePath(source: string): string {\n if (source.includes('/')) {\n return source.split('/').filter(Boolean).join(path.sep);\n }\n if (source.includes('\\\\')) {\n return source.split('\\\\').filter(Boolean).join(path.sep);\n }\n return source.split(path.sep).filter(Boolean).join(path.sep);\n }\n\n relativePathFromFile(file: Pick<ICodegenFile, 'path'>): string {\n let relativePath = path.posix.relative(\n path.posix.dirname(file.path),\n this.path,\n );\n if (!relativePath.startsWith('.')) {\n relativePath = `./${relativePath}`;\n }\n return relativePath;\n }\n\n relativePathToFile(file: Pick<ICodegenFile, 'path'>): string {\n let relativePath = path.posix.relative(\n path.posix.dirname(this.path),\n file.path,\n );\n if (!relativePath.startsWith('.')) {\n relativePath = `./${relativePath}`;\n }\n return relativePath;\n }\n\n get symbols(): ReadonlyArray<ICodegenSymbol> {\n if (!this.cache.symbols) {\n this.cache.symbols = Array.from(this.state.symbols.values());\n }\n return this.cache.symbols;\n }\n}\n","import { CodegenFile } from '../files/file';\nimport type { ICodegenImport } from '../imports/types';\nimport type { ICodegenMeta } from '../meta/types';\nimport type { ICodegenOutput } from '../output/types';\nimport type { ICodegenRenderer } from '../renderers/types';\nimport type { ICodegenSymbol } from '../symbols/types';\nimport type { ICodegenProject } from './types';\n\nexport class CodegenProject implements ICodegenProject {\n private filesMap: Map<string, CodegenFile> = new Map();\n private filesOrder: Array<CodegenFile> = [];\n private renderers: Map<string, ICodegenRenderer> = new Map();\n\n addExportToFile(fileOrPath: CodegenFile | string, imp: ICodegenImport): void {\n const file = this.ensureFile(fileOrPath);\n file.addExport(imp);\n }\n\n addImportToFile(fileOrPath: CodegenFile | string, imp: ICodegenImport): void {\n const file = this.ensureFile(fileOrPath);\n file.addImport(imp);\n }\n\n addSymbolToFile(\n fileOrPath: CodegenFile | string,\n symbol: ICodegenSymbol,\n ): void {\n const file = this.ensureFile(fileOrPath);\n file.addSymbol(symbol);\n }\n\n createFile(\n path: string,\n meta: Omit<CodegenFile['meta'], 'renderer'> & {\n /**\n * Renderer to use to render this file.\n */\n renderer?: ICodegenRenderer;\n } = {},\n ): CodegenFile {\n const { renderer, ...metadata } = meta;\n if (renderer) {\n this.ensureRenderer(renderer);\n }\n\n const existing = this.getFileByPath(path);\n if (existing) {\n // Whoever is creating the file will override the renderer\n if (renderer?.id && renderer.id !== existing.meta.renderer) {\n existing.meta.renderer = renderer.id;\n }\n return existing;\n }\n\n const file = new CodegenFile(path, {\n ...metadata,\n renderer: renderer?.id,\n });\n this.filesOrder.push(file);\n this.filesMap.set(path, file);\n return file;\n }\n\n ensureFile(fileOrPath: CodegenFile | string): CodegenFile {\n if (typeof fileOrPath !== 'string') {\n return fileOrPath;\n }\n const existingFile = this.getFileByPath(fileOrPath);\n if (existingFile) {\n return existingFile;\n }\n return this.createFile(fileOrPath);\n }\n\n private ensureRenderer(renderer: ICodegenRenderer): ICodegenRenderer {\n if (!this.renderers.has(renderer.id)) {\n this.renderers.set(renderer.id, renderer);\n }\n return this.renderers.get(renderer.id)!;\n }\n\n get files(): ReadonlyArray<CodegenFile> {\n return [...this.filesOrder];\n }\n\n getAllSymbols(): ReadonlyArray<ICodegenSymbol> {\n return this.filesOrder.flatMap((file) => file.getAllSymbols());\n }\n\n getFileByPath(path: string): CodegenFile | undefined {\n return this.filesMap.get(path);\n }\n\n render(meta?: ICodegenMeta): ReadonlyArray<ICodegenOutput> {\n const results: Array<ICodegenOutput> = [];\n for (const file of this.filesOrder) {\n if (!file.meta.renderer) continue;\n const renderer = this.renderers.get(file.meta.renderer);\n if (!renderer) continue;\n results.push(renderer.render(file, meta));\n }\n return results;\n }\n}\n"]}
@@ -0,0 +1,391 @@
1
+ /**
2
+ * Arbitrary metadata passed to render functions.
3
+ *
4
+ * Implementors should extend this interface for their own needs.
5
+ */
6
+ interface ICodegenMeta {
7
+ [key: string]: unknown;
8
+ }
9
+
10
+ interface ICodegenOutput {
11
+ /**
12
+ * The main content of the file to output.
13
+ *
14
+ * A raw string representing source code.
15
+ *
16
+ * @example "function foo(): void {\n // implementation\n}\n"
17
+ */
18
+ content: string;
19
+ /**
20
+ * Optional metadata or hints for the emitter, such as formatting options,
21
+ * source maps, or language-specific flags.
22
+ *
23
+ * @example { format: "prettier", sourceMap: true }
24
+ */
25
+ meta: Record<string, unknown>;
26
+ /**
27
+ * Logical output path (used for writing the file).
28
+ *
29
+ * @example "models/user.ts"
30
+ */
31
+ path: string;
32
+ }
33
+
34
+ interface ICodegenRenderer {
35
+ /**
36
+ * Optional: hook for renderer-level setup logic (e.g., formatting, config)
37
+ */
38
+ configure?(options: Record<string, unknown>): void;
39
+ /**
40
+ * Unique identifier for this renderer.
41
+ *
42
+ * @example "typescript"
43
+ */
44
+ id: string;
45
+ /**
46
+ * Returns printable data.
47
+ *
48
+ * @param file The file to render.
49
+ * @param meta Arbitrary metadata.
50
+ * @returns Output for file emit step
51
+ */
52
+ render(file: CodegenFile, meta?: ICodegenMeta): ICodegenOutput;
53
+ }
54
+
55
+ interface ICodegenSymbol {
56
+ /**
57
+ * Optional description or doc comment.
58
+ *
59
+ * @example "Represents a user in the system"
60
+ */
61
+ description?: string;
62
+ /**
63
+ * Optional kind of symbol (e.g. "class", "function", "type", etc.).
64
+ *
65
+ * @example "class"
66
+ */
67
+ kind?: string;
68
+ /**
69
+ * Unique identifier for the symbol within its file.
70
+ *
71
+ * @example "UserModel"
72
+ */
73
+ name: string;
74
+ /**
75
+ * Internal representation of the symbol (e.g. AST node, IR object, raw
76
+ * code). Used to generate output.
77
+ */
78
+ value?: unknown;
79
+ }
80
+
81
+ interface ICodegenFile {
82
+ /**
83
+ * Adds an export to this file.
84
+ *
85
+ * This is also known as a re-export.
86
+ *
87
+ * @param exp The export to add
88
+ */
89
+ addExport(exp: ICodegenImport): void;
90
+ /**
91
+ * Adds an import to this file.
92
+ *
93
+ * @param imp The import to add
94
+ */
95
+ addImport(imp: ICodegenImport): void;
96
+ /**
97
+ * Adds a symbol defined by this file.
98
+ *
99
+ * @param symbol The symbol to add
100
+ */
101
+ addSymbol(symbol: ICodegenSymbol): void;
102
+ /**
103
+ * Symbols exported from other files.
104
+ **/
105
+ exports: ReadonlyArray<ICodegenImport>;
106
+ /**
107
+ * Returns all symbols used in this file (declared + imported).
108
+ *
109
+ * @returns List of all symbols used in this file
110
+ */
111
+ getAllSymbols(): ReadonlyArray<ICodegenSymbol>;
112
+ /**
113
+ * Checks if this file contains any content.
114
+ *
115
+ * This is used to determine whether we want to process the file further.
116
+ * By default, we consider only symbols and exports as content.
117
+ *
118
+ * @returns True if the file contains content
119
+ */
120
+ hasContent(): boolean;
121
+ /**
122
+ * Checks if this file defines a symbol with the given name.
123
+ *
124
+ * @param name Symbol name to check
125
+ * @returns True if the symbol is defined by this file
126
+ */
127
+ hasSymbol(name: string): boolean;
128
+ /**
129
+ * Symbols imported from other files.
130
+ **/
131
+ imports: ReadonlyArray<ICodegenImport>;
132
+ /**
133
+ * Optional metadata about the file.
134
+ **/
135
+ meta: {
136
+ /**
137
+ * Optional file extension.
138
+ *
139
+ * @example ".ts"
140
+ */
141
+ extension?: '.ts' | (string & {});
142
+ /**
143
+ * Optional logical module or package name.
144
+ *
145
+ * @example "models.user"
146
+ */
147
+ moduleName?: string;
148
+ /**
149
+ * Optional path transformer.
150
+ *
151
+ * @param path Original file path passed to the constructor.
152
+ */
153
+ path?: ((path: string) => string) | string;
154
+ /**
155
+ * Renderer ID.
156
+ *
157
+ * @example "typescript"
158
+ */
159
+ renderer?: ICodegenRenderer['id'];
160
+ };
161
+ /**
162
+ * Logical output path (used for writing the file).
163
+ *
164
+ * @example "models/user.ts"
165
+ */
166
+ path: string;
167
+ /**
168
+ * Returns a relative path to this file from another file.
169
+ *
170
+ * @param file The file from which we want the relative path to this file.
171
+ * @example "./this-file.ts"
172
+ */
173
+ relativePathFromFile(file: Pick<ICodegenFile, 'path'>): string;
174
+ /**
175
+ * Returns a relative path to file from this file.
176
+ *
177
+ * @param file The file to which we want the relative path.
178
+ * @example "./another-file.ts"
179
+ */
180
+ relativePathToFile(file: Pick<ICodegenFile, 'path'>): string;
181
+ /**
182
+ * Top-level symbols declared in this file.
183
+ **/
184
+ symbols: ReadonlyArray<ICodegenSymbol>;
185
+ }
186
+
187
+ interface ICodegenImport {
188
+ /**
189
+ * Optional aliasing map for imported symbols.
190
+ *
191
+ * Keys must be a subset of `names`, values are aliases.
192
+ *
193
+ * @example { User: "ImportedUser" }
194
+ */
195
+ aliases?: Record<string, string>;
196
+ /**
197
+ * Name of the default import, if any.
198
+ *
199
+ * @example "React"
200
+ */
201
+ defaultImport?: string;
202
+ /**
203
+ * Source file or external module from which symbols are imported.
204
+ *
205
+ * For internal files, this should be a ICodegenFile instance to enable
206
+ * dynamic path computation. For external or system modules, use a string.
207
+ *
208
+ * @example "./models/user"
209
+ * @example "node:path"
210
+ */
211
+ from: ICodegenFile | string;
212
+ /**
213
+ * Names of the symbols imported from the source.
214
+ *
215
+ * Must be non-empty unless `isNamespaceImport` is true.
216
+ * All imported names, regardless of whether they are used as types or values.
217
+ *
218
+ * @example ["User", "UserDTO"]
219
+ */
220
+ names?: ReadonlyArray<string>;
221
+ /**
222
+ * If this import is a namespace import (e.g. `import * as ns from "..."`),
223
+ * this should be the namespace alias. Set to `true` if no alias is needed.
224
+ *
225
+ * @example "utils"
226
+ * @example true
227
+ */
228
+ namespaceImport?: boolean | string;
229
+ /**
230
+ * Whether the default import is type-only.
231
+ *
232
+ * @example true
233
+ */
234
+ typeDefaultImport?: boolean;
235
+ /**
236
+ * Subset of `names` that are imported using the `type` modifier.
237
+ * These symbols will be emitted as type-only imports in TypeScript.
238
+ *
239
+ * @example ["UserDTO"]
240
+ */
241
+ typeNames?: ReadonlyArray<string>;
242
+ /**
243
+ * Whether the namespace import is type-only.
244
+ *
245
+ * @example true
246
+ */
247
+ typeNamespaceImport?: boolean;
248
+ }
249
+
250
+ declare class CodegenFile implements ICodegenFile {
251
+ path: string;
252
+ meta: ICodegenFile['meta'];
253
+ private cache;
254
+ private state;
255
+ constructor(path: string, meta?: ICodegenFile['meta']);
256
+ addExport(exp: ICodegenImport): void;
257
+ addImport(imp: ICodegenImport): void;
258
+ private addImportExport;
259
+ addSymbol(symbol: ICodegenSymbol): void;
260
+ get exports(): ReadonlyArray<ICodegenImport>;
261
+ getAllSymbols(): ReadonlyArray<ICodegenSymbol>;
262
+ hasContent(): boolean;
263
+ hasSymbol(name: string): boolean;
264
+ get imports(): ReadonlyArray<ICodegenImport>;
265
+ private mergeImportExportValues;
266
+ static pathToFilePath(source: string): string;
267
+ relativePathFromFile(file: Pick<ICodegenFile, 'path'>): string;
268
+ relativePathToFile(file: Pick<ICodegenFile, 'path'>): string;
269
+ get symbols(): ReadonlyArray<ICodegenSymbol>;
270
+ }
271
+
272
+ /**
273
+ * Represents a code generation project consisting of multiple codegen files.
274
+ * Manages imports, symbols, and output generation across the project.
275
+ */
276
+ interface ICodegenProject {
277
+ /**
278
+ * Adds an export declaration to a specific file, creating the file if it doesn't exist.
279
+ *
280
+ * @param fileOrPath - File instance or file path where to add the export.
281
+ * @param imp - The export declaration to add.
282
+ * @example
283
+ * project.addExportToFile("models/user.ts", { from: "lib", names: ["User"] });
284
+ */
285
+ addExportToFile(fileOrPath: ICodegenFile | string, imp: ICodegenImport): void;
286
+ /**
287
+ * Adds an import declaration to a specific file, creating the file if it doesn't exist.
288
+ *
289
+ * @param fileOrPath - File instance or file path where to add the import.
290
+ * @param imp - The import declaration to add.
291
+ * @example
292
+ * project.addImportToFile("models/user.ts", { from: "lib", names: ["User"] });
293
+ */
294
+ addImportToFile(fileOrPath: ICodegenFile | string, imp: ICodegenImport): void;
295
+ /**
296
+ * Adds a symbol to a specific file, creating the file if it doesn't exist.
297
+ *
298
+ * @param fileOrPath - File instance or file path where to add the symbol.
299
+ * @param symbol - The symbol to add.
300
+ * @example
301
+ * project.addSymbolToFile("models/user.ts", { name: "User", value: tsNode });
302
+ */
303
+ addSymbolToFile(
304
+ fileOrPath: ICodegenFile | string,
305
+ symbol: ICodegenSymbol,
306
+ ): void;
307
+ /**
308
+ * Creates a new codegen file with optional metadata and adds it to the project.
309
+ *
310
+ * If a file with the same path already exists, it is returned instead.
311
+ *
312
+ * @param path - The logical output path for the file (e.g. "models/user.ts").
313
+ * @param meta - Optional renderer and metadata to attach to the file (e.g. { isInternal: true }).
314
+ * @returns The newly created file instance.
315
+ * @example
316
+ * const file = project.createFile("models/user.ts", { isInternal: true });
317
+ */
318
+ createFile(
319
+ path: string,
320
+ meta?: ICodegenFile['meta'] & { renderer?: ICodegenRenderer },
321
+ ): ICodegenFile;
322
+ /**
323
+ * Ensures a codegen file exists and returns it.
324
+ *
325
+ * If a file does not exist yet, it is created with minimal information.
326
+ * Later, it is expected `createFile()` will be called which will fill in
327
+ * the missing information such as optional metadata.
328
+ *
329
+ * @param fileOrPath - The logical output path for the file or the file itself.
330
+ * @returns The file instance.
331
+ * @example
332
+ * const file = project.ensureFile("models/user.ts");
333
+ */
334
+ ensureFile(fileOrPath: ICodegenFile | string): ICodegenFile;
335
+ /**
336
+ * Returns all files in the project in insertion order.
337
+ *
338
+ * @example
339
+ * project.files.forEach(file => console.log(file.path));
340
+ */
341
+ readonly files: ReadonlyArray<ICodegenFile>;
342
+ /**
343
+ * Returns all symbols declared or imported across all files.
344
+ *
345
+ * @returns Flattened list of all codegen symbols.
346
+ * @example
347
+ * project.getAllSymbols().filter(s => s.name === "User");
348
+ */
349
+ getAllSymbols(): ReadonlyArray<ICodegenSymbol>;
350
+ /**
351
+ * Retrieves a file by its logical output path.
352
+ *
353
+ * @param path - The file path to find.
354
+ * @returns The file if found, or undefined otherwise.
355
+ * @example
356
+ * const file = project.getFileByPath("models/user.ts");
357
+ */
358
+ getFileByPath(path: string): ICodegenFile | undefined;
359
+ /**
360
+ * Produces output representations for all files in the project.
361
+ *
362
+ * @param meta Arbitrary metadata.
363
+ * @returns Array of outputs ready for writing or further processing.
364
+ * @example
365
+ * project.render().forEach(output => writeFile(output));
366
+ */
367
+ render(meta?: ICodegenMeta): ReadonlyArray<ICodegenOutput>;
368
+ }
369
+
370
+ declare class CodegenProject implements ICodegenProject {
371
+ private filesMap;
372
+ private filesOrder;
373
+ private renderers;
374
+ addExportToFile(fileOrPath: CodegenFile | string, imp: ICodegenImport): void;
375
+ addImportToFile(fileOrPath: CodegenFile | string, imp: ICodegenImport): void;
376
+ addSymbolToFile(fileOrPath: CodegenFile | string, symbol: ICodegenSymbol): void;
377
+ createFile(path: string, meta?: Omit<CodegenFile['meta'], 'renderer'> & {
378
+ /**
379
+ * Renderer to use to render this file.
380
+ */
381
+ renderer?: ICodegenRenderer;
382
+ }): CodegenFile;
383
+ ensureFile(fileOrPath: CodegenFile | string): CodegenFile;
384
+ private ensureRenderer;
385
+ get files(): ReadonlyArray<CodegenFile>;
386
+ getAllSymbols(): ReadonlyArray<ICodegenSymbol>;
387
+ getFileByPath(path: string): CodegenFile | undefined;
388
+ render(meta?: ICodegenMeta): ReadonlyArray<ICodegenOutput>;
389
+ }
390
+
391
+ export { CodegenFile, CodegenProject, type ICodegenFile, type ICodegenImport, type ICodegenMeta, type ICodegenOutput, type ICodegenProject, type ICodegenRenderer, type ICodegenSymbol };
@@ -0,0 +1,391 @@
1
+ /**
2
+ * Arbitrary metadata passed to render functions.
3
+ *
4
+ * Implementors should extend this interface for their own needs.
5
+ */
6
+ interface ICodegenMeta {
7
+ [key: string]: unknown;
8
+ }
9
+
10
+ interface ICodegenOutput {
11
+ /**
12
+ * The main content of the file to output.
13
+ *
14
+ * A raw string representing source code.
15
+ *
16
+ * @example "function foo(): void {\n // implementation\n}\n"
17
+ */
18
+ content: string;
19
+ /**
20
+ * Optional metadata or hints for the emitter, such as formatting options,
21
+ * source maps, or language-specific flags.
22
+ *
23
+ * @example { format: "prettier", sourceMap: true }
24
+ */
25
+ meta: Record<string, unknown>;
26
+ /**
27
+ * Logical output path (used for writing the file).
28
+ *
29
+ * @example "models/user.ts"
30
+ */
31
+ path: string;
32
+ }
33
+
34
+ interface ICodegenRenderer {
35
+ /**
36
+ * Optional: hook for renderer-level setup logic (e.g., formatting, config)
37
+ */
38
+ configure?(options: Record<string, unknown>): void;
39
+ /**
40
+ * Unique identifier for this renderer.
41
+ *
42
+ * @example "typescript"
43
+ */
44
+ id: string;
45
+ /**
46
+ * Returns printable data.
47
+ *
48
+ * @param file The file to render.
49
+ * @param meta Arbitrary metadata.
50
+ * @returns Output for file emit step
51
+ */
52
+ render(file: CodegenFile, meta?: ICodegenMeta): ICodegenOutput;
53
+ }
54
+
55
+ interface ICodegenSymbol {
56
+ /**
57
+ * Optional description or doc comment.
58
+ *
59
+ * @example "Represents a user in the system"
60
+ */
61
+ description?: string;
62
+ /**
63
+ * Optional kind of symbol (e.g. "class", "function", "type", etc.).
64
+ *
65
+ * @example "class"
66
+ */
67
+ kind?: string;
68
+ /**
69
+ * Unique identifier for the symbol within its file.
70
+ *
71
+ * @example "UserModel"
72
+ */
73
+ name: string;
74
+ /**
75
+ * Internal representation of the symbol (e.g. AST node, IR object, raw
76
+ * code). Used to generate output.
77
+ */
78
+ value?: unknown;
79
+ }
80
+
81
+ interface ICodegenFile {
82
+ /**
83
+ * Adds an export to this file.
84
+ *
85
+ * This is also known as a re-export.
86
+ *
87
+ * @param exp The export to add
88
+ */
89
+ addExport(exp: ICodegenImport): void;
90
+ /**
91
+ * Adds an import to this file.
92
+ *
93
+ * @param imp The import to add
94
+ */
95
+ addImport(imp: ICodegenImport): void;
96
+ /**
97
+ * Adds a symbol defined by this file.
98
+ *
99
+ * @param symbol The symbol to add
100
+ */
101
+ addSymbol(symbol: ICodegenSymbol): void;
102
+ /**
103
+ * Symbols exported from other files.
104
+ **/
105
+ exports: ReadonlyArray<ICodegenImport>;
106
+ /**
107
+ * Returns all symbols used in this file (declared + imported).
108
+ *
109
+ * @returns List of all symbols used in this file
110
+ */
111
+ getAllSymbols(): ReadonlyArray<ICodegenSymbol>;
112
+ /**
113
+ * Checks if this file contains any content.
114
+ *
115
+ * This is used to determine whether we want to process the file further.
116
+ * By default, we consider only symbols and exports as content.
117
+ *
118
+ * @returns True if the file contains content
119
+ */
120
+ hasContent(): boolean;
121
+ /**
122
+ * Checks if this file defines a symbol with the given name.
123
+ *
124
+ * @param name Symbol name to check
125
+ * @returns True if the symbol is defined by this file
126
+ */
127
+ hasSymbol(name: string): boolean;
128
+ /**
129
+ * Symbols imported from other files.
130
+ **/
131
+ imports: ReadonlyArray<ICodegenImport>;
132
+ /**
133
+ * Optional metadata about the file.
134
+ **/
135
+ meta: {
136
+ /**
137
+ * Optional file extension.
138
+ *
139
+ * @example ".ts"
140
+ */
141
+ extension?: '.ts' | (string & {});
142
+ /**
143
+ * Optional logical module or package name.
144
+ *
145
+ * @example "models.user"
146
+ */
147
+ moduleName?: string;
148
+ /**
149
+ * Optional path transformer.
150
+ *
151
+ * @param path Original file path passed to the constructor.
152
+ */
153
+ path?: ((path: string) => string) | string;
154
+ /**
155
+ * Renderer ID.
156
+ *
157
+ * @example "typescript"
158
+ */
159
+ renderer?: ICodegenRenderer['id'];
160
+ };
161
+ /**
162
+ * Logical output path (used for writing the file).
163
+ *
164
+ * @example "models/user.ts"
165
+ */
166
+ path: string;
167
+ /**
168
+ * Returns a relative path to this file from another file.
169
+ *
170
+ * @param file The file from which we want the relative path to this file.
171
+ * @example "./this-file.ts"
172
+ */
173
+ relativePathFromFile(file: Pick<ICodegenFile, 'path'>): string;
174
+ /**
175
+ * Returns a relative path to file from this file.
176
+ *
177
+ * @param file The file to which we want the relative path.
178
+ * @example "./another-file.ts"
179
+ */
180
+ relativePathToFile(file: Pick<ICodegenFile, 'path'>): string;
181
+ /**
182
+ * Top-level symbols declared in this file.
183
+ **/
184
+ symbols: ReadonlyArray<ICodegenSymbol>;
185
+ }
186
+
187
+ interface ICodegenImport {
188
+ /**
189
+ * Optional aliasing map for imported symbols.
190
+ *
191
+ * Keys must be a subset of `names`, values are aliases.
192
+ *
193
+ * @example { User: "ImportedUser" }
194
+ */
195
+ aliases?: Record<string, string>;
196
+ /**
197
+ * Name of the default import, if any.
198
+ *
199
+ * @example "React"
200
+ */
201
+ defaultImport?: string;
202
+ /**
203
+ * Source file or external module from which symbols are imported.
204
+ *
205
+ * For internal files, this should be a ICodegenFile instance to enable
206
+ * dynamic path computation. For external or system modules, use a string.
207
+ *
208
+ * @example "./models/user"
209
+ * @example "node:path"
210
+ */
211
+ from: ICodegenFile | string;
212
+ /**
213
+ * Names of the symbols imported from the source.
214
+ *
215
+ * Must be non-empty unless `isNamespaceImport` is true.
216
+ * All imported names, regardless of whether they are used as types or values.
217
+ *
218
+ * @example ["User", "UserDTO"]
219
+ */
220
+ names?: ReadonlyArray<string>;
221
+ /**
222
+ * If this import is a namespace import (e.g. `import * as ns from "..."`),
223
+ * this should be the namespace alias. Set to `true` if no alias is needed.
224
+ *
225
+ * @example "utils"
226
+ * @example true
227
+ */
228
+ namespaceImport?: boolean | string;
229
+ /**
230
+ * Whether the default import is type-only.
231
+ *
232
+ * @example true
233
+ */
234
+ typeDefaultImport?: boolean;
235
+ /**
236
+ * Subset of `names` that are imported using the `type` modifier.
237
+ * These symbols will be emitted as type-only imports in TypeScript.
238
+ *
239
+ * @example ["UserDTO"]
240
+ */
241
+ typeNames?: ReadonlyArray<string>;
242
+ /**
243
+ * Whether the namespace import is type-only.
244
+ *
245
+ * @example true
246
+ */
247
+ typeNamespaceImport?: boolean;
248
+ }
249
+
250
+ declare class CodegenFile implements ICodegenFile {
251
+ path: string;
252
+ meta: ICodegenFile['meta'];
253
+ private cache;
254
+ private state;
255
+ constructor(path: string, meta?: ICodegenFile['meta']);
256
+ addExport(exp: ICodegenImport): void;
257
+ addImport(imp: ICodegenImport): void;
258
+ private addImportExport;
259
+ addSymbol(symbol: ICodegenSymbol): void;
260
+ get exports(): ReadonlyArray<ICodegenImport>;
261
+ getAllSymbols(): ReadonlyArray<ICodegenSymbol>;
262
+ hasContent(): boolean;
263
+ hasSymbol(name: string): boolean;
264
+ get imports(): ReadonlyArray<ICodegenImport>;
265
+ private mergeImportExportValues;
266
+ static pathToFilePath(source: string): string;
267
+ relativePathFromFile(file: Pick<ICodegenFile, 'path'>): string;
268
+ relativePathToFile(file: Pick<ICodegenFile, 'path'>): string;
269
+ get symbols(): ReadonlyArray<ICodegenSymbol>;
270
+ }
271
+
272
+ /**
273
+ * Represents a code generation project consisting of multiple codegen files.
274
+ * Manages imports, symbols, and output generation across the project.
275
+ */
276
+ interface ICodegenProject {
277
+ /**
278
+ * Adds an export declaration to a specific file, creating the file if it doesn't exist.
279
+ *
280
+ * @param fileOrPath - File instance or file path where to add the export.
281
+ * @param imp - The export declaration to add.
282
+ * @example
283
+ * project.addExportToFile("models/user.ts", { from: "lib", names: ["User"] });
284
+ */
285
+ addExportToFile(fileOrPath: ICodegenFile | string, imp: ICodegenImport): void;
286
+ /**
287
+ * Adds an import declaration to a specific file, creating the file if it doesn't exist.
288
+ *
289
+ * @param fileOrPath - File instance or file path where to add the import.
290
+ * @param imp - The import declaration to add.
291
+ * @example
292
+ * project.addImportToFile("models/user.ts", { from: "lib", names: ["User"] });
293
+ */
294
+ addImportToFile(fileOrPath: ICodegenFile | string, imp: ICodegenImport): void;
295
+ /**
296
+ * Adds a symbol to a specific file, creating the file if it doesn't exist.
297
+ *
298
+ * @param fileOrPath - File instance or file path where to add the symbol.
299
+ * @param symbol - The symbol to add.
300
+ * @example
301
+ * project.addSymbolToFile("models/user.ts", { name: "User", value: tsNode });
302
+ */
303
+ addSymbolToFile(
304
+ fileOrPath: ICodegenFile | string,
305
+ symbol: ICodegenSymbol,
306
+ ): void;
307
+ /**
308
+ * Creates a new codegen file with optional metadata and adds it to the project.
309
+ *
310
+ * If a file with the same path already exists, it is returned instead.
311
+ *
312
+ * @param path - The logical output path for the file (e.g. "models/user.ts").
313
+ * @param meta - Optional renderer and metadata to attach to the file (e.g. { isInternal: true }).
314
+ * @returns The newly created file instance.
315
+ * @example
316
+ * const file = project.createFile("models/user.ts", { isInternal: true });
317
+ */
318
+ createFile(
319
+ path: string,
320
+ meta?: ICodegenFile['meta'] & { renderer?: ICodegenRenderer },
321
+ ): ICodegenFile;
322
+ /**
323
+ * Ensures a codegen file exists and returns it.
324
+ *
325
+ * If a file does not exist yet, it is created with minimal information.
326
+ * Later, it is expected `createFile()` will be called which will fill in
327
+ * the missing information such as optional metadata.
328
+ *
329
+ * @param fileOrPath - The logical output path for the file or the file itself.
330
+ * @returns The file instance.
331
+ * @example
332
+ * const file = project.ensureFile("models/user.ts");
333
+ */
334
+ ensureFile(fileOrPath: ICodegenFile | string): ICodegenFile;
335
+ /**
336
+ * Returns all files in the project in insertion order.
337
+ *
338
+ * @example
339
+ * project.files.forEach(file => console.log(file.path));
340
+ */
341
+ readonly files: ReadonlyArray<ICodegenFile>;
342
+ /**
343
+ * Returns all symbols declared or imported across all files.
344
+ *
345
+ * @returns Flattened list of all codegen symbols.
346
+ * @example
347
+ * project.getAllSymbols().filter(s => s.name === "User");
348
+ */
349
+ getAllSymbols(): ReadonlyArray<ICodegenSymbol>;
350
+ /**
351
+ * Retrieves a file by its logical output path.
352
+ *
353
+ * @param path - The file path to find.
354
+ * @returns The file if found, or undefined otherwise.
355
+ * @example
356
+ * const file = project.getFileByPath("models/user.ts");
357
+ */
358
+ getFileByPath(path: string): ICodegenFile | undefined;
359
+ /**
360
+ * Produces output representations for all files in the project.
361
+ *
362
+ * @param meta Arbitrary metadata.
363
+ * @returns Array of outputs ready for writing or further processing.
364
+ * @example
365
+ * project.render().forEach(output => writeFile(output));
366
+ */
367
+ render(meta?: ICodegenMeta): ReadonlyArray<ICodegenOutput>;
368
+ }
369
+
370
+ declare class CodegenProject implements ICodegenProject {
371
+ private filesMap;
372
+ private filesOrder;
373
+ private renderers;
374
+ addExportToFile(fileOrPath: CodegenFile | string, imp: ICodegenImport): void;
375
+ addImportToFile(fileOrPath: CodegenFile | string, imp: ICodegenImport): void;
376
+ addSymbolToFile(fileOrPath: CodegenFile | string, symbol: ICodegenSymbol): void;
377
+ createFile(path: string, meta?: Omit<CodegenFile['meta'], 'renderer'> & {
378
+ /**
379
+ * Renderer to use to render this file.
380
+ */
381
+ renderer?: ICodegenRenderer;
382
+ }): CodegenFile;
383
+ ensureFile(fileOrPath: CodegenFile | string): CodegenFile;
384
+ private ensureRenderer;
385
+ get files(): ReadonlyArray<CodegenFile>;
386
+ getAllSymbols(): ReadonlyArray<ICodegenSymbol>;
387
+ getFileByPath(path: string): CodegenFile | undefined;
388
+ render(meta?: ICodegenMeta): ReadonlyArray<ICodegenOutput>;
389
+ }
390
+
391
+ export { CodegenFile, CodegenProject, type ICodegenFile, type ICodegenImport, type ICodegenMeta, type ICodegenOutput, type ICodegenProject, type ICodegenRenderer, type ICodegenSymbol };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import {createRequire}from'module';import s from'node:path';createRequire(import.meta.url);
2
+ var i=class d{constructor(e,t={}){this.path=e;this.meta=t;let r=d.pathToFilePath(e);t.path&&(typeof t.path=="function"?r=t.path(r):r=t.path.replace("{{path}}",r)),this.path=r;}cache={};state={exports:new Map,imports:new Map,symbols:new Map};addExport(e){return this.addImportExport(e,"exports")}addImport(e){return this.addImportExport(e,"imports")}addImportExport(e,t){let r=typeof e.from=="string"?e.from:e.from.path,o=this.state[t].get(r);o?(this.mergeImportExportValues(o,e),this.state[t].set(r,o)):this.state[t].set(r,{...e}),this.cache[t]=void 0;}addSymbol(e){let t=e.name,r=this.state.symbols.get(t);r?(r.value=e.value,this.state.symbols.set(t,r)):this.state.symbols.set(t,{...e}),this.cache.symbols=void 0;}get exports(){return this.cache.exports||(this.cache.exports=Array.from(this.state.exports.values())),this.cache.exports}getAllSymbols(){return [...this.symbols,...this.imports.flatMap(e=>(e.names??[]).map(t=>({name:e.aliases?.[t]??t}))),...this.exports.flatMap(e=>(e.names??[]).map(t=>({name:e.aliases?.[t]??t})))]}hasContent(){return this.state.symbols.size>0||this.state.exports.size>0}hasSymbol(e){return this.state.symbols.has(e)}get imports(){return this.cache.imports||(this.cache.imports=Array.from(this.state.imports.values())),this.cache.imports}mergeImportExportValues(e,t){e.aliases={...e.aliases,...t.aliases},t.defaultImport!==void 0&&(e.defaultImport=t.defaultImport),e.names=[...new Set([...e.names??[],...t.names??[]])],t.namespaceImport!==void 0&&(e.namespaceImport=t.namespaceImport),t.typeDefaultImport!==void 0&&(e.typeDefaultImport=t.typeDefaultImport),e.typeNames=[...new Set([...e.typeNames??[],...t.typeNames??[]])],t.typeNamespaceImport!==void 0&&(e.typeNamespaceImport=t.typeNamespaceImport);}static pathToFilePath(e){return e.includes("/")?e.split("/").filter(Boolean).join(s.sep):e.includes("\\")?e.split("\\").filter(Boolean).join(s.sep):e.split(s.sep).filter(Boolean).join(s.sep)}relativePathFromFile(e){let t=s.posix.relative(s.posix.dirname(e.path),this.path);return t.startsWith(".")||(t=`./${t}`),t}relativePathToFile(e){let t=s.posix.relative(s.posix.dirname(this.path),e.path);return t.startsWith(".")||(t=`./${t}`),t}get symbols(){return this.cache.symbols||(this.cache.symbols=Array.from(this.state.symbols.values())),this.cache.symbols}};var a=class{filesMap=new Map;filesOrder=[];renderers=new Map;addExportToFile(e,t){this.ensureFile(e).addExport(t);}addImportToFile(e,t){this.ensureFile(e).addImport(t);}addSymbolToFile(e,t){this.ensureFile(e).addSymbol(t);}createFile(e,t={}){let{renderer:r,...o}=t;r&&this.ensureRenderer(r);let n=this.getFileByPath(e);if(n)return r?.id&&r.id!==n.meta.renderer&&(n.meta.renderer=r.id),n;let p=new i(e,{...o,renderer:r?.id});return this.filesOrder.push(p),this.filesMap.set(e,p),p}ensureFile(e){if(typeof e!="string")return e;let t=this.getFileByPath(e);return t||this.createFile(e)}ensureRenderer(e){return this.renderers.has(e.id)||this.renderers.set(e.id,e),this.renderers.get(e.id)}get files(){return [...this.filesOrder]}getAllSymbols(){return this.filesOrder.flatMap(e=>e.getAllSymbols())}getFileByPath(e){return this.filesMap.get(e)}render(e){let t=[];for(let r of this.filesOrder){if(!r.meta.renderer)continue;let o=this.renderers.get(r.meta.renderer);o&&t.push(o.render(r,e));}return t}};export{i as CodegenFile,a as CodegenProject};//# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/files/file.ts","../src/project/project.ts"],"names":["CodegenFile","_CodegenFile","path","meta","filePath","exp","imp","value","field","key","existing","symbol","name","target","source","file","relativePath","CodegenProject","fileOrPath","renderer","metadata","existingFile","results"],"mappings":";AAMO,IAAMA,EAAN,MAAMC,CAAoC,CAiB/C,WAAA,CACSC,CAAAA,CACAC,EAA6B,EAAC,CACrC,CAFO,IAAA,CAAA,IAAA,CAAAD,CAAAA,CACA,UAAAC,CAAAA,CAEP,IAAIC,EAAWH,CAAAA,CAAY,cAAA,CAAeC,CAAI,CAAA,CAC1CC,EAAK,IAAA,GACH,OAAOA,EAAK,IAAA,EAAS,UAAA,CACvBC,EAAWD,CAAAA,CAAK,IAAA,CAAKC,CAAQ,CAAA,CAE7BA,CAAAA,CAAWD,EAAK,IAAA,CAAK,OAAA,CAAQ,WAAYC,CAAQ,CAAA,CAAA,CAGrD,KAAK,IAAA,CAAOA,EACd,CA7BQ,KAAA,CAIJ,EAAC,CAEG,KAAA,CAIJ,CACF,OAAA,CAAS,IAAI,IACb,OAAA,CAAS,IAAI,IACb,OAAA,CAAS,IAAI,GACf,CAAA,CAiBA,SAAA,CAAUC,EAA2B,CACnC,OAAO,KAAK,eAAA,CAAgBA,CAAAA,CAAK,SAAS,CAC5C,CAEA,SAAA,CAAUC,CAAAA,CAA2B,CACnC,OAAO,IAAA,CAAK,gBAAgBA,CAAAA,CAAK,SAAS,CAC5C,CAEQ,eAAA,CACNC,EACAC,CAAAA,CACM,CACN,IAAMC,CAAAA,CAAM,OAAOF,EAAM,IAAA,EAAS,QAAA,CAAWA,CAAAA,CAAM,IAAA,CAAOA,EAAM,IAAA,CAAK,IAAA,CAC/DG,EAAW,IAAA,CAAK,KAAA,CAAMF,CAAK,CAAA,CAAE,GAAA,CAAIC,CAAG,CAAA,CACtCC,CAAAA,EACF,KAAK,uBAAA,CAAwBA,CAAAA,CAAUH,CAAK,CAAA,CAC5C,IAAA,CAAK,MAAMC,CAAK,CAAA,CAAE,GAAA,CAAIC,CAAAA,CAAKC,CAAQ,CAAA,EAEnC,IAAA,CAAK,MAAMF,CAAK,CAAA,CAAE,IAAIC,CAAAA,CAAK,CAAE,GAAGF,CAAM,CAAC,EAEzC,IAAA,CAAK,KAAA,CAAMC,CAAK,CAAA,CAAI,OACtB,CAEA,SAAA,CAAUG,CAAAA,CAA8B,CACtC,IAAMF,EAAME,CAAAA,CAAO,IAAA,CACbD,EAAW,IAAA,CAAK,KAAA,CAAM,QAAQ,GAAA,CAAID,CAAG,EACvCC,CAAAA,EACFA,CAAAA,CAAS,MAAQC,CAAAA,CAAO,KAAA,CACxB,KAAK,KAAA,CAAM,OAAA,CAAQ,IAAIF,CAAAA,CAAKC,CAAQ,GAEpC,IAAA,CAAK,KAAA,CAAM,QAAQ,GAAA,CAAID,CAAAA,CAAK,CAAE,GAAGE,CAAO,CAAC,CAAA,CAE3C,IAAA,CAAK,MAAM,OAAA,CAAU,OACvB,CAEA,IAAI,OAAA,EAAyC,CAC3C,OAAK,IAAA,CAAK,MAAM,OAAA,GACd,IAAA,CAAK,KAAA,CAAM,OAAA,CAAU,MAAM,IAAA,CAAK,IAAA,CAAK,MAAM,OAAA,CAAQ,MAAA,EAAQ,CAAA,CAAA,CAEtD,IAAA,CAAK,MAAM,OACpB,CAEA,eAA+C,CAC7C,OAAO,CACL,GAAG,IAAA,CAAK,QACR,GAAG,IAAA,CAAK,OAAA,CAAQ,OAAA,CAASL,IACtBA,CAAAA,CAAI,KAAA,EAAS,EAAC,EAAG,GAAA,CAAKM,IAAU,CAC/B,IAAA,CAAMN,EAAI,OAAA,GAAUM,CAAI,GAAKA,CAC/B,CAAA,CAAE,CACJ,CAAA,CACA,GAAG,KAAK,OAAA,CAAQ,OAAA,CAASN,CAAAA,EAAAA,CACtBA,CAAAA,CAAI,OAAS,EAAC,EAAG,IAAKM,CAAAA,GAAU,CAC/B,KAAMN,CAAAA,CAAI,OAAA,GAAUM,CAAI,CAAA,EAAKA,CAC/B,EAAE,CACJ,CACF,CACF,CAEA,UAAA,EAAsB,CACpB,OAAO,IAAA,CAAK,MAAM,OAAA,CAAQ,IAAA,CAAO,GAAK,IAAA,CAAK,KAAA,CAAM,QAAQ,IAAA,CAAO,CAClE,CAEA,SAAA,CAAUA,CAAAA,CAAuB,CAC/B,OAAO,IAAA,CAAK,MAAM,OAAA,CAAQ,GAAA,CAAIA,CAAI,CACpC,CAEA,IAAI,OAAA,EAAyC,CAC3C,OAAK,IAAA,CAAK,MAAM,OAAA,GACd,IAAA,CAAK,MAAM,OAAA,CAAU,KAAA,CAAM,KAAK,IAAA,CAAK,KAAA,CAAM,QAAQ,MAAA,EAAQ,GAEtD,IAAA,CAAK,KAAA,CAAM,OACpB,CAEQ,uBAAA,CACNC,EACAC,CAAAA,CACM,CACND,CAAAA,CAAO,OAAA,CAAU,CAAE,GAAGA,CAAAA,CAAO,QAAS,GAAGC,CAAAA,CAAO,OAAQ,CAAA,CACpDA,CAAAA,CAAO,gBAAkB,MAAA,GAC3BD,CAAAA,CAAO,cAAgBC,CAAAA,CAAO,aAAA,CAAA,CAEhCD,EAAO,KAAA,CAAQ,CACb,GAAG,IAAI,GAAA,CAAI,CAAC,GAAIA,EAAO,KAAA,EAAS,GAAK,GAAIC,CAAAA,CAAO,OAAS,EAAG,CAAC,CAC/D,CAAA,CACIA,EAAO,eAAA,GAAoB,MAAA,GAC7BD,EAAO,eAAA,CAAkBC,CAAAA,CAAO,iBAE9BA,CAAAA,CAAO,iBAAA,GAAsB,SAC/BD,CAAAA,CAAO,iBAAA,CAAoBC,EAAO,iBAAA,CAAA,CAEpCD,CAAAA,CAAO,UAAY,CACjB,GAAG,IAAI,GAAA,CAAI,CAAC,GAAIA,CAAAA,CAAO,SAAA,EAAa,EAAC,CAAI,GAAIC,EAAO,SAAA,EAAa,EAAG,CAAC,CACvE,CAAA,CACIA,CAAAA,CAAO,sBAAwB,MAAA,GACjCD,CAAAA,CAAO,oBAAsBC,CAAAA,CAAO,mBAAA,EAExC,CAEA,OAAO,cAAA,CAAeA,EAAwB,CAC5C,OAAIA,EAAO,QAAA,CAAS,GAAG,EACdA,CAAAA,CAAO,KAAA,CAAM,GAAG,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,KAAKZ,CAAAA,CAAK,GAAG,EAEpDY,CAAAA,CAAO,QAAA,CAAS,IAAI,CAAA,CACfA,CAAAA,CAAO,MAAM,IAAI,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,KAAKZ,CAAAA,CAAK,GAAG,EAElDY,CAAAA,CAAO,KAAA,CAAMZ,CAAAA,CAAK,GAAG,EAAE,MAAA,CAAO,OAAO,EAAE,IAAA,CAAKA,CAAAA,CAAK,GAAG,CAC7D,CAEA,qBAAqBa,CAAAA,CAA0C,CAC7D,IAAIC,CAAAA,CAAed,CAAAA,CAAK,MAAM,QAAA,CAC5BA,CAAAA,CAAK,MAAM,OAAA,CAAQa,CAAAA,CAAK,IAAI,CAAA,CAC5B,KAAK,IACP,CAAA,CACA,OAAKC,CAAAA,CAAa,UAAA,CAAW,GAAG,CAAA,GAC9BA,CAAAA,CAAe,KAAKA,CAAY,CAAA,CAAA,CAAA,CAE3BA,CACT,CAEA,kBAAA,CAAmBD,EAA0C,CAC3D,IAAIC,EAAed,CAAAA,CAAK,KAAA,CAAM,QAAA,CAC5BA,CAAAA,CAAK,MAAM,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,CAC5Ba,CAAAA,CAAK,IACP,CAAA,CACA,OAAKC,EAAa,UAAA,CAAW,GAAG,IAC9BA,CAAAA,CAAe,CAAA,EAAA,EAAKA,CAAY,CAAA,CAAA,CAAA,CAE3BA,CACT,CAEA,IAAI,OAAA,EAAyC,CAC3C,OAAK,KAAK,KAAA,CAAM,OAAA,GACd,KAAK,KAAA,CAAM,OAAA,CAAU,MAAM,IAAA,CAAK,IAAA,CAAK,MAAM,OAAA,CAAQ,MAAA,EAAQ,CAAA,CAAA,CAEtD,IAAA,CAAK,MAAM,OACpB,CACF,ECtKO,IAAMC,CAAAA,CAAN,KAAgD,CAC7C,SAAqC,IAAI,GAAA,CACzC,WAAiC,EAAC,CAClC,UAA2C,IAAI,GAAA,CAEvD,gBAAgBC,CAAAA,CAAkCZ,CAAAA,CAA2B,CAC9D,IAAA,CAAK,UAAA,CAAWY,CAAU,CAAA,CAClC,SAAA,CAAUZ,CAAG,EACpB,CAEA,gBAAgBY,CAAAA,CAAkCZ,CAAAA,CAA2B,CAC9D,IAAA,CAAK,UAAA,CAAWY,CAAU,CAAA,CAClC,SAAA,CAAUZ,CAAG,EACpB,CAEA,gBACEY,CAAAA,CACAP,CAAAA,CACM,CACO,IAAA,CAAK,UAAA,CAAWO,CAAU,CAAA,CAClC,SAAA,CAAUP,CAAM,EACvB,CAEA,UAAA,CACET,CAAAA,CACAC,EAKI,EAAC,CACQ,CACb,GAAM,CAAE,SAAAgB,CAAAA,CAAU,GAAGC,CAAS,CAAA,CAAIjB,CAAAA,CAC9BgB,GACF,IAAA,CAAK,cAAA,CAAeA,CAAQ,CAAA,CAG9B,IAAMT,EAAW,IAAA,CAAK,aAAA,CAAcR,CAAI,CAAA,CACxC,GAAIQ,CAAAA,CAEF,OAAIS,GAAU,EAAA,EAAMA,CAAAA,CAAS,KAAOT,CAAAA,CAAS,IAAA,CAAK,WAChDA,CAAAA,CAAS,IAAA,CAAK,SAAWS,CAAAA,CAAS,EAAA,CAAA,CAE7BT,EAGT,IAAMK,CAAAA,CAAO,IAAIf,CAAAA,CAAYE,CAAAA,CAAM,CACjC,GAAGkB,EACH,QAAA,CAAUD,CAAAA,EAAU,EACtB,CAAC,CAAA,CACD,YAAK,UAAA,CAAW,IAAA,CAAKJ,CAAI,CAAA,CACzB,IAAA,CAAK,SAAS,GAAA,CAAIb,CAAAA,CAAMa,CAAI,CAAA,CACrBA,CACT,CAEA,UAAA,CAAWG,CAAAA,CAA+C,CACxD,GAAI,OAAOA,GAAe,QAAA,CACxB,OAAOA,EAET,IAAMG,CAAAA,CAAe,KAAK,aAAA,CAAcH,CAAU,EAClD,OAAIG,CAAAA,EAGG,KAAK,UAAA,CAAWH,CAAU,CACnC,CAEQ,cAAA,CAAeC,EAA8C,CACnE,OAAK,IAAA,CAAK,SAAA,CAAU,IAAIA,CAAAA,CAAS,EAAE,GACjC,IAAA,CAAK,SAAA,CAAU,IAAIA,CAAAA,CAAS,EAAA,CAAIA,CAAQ,CAAA,CAEnC,IAAA,CAAK,UAAU,GAAA,CAAIA,CAAAA,CAAS,EAAE,CACvC,CAEA,IAAI,KAAA,EAAoC,CACtC,OAAO,CAAC,GAAG,IAAA,CAAK,UAAU,CAC5B,CAEA,aAAA,EAA+C,CAC7C,OAAO,IAAA,CAAK,WAAW,OAAA,CAASJ,CAAAA,EAASA,EAAK,aAAA,EAAe,CAC/D,CAEA,aAAA,CAAcb,EAAuC,CACnD,OAAO,IAAA,CAAK,QAAA,CAAS,IAAIA,CAAI,CAC/B,CAEA,MAAA,CAAOC,CAAAA,CAAoD,CACzD,IAAMmB,CAAAA,CAAiC,EAAC,CACxC,IAAA,IAAWP,KAAQ,IAAA,CAAK,UAAA,CAAY,CAClC,GAAI,CAACA,EAAK,IAAA,CAAK,QAAA,CAAU,SACzB,IAAMI,CAAAA,CAAW,KAAK,SAAA,CAAU,GAAA,CAAIJ,EAAK,IAAA,CAAK,QAAQ,EACjDI,CAAAA,EACLG,CAAAA,CAAQ,KAAKH,CAAAA,CAAS,MAAA,CAAOJ,EAAMZ,CAAI,CAAC,EAC1C,CACA,OAAOmB,CACT,CACF","file":"index.js","sourcesContent":["import path from 'node:path';\n\nimport type { ICodegenImport } from '../imports/types';\nimport type { ICodegenSymbol } from '../symbols/types';\nimport type { ICodegenFile } from './types';\n\nexport class CodegenFile implements ICodegenFile {\n private cache: {\n exports?: ReadonlyArray<ICodegenImport>;\n imports?: ReadonlyArray<ICodegenImport>;\n symbols?: ReadonlyArray<ICodegenSymbol>;\n } = {};\n\n private state: {\n exports: Map<string, ICodegenImport>;\n imports: Map<string, ICodegenImport>;\n symbols: Map<string, ICodegenSymbol>;\n } = {\n exports: new Map(),\n imports: new Map(),\n symbols: new Map(),\n };\n\n constructor(\n public path: string,\n public meta: ICodegenFile['meta'] = {},\n ) {\n let filePath = CodegenFile.pathToFilePath(path);\n if (meta.path) {\n if (typeof meta.path === 'function') {\n filePath = meta.path(filePath);\n } else {\n filePath = meta.path.replace('{{path}}', filePath);\n }\n }\n this.path = filePath;\n }\n\n addExport(exp: ICodegenImport): void {\n return this.addImportExport(exp, 'exports');\n }\n\n addImport(imp: ICodegenImport): void {\n return this.addImportExport(imp, 'imports');\n }\n\n private addImportExport(\n value: ICodegenImport,\n field: 'exports' | 'imports',\n ): void {\n const key = typeof value.from === 'string' ? value.from : value.from.path;\n const existing = this.state[field].get(key);\n if (existing) {\n this.mergeImportExportValues(existing, value);\n this.state[field].set(key, existing);\n } else {\n this.state[field].set(key, { ...value }); // clone to avoid mutation\n }\n this.cache[field] = undefined;\n }\n\n addSymbol(symbol: ICodegenSymbol): void {\n const key = symbol.name;\n const existing = this.state.symbols.get(key);\n if (existing) {\n existing.value = symbol.value;\n this.state.symbols.set(key, existing);\n } else {\n this.state.symbols.set(key, { ...symbol }); // clone to avoid mutation\n }\n this.cache.symbols = undefined;\n }\n\n get exports(): ReadonlyArray<ICodegenImport> {\n if (!this.cache.exports) {\n this.cache.exports = Array.from(this.state.exports.values());\n }\n return this.cache.exports;\n }\n\n getAllSymbols(): ReadonlyArray<ICodegenSymbol> {\n return [\n ...this.symbols,\n ...this.imports.flatMap((imp) =>\n (imp.names ?? []).map((name) => ({\n name: imp.aliases?.[name] ?? name,\n })),\n ),\n ...this.exports.flatMap((imp) =>\n (imp.names ?? []).map((name) => ({\n name: imp.aliases?.[name] ?? name,\n })),\n ),\n ];\n }\n\n hasContent(): boolean {\n return this.state.symbols.size > 0 || this.state.exports.size > 0;\n }\n\n hasSymbol(name: string): boolean {\n return this.state.symbols.has(name);\n }\n\n get imports(): ReadonlyArray<ICodegenImport> {\n if (!this.cache.imports) {\n this.cache.imports = Array.from(this.state.imports.values());\n }\n return this.cache.imports;\n }\n\n private mergeImportExportValues(\n target: ICodegenImport,\n source: ICodegenImport,\n ): void {\n target.aliases = { ...target.aliases, ...source.aliases };\n if (source.defaultImport !== undefined) {\n target.defaultImport = source.defaultImport;\n }\n target.names = [\n ...new Set([...(target.names ?? []), ...(source.names ?? [])]),\n ];\n if (source.namespaceImport !== undefined) {\n target.namespaceImport = source.namespaceImport;\n }\n if (source.typeDefaultImport !== undefined) {\n target.typeDefaultImport = source.typeDefaultImport;\n }\n target.typeNames = [\n ...new Set([...(target.typeNames ?? []), ...(source.typeNames ?? [])]),\n ];\n if (source.typeNamespaceImport !== undefined) {\n target.typeNamespaceImport = source.typeNamespaceImport;\n }\n }\n\n static pathToFilePath(source: string): string {\n if (source.includes('/')) {\n return source.split('/').filter(Boolean).join(path.sep);\n }\n if (source.includes('\\\\')) {\n return source.split('\\\\').filter(Boolean).join(path.sep);\n }\n return source.split(path.sep).filter(Boolean).join(path.sep);\n }\n\n relativePathFromFile(file: Pick<ICodegenFile, 'path'>): string {\n let relativePath = path.posix.relative(\n path.posix.dirname(file.path),\n this.path,\n );\n if (!relativePath.startsWith('.')) {\n relativePath = `./${relativePath}`;\n }\n return relativePath;\n }\n\n relativePathToFile(file: Pick<ICodegenFile, 'path'>): string {\n let relativePath = path.posix.relative(\n path.posix.dirname(this.path),\n file.path,\n );\n if (!relativePath.startsWith('.')) {\n relativePath = `./${relativePath}`;\n }\n return relativePath;\n }\n\n get symbols(): ReadonlyArray<ICodegenSymbol> {\n if (!this.cache.symbols) {\n this.cache.symbols = Array.from(this.state.symbols.values());\n }\n return this.cache.symbols;\n }\n}\n","import { CodegenFile } from '../files/file';\nimport type { ICodegenImport } from '../imports/types';\nimport type { ICodegenMeta } from '../meta/types';\nimport type { ICodegenOutput } from '../output/types';\nimport type { ICodegenRenderer } from '../renderers/types';\nimport type { ICodegenSymbol } from '../symbols/types';\nimport type { ICodegenProject } from './types';\n\nexport class CodegenProject implements ICodegenProject {\n private filesMap: Map<string, CodegenFile> = new Map();\n private filesOrder: Array<CodegenFile> = [];\n private renderers: Map<string, ICodegenRenderer> = new Map();\n\n addExportToFile(fileOrPath: CodegenFile | string, imp: ICodegenImport): void {\n const file = this.ensureFile(fileOrPath);\n file.addExport(imp);\n }\n\n addImportToFile(fileOrPath: CodegenFile | string, imp: ICodegenImport): void {\n const file = this.ensureFile(fileOrPath);\n file.addImport(imp);\n }\n\n addSymbolToFile(\n fileOrPath: CodegenFile | string,\n symbol: ICodegenSymbol,\n ): void {\n const file = this.ensureFile(fileOrPath);\n file.addSymbol(symbol);\n }\n\n createFile(\n path: string,\n meta: Omit<CodegenFile['meta'], 'renderer'> & {\n /**\n * Renderer to use to render this file.\n */\n renderer?: ICodegenRenderer;\n } = {},\n ): CodegenFile {\n const { renderer, ...metadata } = meta;\n if (renderer) {\n this.ensureRenderer(renderer);\n }\n\n const existing = this.getFileByPath(path);\n if (existing) {\n // Whoever is creating the file will override the renderer\n if (renderer?.id && renderer.id !== existing.meta.renderer) {\n existing.meta.renderer = renderer.id;\n }\n return existing;\n }\n\n const file = new CodegenFile(path, {\n ...metadata,\n renderer: renderer?.id,\n });\n this.filesOrder.push(file);\n this.filesMap.set(path, file);\n return file;\n }\n\n ensureFile(fileOrPath: CodegenFile | string): CodegenFile {\n if (typeof fileOrPath !== 'string') {\n return fileOrPath;\n }\n const existingFile = this.getFileByPath(fileOrPath);\n if (existingFile) {\n return existingFile;\n }\n return this.createFile(fileOrPath);\n }\n\n private ensureRenderer(renderer: ICodegenRenderer): ICodegenRenderer {\n if (!this.renderers.has(renderer.id)) {\n this.renderers.set(renderer.id, renderer);\n }\n return this.renderers.get(renderer.id)!;\n }\n\n get files(): ReadonlyArray<CodegenFile> {\n return [...this.filesOrder];\n }\n\n getAllSymbols(): ReadonlyArray<ICodegenSymbol> {\n return this.filesOrder.flatMap((file) => file.getAllSymbols());\n }\n\n getFileByPath(path: string): CodegenFile | undefined {\n return this.filesMap.get(path);\n }\n\n render(meta?: ICodegenMeta): ReadonlyArray<ICodegenOutput> {\n const results: Array<ICodegenOutput> = [];\n for (const file of this.filesOrder) {\n if (!file.meta.renderer) continue;\n const renderer = this.renderers.get(file.meta.renderer);\n if (!renderer) continue;\n results.push(renderer.render(file, meta));\n }\n return results;\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@hey-api/codegen-core",
3
+ "version": "0.0.1",
4
+ "description": "🧱 TypeScript framework for generating structured, multi-file source code from abstract syntax trees.",
5
+ "homepage": "https://heyapi.dev/",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/hey-api/openapi-ts.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/hey-api/openapi-ts/issues"
12
+ },
13
+ "license": "MIT",
14
+ "author": {
15
+ "email": "lubos@heyapi.dev",
16
+ "name": "Hey API",
17
+ "url": "https://heyapi.dev"
18
+ },
19
+ "funding": "https://github.com/sponsors/hey-api",
20
+ "keywords": [
21
+ "codegen",
22
+ "generator",
23
+ "javascript",
24
+ "node",
25
+ "typescript"
26
+ ],
27
+ "type": "module",
28
+ "main": "./dist/index.cjs",
29
+ "module": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "import": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ },
37
+ "require": {
38
+ "types": "./dist/index.d.cts",
39
+ "default": "./dist/index.cjs"
40
+ }
41
+ },
42
+ "./package.json": "./package.json"
43
+ },
44
+ "files": [
45
+ "dist",
46
+ "LICENSE.md"
47
+ ],
48
+ "engines": {
49
+ "node": "^18.18.0 || ^20.9.0 || >=22.10.0"
50
+ },
51
+ "peerDependencies": {
52
+ "typescript": ">=5.5.3"
53
+ },
54
+ "devDependencies": {
55
+ "eslint": "9.17.0",
56
+ "prettier": "3.4.2",
57
+ "typescript": "5.8.3",
58
+ "@config/vite-base": "0.0.1"
59
+ },
60
+ "scripts": {
61
+ "build": "tsup && pnpm check-exports",
62
+ "check-exports": "attw --pack . --profile node16",
63
+ "dev": "tsup --watch",
64
+ "test:coverage": "vitest run --coverage",
65
+ "test:update": "vitest watch --update",
66
+ "test:watch": "vitest watch",
67
+ "test": "vitest run",
68
+ "typecheck": "tsc --noEmit"
69
+ }
70
+ }