@atomic-ehr/codegen 0.0.1-canary.20250821160126.c552195 → 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.
Files changed (122) hide show
  1. package/dist/api/builder.d.ts +3 -3
  2. package/dist/api/builder.d.ts.map +1 -1
  3. package/dist/api/builder.js +374 -0
  4. package/dist/api/generators/base/BaseGenerator.d.ts +4 -4
  5. package/dist/api/generators/base/BaseGenerator.d.ts.map +1 -1
  6. package/dist/api/generators/base/BaseGenerator.js +572 -0
  7. package/dist/api/generators/base/FileManager.d.ts +2 -2
  8. package/dist/api/generators/base/FileManager.d.ts.map +1 -1
  9. package/dist/api/generators/base/FileManager.js +204 -0
  10. package/dist/api/generators/base/PythonTypeMapper.d.ts +2 -2
  11. package/dist/api/generators/base/PythonTypeMapper.d.ts.map +1 -1
  12. package/dist/api/generators/base/PythonTypeMapper.js +71 -0
  13. package/dist/api/generators/base/TemplateEngine.d.ts +1 -1
  14. package/dist/api/generators/base/TemplateEngine.d.ts.map +1 -1
  15. package/dist/api/generators/base/TemplateEngine.js +133 -0
  16. package/dist/api/generators/base/TypeMapper.js +153 -0
  17. package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +1 -1
  18. package/dist/api/generators/base/TypeScriptTypeMapper.d.ts.map +1 -1
  19. package/dist/api/generators/base/TypeScriptTypeMapper.js +232 -0
  20. package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +4 -4
  21. package/dist/api/generators/base/builders/DirectoryBuilder.d.ts.map +1 -1
  22. package/dist/api/generators/base/builders/DirectoryBuilder.js +215 -0
  23. package/dist/api/generators/base/builders/FileBuilder.d.ts +2 -2
  24. package/dist/api/generators/base/builders/FileBuilder.d.ts.map +1 -1
  25. package/dist/api/generators/base/builders/FileBuilder.js +408 -0
  26. package/dist/api/generators/base/builders/IndexBuilder.d.ts +2 -2
  27. package/dist/api/generators/base/builders/IndexBuilder.d.ts.map +1 -1
  28. package/dist/api/generators/base/builders/IndexBuilder.js +290 -0
  29. package/dist/api/generators/base/enhanced-errors.d.ts +2 -2
  30. package/dist/api/generators/base/enhanced-errors.d.ts.map +1 -1
  31. package/dist/api/generators/base/enhanced-errors.js +259 -0
  32. package/dist/api/generators/base/error-handler.d.ts +1 -1
  33. package/dist/api/generators/base/error-handler.d.ts.map +1 -1
  34. package/dist/api/generators/base/error-handler.js +243 -0
  35. package/dist/api/generators/base/errors.d.ts +2 -2
  36. package/dist/api/generators/base/errors.d.ts.map +1 -1
  37. package/dist/api/generators/base/errors.js +694 -0
  38. package/dist/api/generators/base/index.d.ts +22 -22
  39. package/dist/api/generators/base/index.d.ts.map +1 -1
  40. package/dist/api/generators/base/index.js +161 -0
  41. package/dist/api/generators/base/types.d.ts +2 -2
  42. package/dist/api/generators/base/types.d.ts.map +1 -1
  43. package/dist/api/generators/base/types.js +12 -0
  44. package/dist/api/generators/rest-client.d.ts +2 -2
  45. package/dist/api/generators/rest-client.d.ts.map +1 -1
  46. package/dist/api/generators/rest-client.js +847 -0
  47. package/dist/api/generators/search-parameter-enhancer.d.ts +1 -1
  48. package/dist/api/generators/search-parameter-enhancer.d.ts.map +1 -1
  49. package/dist/api/generators/search-parameter-enhancer.js +801 -0
  50. package/dist/api/generators/types.js +4 -0
  51. package/dist/api/generators/typescript.d.ts +3 -3
  52. package/dist/api/generators/typescript.d.ts.map +1 -1
  53. package/dist/api/generators/typescript.js +537 -0
  54. package/dist/api/generators/validation-generator.js +632 -0
  55. package/dist/api/index.d.ts +10 -10
  56. package/dist/api/index.d.ts.map +1 -1
  57. package/dist/api/index.js +51 -0
  58. package/dist/cli/commands/generate/typescript.d.ts +1 -1
  59. package/dist/cli/commands/generate/typescript.d.ts.map +1 -1
  60. package/dist/cli/commands/generate/typescript.js +52 -0
  61. package/dist/cli/commands/generate.d.ts +5 -12
  62. package/dist/cli/commands/generate.d.ts.map +1 -1
  63. package/dist/cli/commands/generate.js +158 -0
  64. package/dist/cli/commands/index.d.ts +2 -1
  65. package/dist/cli/commands/index.d.ts.map +1 -1
  66. package/dist/cli/commands/index.js +100 -0
  67. package/dist/cli/commands/typeschema/generate.js +130 -0
  68. package/dist/cli/commands/typeschema.js +48 -0
  69. package/dist/cli/index.js +12 -8664
  70. package/dist/cli/utils/log.d.ts +2 -2
  71. package/dist/cli/utils/log.d.ts.map +1 -1
  72. package/dist/cli/utils/log.js +23 -0
  73. package/dist/cli/utils/prompts.js +224 -0
  74. package/dist/cli/utils/spinner.js +270 -0
  75. package/dist/config.d.ts +22 -2
  76. package/dist/config.d.ts.map +1 -1
  77. package/dist/config.js +703 -0
  78. package/dist/index.d.ts +2 -2
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +84 -38
  81. package/dist/logger.js +290 -0
  82. package/dist/typeschema/cache.d.ts +2 -2
  83. package/dist/typeschema/cache.d.ts.map +1 -1
  84. package/dist/typeschema/cache.js +285 -0
  85. package/dist/typeschema/core/binding.d.ts +1 -1
  86. package/dist/typeschema/core/binding.d.ts.map +1 -1
  87. package/dist/typeschema/core/binding.js +187 -0
  88. package/dist/typeschema/core/field-builder.d.ts +1 -1
  89. package/dist/typeschema/core/field-builder.d.ts.map +1 -1
  90. package/dist/typeschema/core/field-builder.js +259 -0
  91. package/dist/typeschema/core/identifier.js +117 -0
  92. package/dist/typeschema/core/nested-types.d.ts +1 -1
  93. package/dist/typeschema/core/nested-types.d.ts.map +1 -1
  94. package/dist/typeschema/core/nested-types.js +111 -0
  95. package/dist/typeschema/core/transformer.d.ts +2 -2
  96. package/dist/typeschema/core/transformer.d.ts.map +1 -1
  97. package/dist/typeschema/core/transformer.js +345 -0
  98. package/dist/typeschema/generator.d.ts +3 -3
  99. package/dist/typeschema/generator.d.ts.map +1 -1
  100. package/dist/typeschema/generator.js +352 -0
  101. package/dist/typeschema/index.d.ts +14 -14
  102. package/dist/typeschema/index.d.ts.map +1 -1
  103. package/dist/typeschema/index.js +92 -0
  104. package/dist/typeschema/parser.d.ts +2 -2
  105. package/dist/typeschema/parser.d.ts.map +1 -1
  106. package/dist/typeschema/parser.js +310 -0
  107. package/dist/typeschema/profile/processor.d.ts +1 -1
  108. package/dist/typeschema/profile/processor.d.ts.map +1 -1
  109. package/dist/typeschema/profile/processor.js +268 -0
  110. package/dist/typeschema/schema.js +456 -0
  111. package/dist/typeschema/type-schema.types.js +39 -0
  112. package/dist/typeschema/types.js +4 -0
  113. package/dist/typeschema/utils.d.ts +1 -1
  114. package/dist/typeschema/utils.d.ts.map +1 -1
  115. package/dist/typeschema/utils.js +13 -0
  116. package/dist/typeschema/value-set/processor.d.ts +1 -1
  117. package/dist/typeschema/value-set/processor.d.ts.map +1 -1
  118. package/dist/typeschema/value-set/processor.js +168 -0
  119. package/dist/utils/codegen-logger.js +204 -0
  120. package/dist/utils.js +42 -0
  121. package/package.json +15 -4
  122. package/dist/index-e7pfye24.js +0 -8532
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Value Set Processing
3
+ *
4
+ * Functions for transforming FHIR ValueSets into TypeSchema format
5
+ */
6
+ import { buildValueSetIdentifier } from "../core/identifier.js";
7
+ /**
8
+ * Extract concepts from a CodeSystem
9
+ */
10
+ async function extractCodeSystemConcepts(codeSystemUrl, manager) {
11
+ try {
12
+ const codeSystem = await manager.resolve(codeSystemUrl);
13
+ if (!codeSystem || codeSystem.resourceType !== "CodeSystem") {
14
+ return undefined;
15
+ }
16
+ const concepts = [];
17
+ // Recursive function to extract concepts (including nested ones)
18
+ const extractConcepts = (conceptList, system) => {
19
+ for (const concept of conceptList) {
20
+ concepts.push({
21
+ system,
22
+ code: concept.code,
23
+ display: concept.display,
24
+ });
25
+ // Handle nested concepts
26
+ if (concept.concept) {
27
+ extractConcepts(concept.concept, system);
28
+ }
29
+ }
30
+ };
31
+ if (codeSystem.concept) {
32
+ extractConcepts(codeSystem.concept, codeSystemUrl);
33
+ }
34
+ return concepts;
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ }
40
+ /**
41
+ * Process ValueSet compose include/exclude
42
+ */
43
+ async function processComposeItem(item, manager) {
44
+ const concepts = [];
45
+ // Direct concept list
46
+ if (item.concept) {
47
+ for (const concept of item.concept) {
48
+ concepts.push({
49
+ system: item.system,
50
+ code: concept.code,
51
+ display: concept.display,
52
+ });
53
+ }
54
+ return concepts;
55
+ }
56
+ // Include all from CodeSystem (no filter)
57
+ if (item.system && !item.filter) {
58
+ const csConcepts = await extractCodeSystemConcepts(item.system, manager);
59
+ if (csConcepts) {
60
+ concepts.push(...csConcepts);
61
+ }
62
+ }
63
+ // Include from another ValueSet
64
+ if (item.valueSet) {
65
+ for (const vsUrl of item.valueSet) {
66
+ try {
67
+ const vs = await manager.resolve(vsUrl);
68
+ if (vs) {
69
+ const vsConcepts = await extractValueSetConcepts(vs, manager);
70
+ if (vsConcepts) {
71
+ concepts.push(...vsConcepts);
72
+ }
73
+ }
74
+ }
75
+ catch {
76
+ // Ignore if we can't resolve
77
+ }
78
+ }
79
+ }
80
+ return concepts;
81
+ }
82
+ /**
83
+ * Extract all concepts from a ValueSet
84
+ */
85
+ export async function extractValueSetConcepts(valueSet, manager) {
86
+ try {
87
+ const concepts = [];
88
+ if (valueSet.compose) {
89
+ // Process includes
90
+ if (valueSet.compose.include) {
91
+ for (const include of valueSet.compose.include) {
92
+ const includeConcepts = await processComposeItem(include, manager);
93
+ concepts.push(...includeConcepts);
94
+ }
95
+ }
96
+ // Process excludes (remove them from the list)
97
+ if (valueSet.compose.exclude) {
98
+ const excludeConcepts = new Set();
99
+ for (const exclude of valueSet.compose.exclude) {
100
+ const excludeList = await processComposeItem(exclude, manager);
101
+ for (const concept of excludeList) {
102
+ excludeConcepts.add(`${concept.system}|${concept.code}`);
103
+ }
104
+ }
105
+ // Filter out excluded concepts
106
+ return concepts.filter((c) => !excludeConcepts.has(`${c.system}|${c.code}`));
107
+ }
108
+ }
109
+ return concepts.length > 0 ? concepts : undefined;
110
+ }
111
+ catch (error) {
112
+ console.error("Error extracting ValueSet concepts:", error);
113
+ return undefined;
114
+ }
115
+ }
116
+ /**
117
+ * Transform a FHIR ValueSet to TypeSchema format
118
+ */
119
+ export async function transformValueSet(valueSet, manager, packageInfo) {
120
+ const identifier = buildValueSetIdentifier(valueSet.url, valueSet, packageInfo);
121
+ const typeSchemaValueSet = {
122
+ identifier,
123
+ };
124
+ // Add description if present
125
+ if (valueSet.description) {
126
+ typeSchemaValueSet.description = valueSet.description;
127
+ }
128
+ // Try to extract concepts
129
+ const concepts = await extractValueSetConcepts(valueSet, manager);
130
+ if (concepts && concepts.length > 0) {
131
+ // If we can expand, include the concepts
132
+ typeSchemaValueSet.concept = concepts;
133
+ }
134
+ else if (valueSet.compose) {
135
+ // If we can't expand, include the compose structure
136
+ typeSchemaValueSet.compose = valueSet.compose;
137
+ }
138
+ // Extract dependencies from compose
139
+ if (valueSet.compose) {
140
+ const deps = [];
141
+ // Helper to process include/exclude
142
+ const processCompose = (items) => {
143
+ for (const item of items) {
144
+ if (item.system) {
145
+ deps.push({
146
+ kind: "value-set",
147
+ package: packageInfo?.name || "undefined",
148
+ version: packageInfo?.version || "undefined",
149
+ name: item.system.split("/").pop() || "unknown",
150
+ url: item.system,
151
+ });
152
+ }
153
+ if (item.valueSet) {
154
+ for (const vsUrl of item.valueSet) {
155
+ deps.push(buildValueSetIdentifier(vsUrl, undefined, packageInfo));
156
+ }
157
+ }
158
+ }
159
+ };
160
+ if (valueSet.compose.include) {
161
+ processCompose(valueSet.compose.include);
162
+ }
163
+ if (valueSet.compose.exclude) {
164
+ processCompose(valueSet.compose.exclude);
165
+ }
166
+ }
167
+ return typeSchemaValueSet;
168
+ }
@@ -0,0 +1,204 @@
1
+ /**
2
+ * CodeGen Logger
3
+ *
4
+ * Clean, colorful logging designed for code generation tools
5
+ */
6
+ import pc from "picocolors";
7
+ /**
8
+ * Simple code generation logger with pretty colors and clean formatting
9
+ */
10
+ export class CodegenLogger {
11
+ options;
12
+ constructor(options = {}) {
13
+ this.options = {
14
+ timestamp: false,
15
+ verbose: false,
16
+ ...options,
17
+ };
18
+ }
19
+ formatMessage(level, message, color) {
20
+ const timestamp = this.options.timestamp
21
+ ? `${pc.gray(new Date().toLocaleTimeString())} `
22
+ : "";
23
+ const prefix = this.options.prefix
24
+ ? `${pc.cyan(`[${this.options.prefix}]`)} `
25
+ : "";
26
+ return `${timestamp}${color(level)} ${prefix}${message}`;
27
+ }
28
+ /**
29
+ * Success message with checkmark
30
+ */
31
+ success(message) {
32
+ console.log(this.formatMessage("✅", message, pc.green));
33
+ }
34
+ /**
35
+ * Error message with X mark
36
+ */
37
+ error(message, error) {
38
+ console.error(this.formatMessage("❌", message, pc.red));
39
+ if (error && this.options.verbose) {
40
+ console.error(pc.red(` ${error.message}`));
41
+ if (error.stack) {
42
+ console.error(pc.gray(error.stack));
43
+ }
44
+ }
45
+ }
46
+ /**
47
+ * Warning message with warning sign
48
+ */
49
+ warn(message) {
50
+ console.warn(this.formatMessage("⚠️", message, pc.yellow));
51
+ }
52
+ /**
53
+ * Info message with info icon
54
+ */
55
+ info(message) {
56
+ console.log(this.formatMessage("ℹ️", message, pc.blue));
57
+ }
58
+ /**
59
+ * Debug message (only shows in verbose mode)
60
+ */
61
+ debug(message) {
62
+ if (this.options.verbose) {
63
+ console.log(this.formatMessage("🐛", message, pc.magenta));
64
+ }
65
+ }
66
+ /**
67
+ * Step message with rocket
68
+ */
69
+ step(message) {
70
+ console.log(this.formatMessage("🚀", message, pc.cyan));
71
+ }
72
+ /**
73
+ * Progress message with clock
74
+ */
75
+ progress(message) {
76
+ console.log(this.formatMessage("⏳", message, pc.blue));
77
+ }
78
+ /**
79
+ * Plain message (no icon, just colored text)
80
+ */
81
+ plain(message, color = (s) => s) {
82
+ const timestamp = this.options.timestamp
83
+ ? `${pc.gray(new Date().toLocaleTimeString())} `
84
+ : "";
85
+ const prefix = this.options.prefix
86
+ ? `${pc.cyan(`[${this.options.prefix}]`)} `
87
+ : "";
88
+ console.log(`${timestamp}${prefix}${color(message)}`);
89
+ }
90
+ /**
91
+ * Dimmed/gray text for less important info
92
+ */
93
+ dim(message) {
94
+ this.plain(message, pc.gray);
95
+ }
96
+ /**
97
+ * Create a child logger with a prefix
98
+ */
99
+ child(prefix) {
100
+ return new CodegenLogger({
101
+ ...this.options,
102
+ prefix: this.options.prefix ? `${this.options.prefix}:${prefix}` : prefix,
103
+ });
104
+ }
105
+ /**
106
+ * Update options
107
+ */
108
+ configure(options) {
109
+ this.options = { ...this.options, ...options };
110
+ }
111
+ }
112
+ /**
113
+ * Quick logging functions for simple usage
114
+ */
115
+ const defaultLogger = new CodegenLogger();
116
+ export function success(message) {
117
+ defaultLogger.success(message);
118
+ }
119
+ export function error(message, err) {
120
+ defaultLogger.error(message, err);
121
+ }
122
+ export function warn(message) {
123
+ defaultLogger.warn(message);
124
+ }
125
+ export function info(message) {
126
+ defaultLogger.info(message);
127
+ }
128
+ export function debug(message) {
129
+ defaultLogger.debug(message);
130
+ }
131
+ export function step(message) {
132
+ defaultLogger.step(message);
133
+ }
134
+ export function progress(message) {
135
+ defaultLogger.progress(message);
136
+ }
137
+ export function plain(message, color) {
138
+ defaultLogger.plain(message, color);
139
+ }
140
+ export function dim(message) {
141
+ defaultLogger.dim(message);
142
+ }
143
+ /**
144
+ * Configure the default logger
145
+ */
146
+ export function configure(options) {
147
+ defaultLogger.configure(options);
148
+ }
149
+ /**
150
+ * Create a new logger instance
151
+ */
152
+ export function createLogger(options = {}) {
153
+ return new CodegenLogger(options);
154
+ }
155
+ /**
156
+ * Convenience functions for common CLI patterns
157
+ */
158
+ /**
159
+ * Show a command header with separator
160
+ */
161
+ export function header(title) {
162
+ console.log();
163
+ console.log(pc.cyan(pc.bold(`━━━ ${title} ━━━`)));
164
+ }
165
+ /**
166
+ * Show a section break
167
+ */
168
+ export function section(title) {
169
+ console.log();
170
+ console.log(pc.bold(title));
171
+ }
172
+ /**
173
+ * Show completion message with stats
174
+ */
175
+ export function complete(message, duration, stats) {
176
+ let msg = message;
177
+ if (duration) {
178
+ msg += ` ${pc.gray(`(${duration}ms)`)}`;
179
+ }
180
+ success(msg);
181
+ if (stats) {
182
+ Object.entries(stats).forEach(([key, value]) => {
183
+ dim(` ${key}: ${value}`);
184
+ });
185
+ }
186
+ }
187
+ /**
188
+ * Show a list of items
189
+ */
190
+ export function list(items, bullet = "•") {
191
+ items.forEach((item) => {
192
+ console.log(pc.gray(` ${bullet} ${item}`));
193
+ });
194
+ }
195
+ /**
196
+ * Show key-value pairs
197
+ */
198
+ export function table(data) {
199
+ const maxKeyLength = Math.max(...Object.keys(data).map((k) => k.length));
200
+ Object.entries(data).forEach(([key, value]) => {
201
+ const paddedKey = key.padEnd(maxKeyLength);
202
+ console.log(` ${pc.blue(paddedKey)} ${pc.gray("─")} ${value}`);
203
+ });
204
+ }
package/dist/utils.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Convert a string into PascalCase.
3
+ * Examples:
4
+ * - "patient-name" -> "PatientName"
5
+ * - "Patient name" -> "PatientName"
6
+ * - "patient_name" -> "PatientName"
7
+ * - "patientName" -> "PatientName"
8
+ */
9
+ export function toPascalCase(input) {
10
+ const parts = input
11
+ .replace(/[^A-Za-z0-9]+/g, " ")
12
+ .split(" ")
13
+ .map((p) => p.trim())
14
+ .filter(Boolean);
15
+ if (parts.length === 0)
16
+ return "";
17
+ return parts.map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
18
+ }
19
+ /**
20
+ * Split an array into chunks of a given size.
21
+ *
22
+ * Examples:
23
+ * - chunkArray([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]]
24
+ * - chunkArray([], 3) -> []
25
+ *
26
+ * @param arr - The array to split.
27
+ * @param size - The maximum size of each chunk (must be >= 1).
28
+ * @returns An array of chunks (each chunk is an array of T).
29
+ * @throws RangeError if size is less than 1.
30
+ */
31
+ export function chunkArray(arr, size) {
32
+ if (!Number.isInteger(size) || size < 1) {
33
+ throw new RangeError("chunk size must be an integer greater than 0");
34
+ }
35
+ const result = [];
36
+ if (!arr || arr.length === 0)
37
+ return result;
38
+ for (let i = 0; i < arr.length; i += size) {
39
+ result.push(arr.slice(i, i + size));
40
+ }
41
+ return result;
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomic-ehr/codegen",
3
- "version": "0.0.1-canary.20250821160126.c552195",
3
+ "version": "0.0.1-canary.20250822150706.c3b8669",
4
4
  "description": "Code generation tools for FHIR resources and TypeSchema definitions",
5
5
  "keywords": [
6
6
  "fhir",
@@ -10,9 +10,20 @@
10
10
  "ehr",
11
11
  "typeschema"
12
12
  ],
13
- "module": "./dist/index.js",
14
13
  "main": "./dist/index.js",
15
14
  "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "./cli": {
22
+ "types": "./dist/cli/index.d.ts",
23
+ "import": "./dist/cli/index.js",
24
+ "default": "./dist/cli/index.js"
25
+ }
26
+ },
16
27
  "type": "module",
17
28
  "bin": {
18
29
  "atomic-codegen": "./dist/cli/index.js"
@@ -31,9 +42,9 @@
31
42
  "test:verbose": "bun test --verbose",
32
43
  "test:helpers": "bun test test/helpers/",
33
44
  "test:quick": "bun test test/unit/ --timeout 5000",
34
- "build": "rm -rf dist && bun build src/index.ts src/cli/index.ts --outdir dist --target node --format esm --splitting --external typescript && bunx tsc --project tsconfig.build.json && chmod +x dist/cli/index.js",
45
+ "build": "rm -rf dist && bunx tsc --project tsconfig.build.json && chmod +x dist/cli/index.js",
35
46
  "typecheck": "bunx tsc --noEmit",
36
- "lint": "biome check --write ./src",
47
+ "lint": "biome check --write",
37
48
  "quality": "bun run typecheck && bun run lint && bun run test:unit",
38
49
  "cli": "bun run src/cli/index.ts",
39
50
  "codegen": "bun run src/cli/index.ts",