@atomic-ehr/codegen 0.0.1-canary.20250822114054.4ca1428 → 0.0.1-canary.20250822150706.c3b8669
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/builder.d.ts +3 -3
- package/dist/api/builder.d.ts.map +1 -1
- package/dist/api/builder.js +374 -0
- package/dist/api/generators/base/BaseGenerator.d.ts +4 -4
- package/dist/api/generators/base/BaseGenerator.d.ts.map +1 -1
- package/dist/api/generators/base/BaseGenerator.js +572 -0
- package/dist/api/generators/base/FileManager.d.ts +2 -2
- package/dist/api/generators/base/FileManager.d.ts.map +1 -1
- package/dist/api/generators/base/FileManager.js +204 -0
- package/dist/api/generators/base/PythonTypeMapper.d.ts +2 -2
- package/dist/api/generators/base/PythonTypeMapper.d.ts.map +1 -1
- package/dist/api/generators/base/PythonTypeMapper.js +71 -0
- package/dist/api/generators/base/TemplateEngine.d.ts +1 -1
- package/dist/api/generators/base/TemplateEngine.d.ts.map +1 -1
- package/dist/api/generators/base/TemplateEngine.js +133 -0
- package/dist/api/generators/base/TypeMapper.js +153 -0
- package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +1 -1
- package/dist/api/generators/base/TypeScriptTypeMapper.d.ts.map +1 -1
- package/dist/api/generators/base/TypeScriptTypeMapper.js +232 -0
- package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +4 -4
- package/dist/api/generators/base/builders/DirectoryBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/DirectoryBuilder.js +215 -0
- package/dist/api/generators/base/builders/FileBuilder.d.ts +2 -2
- package/dist/api/generators/base/builders/FileBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/FileBuilder.js +408 -0
- package/dist/api/generators/base/builders/IndexBuilder.d.ts +2 -2
- package/dist/api/generators/base/builders/IndexBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/IndexBuilder.js +290 -0
- package/dist/api/generators/base/enhanced-errors.d.ts +2 -2
- package/dist/api/generators/base/enhanced-errors.d.ts.map +1 -1
- package/dist/api/generators/base/enhanced-errors.js +259 -0
- package/dist/api/generators/base/error-handler.d.ts +1 -1
- package/dist/api/generators/base/error-handler.d.ts.map +1 -1
- package/dist/api/generators/base/error-handler.js +243 -0
- package/dist/api/generators/base/errors.d.ts +2 -2
- package/dist/api/generators/base/errors.d.ts.map +1 -1
- package/dist/api/generators/base/errors.js +694 -0
- package/dist/api/generators/base/index.d.ts +22 -22
- package/dist/api/generators/base/index.d.ts.map +1 -1
- package/dist/api/generators/base/index.js +161 -0
- package/dist/api/generators/base/types.d.ts +2 -2
- package/dist/api/generators/base/types.d.ts.map +1 -1
- package/dist/api/generators/base/types.js +12 -0
- package/dist/api/generators/rest-client.d.ts +2 -2
- package/dist/api/generators/rest-client.d.ts.map +1 -1
- package/dist/api/generators/rest-client.js +847 -0
- package/dist/api/generators/search-parameter-enhancer.d.ts +1 -1
- package/dist/api/generators/search-parameter-enhancer.d.ts.map +1 -1
- package/dist/api/generators/search-parameter-enhancer.js +801 -0
- package/dist/api/generators/types.js +4 -0
- package/dist/api/generators/typescript.d.ts +3 -3
- package/dist/api/generators/typescript.d.ts.map +1 -1
- package/dist/api/generators/typescript.js +537 -0
- package/dist/api/generators/validation-generator.js +632 -0
- package/dist/api/index.d.ts +10 -10
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +51 -0
- package/dist/cli/commands/generate/typescript.d.ts +1 -1
- package/dist/cli/commands/generate/typescript.d.ts.map +1 -1
- package/dist/cli/commands/generate/typescript.js +52 -0
- package/dist/cli/commands/generate.d.ts +5 -12
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +158 -0
- package/dist/cli/commands/index.d.ts +2 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +100 -0
- package/dist/cli/commands/typeschema/generate.js +130 -0
- package/dist/cli/commands/typeschema.js +48 -0
- package/dist/cli/index.js +12 -8664
- package/dist/cli/utils/log.d.ts +2 -2
- package/dist/cli/utils/log.d.ts.map +1 -1
- package/dist/cli/utils/log.js +23 -0
- package/dist/cli/utils/prompts.js +224 -0
- package/dist/cli/utils/spinner.js +270 -0
- package/dist/config.js +703 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +84 -40
- package/dist/logger.js +290 -0
- package/dist/typeschema/cache.d.ts +2 -2
- package/dist/typeschema/cache.d.ts.map +1 -1
- package/dist/typeschema/cache.js +285 -0
- package/dist/typeschema/core/binding.d.ts +1 -1
- package/dist/typeschema/core/binding.d.ts.map +1 -1
- package/dist/typeschema/core/binding.js +187 -0
- package/dist/typeschema/core/field-builder.d.ts +1 -1
- package/dist/typeschema/core/field-builder.d.ts.map +1 -1
- package/dist/typeschema/core/field-builder.js +259 -0
- package/dist/typeschema/core/identifier.js +117 -0
- package/dist/typeschema/core/nested-types.d.ts +1 -1
- package/dist/typeschema/core/nested-types.d.ts.map +1 -1
- package/dist/typeschema/core/nested-types.js +111 -0
- package/dist/typeschema/core/transformer.d.ts +2 -2
- package/dist/typeschema/core/transformer.d.ts.map +1 -1
- package/dist/typeschema/core/transformer.js +345 -0
- package/dist/typeschema/generator.d.ts +3 -3
- package/dist/typeschema/generator.d.ts.map +1 -1
- package/dist/typeschema/generator.js +352 -0
- package/dist/typeschema/index.d.ts +14 -14
- package/dist/typeschema/index.d.ts.map +1 -1
- package/dist/typeschema/index.js +92 -0
- package/dist/typeschema/parser.d.ts +2 -2
- package/dist/typeschema/parser.d.ts.map +1 -1
- package/dist/typeschema/parser.js +310 -0
- package/dist/typeschema/profile/processor.d.ts +1 -1
- package/dist/typeschema/profile/processor.d.ts.map +1 -1
- package/dist/typeschema/profile/processor.js +268 -0
- package/dist/typeschema/schema.js +456 -0
- package/dist/typeschema/type-schema.types.js +39 -0
- package/dist/typeschema/types.js +4 -0
- package/dist/typeschema/utils.d.ts +1 -1
- package/dist/typeschema/utils.d.ts.map +1 -1
- package/dist/typeschema/utils.js +13 -0
- package/dist/typeschema/value-set/processor.d.ts +1 -1
- package/dist/typeschema/value-set/processor.d.ts.map +1 -1
- package/dist/typeschema/value-set/processor.js +168 -0
- package/dist/utils/codegen-logger.js +204 -0
- package/dist/utils.js +42 -0
- package/package.json +15 -4
- package/dist/index-fgcebdva.js +0 -8515
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core file management system with batching and performance optimizations
|
|
3
|
+
*
|
|
4
|
+
* This replaces scattered writeFile calls with a comprehensive file management
|
|
5
|
+
* system that provides better error handling, performance, and maintainability.
|
|
6
|
+
*/
|
|
7
|
+
import { access, mkdir, rm, stat, writeFile } from "node:fs/promises";
|
|
8
|
+
import { dirname, join, relative } from "node:path";
|
|
9
|
+
import { FileOperationError } from "./errors.js";
|
|
10
|
+
/**
|
|
11
|
+
* High-performance file manager with batching and error recovery
|
|
12
|
+
*
|
|
13
|
+
* Features:
|
|
14
|
+
* - Automatic directory creation
|
|
15
|
+
* - Batch operations for better performance
|
|
16
|
+
* - Comprehensive error handling with recovery suggestions
|
|
17
|
+
* - Import path resolution
|
|
18
|
+
* - File existence checks
|
|
19
|
+
*/
|
|
20
|
+
export class FileManager {
|
|
21
|
+
options;
|
|
22
|
+
logger;
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.options = {
|
|
25
|
+
overwrite: true,
|
|
26
|
+
batchSize: 10,
|
|
27
|
+
...options,
|
|
28
|
+
};
|
|
29
|
+
this.logger = options.logger;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Write a file with automatic directory creation
|
|
33
|
+
* @param relativePath Path relative to output directory
|
|
34
|
+
* @param content File content
|
|
35
|
+
* @param options Write options
|
|
36
|
+
*/
|
|
37
|
+
async writeFile(relativePath, content, options = {}) {
|
|
38
|
+
const startTime = performance.now();
|
|
39
|
+
const fullPath = join(this.options.outputDir, relativePath);
|
|
40
|
+
const encoding = options.encoding || "utf-8";
|
|
41
|
+
const overwrite = options.overwrite ?? this.options.overwrite;
|
|
42
|
+
try {
|
|
43
|
+
// Check if file exists and overwrite is disabled
|
|
44
|
+
if (!overwrite) {
|
|
45
|
+
try {
|
|
46
|
+
await access(fullPath);
|
|
47
|
+
this.logger.debug(`Skipping existing file: ${relativePath}`);
|
|
48
|
+
const stats = await stat(fullPath);
|
|
49
|
+
return {
|
|
50
|
+
path: fullPath,
|
|
51
|
+
size: stats.size,
|
|
52
|
+
writeTime: 0,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// File doesn't exist, continue with write
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Ensure directory exists
|
|
60
|
+
await this.ensureDirectory(dirname(fullPath));
|
|
61
|
+
// Write file
|
|
62
|
+
await writeFile(fullPath, content, encoding);
|
|
63
|
+
const writeTime = performance.now() - startTime;
|
|
64
|
+
const size = Buffer.byteLength(content, encoding);
|
|
65
|
+
this.logger.debug(`Written ${relativePath} (${size} bytes, ${writeTime.toFixed(2)}ms)`);
|
|
66
|
+
return {
|
|
67
|
+
path: fullPath,
|
|
68
|
+
size,
|
|
69
|
+
writeTime,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
throw new FileOperationError(`Failed to write file '${relativePath}': ${error}`, "write", fullPath, error instanceof Error ? error : undefined, {
|
|
74
|
+
canRetry: true,
|
|
75
|
+
alternativePaths: [
|
|
76
|
+
join(process.cwd(), "backup-output", relativePath),
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Write multiple files in batch for better performance
|
|
83
|
+
* @param files Map of relative path to content
|
|
84
|
+
*/
|
|
85
|
+
async writeBatch(files) {
|
|
86
|
+
this.logger.debug(`Writing batch of ${files.size} files`);
|
|
87
|
+
const entries = Array.from(files.entries());
|
|
88
|
+
const results = [];
|
|
89
|
+
// Process in batches to avoid overwhelming the filesystem
|
|
90
|
+
for (let i = 0; i < entries.length; i += this.options.batchSize) {
|
|
91
|
+
const batch = entries.slice(i, i + this.options.batchSize);
|
|
92
|
+
const batchPromises = batch.map(([path, content]) => this.writeFile(path, content));
|
|
93
|
+
const batchResults = await Promise.all(batchPromises);
|
|
94
|
+
results.push(...batchResults);
|
|
95
|
+
// Small delay between batches to be filesystem-friendly
|
|
96
|
+
if (i + this.options.batchSize < entries.length) {
|
|
97
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return results;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Ensure directory exists, creating parent directories as needed
|
|
104
|
+
* @param dirPath Full directory path
|
|
105
|
+
*/
|
|
106
|
+
async ensureDirectory(dirPath) {
|
|
107
|
+
try {
|
|
108
|
+
await mkdir(dirPath, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
throw new FileOperationError(`Failed to create directory '${dirPath}': ${error}`, "create", dirPath, error instanceof Error ? error : undefined, {
|
|
112
|
+
canRetry: true,
|
|
113
|
+
permissionFix: `chmod 755 "${dirname(dirPath)}"`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Clean directory by removing all contents
|
|
119
|
+
* @param relativePath Path relative to output directory
|
|
120
|
+
*/
|
|
121
|
+
async cleanDirectory(relativePath = ".") {
|
|
122
|
+
const fullPath = join(this.options.outputDir, relativePath);
|
|
123
|
+
try {
|
|
124
|
+
await access(fullPath);
|
|
125
|
+
this.logger.debug(`Cleaning directory: ${relativePath}`);
|
|
126
|
+
await rm(fullPath, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
// Directory doesn't exist - that's fine
|
|
130
|
+
if (error?.code !== "ENOENT") {
|
|
131
|
+
throw new FileOperationError(`Failed to clean directory '${relativePath}': ${error}`, "delete", fullPath, error instanceof Error ? error : undefined, {
|
|
132
|
+
canRetry: true,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get relative import path between two files
|
|
139
|
+
* @param fromFile Source file path
|
|
140
|
+
* @param toFile Target file path
|
|
141
|
+
*/
|
|
142
|
+
getRelativeImportPath(fromFile, toFile) {
|
|
143
|
+
const from = dirname(join(this.options.outputDir, fromFile));
|
|
144
|
+
const to = join(this.options.outputDir, toFile);
|
|
145
|
+
let relativePath = relative(from, to);
|
|
146
|
+
// Ensure relative imports start with './' or '../'
|
|
147
|
+
if (!relativePath.startsWith(".")) {
|
|
148
|
+
relativePath = `./${relativePath}`;
|
|
149
|
+
}
|
|
150
|
+
// Remove file extension for imports (handle .d.ts files properly)
|
|
151
|
+
return relativePath.replace(/\.(d\.ts|ts|tsx|js|jsx)$/, "");
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Check if a file would be overwritten
|
|
155
|
+
* @param relativePath Path relative to output directory
|
|
156
|
+
*/
|
|
157
|
+
async wouldOverwrite(relativePath) {
|
|
158
|
+
const fullPath = join(this.options.outputDir, relativePath);
|
|
159
|
+
try {
|
|
160
|
+
await access(fullPath);
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get file statistics
|
|
169
|
+
* @param relativePath Path relative to output directory
|
|
170
|
+
*/
|
|
171
|
+
async getFileStats(relativePath) {
|
|
172
|
+
const fullPath = join(this.options.outputDir, relativePath);
|
|
173
|
+
try {
|
|
174
|
+
const stats = await stat(fullPath);
|
|
175
|
+
return {
|
|
176
|
+
size: stats.size,
|
|
177
|
+
generationTime: 0, // Will be set by caller
|
|
178
|
+
writeTime: 0, // Will be set by caller
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get output directory
|
|
187
|
+
*/
|
|
188
|
+
getOutputDirectory() {
|
|
189
|
+
return this.options.outputDir;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Set batch size for operations
|
|
193
|
+
* @param size Batch size
|
|
194
|
+
*/
|
|
195
|
+
setBatchSize(size) {
|
|
196
|
+
this.options.batchSize = Math.max(1, Math.min(50, size));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get current batch size
|
|
200
|
+
*/
|
|
201
|
+
getBatchSize() {
|
|
202
|
+
return this.options.batchSize;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Python type mapper implementation (basic version)
|
|
3
3
|
*/
|
|
4
|
-
import type { TypeSchemaIdentifier } from "../../../typeschema";
|
|
5
|
-
import { type LanguageType, TypeMapper } from "./TypeMapper";
|
|
4
|
+
import type { TypeSchemaIdentifier } from "../../../typeschema/index.js";
|
|
5
|
+
import { type LanguageType, TypeMapper } from "./TypeMapper.js";
|
|
6
6
|
export declare class PythonTypeMapper extends TypeMapper {
|
|
7
7
|
getLanguageName(): string;
|
|
8
8
|
mapPrimitive(fhirType: string): LanguageType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PythonTypeMapper.d.ts","sourceRoot":"","sources":["../../../../src/api/generators/base/PythonTypeMapper.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"PythonTypeMapper.d.ts","sourceRoot":"","sources":["../../../../src/api/generators/base/PythonTypeMapper.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,KAAK,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,qBAAa,gBAAiB,SAAQ,UAAU;IAC/C,eAAe,IAAI,MAAM;IAIzB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY;IAkB5C,YAAY,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,YAAY;IAS5D,QAAQ,CAAC,WAAW,EAAE,YAAY,GAAG,YAAY;IAUjD,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,GAAG,YAAY;IAUhE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY;IAQvD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIpC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAQrC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAGpC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python type mapper implementation (basic version)
|
|
3
|
+
*/
|
|
4
|
+
import { TypeMapper } from "./TypeMapper.js";
|
|
5
|
+
export class PythonTypeMapper extends TypeMapper {
|
|
6
|
+
getLanguageName() {
|
|
7
|
+
return "Python";
|
|
8
|
+
}
|
|
9
|
+
mapPrimitive(fhirType) {
|
|
10
|
+
const primitiveMap = {
|
|
11
|
+
string: "str",
|
|
12
|
+
integer: "int",
|
|
13
|
+
decimal: "float",
|
|
14
|
+
boolean: "bool",
|
|
15
|
+
dateTime: "datetime",
|
|
16
|
+
date: "date",
|
|
17
|
+
time: "time",
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
name: primitiveMap[fhirType] || "Any",
|
|
21
|
+
isPrimitive: true,
|
|
22
|
+
nullable: false,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
mapReference(_targets) {
|
|
26
|
+
return {
|
|
27
|
+
name: "Reference",
|
|
28
|
+
isPrimitive: false,
|
|
29
|
+
importPath: ".reference",
|
|
30
|
+
nullable: false,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
mapArray(elementType) {
|
|
34
|
+
return {
|
|
35
|
+
name: `List[${elementType.name}]`,
|
|
36
|
+
isPrimitive: false,
|
|
37
|
+
importPath: "typing",
|
|
38
|
+
isArray: true,
|
|
39
|
+
nullable: false,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
mapOptional(type, required) {
|
|
43
|
+
if (required)
|
|
44
|
+
return type;
|
|
45
|
+
return {
|
|
46
|
+
...type,
|
|
47
|
+
name: `Optional[${type.name}]`,
|
|
48
|
+
nullable: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
mapEnum(_values, name) {
|
|
52
|
+
return {
|
|
53
|
+
name: name ? this.formatTypeName(name) : "Literal",
|
|
54
|
+
isPrimitive: false,
|
|
55
|
+
nullable: false,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
formatTypeName(name) {
|
|
59
|
+
return this.applyNamingConvention(name);
|
|
60
|
+
}
|
|
61
|
+
formatFieldName(name) {
|
|
62
|
+
// Convert camelCase to snake_case
|
|
63
|
+
return name
|
|
64
|
+
.replace(/([A-Z])/g, "_$1")
|
|
65
|
+
.toLowerCase()
|
|
66
|
+
.replace(/^_/, "");
|
|
67
|
+
}
|
|
68
|
+
formatFileName(name) {
|
|
69
|
+
return this.formatFieldName(name);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - Function templates (TypeScript functions)
|
|
8
8
|
* - Inline templates (template literals)
|
|
9
9
|
*/
|
|
10
|
-
import type { CodegenLogger } from "../../../utils/codegen-logger";
|
|
10
|
+
import type { CodegenLogger } from "../../../utils/codegen-logger.js";
|
|
11
11
|
/**
|
|
12
12
|
* Template context passed to templates
|
|
13
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TemplateEngine.d.ts","sourceRoot":"","sources":["../../../../src/api/generators/base/TemplateEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"TemplateEngine.d.ts","sourceRoot":"","sources":["../../../../src/api/generators/base/TemplateEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAGtE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,iCAAiC;IACjC,MAAM,CAAC,EAAE,GAAG,CAAC;IAEb,8CAA8C;IAC9C,UAAU,CAAC,EAAE,GAAG,CAAC;IAEjB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,wBAAwB;IACxB,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE9B,mBAAmB;IACnB,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAEtB,6BAA6B;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,sBAAsB;IACtB,MAAM,CAAC,EAAE,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;IAE9C,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEnC,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAChB,OAAO,EAAE,eAAe,CAAC;QACzB,QAAQ,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACH;AAED;;GAEG;AACH,8BAAsB,cAAc;IACnC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,SAAS,mBAA0B;IACtD,SAAS,CAAC,QAAQ,CAAC,aAAa,mBAA0B;IAC1D,SAAS,CAAC,QAAQ,CAAC,OAAO,wBAA+B;gBAE7C,OAAO,EAAE;QAAE,MAAM,EAAE,aAAa,CAAA;KAAE;IAS9C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CACd,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,MAAM,CAAC;IAElB;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAC3B,OAAO,CAAC,EAAE,eAAe,GACvB,IAAI;IAEP;;;OAGG;IACH,QAAQ,CAAC,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrE;;;;OAIG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI;IAKpD;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE;IAIjC;;;OAGG;IACH,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAa/D;;;OAGG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI1C;;;OAGG;IACH,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IASjD;;OAEG;IACH,cAAc,IAAI,IAAI;IAMtB;;;;OAIG;IACH,SAAS,CAAC,eAAe,CACxB,OAAO,EAAE,eAAe,EACxB,cAAc,GAAE,MAAM,EAAO,GAC3B,IAAI;IAgBP;;OAEG;IACH,SAAS,CAAC,sBAAsB,IAAI,IAAI;CAwDxC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract template engine for code generation
|
|
3
|
+
*
|
|
4
|
+
* Supports multiple template formats:
|
|
5
|
+
* - Handlebars templates (.hbs)
|
|
6
|
+
* - String templates (.template)
|
|
7
|
+
* - Function templates (TypeScript functions)
|
|
8
|
+
* - Inline templates (template literals)
|
|
9
|
+
*/
|
|
10
|
+
import { TemplateError } from "./errors.js";
|
|
11
|
+
/**
|
|
12
|
+
* Abstract template engine
|
|
13
|
+
*/
|
|
14
|
+
export class TemplateEngine {
|
|
15
|
+
logger;
|
|
16
|
+
templates = new Map();
|
|
17
|
+
templateCache = new Map();
|
|
18
|
+
helpers = new Map();
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.logger = options.logger;
|
|
21
|
+
this.registerDefaultHelpers();
|
|
22
|
+
}
|
|
23
|
+
// ==========================================
|
|
24
|
+
// Concrete Methods
|
|
25
|
+
// ==========================================
|
|
26
|
+
/**
|
|
27
|
+
* Register a template helper function
|
|
28
|
+
* @param name Helper name
|
|
29
|
+
* @param helper Helper function
|
|
30
|
+
*/
|
|
31
|
+
registerHelper(name, helper) {
|
|
32
|
+
this.helpers.set(name, helper);
|
|
33
|
+
this.logger.debug(`Registered template helper: ${name}`);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get available template names
|
|
37
|
+
*/
|
|
38
|
+
getAvailableTemplates() {
|
|
39
|
+
return Array.from(this.templates.keys()).sort();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get template information
|
|
43
|
+
* @param templateName Template name
|
|
44
|
+
*/
|
|
45
|
+
getTemplateInfo(templateName) {
|
|
46
|
+
const template = this.templates.get(templateName);
|
|
47
|
+
if (!template)
|
|
48
|
+
return undefined;
|
|
49
|
+
return {
|
|
50
|
+
name: templateName,
|
|
51
|
+
format: template.format || "unknown",
|
|
52
|
+
path: template.path,
|
|
53
|
+
description: template.description,
|
|
54
|
+
examples: template.examples || [],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Check if template exists
|
|
59
|
+
* @param templateName Template name
|
|
60
|
+
*/
|
|
61
|
+
hasTemplate(templateName) {
|
|
62
|
+
return this.templates.has(templateName);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Remove a template
|
|
66
|
+
* @param templateName Template name
|
|
67
|
+
*/
|
|
68
|
+
unregisterTemplate(templateName) {
|
|
69
|
+
const removed = this.templates.delete(templateName);
|
|
70
|
+
this.templateCache.delete(templateName);
|
|
71
|
+
if (removed) {
|
|
72
|
+
this.logger.debug(`Unregistered template: ${templateName}`);
|
|
73
|
+
}
|
|
74
|
+
return removed;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Clear all templates and cache
|
|
78
|
+
*/
|
|
79
|
+
clearTemplates() {
|
|
80
|
+
this.templates.clear();
|
|
81
|
+
this.templateCache.clear();
|
|
82
|
+
this.logger.debug("Cleared all templates");
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Validate template context
|
|
86
|
+
* @param context Template context
|
|
87
|
+
* @param requiredFields Required context fields
|
|
88
|
+
*/
|
|
89
|
+
validateContext(context, requiredFields = []) {
|
|
90
|
+
for (const field of requiredFields) {
|
|
91
|
+
if (!(field in context)) {
|
|
92
|
+
throw new TemplateError(`Missing required context field: ${field}`, "unknown", context, {
|
|
93
|
+
missingVariables: [field],
|
|
94
|
+
availableTemplates: this.getAvailableTemplates(),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Register default template helpers
|
|
101
|
+
*/
|
|
102
|
+
registerDefaultHelpers() {
|
|
103
|
+
// String manipulation helpers
|
|
104
|
+
this.registerHelper("capitalize", (str) => str.charAt(0).toUpperCase() + str.slice(1));
|
|
105
|
+
this.registerHelper("lowercase", (str) => str.toLowerCase());
|
|
106
|
+
this.registerHelper("uppercase", (str) => str.toUpperCase());
|
|
107
|
+
this.registerHelper("camelCase", (str) => str.replace(/[-_\s]+(.)/g, (_, char) => char.toUpperCase()));
|
|
108
|
+
this.registerHelper("pascalCase", (str) => {
|
|
109
|
+
const camelCase = str.replace(/[-_\s]+(.)/g, (_, char) => char.toUpperCase());
|
|
110
|
+
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
111
|
+
});
|
|
112
|
+
this.registerHelper("snakeCase", (str) => str
|
|
113
|
+
.replace(/([A-Z])/g, "_$1")
|
|
114
|
+
.replace(/[-\s]+/g, "_")
|
|
115
|
+
.toLowerCase()
|
|
116
|
+
.replace(/^_/, ""));
|
|
117
|
+
// Array helpers
|
|
118
|
+
this.registerHelper("join", (arr, separator = ", ") => Array.isArray(arr) ? arr.join(separator) : "");
|
|
119
|
+
this.registerHelper("length", (arr) => Array.isArray(arr) ? arr.length : 0);
|
|
120
|
+
// Logic helpers
|
|
121
|
+
this.registerHelper("eq", (a, b) => a === b);
|
|
122
|
+
this.registerHelper("ne", (a, b) => a !== b);
|
|
123
|
+
this.registerHelper("gt", (a, b) => a > b);
|
|
124
|
+
this.registerHelper("lt", (a, b) => a < b);
|
|
125
|
+
// Utility helpers
|
|
126
|
+
this.registerHelper("json", (obj) => JSON.stringify(obj, null, 2));
|
|
127
|
+
this.registerHelper("indent", (str, spaces = 2) => str
|
|
128
|
+
.split("\n")
|
|
129
|
+
.map((line) => " ".repeat(spaces) + line)
|
|
130
|
+
.join("\n"));
|
|
131
|
+
this.registerHelper("timestamp", () => new Date().toISOString());
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base class for language-specific type mapping
|
|
3
|
+
*
|
|
4
|
+
* This provides the interface that all language generators must implement
|
|
5
|
+
* to convert FHIR TypeSchema types into their target language types.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Abstract type mapper for language-specific type conversion
|
|
9
|
+
*/
|
|
10
|
+
export class TypeMapper {
|
|
11
|
+
options;
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
this.options = {
|
|
14
|
+
generateNullable: true,
|
|
15
|
+
strictTypes: true,
|
|
16
|
+
customMappings: {},
|
|
17
|
+
preferArraySyntax: true,
|
|
18
|
+
namingConvention: "PascalCase",
|
|
19
|
+
...options,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// ==========================================
|
|
23
|
+
// Concrete Methods - Shared functionality
|
|
24
|
+
// ==========================================
|
|
25
|
+
/**
|
|
26
|
+
* Main entry point for type mapping
|
|
27
|
+
* @param schemaType Type from TypeSchema
|
|
28
|
+
*/
|
|
29
|
+
mapType(schemaType) {
|
|
30
|
+
// Handle primitive types
|
|
31
|
+
if (typeof schemaType === "string") {
|
|
32
|
+
return this.mapPrimitive(schemaType);
|
|
33
|
+
}
|
|
34
|
+
// Handle complex types
|
|
35
|
+
if (schemaType && typeof schemaType === "object") {
|
|
36
|
+
const kind = schemaType.kind || schemaType.type;
|
|
37
|
+
switch (kind) {
|
|
38
|
+
case "primitive-type":
|
|
39
|
+
return this.mapPrimitive(schemaType.name);
|
|
40
|
+
case "reference":
|
|
41
|
+
return this.mapReference(schemaType.targets || []);
|
|
42
|
+
case "array": {
|
|
43
|
+
const elementType = this.mapType(schemaType.element);
|
|
44
|
+
return this.mapArray(elementType);
|
|
45
|
+
}
|
|
46
|
+
case "enum":
|
|
47
|
+
case "coded":
|
|
48
|
+
return this.mapEnum(schemaType.values || [], schemaType.name);
|
|
49
|
+
case "complex-type":
|
|
50
|
+
case "resource":
|
|
51
|
+
return this.mapComplexType(schemaType);
|
|
52
|
+
default:
|
|
53
|
+
return this.mapUnknownType(schemaType);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return this.mapUnknownType(schemaType);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Map a complex type (resource, complex-type)
|
|
60
|
+
* @param schemaType Complex type from schema
|
|
61
|
+
*/
|
|
62
|
+
mapComplexType(schemaType) {
|
|
63
|
+
const typeName = this.formatTypeName(schemaType.name || "Unknown");
|
|
64
|
+
return {
|
|
65
|
+
name: typeName,
|
|
66
|
+
isPrimitive: false,
|
|
67
|
+
importPath: this.calculateImportPath(schemaType),
|
|
68
|
+
nullable: !schemaType.required && this.options.generateNullable,
|
|
69
|
+
metadata: {
|
|
70
|
+
kind: schemaType.kind,
|
|
71
|
+
package: schemaType.package,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Handle unknown/unmapped types
|
|
77
|
+
* @param schemaType Unknown type
|
|
78
|
+
*/
|
|
79
|
+
mapUnknownType(schemaType) {
|
|
80
|
+
// console.warn(`Unknown type encountered:`, schemaType);
|
|
81
|
+
return {
|
|
82
|
+
name: "unknown",
|
|
83
|
+
isPrimitive: true,
|
|
84
|
+
nullable: true,
|
|
85
|
+
metadata: {
|
|
86
|
+
originalType: schemaType,
|
|
87
|
+
warning: "unmapped_type",
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Calculate import path for a type
|
|
93
|
+
* @param schemaType Type to calculate import for
|
|
94
|
+
*/
|
|
95
|
+
calculateImportPath(schemaType) {
|
|
96
|
+
if (!schemaType.name)
|
|
97
|
+
return undefined;
|
|
98
|
+
const fileName = this.formatFileName(schemaType.name);
|
|
99
|
+
return `./${fileName}`;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Apply naming convention to a string
|
|
103
|
+
* @param name Input name
|
|
104
|
+
*/
|
|
105
|
+
applyNamingConvention(name) {
|
|
106
|
+
switch (this.options.namingConvention) {
|
|
107
|
+
case "camelCase":
|
|
108
|
+
return toCamelCase(name);
|
|
109
|
+
case "PascalCase":
|
|
110
|
+
return toPascalCase(name);
|
|
111
|
+
case "snake_case":
|
|
112
|
+
return toSnakeCase(name);
|
|
113
|
+
case "kebab-case":
|
|
114
|
+
return toKebabCase(name);
|
|
115
|
+
default:
|
|
116
|
+
return name;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get custom mapping if available
|
|
121
|
+
* @param type Original type name
|
|
122
|
+
*/
|
|
123
|
+
getCustomMapping(type) {
|
|
124
|
+
return this.options.customMappings[type];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Check if type should be nullable
|
|
128
|
+
* @param required Whether field is required
|
|
129
|
+
*/
|
|
130
|
+
shouldBeNullable(required) {
|
|
131
|
+
return !required && this.options.generateNullable;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// ==========================================
|
|
135
|
+
// Utility Functions
|
|
136
|
+
// ==========================================
|
|
137
|
+
function toCamelCase(str) {
|
|
138
|
+
return str.replace(/[-_\s]+(.)?/g, (_, char) => char?.toUpperCase() || "");
|
|
139
|
+
}
|
|
140
|
+
function toPascalCase(str) {
|
|
141
|
+
const camelCase = toCamelCase(str);
|
|
142
|
+
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
143
|
+
}
|
|
144
|
+
function toSnakeCase(str) {
|
|
145
|
+
return str
|
|
146
|
+
.replace(/([A-Z])/g, "_$1")
|
|
147
|
+
.replace(/[-\s]+/g, "_")
|
|
148
|
+
.toLowerCase()
|
|
149
|
+
.replace(/^_/, "");
|
|
150
|
+
}
|
|
151
|
+
function toKebabCase(str) {
|
|
152
|
+
return toSnakeCase(str).replace(/_/g, "-");
|
|
153
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* TypeScript-specific type mapper implementation
|
|
3
3
|
*/
|
|
4
4
|
import type { TypeSchemaIdentifier } from "../../../typeschema/type-schema.types";
|
|
5
|
-
import { type LanguageType, TypeMapper, type TypeMapperOptions } from "./TypeMapper";
|
|
5
|
+
import { type LanguageType, TypeMapper, type TypeMapperOptions } from "./TypeMapper.js";
|
|
6
6
|
/**
|
|
7
7
|
* TypeScript-specific options
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypeScriptTypeMapper.d.ts","sourceRoot":"","sources":["../../../../src/api/generators/base/TypeScriptTypeMapper.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EACN,KAAK,YAAY,EACjB,UAAU,EACV,KAAK,iBAAiB,EACtB,MAAM,
|
|
1
|
+
{"version":3,"file":"TypeScriptTypeMapper.d.ts","sourceRoot":"","sources":["../../../../src/api/generators/base/TypeScriptTypeMapper.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EACN,KAAK,YAAY,EACjB,UAAU,EACV,KAAK,iBAAiB,EACtB,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,MAAM,WAAW,2BAA4B,SAAQ,iBAAiB;IACrE,2DAA2D;IAC3D,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,uDAAuD;IACvD,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,8DAA8D;IAC9D,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,gCAAgC;IAChC,YAAY,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC;CAClC;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwC;gBAEtD,OAAO,GAAE,2BAAgC;IAarD,eAAe,IAAI,MAAM;IAIzB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY;IAgE5C,YAAY,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,YAAY;IA6C3D,QAAQ,CAAC,WAAW,EAAE,YAAY,GAAG,YAAY;IA4BjD,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,GAAG,YAAY;IAmBhE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY;IAiBtD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIpC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIrC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIpC;;;;;OAKG;IACH,sBAAsB,CACrB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,YAAY,EACvB,QAAQ,EAAE,OAAO,GACf,MAAM;IAOT;;;OAGG;IACH,uBAAuB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS;IAY/D;;;OAGG;IACH,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE;CAYnD"}
|