@atomic-ehr/codegen 0.0.1-canary.20251006092200.fdb4a88 → 0.0.1-canary.20251006094042.7f0be72
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/cli/index.js +45 -124
- package/dist/index.d.ts +2130 -62
- package/dist/index.js +5865 -84
- package/dist/index.js.map +1 -0
- package/package.json +3 -7
- package/dist/api/builder.d.ts +0 -154
- package/dist/api/builder.js +0 -341
- package/dist/api/generators/base/BaseGenerator.d.ts +0 -186
- package/dist/api/generators/base/BaseGenerator.js +0 -565
- package/dist/api/generators/base/FileManager.d.ts +0 -88
- package/dist/api/generators/base/FileManager.js +0 -202
- package/dist/api/generators/base/PythonTypeMapper.d.ts +0 -16
- package/dist/api/generators/base/PythonTypeMapper.js +0 -71
- package/dist/api/generators/base/TemplateEngine.d.ts +0 -126
- package/dist/api/generators/base/TemplateEngine.js +0 -133
- package/dist/api/generators/base/TypeMapper.d.ts +0 -129
- package/dist/api/generators/base/TypeMapper.js +0 -153
- package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +0 -51
- package/dist/api/generators/base/TypeScriptTypeMapper.js +0 -232
- package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +0 -99
- package/dist/api/generators/base/builders/DirectoryBuilder.js +0 -215
- package/dist/api/generators/base/builders/FileBuilder.d.ts +0 -160
- package/dist/api/generators/base/builders/FileBuilder.js +0 -406
- package/dist/api/generators/base/builders/IndexBuilder.d.ts +0 -126
- package/dist/api/generators/base/builders/IndexBuilder.js +0 -290
- package/dist/api/generators/base/enhanced-errors.d.ts +0 -84
- package/dist/api/generators/base/enhanced-errors.js +0 -259
- package/dist/api/generators/base/error-handler.d.ts +0 -89
- package/dist/api/generators/base/error-handler.js +0 -243
- package/dist/api/generators/base/errors.d.ts +0 -251
- package/dist/api/generators/base/errors.js +0 -692
- package/dist/api/generators/base/index.d.ts +0 -99
- package/dist/api/generators/base/index.js +0 -160
- package/dist/api/generators/base/types.d.ts +0 -433
- package/dist/api/generators/base/types.js +0 -12
- package/dist/api/generators/types.d.ts +0 -53
- package/dist/api/generators/types.js +0 -4
- package/dist/api/generators/typescript.d.ts +0 -190
- package/dist/api/generators/typescript.js +0 -819
- package/dist/api/index.d.ts +0 -51
- package/dist/api/index.js +0 -50
- package/dist/cli/commands/generate/typescript.d.ts +0 -10
- package/dist/cli/commands/generate/typescript.js +0 -52
- package/dist/cli/commands/generate.d.ts +0 -15
- package/dist/cli/commands/generate.js +0 -159
- package/dist/cli/commands/index.d.ts +0 -29
- package/dist/cli/commands/index.js +0 -100
- package/dist/cli/commands/typeschema/generate.d.ts +0 -19
- package/dist/cli/commands/typeschema/generate.js +0 -124
- package/dist/cli/commands/typeschema.d.ts +0 -10
- package/dist/cli/commands/typeschema.js +0 -47
- package/dist/cli/index.d.ts +0 -9
- package/dist/cli/utils/log.d.ts +0 -10
- package/dist/cli/utils/log.js +0 -23
- package/dist/cli/utils/prompts.d.ts +0 -56
- package/dist/cli/utils/prompts.js +0 -202
- package/dist/cli/utils/spinner.d.ts +0 -110
- package/dist/cli/utils/spinner.js +0 -266
- package/dist/config.d.ts +0 -217
- package/dist/config.js +0 -591
- package/dist/logger.d.ts +0 -157
- package/dist/logger.js +0 -281
- package/dist/typeschema/cache.d.ts +0 -80
- package/dist/typeschema/cache.js +0 -239
- package/dist/typeschema/core/binding.d.ts +0 -11
- package/dist/typeschema/core/binding.js +0 -143
- package/dist/typeschema/core/field-builder.d.ts +0 -12
- package/dist/typeschema/core/field-builder.js +0 -123
- package/dist/typeschema/core/identifier.d.ts +0 -13
- package/dist/typeschema/core/identifier.js +0 -94
- package/dist/typeschema/core/nested-types.d.ts +0 -9
- package/dist/typeschema/core/nested-types.js +0 -93
- package/dist/typeschema/core/transformer.d.ts +0 -11
- package/dist/typeschema/core/transformer.js +0 -235
- package/dist/typeschema/generator.d.ts +0 -36
- package/dist/typeschema/generator.js +0 -243
- package/dist/typeschema/index.d.ts +0 -15
- package/dist/typeschema/index.js +0 -15
- package/dist/typeschema/parser.d.ts +0 -79
- package/dist/typeschema/parser.js +0 -274
- package/dist/typeschema/profile/processor.d.ts +0 -14
- package/dist/typeschema/profile/processor.js +0 -261
- package/dist/typeschema/register.d.ts +0 -21
- package/dist/typeschema/register.js +0 -117
- package/dist/typeschema/types.d.ts +0 -240
- package/dist/typeschema/types.js +0 -19
- package/dist/utils/codegen-logger.d.ts +0 -102
- package/dist/utils/codegen-logger.js +0 -196
- package/dist/utils.d.ts +0 -22
- package/dist/utils.js +0 -42
|
@@ -1,202 +0,0 @@
|
|
|
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";
|
|
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: [join(process.cwd(), "backup-output", relativePath)],
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Write multiple files in batch for better performance
|
|
81
|
-
* @param files Map of relative path to content
|
|
82
|
-
*/
|
|
83
|
-
async writeBatch(files) {
|
|
84
|
-
this.logger.debug(`Writing batch of ${files.size} files`);
|
|
85
|
-
const entries = Array.from(files.entries());
|
|
86
|
-
const results = [];
|
|
87
|
-
// Process in batches to avoid overwhelming the filesystem
|
|
88
|
-
for (let i = 0; i < entries.length; i += this.options.batchSize) {
|
|
89
|
-
const batch = entries.slice(i, i + this.options.batchSize);
|
|
90
|
-
const batchPromises = batch.map(([path, content]) => this.writeFile(path, content));
|
|
91
|
-
const batchResults = await Promise.all(batchPromises);
|
|
92
|
-
results.push(...batchResults);
|
|
93
|
-
// Small delay between batches to be filesystem-friendly
|
|
94
|
-
if (i + this.options.batchSize < entries.length) {
|
|
95
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return results;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Ensure directory exists, creating parent directories as needed
|
|
102
|
-
* @param dirPath Full directory path
|
|
103
|
-
*/
|
|
104
|
-
async ensureDirectory(dirPath) {
|
|
105
|
-
try {
|
|
106
|
-
await mkdir(dirPath, { recursive: true });
|
|
107
|
-
}
|
|
108
|
-
catch (error) {
|
|
109
|
-
throw new FileOperationError(`Failed to create directory '${dirPath}': ${error}`, "create", dirPath, error instanceof Error ? error : undefined, {
|
|
110
|
-
canRetry: true,
|
|
111
|
-
permissionFix: `chmod 755 "${dirname(dirPath)}"`,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Clean directory by removing all contents
|
|
117
|
-
* @param relativePath Path relative to output directory
|
|
118
|
-
*/
|
|
119
|
-
async cleanDirectory(relativePath = ".") {
|
|
120
|
-
const fullPath = join(this.options.outputDir, relativePath);
|
|
121
|
-
try {
|
|
122
|
-
await access(fullPath);
|
|
123
|
-
this.logger.debug(`Cleaning directory: ${relativePath}`);
|
|
124
|
-
await rm(fullPath, { recursive: true, force: true });
|
|
125
|
-
}
|
|
126
|
-
catch (error) {
|
|
127
|
-
// Directory doesn't exist - that's fine
|
|
128
|
-
if (error?.code !== "ENOENT") {
|
|
129
|
-
throw new FileOperationError(`Failed to clean directory '${relativePath}': ${error}`, "delete", fullPath, error instanceof Error ? error : undefined, {
|
|
130
|
-
canRetry: true,
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Get relative import path between two files
|
|
137
|
-
* @param fromFile Source file path
|
|
138
|
-
* @param toFile Target file path
|
|
139
|
-
*/
|
|
140
|
-
getRelativeImportPath(fromFile, toFile) {
|
|
141
|
-
const from = dirname(join(this.options.outputDir, fromFile));
|
|
142
|
-
const to = join(this.options.outputDir, toFile);
|
|
143
|
-
let relativePath = relative(from, to);
|
|
144
|
-
// Ensure relative imports start with './' or '../'
|
|
145
|
-
if (!relativePath.startsWith(".")) {
|
|
146
|
-
relativePath = `./${relativePath}`;
|
|
147
|
-
}
|
|
148
|
-
// Remove file extension for imports (handle .d.ts files properly)
|
|
149
|
-
return relativePath.replace(/\.(d\.ts|ts|tsx|js|jsx)$/, "");
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Check if a file would be overwritten
|
|
153
|
-
* @param relativePath Path relative to output directory
|
|
154
|
-
*/
|
|
155
|
-
async wouldOverwrite(relativePath) {
|
|
156
|
-
const fullPath = join(this.options.outputDir, relativePath);
|
|
157
|
-
try {
|
|
158
|
-
await access(fullPath);
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
|
-
catch {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Get file statistics
|
|
167
|
-
* @param relativePath Path relative to output directory
|
|
168
|
-
*/
|
|
169
|
-
async getFileStats(relativePath) {
|
|
170
|
-
const fullPath = join(this.options.outputDir, relativePath);
|
|
171
|
-
try {
|
|
172
|
-
const stats = await stat(fullPath);
|
|
173
|
-
return {
|
|
174
|
-
size: stats.size,
|
|
175
|
-
generationTime: 0, // Will be set by caller
|
|
176
|
-
writeTime: 0, // Will be set by caller
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
catch {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Get output directory
|
|
185
|
-
*/
|
|
186
|
-
getOutputDirectory() {
|
|
187
|
-
return this.options.outputDir;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Set batch size for operations
|
|
191
|
-
* @param size Batch size
|
|
192
|
-
*/
|
|
193
|
-
setBatchSize(size) {
|
|
194
|
-
this.options.batchSize = Math.max(1, Math.min(50, size));
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Get current batch size
|
|
198
|
-
*/
|
|
199
|
-
getBatchSize() {
|
|
200
|
-
return this.options.batchSize;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Python type mapper implementation (basic version)
|
|
3
|
-
*/
|
|
4
|
-
import type { Identifier } from "@typeschema/index";
|
|
5
|
-
import { type LanguageType, TypeMapper } from "./TypeMapper";
|
|
6
|
-
export declare class PythonTypeMapper extends TypeMapper {
|
|
7
|
-
getLanguageName(): string;
|
|
8
|
-
mapPrimitive(fhirType: string): LanguageType;
|
|
9
|
-
mapReference(_targets: Identifier[]): LanguageType;
|
|
10
|
-
mapArray(elementType: LanguageType): LanguageType;
|
|
11
|
-
mapOptional(type: LanguageType, required: boolean): LanguageType;
|
|
12
|
-
mapEnum(_values: string[], name?: string): LanguageType;
|
|
13
|
-
formatTypeName(name: string): string;
|
|
14
|
-
formatFieldName(name: string): string;
|
|
15
|
-
formatFileName(name: string): string;
|
|
16
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Python type mapper implementation (basic version)
|
|
3
|
-
*/
|
|
4
|
-
import { TypeMapper } from "./TypeMapper";
|
|
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
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
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 type { CodegenLogger } from "../../../utils/codegen-logger";
|
|
11
|
-
/**
|
|
12
|
-
* Template context passed to templates
|
|
13
|
-
*/
|
|
14
|
-
export interface TemplateContext {
|
|
15
|
-
/** The schema being processed */
|
|
16
|
-
schema?: any;
|
|
17
|
-
/** Type mapper for language-specific types */
|
|
18
|
-
typeMapper?: any;
|
|
19
|
-
/** File name being generated */
|
|
20
|
-
filename?: string;
|
|
21
|
-
/** Target language */
|
|
22
|
-
language?: string;
|
|
23
|
-
/** Timestamp for generation */
|
|
24
|
-
timestamp?: string;
|
|
25
|
-
/** Import statements */
|
|
26
|
-
imports?: Map<string, string>;
|
|
27
|
-
/** Export names */
|
|
28
|
-
exports?: Set<string>;
|
|
29
|
-
/** Any additional context */
|
|
30
|
-
[key: string]: unknown;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Template registration options
|
|
34
|
-
*/
|
|
35
|
-
export interface TemplateOptions {
|
|
36
|
-
/** Template format */
|
|
37
|
-
format?: "handlebars" | "string" | "function";
|
|
38
|
-
/** Whether to cache compiled templates */
|
|
39
|
-
cache?: boolean;
|
|
40
|
-
/** Custom helpers for the template */
|
|
41
|
-
helpers?: Record<string, Function>;
|
|
42
|
-
/** Template-specific options */
|
|
43
|
-
options?: Record<string, unknown>;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Template metadata
|
|
47
|
-
*/
|
|
48
|
-
export interface TemplateInfo {
|
|
49
|
-
name: string;
|
|
50
|
-
format: string;
|
|
51
|
-
path?: string;
|
|
52
|
-
description?: string;
|
|
53
|
-
examples?: Array<{
|
|
54
|
-
context: TemplateContext;
|
|
55
|
-
expected: string;
|
|
56
|
-
}>;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Abstract template engine
|
|
60
|
-
*/
|
|
61
|
-
export declare abstract class TemplateEngine {
|
|
62
|
-
protected readonly logger: CodegenLogger;
|
|
63
|
-
protected readonly templates: Map<string, any>;
|
|
64
|
-
protected readonly templateCache: Map<string, any>;
|
|
65
|
-
protected readonly helpers: Map<string, Function>;
|
|
66
|
-
constructor(options: {
|
|
67
|
-
logger: CodegenLogger;
|
|
68
|
-
});
|
|
69
|
-
/**
|
|
70
|
-
* Render a template with context
|
|
71
|
-
* @param templateName Name of template to render
|
|
72
|
-
* @param context Template context
|
|
73
|
-
*/
|
|
74
|
-
abstract render(templateName: string, context: TemplateContext): Promise<string>;
|
|
75
|
-
/**
|
|
76
|
-
* Register a template
|
|
77
|
-
* @param name Template name
|
|
78
|
-
* @param template Template content or function
|
|
79
|
-
* @param options Template options
|
|
80
|
-
*/
|
|
81
|
-
abstract registerTemplate(name: string, template: string | Function, options?: TemplateOptions): void;
|
|
82
|
-
/**
|
|
83
|
-
* Load templates from directory
|
|
84
|
-
* @param directory Directory containing templates
|
|
85
|
-
*/
|
|
86
|
-
abstract loadTemplatesFromDirectory(directory: string): Promise<void>;
|
|
87
|
-
/**
|
|
88
|
-
* Register a template helper function
|
|
89
|
-
* @param name Helper name
|
|
90
|
-
* @param helper Helper function
|
|
91
|
-
*/
|
|
92
|
-
registerHelper(name: string, helper: Function): void;
|
|
93
|
-
/**
|
|
94
|
-
* Get available template names
|
|
95
|
-
*/
|
|
96
|
-
getAvailableTemplates(): string[];
|
|
97
|
-
/**
|
|
98
|
-
* Get template information
|
|
99
|
-
* @param templateName Template name
|
|
100
|
-
*/
|
|
101
|
-
getTemplateInfo(templateName: string): TemplateInfo | undefined;
|
|
102
|
-
/**
|
|
103
|
-
* Check if template exists
|
|
104
|
-
* @param templateName Template name
|
|
105
|
-
*/
|
|
106
|
-
hasTemplate(templateName: string): boolean;
|
|
107
|
-
/**
|
|
108
|
-
* Remove a template
|
|
109
|
-
* @param templateName Template name
|
|
110
|
-
*/
|
|
111
|
-
unregisterTemplate(templateName: string): boolean;
|
|
112
|
-
/**
|
|
113
|
-
* Clear all templates and cache
|
|
114
|
-
*/
|
|
115
|
-
clearTemplates(): void;
|
|
116
|
-
/**
|
|
117
|
-
* Validate template context
|
|
118
|
-
* @param context Template context
|
|
119
|
-
* @param requiredFields Required context fields
|
|
120
|
-
*/
|
|
121
|
-
protected validateContext(context: TemplateContext, requiredFields?: string[]): void;
|
|
122
|
-
/**
|
|
123
|
-
* Register default template helpers
|
|
124
|
-
*/
|
|
125
|
-
protected registerDefaultHelpers(): void;
|
|
126
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
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";
|
|
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
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
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
|
-
import type { Identifier } from "@typeschema/types";
|
|
8
|
-
/**
|
|
9
|
-
* Represents a type in the target language
|
|
10
|
-
*/
|
|
11
|
-
export interface LanguageType {
|
|
12
|
-
/** The type name in the target language */
|
|
13
|
-
name: string;
|
|
14
|
-
/** Whether this is a primitive type (doesn't need imports) */
|
|
15
|
-
isPrimitive: boolean;
|
|
16
|
-
/** Import path if this type needs to be imported */
|
|
17
|
-
importPath?: string;
|
|
18
|
-
/** Generic type parameters if applicable */
|
|
19
|
-
generics?: string[];
|
|
20
|
-
/** Whether this type can be null/undefined */
|
|
21
|
-
nullable?: boolean;
|
|
22
|
-
/** Whether this is an array type */
|
|
23
|
-
isArray?: boolean;
|
|
24
|
-
/** Additional metadata for language-specific features */
|
|
25
|
-
metadata?: Record<string, unknown>;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Configuration for type mapping behavior
|
|
29
|
-
*/
|
|
30
|
-
export interface TypeMapperOptions {
|
|
31
|
-
/** Whether to generate nullable types (e.g., T | null) */
|
|
32
|
-
generateNullable?: boolean;
|
|
33
|
-
/** Whether to use strict type checking */
|
|
34
|
-
strictTypes?: boolean;
|
|
35
|
-
/** Custom type mappings */
|
|
36
|
-
customMappings?: Record<string, string>;
|
|
37
|
-
/** Whether to generate array types or use generic collections */
|
|
38
|
-
preferArraySyntax?: boolean;
|
|
39
|
-
/** Naming convention strategy */
|
|
40
|
-
namingConvention?: "camelCase" | "PascalCase" | "snake_case" | "kebab-case";
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Abstract type mapper for language-specific type conversion
|
|
44
|
-
*/
|
|
45
|
-
export declare abstract class TypeMapper {
|
|
46
|
-
protected readonly options: Required<TypeMapperOptions>;
|
|
47
|
-
constructor(options?: TypeMapperOptions);
|
|
48
|
-
/**
|
|
49
|
-
* Get the target language name (e.g., "TypeScript", "Python")
|
|
50
|
-
*/
|
|
51
|
-
abstract getLanguageName(): string;
|
|
52
|
-
/**
|
|
53
|
-
* Map a FHIR primitive type to target language
|
|
54
|
-
* @param fhirType FHIR primitive type (string, integer, boolean, etc.)
|
|
55
|
-
*/
|
|
56
|
-
abstract mapPrimitive(fhirType: string): LanguageType;
|
|
57
|
-
/**
|
|
58
|
-
* Map a reference type to target language
|
|
59
|
-
* @param targets Array of possible reference targets
|
|
60
|
-
*/
|
|
61
|
-
abstract mapReference(targets: Identifier[]): LanguageType;
|
|
62
|
-
/**
|
|
63
|
-
* Map an array type to target language
|
|
64
|
-
* @param elementType The type of array elements
|
|
65
|
-
*/
|
|
66
|
-
abstract mapArray(elementType: LanguageType): LanguageType;
|
|
67
|
-
/**
|
|
68
|
-
* Map an optional/nullable type
|
|
69
|
-
* @param type The base type
|
|
70
|
-
* @param required Whether the field is required
|
|
71
|
-
*/
|
|
72
|
-
abstract mapOptional(type: LanguageType, required: boolean): LanguageType;
|
|
73
|
-
/**
|
|
74
|
-
* Map an enum/coded type
|
|
75
|
-
* @param values Possible enum values
|
|
76
|
-
* @param name Optional enum name
|
|
77
|
-
*/
|
|
78
|
-
abstract mapEnum(values: string[], name?: string): LanguageType;
|
|
79
|
-
/**
|
|
80
|
-
* Format a type name according to language conventions
|
|
81
|
-
* @param name Raw type name
|
|
82
|
-
*/
|
|
83
|
-
abstract formatTypeName(name: string): string;
|
|
84
|
-
/**
|
|
85
|
-
* Format a field name according to language conventions
|
|
86
|
-
* @param name Raw field name
|
|
87
|
-
*/
|
|
88
|
-
abstract formatFieldName(name: string): string;
|
|
89
|
-
/**
|
|
90
|
-
* Format a file name according to language conventions
|
|
91
|
-
* @param name Raw file name (without extension)
|
|
92
|
-
*/
|
|
93
|
-
abstract formatFileName(name: string): string;
|
|
94
|
-
/**
|
|
95
|
-
* Main entry point for type mapping
|
|
96
|
-
* @param schemaType Type from TypeSchema
|
|
97
|
-
*/
|
|
98
|
-
mapType(schemaType: any): LanguageType;
|
|
99
|
-
/**
|
|
100
|
-
* Map a complex type (resource, complex-type)
|
|
101
|
-
* @param schemaType Complex type from schema
|
|
102
|
-
*/
|
|
103
|
-
protected mapComplexType(schemaType: any): LanguageType;
|
|
104
|
-
/**
|
|
105
|
-
* Handle unknown/unmapped types
|
|
106
|
-
* @param schemaType Unknown type
|
|
107
|
-
*/
|
|
108
|
-
protected mapUnknownType(schemaType: any): LanguageType;
|
|
109
|
-
/**
|
|
110
|
-
* Calculate import path for a type
|
|
111
|
-
* @param schemaType Type to calculate import for
|
|
112
|
-
*/
|
|
113
|
-
protected calculateImportPath(schemaType: any): string | undefined;
|
|
114
|
-
/**
|
|
115
|
-
* Apply naming convention to a string
|
|
116
|
-
* @param name Input name
|
|
117
|
-
*/
|
|
118
|
-
protected applyNamingConvention(name: string): string;
|
|
119
|
-
/**
|
|
120
|
-
* Get custom mapping if available
|
|
121
|
-
* @param type Original type name
|
|
122
|
-
*/
|
|
123
|
-
protected getCustomMapping(type: string): string | undefined;
|
|
124
|
-
/**
|
|
125
|
-
* Check if type should be nullable
|
|
126
|
-
* @param required Whether field is required
|
|
127
|
-
*/
|
|
128
|
-
protected shouldBeNullable(required: boolean): boolean;
|
|
129
|
-
}
|