@atomic-ehr/codegen 0.0.1-canary.20250927094522.7f26cfe → 0.0.1-canary.20250930075344.1c0b689

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 (45) hide show
  1. package/dist/api/builder.d.ts +2 -2
  2. package/dist/api/builder.js +1 -1
  3. package/dist/api/generators/base/BaseGenerator.js +5 -12
  4. package/dist/api/generators/base/FileManager.js +1 -3
  5. package/dist/api/generators/base/TemplateEngine.js +2 -2
  6. package/dist/api/generators/base/TypeScriptTypeMapper.js +1 -1
  7. package/dist/api/generators/base/builders/FileBuilder.js +6 -8
  8. package/dist/api/generators/base/errors.js +1 -3
  9. package/dist/api/generators/base/index.d.ts +1 -1
  10. package/dist/api/generators/base/index.js +1 -2
  11. package/dist/api/generators/base/types.d.ts +1 -1
  12. package/dist/api/generators/typescript.d.ts +1 -3
  13. package/dist/api/generators/typescript.js +13 -38
  14. package/dist/api/index.d.ts +1 -2
  15. package/dist/cli/commands/typeschema/generate.js +4 -10
  16. package/dist/cli/commands/typeschema.js +1 -2
  17. package/dist/cli/index.js +54 -54
  18. package/dist/cli/utils/spinner.js +2 -6
  19. package/dist/config.js +4 -16
  20. package/dist/logger.js +4 -13
  21. package/dist/typeschema/cache.d.ts +1 -1
  22. package/dist/typeschema/core/binding.d.ts +4 -7
  23. package/dist/typeschema/core/binding.js +16 -30
  24. package/dist/typeschema/core/field-builder.d.ts +6 -14
  25. package/dist/typeschema/core/field-builder.js +42 -88
  26. package/dist/typeschema/core/identifier.d.ts +5 -8
  27. package/dist/typeschema/core/identifier.js +8 -15
  28. package/dist/typeschema/core/nested-types.d.ts +4 -7
  29. package/dist/typeschema/core/nested-types.js +15 -14
  30. package/dist/typeschema/core/transformer.d.ts +6 -13
  31. package/dist/typeschema/core/transformer.js +74 -144
  32. package/dist/typeschema/generator.d.ts +5 -8
  33. package/dist/typeschema/generator.js +26 -24
  34. package/dist/typeschema/parser.d.ts +7 -8
  35. package/dist/typeschema/parser.js +67 -82
  36. package/dist/typeschema/profile/processor.d.ts +3 -2
  37. package/dist/typeschema/profile/processor.js +13 -23
  38. package/dist/typeschema/register.d.ts +16 -0
  39. package/dist/typeschema/register.js +65 -0
  40. package/dist/typeschema/types.d.ts +32 -21
  41. package/dist/typeschema/types.js +5 -5
  42. package/dist/typeschema/value-set/processor.d.ts +2 -2
  43. package/dist/typeschema/value-set/processor.js +3 -3
  44. package/dist/utils/codegen-logger.js +4 -12
  45. package/package.json +2 -2
@@ -4,10 +4,10 @@
4
4
  * Provides a fluent, chainable API for common codegen use cases with pre-built generators.
5
5
  * This builder pattern allows users to configure generation in a declarative way.
6
6
  */
7
- import type { Config, TypeSchemaConfig } from "../config";
7
+ import type { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
8
8
  import type { TypeSchema } from "@typeschema/types";
9
+ import type { Config, TypeSchemaConfig } from "../config";
9
10
  import type { CodegenLogger } from "../utils/codegen-logger";
10
- import type { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
11
11
  /**
12
12
  * Configuration options for the API builder
13
13
  */
@@ -4,7 +4,7 @@
4
4
  * Provides a fluent, chainable API for common codegen use cases with pre-built generators.
5
5
  * This builder pattern allows users to configure generation in a declarative way.
6
6
  */
7
- import { TypeSchemaCache, TypeSchemaGenerator, TypeSchemaParser, } from "@typeschema/index";
7
+ import { TypeSchemaCache, TypeSchemaGenerator, TypeSchemaParser } from "@typeschema/index";
8
8
  import { createLogger } from "../utils/codegen-logger";
9
9
  import { TypeScriptGenerator } from "./generators/typescript";
10
10
  /**
@@ -255,17 +255,14 @@ export class BaseGenerator {
255
255
  if (options.outputDir && typeof options.outputDir !== "string") {
256
256
  errors.push("outputDir must be a string");
257
257
  }
258
- if (options.overwrite !== undefined &&
259
- typeof options.overwrite !== "boolean") {
258
+ if (options.overwrite !== undefined && typeof options.overwrite !== "boolean") {
260
259
  errors.push("overwrite must be a boolean");
261
260
  }
262
- if (options.validate !== undefined &&
263
- typeof options.validate !== "boolean") {
261
+ if (options.validate !== undefined && typeof options.validate !== "boolean") {
264
262
  errors.push("validate must be a boolean");
265
263
  }
266
264
  // Warnings for suboptimal configuration
267
- if (options.outputDir &&
268
- !require("node:path").isAbsolute(options.outputDir)) {
265
+ if (options.outputDir && !require("node:path").isAbsolute(options.outputDir)) {
269
266
  warnings.push("Using relative path for outputDir - consider using absolute path");
270
267
  suggestions.push("Use path.resolve() to convert to absolute path");
271
268
  }
@@ -559,13 +556,9 @@ export class BaseGenerator {
559
556
  return {
560
557
  filesGenerated: this.generatedFiles.length,
561
558
  totalSize,
562
- averageFileSize: this.generatedFiles.length > 0
563
- ? totalSize / this.generatedFiles.length
564
- : 0,
559
+ averageFileSize: this.generatedFiles.length > 0 ? totalSize / this.generatedFiles.length : 0,
565
560
  generationTime,
566
- averageTimePerFile: this.generatedFiles.length > 0
567
- ? generationTime / this.generatedFiles.length
568
- : 0,
561
+ averageTimePerFile: this.generatedFiles.length > 0 ? generationTime / this.generatedFiles.length : 0,
569
562
  cacheHitRate: 0, // TODO: Implement cache hit tracking
570
563
  };
571
564
  }
@@ -72,9 +72,7 @@ export class FileManager {
72
72
  catch (error) {
73
73
  throw new FileOperationError(`Failed to write file '${relativePath}': ${error}`, "write", fullPath, error instanceof Error ? error : undefined, {
74
74
  canRetry: true,
75
- alternativePaths: [
76
- join(process.cwd(), "backup-output", relativePath),
77
- ],
75
+ alternativePaths: [join(process.cwd(), "backup-output", relativePath)],
78
76
  });
79
77
  }
80
78
  }
@@ -115,8 +115,8 @@ export class TemplateEngine {
115
115
  .toLowerCase()
116
116
  .replace(/^_/, ""));
117
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);
118
+ this.registerHelper("join", (arr, separator = ", ") => (Array.isArray(arr) ? arr.join(separator) : ""));
119
+ this.registerHelper("length", (arr) => (Array.isArray(arr) ? arr.length : 0));
120
120
  // Logic helpers
121
121
  this.registerHelper("eq", (a, b) => a === b);
122
122
  this.registerHelper("ne", (a, b) => a !== b);
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * TypeScript-specific type mapper implementation
3
3
  */
4
- import { TypeMapper, } from "./TypeMapper";
4
+ import { TypeMapper } from "./TypeMapper";
5
5
  /**
6
6
  * TypeScript type mapper
7
7
  */
@@ -238,7 +238,9 @@ export class FileBuilder {
238
238
  await this.validateContent(context.content);
239
239
  }
240
240
  // Write file
241
- const result = await this.config.fileManager.writeFile(this.config.filename, context.content, { encoding: this.options.encoding });
241
+ const result = await this.config.fileManager.writeFile(this.config.filename, context.content, {
242
+ encoding: this.options.encoding,
243
+ });
242
244
  const stats = {
243
245
  size: result.size,
244
246
  generationTime: 0, // Set by caller if needed
@@ -346,9 +348,7 @@ export class FileBuilder {
346
348
  // Basic prettification
347
349
  return content
348
350
  .replace(/\n{3,}/g, "\n\n") // Max 2 consecutive newlines
349
- .replace(/\t/g, this.options.formatting?.useTabs
350
- ? "\t"
351
- : " ".repeat(this.options.formatting?.indentSize || 2))
351
+ .replace(/\t/g, this.options.formatting?.useTabs ? "\t" : " ".repeat(this.options.formatting?.indentSize || 2))
352
352
  .trim();
353
353
  }
354
354
  /**
@@ -372,10 +372,8 @@ export class FileBuilder {
372
372
  issues.push(`Unmatched parentheses: ${openParens} open, ${closeParens} close`);
373
373
  }
374
374
  // Check for basic TypeScript syntax issues
375
- if (this.config.filename.endsWith(".ts") ||
376
- this.config.filename.endsWith(".tsx")) {
377
- if (content.includes("interface") &&
378
- !content.match(/interface\s+\w+\s*\{/)) {
375
+ if (this.config.filename.endsWith(".ts") || this.config.filename.endsWith(".tsx")) {
376
+ if (content.includes("interface") && !content.match(/interface\s+\w+\s*\{/)) {
379
377
  issues.push("Invalid interface syntax detected");
380
378
  }
381
379
  }
@@ -636,9 +636,7 @@ export class BatchOperationError extends GeneratorError {
636
636
  }
637
637
  // Show most common suggestions with proper prefixing
638
638
  suggestions.push("💡 Most relevant suggestions:");
639
- const prefixedSuggestions = uniqueSuggestions
640
- .slice(0, 8)
641
- .map((suggestion) => ` ${suggestion}`);
639
+ const prefixedSuggestions = uniqueSuggestions.slice(0, 8).map((suggestion) => ` ${suggestion}`);
642
640
  suggestions.push(...prefixedSuggestions);
643
641
  return suggestions;
644
642
  }
@@ -23,7 +23,7 @@ export type { FileManagerOptions, WriteFileResult } from "./FileManager";
23
23
  export { FileManager } from "./FileManager";
24
24
  export { BatchOperationError, ConfigurationError, createErrorWithContext, FileOperationError, GeneratorError, SchemaValidationError, TemplateError, TypeMappingError, } from "./errors";
25
25
  export type { AfterSaveHook, BatchResult, BeforeSaveHook, ErrorHook, FileContext, FileStats, GeneratedFile, ProgressCallback, } from "./types";
26
- export type { TypeSchema, Identifier } from "@typeschema/index";
26
+ export type { Identifier, TypeSchema } from "@typeschema/index";
27
27
  export type { CodegenLogger } from "../../../utils/codegen-logger";
28
28
  /**
29
29
  * Helper type for creating generator options with language-specific extensions
@@ -87,8 +87,7 @@ export function validateGeneratorOptions(options) {
87
87
  if (options.outputDir && typeof options.outputDir !== "string") {
88
88
  errors.push("outputDir must be a string");
89
89
  }
90
- if (options.overwrite !== undefined &&
91
- typeof options.overwrite !== "boolean") {
90
+ if (options.overwrite !== undefined && typeof options.overwrite !== "boolean") {
92
91
  errors.push("overwrite must be a boolean");
93
92
  }
94
93
  if (options.validate !== undefined && typeof options.validate !== "boolean") {
@@ -4,7 +4,7 @@
4
4
  * This module provides the foundational type definitions that all generators
5
5
  * build upon, ensuring consistency and type safety across the system.
6
6
  */
7
- import type { TypeSchema, Identifier } from "@typeschema/index";
7
+ import type { Identifier, TypeSchema } from "@typeschema/index";
8
8
  import type { CodegenLogger } from "../../../utils/codegen-logger";
9
9
  /**
10
10
  * Base configuration options that all generators must support
@@ -66,14 +66,13 @@ export interface GeneratedTypeScript {
66
66
  * Uses the new BaseGenerator architecture for maintainability and extensibility.
67
67
  */
68
68
  export declare class TypeScriptGenerator extends BaseGenerator<TypeScriptGeneratorOptions, GeneratedFile[]> {
69
- private readonly profilesByPackage;
70
69
  private readonly resourceTypes;
71
70
  private collectedValueSets;
72
71
  private get tsOptions();
73
72
  protected getLanguageName(): string;
74
73
  protected getFileExtension(): string;
75
74
  protected createTypeMapper(): TypeMapper;
76
- protected generateSchemaContent(schema: TypeSchema, context: TemplateContext): Promise<string>;
75
+ protected generateSchemaContent(schema: TypeSchema, _context: TemplateContext): Promise<string>;
77
76
  protected filterAndSortSchemas(schemas: TypeSchema[]): TypeSchema[];
78
77
  protected validateContent(content: string, context: TemplateContext): Promise<void>;
79
78
  /**
@@ -112,7 +111,6 @@ export declare class TypeScriptGenerator extends BaseGenerator<TypeScriptGenerat
112
111
  private getFilenameForSchema;
113
112
  private extractImportsFromContent;
114
113
  private extractExportsFromContent;
115
- private sanitizePackageName;
116
114
  /**
117
115
  * Generate special Reference interface with generics
118
116
  */
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { isBindingSchema } from "@typeschema/types";
8
8
  import { BaseGenerator } from "./base/BaseGenerator";
9
- import { TypeScriptTypeMapper, } from "./base/TypeScriptTypeMapper";
9
+ import { TypeScriptTypeMapper } from "./base/TypeScriptTypeMapper";
10
10
  /**
11
11
  * Modern TypeScript Generator
12
12
  *
@@ -14,7 +14,6 @@ import { TypeScriptTypeMapper, } from "./base/TypeScriptTypeMapper";
14
14
  * Uses the new BaseGenerator architecture for maintainability and extensibility.
15
15
  */
16
16
  export class TypeScriptGenerator extends BaseGenerator {
17
- profilesByPackage = new Map();
18
17
  resourceTypes = new Set();
19
18
  collectedValueSets = new Map();
20
19
  get tsOptions() {
@@ -29,15 +28,13 @@ export class TypeScriptGenerator extends BaseGenerator {
29
28
  createTypeMapper() {
30
29
  const options = this.options;
31
30
  return new TypeScriptTypeMapper({
32
- namingConvention: (options.namingConvention ?? "PascalCase") === "PascalCase"
33
- ? "PascalCase"
34
- : "camelCase",
31
+ namingConvention: (options.namingConvention ?? "PascalCase") === "PascalCase" ? "PascalCase" : "camelCase",
35
32
  moduleFormat: options.moduleFormat === "cjs" ? "commonjs" : "esm",
36
33
  preferUndefined: true,
37
34
  ...options.typeMapperOptions,
38
35
  });
39
36
  }
40
- async generateSchemaContent(schema, context) {
37
+ async generateSchemaContent(schema, _context) {
41
38
  // Skip unsupported schema types
42
39
  if (this.shouldSkipSchema(schema)) {
43
40
  return "";
@@ -146,10 +143,7 @@ export class TypeScriptGenerator extends BaseGenerator {
146
143
  * Check if a binding schema should generate a value set file
147
144
  */
148
145
  shouldGenerateValueSet(schema) {
149
- if (!isBindingSchema(schema) ||
150
- !schema.enum ||
151
- !Array.isArray(schema.enum) ||
152
- schema.enum.length === 0) {
146
+ if (!isBindingSchema(schema) || !schema.enum || !Array.isArray(schema.enum) || schema.enum.length === 0) {
153
147
  return false;
154
148
  }
155
149
  // Handle different value set modes
@@ -159,11 +153,10 @@ export class TypeScriptGenerator extends BaseGenerator {
159
153
  return true; // Generate for all binding strengths
160
154
  case "required-only":
161
155
  return schema.strength === "required";
162
- case "custom":
163
- const strengths = this.options.valueSetStrengths || [
164
- "required",
165
- ];
156
+ case "custom": {
157
+ const strengths = this.options.valueSetStrengths || ["required"];
166
158
  return strengths.includes(schema.strength);
159
+ }
167
160
  default:
168
161
  return schema.strength === "required";
169
162
  }
@@ -223,9 +216,7 @@ export class TypeScriptGenerator extends BaseGenerator {
223
216
  return "string"; // fallback
224
217
  }
225
218
  // Create union type from enum values
226
- const enumValues = field.enum
227
- .map((value) => `'${value}'`)
228
- .join(" | ");
219
+ const enumValues = field.enum.map((value) => `'${value}'`).join(" | ");
229
220
  return enumValues;
230
221
  }
231
222
  shouldSkipSchema(schema) {
@@ -239,7 +230,7 @@ export class TypeScriptGenerator extends BaseGenerator {
239
230
  if (!this.tsOptions.includeExtensions) {
240
231
  // Check if this is a FHIR extension by looking at the URL pattern
241
232
  const url = schema.identifier.url;
242
- if (url && url.includes("StructureDefinition/")) {
233
+ if (url?.includes("StructureDefinition/")) {
243
234
  // Extensions typically have URLs like:
244
235
  // http://hl7.org/fhir/StructureDefinition/extension-name
245
236
  // http://hl7.org/fhir/StructureDefinition/resource-extension
@@ -291,9 +282,6 @@ export class TypeScriptGenerator extends BaseGenerator {
291
282
  exports.add(this.typeMapper.formatTypeName(schema.identifier.name));
292
283
  return exports;
293
284
  }
294
- sanitizePackageName(packageName) {
295
- return packageName.replace(/[^a-zA-Z0-9-_.]/g, "-");
296
- }
297
285
  /**
298
286
  * Generate special Reference interface with generics
299
287
  */
@@ -463,15 +451,7 @@ export class TypeScriptGenerator extends BaseGenerator {
463
451
  const languageType = this.typeMapper.mapType(field.type);
464
452
  // Only import non-primitive types that are not built-in
465
453
  if (!languageType.isPrimitive && languageType.name !== "any") {
466
- const builtInTypes = [
467
- "string",
468
- "number",
469
- "boolean",
470
- "Date",
471
- "object",
472
- "unknown",
473
- "any",
474
- ];
454
+ const builtInTypes = ["string", "number", "boolean", "Date", "object", "unknown", "any"];
475
455
  if (!builtInTypes.includes(languageType.name)) {
476
456
  imports.push(languageType.name);
477
457
  }
@@ -584,15 +564,11 @@ export class TypeScriptGenerator extends BaseGenerator {
584
564
  typeString = this.typeMapper.formatTypeName(field.type.name);
585
565
  }
586
566
  }
587
- else if (typeString === "Reference" &&
588
- field.reference &&
589
- Array.isArray(field.reference)) {
567
+ else if (typeString === "Reference" && field.reference && Array.isArray(field.reference)) {
590
568
  const referenceTypes = this.extractReferenceTypes(field.reference);
591
569
  if (referenceTypes.length > 0) {
592
570
  referenceTypes.forEach((type) => this.resourceTypes.add(type));
593
- const unionType = referenceTypes
594
- .map((type) => `'${type}'`)
595
- .join(" | ");
571
+ const unionType = referenceTypes.map((type) => `'${type}'`).join(" | ");
596
572
  typeString = `Reference<${unionType}>`;
597
573
  }
598
574
  }
@@ -770,8 +746,7 @@ export class TypeScriptGenerator extends BaseGenerator {
770
746
  * Create valuesets directory and generate all value set files
771
747
  */
772
748
  async generateValueSetFiles() {
773
- if (!this.tsOptions.generateValueSets ||
774
- this.collectedValueSets.size === 0) {
749
+ if (!this.tsOptions.generateValueSets || this.collectedValueSets.size === 0) {
775
750
  return;
776
751
  }
777
752
  // Generate individual value set files in valuesets/
@@ -7,8 +7,7 @@
7
7
  * @packageDocumentation
8
8
  */
9
9
  export { TypeSchemaCache, TypeSchemaGenerator, TypeSchemaParser, } from "@typeschema/index";
10
- export type { TypeSchema, TypeSchemaField, Identifier as TypeSchemaIdentifier, } from "@typeschema/types";
11
- export type { PackageInfo } from "@typeschema/types";
10
+ export type { Identifier as TypeSchemaIdentifier, PackageMeta as PackageInfo, TypeSchema, TypeSchemaField, } from "@typeschema/types";
12
11
  export type { APIBuilderOptions, GenerationResult, ProgressCallback, } from "./builder";
13
12
  export { APIBuilder, createAPI, createAPIFromConfig, generateTypesFromFiles, generateTypesFromPackage, } from "./builder";
14
13
  export type { GeneratedFile } from "./generators/base/index";
@@ -5,8 +5,8 @@
5
5
  */
6
6
  import { mkdir, writeFile } from "node:fs/promises";
7
7
  import { dirname } from "node:path";
8
- import { loadConfig } from "../../../config";
9
8
  import { TypeSchemaGenerator } from "@typeschema/generator";
9
+ import { loadConfig } from "../../../config";
10
10
  import { complete, createLogger, list } from "../../utils/log";
11
11
  /**
12
12
  * Generate TypeSchema from FHIR packages
@@ -65,15 +65,11 @@ export const generateTypeschemaCommand = {
65
65
  log.info(`Packages: ${argv.packages.join(", ")}`);
66
66
  log.info(`Output: ${argv.output}`);
67
67
  // Merge singleFile options: CLI args take precedence over config file
68
- const singleFileOption = argv.singleFile !== undefined
69
- ? argv.singleFile
70
- : (config.typeSchema?.singleFile ?? false);
68
+ const singleFileOption = argv.singleFile !== undefined ? argv.singleFile : (config.typeSchema?.singleFile ?? false);
71
69
  const outputFormat = singleFileOption ? "ndjson" : argv.format;
72
70
  log.debug(`Format: ${outputFormat}${singleFileOption && argv.format === "json" ? " (forced from json due to singleFile)" : ""}`);
73
71
  // Merge treeshake options: CLI args take precedence over config file
74
- const treeshakeOptions = argv.treeshake && argv.treeshake.length > 0
75
- ? argv.treeshake
76
- : config.typeSchema?.treeshake;
72
+ const treeshakeOptions = argv.treeshake && argv.treeshake.length > 0 ? argv.treeshake : config.typeSchema?.treeshake;
77
73
  if (treeshakeOptions && treeshakeOptions.length > 0) {
78
74
  log.info(`Treeshaking enabled for ResourceTypes: ${treeshakeOptions.join(", ")}`);
79
75
  }
@@ -89,9 +85,7 @@ export const generateTypeschemaCommand = {
89
85
  // Generate schemas from all packages
90
86
  const allSchemas = [];
91
87
  for (const packageSpec of argv.packages) {
92
- const [name, version] = packageSpec.includes("@")
93
- ? packageSpec.split("@")
94
- : [packageSpec, undefined];
88
+ const [name, version] = packageSpec.includes("@") ? packageSpec.split("@") : [packageSpec, undefined];
95
89
  log.progress(`Processing package: ${name}${version ? `@${version}` : ""}`);
96
90
  const schemas = await generator.generateFromPackage(name, version);
97
91
  allSchemas.push(...schemas);
@@ -32,8 +32,7 @@ export const typeschemaCommand = {
32
32
  return;
33
33
  }
34
34
  // If unknown subcommand provided, show error and available commands
35
- if (argv.subcommand &&
36
- !["generate", "validate", "merge"].includes(argv.subcommand)) {
35
+ if (argv.subcommand && !["generate", "validate", "merge"].includes(argv.subcommand)) {
37
36
  error(`Unknown typeschema subcommand: ${argv.subcommand}\n`);
38
37
  info("Available typeschema subcommands:");
39
38
  list([