@atomic-ehr/codegen 0.0.1-canary.20251110083633.71e5f87 → 0.0.1-canary.20251110140511.b3e2283

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/index.d.ts CHANGED
@@ -757,6 +757,10 @@ declare class TypeSchemaParser {
757
757
  private matchesIdentifier;
758
758
  }
759
759
 
760
+ type TypeSchemaShakeRule = {
761
+ ignoreFields?: string[];
762
+ };
763
+ type TreeShake = Record<string, Record<string, TypeSchemaShakeRule>>;
760
764
  interface TypeRelation {
761
765
  parent: Identifier;
762
766
  child: Identifier;
@@ -770,6 +774,7 @@ type TypeSchemaIndex = {
770
774
  collectLogicalModels: () => RegularTypeSchema[];
771
775
  collectProfiles: () => ProfileTypeSchema[];
772
776
  resolve: (id: Identifier) => TypeSchema | undefined;
777
+ resolveByUrl: (pkgName: PackageName, url: CanonicalUrl) => TypeSchema | undefined;
773
778
  resourceChildren: (id: Identifier) => Identifier[];
774
779
  tryHierarchy: (schema: TypeSchema) => TypeSchema[] | undefined;
775
780
  hierarchy: (schema: TypeSchema) => TypeSchema[];
@@ -811,6 +816,7 @@ interface APIBuilderOptions {
811
816
  typeSchemaOutputDir?: string /** if .ndjson -- put in one file, else -- split into separated files*/;
812
817
  throwException?: boolean;
813
818
  exportTypeTree?: string;
819
+ treeShake?: TreeShake;
814
820
  }
815
821
  /**
816
822
  * Progress callback for long-running operations
@@ -875,10 +881,12 @@ declare class APIBuilder {
875
881
  throwException(enabled?: boolean): APIBuilder;
876
882
  cleanOutput(enabled?: boolean): APIBuilder;
877
883
  writeTypeTree(filename: string): this;
884
+ treeShake(tree: TreeShake): this;
878
885
  writeTypeSchemas(target: string): this;
879
886
  private writeTypeSchemasToSeparateFiles;
880
887
  private writeTypeSchemasToSingleFile;
881
888
  private tryWriteTypeSchema;
889
+ cleanup(): Promise<void>;
882
890
  generate(): Promise<GenerationResult>;
883
891
  /**
884
892
  * Generate and return the results without writing to files
package/dist/index.js CHANGED
@@ -1447,6 +1447,9 @@ var isComplexTypeTypeSchema = (schema) => {
1447
1447
  var isResourceTypeSchema = (schema) => {
1448
1448
  return schema?.identifier.kind === "resource";
1449
1449
  };
1450
+ var isPrimitiveTypeSchema = (schema) => {
1451
+ return schema?.identifier.kind === "primitive-type";
1452
+ };
1450
1453
  var isLogicalTypeSchema = (schema) => {
1451
1454
  return schema?.identifier.kind === "logical";
1452
1455
  };
@@ -1456,6 +1459,9 @@ var isProfileTypeSchema = (schema) => {
1456
1459
  function isBindingSchema(schema) {
1457
1460
  return schema?.identifier.kind === "binding";
1458
1461
  }
1462
+ function isValueSetTypeSchema(schema) {
1463
+ return schema?.identifier.kind === "value-set";
1464
+ }
1459
1465
  var isNotChoiceDeclarationField = (field) => {
1460
1466
  if (!field) return false;
1461
1467
  return field.choices === void 0;
@@ -3488,6 +3494,57 @@ var groupByPackages = (typeSchemas) => {
3488
3494
  }
3489
3495
  return grouped;
3490
3496
  };
3497
+ var treeShakeTypeSchema = (schema, rule, _logger) => {
3498
+ schema = structuredClone(schema);
3499
+ if (isPrimitiveTypeSchema(schema) || isValueSetTypeSchema(schema) || isBindingSchema(schema)) return schema;
3500
+ for (const fieldName of rule.ignoreFields ?? []) {
3501
+ if (schema.fields && !schema.fields[fieldName]) throw new Error(`Field ${fieldName} not found`);
3502
+ if (schema.fields) {
3503
+ delete schema.fields[fieldName];
3504
+ }
3505
+ }
3506
+ schema.dependencies = extractDependencies(schema.identifier, schema.base, schema.fields, schema.nested);
3507
+ return schema;
3508
+ };
3509
+ var treeShake = (tsIndex, treeShake2, logger) => {
3510
+ const focusedSchemas = [];
3511
+ for (const [pkgId, requires] of Object.entries(treeShake2)) {
3512
+ for (const [url, rule] of Object.entries(requires)) {
3513
+ const schema = tsIndex.resolveByUrl(pkgId, url);
3514
+ if (!schema) throw new Error(`Schema not found for ${pkgId} ${url}`);
3515
+ const shaked2 = treeShakeTypeSchema(schema, rule);
3516
+ focusedSchemas.push(shaked2);
3517
+ }
3518
+ }
3519
+ const collectDeps = (schemas, acc) => {
3520
+ if (schemas.length === 0) return Object.values(acc);
3521
+ for (const schema of schemas) {
3522
+ acc[JSON.stringify(schema.identifier)] = schema;
3523
+ }
3524
+ const newSchemas = [];
3525
+ for (const schema of schemas) {
3526
+ if (isSpecializationTypeSchema(schema)) {
3527
+ if (!schema.dependencies) continue;
3528
+ schema.dependencies.forEach((dep) => {
3529
+ const depSchema = tsIndex.resolve(dep);
3530
+ if (!depSchema) throw new Error(`Schema not found for ${dep}`);
3531
+ const id = JSON.stringify(depSchema.identifier);
3532
+ if (!acc[id]) newSchemas.push(depSchema);
3533
+ });
3534
+ if (schema.nested) {
3535
+ for (const nest of schema.nested) {
3536
+ if (isNestedIdentifier(nest.identifier)) continue;
3537
+ const id = JSON.stringify(nest.identifier);
3538
+ if (!acc[id]) newSchemas.push(nest);
3539
+ }
3540
+ }
3541
+ }
3542
+ }
3543
+ return collectDeps(newSchemas, acc);
3544
+ };
3545
+ const shaked = collectDeps(focusedSchemas, {});
3546
+ return mkTypeSchemaIndex(shaked, logger);
3547
+ };
3491
3548
  var resourceRelatives = (schemas) => {
3492
3549
  const regularSchemas = schemas.filter(isResourceTypeSchema);
3493
3550
  const directPairs = [];
@@ -3534,6 +3591,7 @@ var mkTypeSchemaIndex = (schemas, logger) => {
3534
3591
  }
3535
3592
  const relations = resourceRelatives(schemas);
3536
3593
  const resolve2 = (id) => index[id.url]?.[id.package];
3594
+ const resolveByUrl = (pkgName, url) => index[url]?.[pkgName];
3537
3595
  const resourceChildren = (id) => {
3538
3596
  return relations.filter((relative2) => relative2.parent.name === id.name).map((relative2) => relative2.child);
3539
3597
  };
@@ -3546,6 +3604,9 @@ var mkTypeSchemaIndex = (schemas, logger) => {
3546
3604
  if (base === void 0) break;
3547
3605
  const resolved = resolve2(base);
3548
3606
  if (!resolved) {
3607
+ logger?.warn(
3608
+ `Failed to resolve base type: ${res.map((e) => `${e.identifier.url} (${e.identifier.kind})`).join(", ")}`
3609
+ );
3549
3610
  return void 0;
3550
3611
  }
3551
3612
  cur = resolved;
@@ -3640,6 +3701,7 @@ var mkTypeSchemaIndex = (schemas, logger) => {
3640
3701
  collectLogicalModels: () => schemas.filter(isLogicalTypeSchema),
3641
3702
  collectProfiles: () => schemas.filter(isProfileTypeSchema),
3642
3703
  resolve: resolve2,
3704
+ resolveByUrl,
3643
3705
  resourceChildren,
3644
3706
  tryHierarchy,
3645
3707
  hierarchy,
@@ -6115,7 +6177,8 @@ var APIBuilder = class {
6115
6177
  manager: options.manager || null,
6116
6178
  throwException: options.throwException || false,
6117
6179
  typeSchemaOutputDir: options.typeSchemaOutputDir,
6118
- exportTypeTree: options.exportTypeTree
6180
+ exportTypeTree: options.exportTypeTree,
6181
+ treeShake: options.treeShake
6119
6182
  };
6120
6183
  this.typeSchemaConfig = options.typeSchemaConfig;
6121
6184
  this.logger = options.logger || createLogger({
@@ -6235,6 +6298,10 @@ var APIBuilder = class {
6235
6298
  this.options.exportTypeTree = filename;
6236
6299
  return this;
6237
6300
  }
6301
+ treeShake(tree) {
6302
+ this.options.treeShake = tree;
6303
+ return this;
6304
+ }
6238
6305
  writeTypeSchemas(target) {
6239
6306
  this.options.typeSchemaOutputDir = target;
6240
6307
  return this;
@@ -6244,7 +6311,10 @@ var APIBuilder = class {
6244
6311
  this.logger.info(`Writing TypeSchema files to ${outputDir}/...`);
6245
6312
  const files = {};
6246
6313
  for (const ts of typeSchemas) {
6247
- const pkg = { name: ts.identifier.package, version: ts.identifier.version };
6314
+ const pkg = {
6315
+ name: ts.identifier.package,
6316
+ version: ts.identifier.version
6317
+ };
6248
6318
  const pkgPath = normalizeFileName(packageMetaToFhir(pkg));
6249
6319
  const name = normalizeFileName(`${ts.identifier.name}(${extractNameFromCanonical(ts.identifier.url)})`);
6250
6320
  const json = JSON.stringify(ts, null, 2);
@@ -6297,6 +6367,31 @@ var APIBuilder = class {
6297
6367
  if (this.options.throwException) throw error;
6298
6368
  }
6299
6369
  }
6370
+ async cleanup() {
6371
+ this.logger.info(`Cleaning outputs...`);
6372
+ try {
6373
+ this.logger.info(`Clean ${this.options.outputDir}`);
6374
+ fs.rmSync(this.options.outputDir, { recursive: true, force: true });
6375
+ if (this.options.typeSchemaOutputDir) {
6376
+ this.logger.info(`Clean ${this.options.typeSchemaOutputDir}`);
6377
+ fs.rmSync(this.options.typeSchemaOutputDir, {
6378
+ recursive: true,
6379
+ force: true
6380
+ });
6381
+ }
6382
+ if (this.options.exportTypeTree) {
6383
+ this.logger.info(`Clean ${this.options.exportTypeTree}`);
6384
+ fs.rmSync(this.options.exportTypeTree, {
6385
+ recursive: true,
6386
+ force: true
6387
+ });
6388
+ }
6389
+ } catch (error) {
6390
+ this.logger.warn(
6391
+ `Error cleaning output directory: ${error instanceof Error ? error.message : String(error)}`
6392
+ );
6393
+ }
6394
+ }
6300
6395
  async generate() {
6301
6396
  const startTime = performance.now();
6302
6397
  const result = {
@@ -6308,26 +6403,8 @@ var APIBuilder = class {
6308
6403
  duration: 0
6309
6404
  };
6310
6405
  this.logger.debug(`Starting generation with ${this.generators.size} generators`);
6311
- if (this.options.cleanOutput) {
6312
- this.logger.info(`Cleaning outputs...`);
6313
- try {
6314
- this.logger.info(`Clean ${this.options.outputDir}`);
6315
- fs.rmSync(this.options.outputDir, { recursive: true, force: true });
6316
- if (this.options.typeSchemaOutputDir) {
6317
- this.logger.info(`Clean ${this.options.typeSchemaOutputDir}`);
6318
- fs.rmSync(this.options.typeSchemaOutputDir, { recursive: true, force: true });
6319
- }
6320
- if (this.options.exportTypeTree) {
6321
- this.logger.info(`Clean ${this.options.exportTypeTree}`);
6322
- fs.rmSync(this.options.exportTypeTree, { recursive: true, force: true });
6323
- }
6324
- } catch (error) {
6325
- this.logger.warn(
6326
- `Error cleaning output directory: ${error instanceof Error ? error.message : String(error)}`
6327
- );
6328
- }
6329
- }
6330
6406
  try {
6407
+ if (this.options.cleanOutput) this.cleanup();
6331
6408
  this.logger.info("Initialize Canonical Manager");
6332
6409
  const manager = CanonicalManager({
6333
6410
  packages: this.packages,
@@ -6340,16 +6417,21 @@ var APIBuilder = class {
6340
6417
  });
6341
6418
  const typeSchemas = await generateTypeSchemas(register, this.logger);
6342
6419
  await this.tryWriteTypeSchema(typeSchemas);
6343
- const tsIndex = mkTypeSchemaIndex(typeSchemas);
6420
+ let tsIndex = mkTypeSchemaIndex(typeSchemas, this.logger);
6421
+ if (this.options.treeShake) tsIndex = treeShake(tsIndex, this.options.treeShake, this.logger);
6344
6422
  if (this.options.exportTypeTree) await tsIndex.exportTree(this.options.exportTypeTree);
6345
6423
  this.logger.debug(`Executing ${this.generators.size} generators`);
6346
- await this.executeGenerators(result, { schemas: typeSchemas, index: tsIndex });
6424
+ await this.executeGenerators(result, {
6425
+ schemas: typeSchemas,
6426
+ index: tsIndex
6427
+ });
6347
6428
  this.logger.info("Generation completed successfully");
6348
6429
  result.success = result.errors.length === 0;
6349
6430
  this.logger.debug(`Generation completed: ${result.filesGenerated.length} files`);
6350
6431
  } catch (error) {
6351
6432
  this.logger.error("Code generation failed", error instanceof Error ? error : new Error(String(error)));
6352
6433
  result.errors.push(error instanceof Error ? error.message : String(error));
6434
+ if (this.options.throwException) throw error;
6353
6435
  }
6354
6436
  return {
6355
6437
  ...result,