babelfhir-ts 1.2.1 → 1.2.3

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.
@@ -0,0 +1,176 @@
1
+ import { generateIntoPackageDirect, resetFetchFailureTracking, getFetchFailureWarning } from "../generator/index.js";
2
+ import { getCacheConfig, clearAllCaches } from "../generator/core/cacheConfig.js";
3
+ import { buildQualityReport, formatReportSummary, resetDiagnostics } from "../generator/core/sdDiagnostics.js";
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { spawn } from 'child_process';
7
+ /** Display all generation warnings (fetch failures, incomplete extension slices, etc.) */
8
+ function showGenerationWarnings() {
9
+ let hasWarnings = false;
10
+ const fetchWarning = getFetchFailureWarning();
11
+ if (fetchWarning) {
12
+ console.warn(fetchWarning);
13
+ hasWarnings = true;
14
+ }
15
+ return hasWarnings;
16
+ }
17
+ function cleanupCache() {
18
+ const cacheConfig = getCacheConfig();
19
+ if (fs.existsSync(cacheConfig.rootDir)) {
20
+ console.log('Cleaning up cache directory...');
21
+ clearAllCaches();
22
+ console.log('Cache cleaned.');
23
+ }
24
+ }
25
+ /** Detect the package manager used in the current working directory */
26
+ function detectPackageManager() {
27
+ const cwd = process.cwd();
28
+ const isWin = process.platform === 'win32';
29
+ if (fs.existsSync(path.join(cwd, 'bun.lock')) || fs.existsSync(path.join(cwd, 'bun.lockb'))) {
30
+ return { cmd: isWin ? 'bun.exe' : 'bun', args: ['add'] };
31
+ }
32
+ if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) {
33
+ return { cmd: isWin ? 'pnpm.cmd' : 'pnpm', args: ['add'] };
34
+ }
35
+ if (fs.existsSync(path.join(cwd, 'yarn.lock'))) {
36
+ return { cmd: isWin ? 'yarn.cmd' : 'yarn', args: ['add'] };
37
+ }
38
+ return { cmd: isWin ? 'npm.cmd' : 'npm', args: ['install'] };
39
+ }
40
+ function npmInstall(packagePath) {
41
+ return new Promise((resolve, reject) => {
42
+ const pm = detectPackageManager();
43
+ const pmName = path.basename(pm.cmd).replace(/\.(cmd|exe)$/, '');
44
+ // Check if the package already exists in package.json to avoid dependency loops.
45
+ const projectPkgPath = path.join(process.cwd(), 'package.json');
46
+ let useInstallOnly = false;
47
+ if (fs.existsSync(projectPkgPath)) {
48
+ try {
49
+ const tgzRelPath = './' + path.relative(process.cwd(), packagePath).replace(/\\/g, '/');
50
+ const projectPkg = JSON.parse(fs.readFileSync(projectPkgPath, 'utf8'));
51
+ const deps = projectPkg.dependencies || {};
52
+ for (const [name, value] of Object.entries(deps)) {
53
+ if (typeof value === 'string' && (value === tgzRelPath || value === packagePath)) {
54
+ console.log(`Package ${name} already in dependencies, running ${pmName} install`);
55
+ useInstallOnly = true;
56
+ break;
57
+ }
58
+ }
59
+ if (!useInstallOnly) {
60
+ const tgzBaseName = path.basename(packagePath, '.tgz').replace(/^-/, '');
61
+ for (const name of Object.keys(deps)) {
62
+ if (name.replace(/[@/]/g, '-') === tgzBaseName) {
63
+ deps[name] = tgzRelPath;
64
+ projectPkg.dependencies = deps;
65
+ fs.writeFileSync(projectPkgPath, JSON.stringify(projectPkg, null, 2) + '\n');
66
+ console.log(`Updated ${name} dependency to ${tgzRelPath}`);
67
+ useInstallOnly = true;
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ }
73
+ catch { /* ignore, fall through to normal add */ }
74
+ }
75
+ const args = useInstallOnly ? ['install'] : [...pm.args, packagePath];
76
+ console.log(`Installing package with ${pmName}...`);
77
+ const child = spawn(pm.cmd, args, {
78
+ stdio: 'inherit',
79
+ shell: true
80
+ });
81
+ child.on('exit', (code) => {
82
+ if (code === 0) {
83
+ console.log(`✓ Package installed successfully`);
84
+ resolve();
85
+ }
86
+ else {
87
+ reject(new Error(`${pmName} install failed with exit code ${code}`));
88
+ }
89
+ });
90
+ child.on('error', (err) => {
91
+ reject(new Error(`Failed to run ${pmName} install: ${err.message}`));
92
+ });
93
+ });
94
+ }
95
+ export async function handleInstallCommand(opts) {
96
+ const { packageToInstall, registry, generationFlags, downloadPackage } = opts;
97
+ // Keep cache by default — dependency packages are large (hl7.fhir.r4.core ~50 MB)
98
+ // and re-downloading them every run is the single biggest bottleneck.
99
+ // Users can opt in to cache cleanup with --no-cache.
100
+ let generationCleanup;
101
+ try {
102
+ let downloadedPath;
103
+ if (fs.existsSync(packageToInstall) && (packageToInstall.endsWith('.tgz') || packageToInstall.endsWith('.zip'))) {
104
+ console.log(`Using local package: ${packageToInstall}`);
105
+ downloadedPath = path.resolve(packageToInstall);
106
+ }
107
+ else {
108
+ downloadedPath = await downloadPackage(packageToInstall, registry);
109
+ }
110
+ console.log(`Processing package...`);
111
+ resetFetchFailureTracking();
112
+ resetDiagnostics();
113
+ // Generate directly into extracted package — no intermediate archive round-trip
114
+ const { generatedDir, cleanup } = await generateIntoPackageDirect(downloadedPath, generationFlags);
115
+ generationCleanup = cleanup;
116
+ // Clean up temp directory only if we downloaded from registry (not for local files)
117
+ if (!fs.existsSync(packageToInstall) || !(packageToInstall.endsWith('.tgz') || packageToInstall.endsWith('.zip'))) {
118
+ const tempDir = path.join(process.cwd(), '.temp-download');
119
+ if (fs.existsSync(tempDir)) {
120
+ fs.rmSync(tempDir, { recursive: true, force: true });
121
+ }
122
+ }
123
+ // Verify package.json exists in generated folder
124
+ const pkgJsonPath = path.join(generatedDir, 'package.json');
125
+ if (!fs.existsSync(pkgJsonPath)) {
126
+ throw new Error(`package.json not found in generated folder: ${generatedDir}`);
127
+ }
128
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
129
+ const packageName = pkgJson.name;
130
+ console.log(`Creating package tarball for ${packageName}...`);
131
+ // Ensure ./lib exists for storing the generated tarball
132
+ const libDir = path.join(process.cwd(), 'lib');
133
+ if (!fs.existsSync(libDir)) {
134
+ fs.mkdirSync(libDir, { recursive: true });
135
+ }
136
+ const { create } = await import('tar');
137
+ const tarballName = `${packageName.replace(/[@/]/g, '-')}.tgz`;
138
+ const tarballPath = path.join(libDir, tarballName);
139
+ // npm expects tarballs to have content under a 'package/' root folder
140
+ await create({
141
+ gzip: true,
142
+ file: tarballPath,
143
+ cwd: generatedDir,
144
+ prefix: 'package'
145
+ }, ['.']);
146
+ console.log(`Installing ${packageName}...`);
147
+ await npmInstall(tarballPath);
148
+ // Clean up extracted package tree (but keep the tarball under ./lib)
149
+ generationCleanup();
150
+ generationCleanup = undefined;
151
+ console.log(`✓ Package tarball saved to ./lib: ${path.basename(tarballPath)}`);
152
+ showGenerationWarnings();
153
+ const report = buildQualityReport();
154
+ const summary = formatReportSummary(report);
155
+ if (summary.trim())
156
+ console.log(summary);
157
+ if (generationFlags.noCache) {
158
+ cleanupCache();
159
+ }
160
+ console.log(`\n✓ Package ${packageToInstall} installed and ready to use!`);
161
+ }
162
+ catch (error) {
163
+ // Clean up extracted package on error
164
+ generationCleanup?.();
165
+ // Clean up temp download directory
166
+ const tempDir = path.join(process.cwd(), '.temp-download');
167
+ if (fs.existsSync(tempDir)) {
168
+ fs.rmSync(tempDir, { recursive: true, force: true });
169
+ }
170
+ if (generationFlags.noCache) {
171
+ cleanupCache();
172
+ }
173
+ console.error(`Error: ${error.message}`);
174
+ process.exit(1);
175
+ }
176
+ }
@@ -13,7 +13,7 @@
13
13
  import fs from 'fs';
14
14
  import path from 'path';
15
15
  import { getFhirPackagesCacheDir, ensureCacheDir } from '../core/cacheConfig.js';
16
- import { fetchArrayBuffer } from '../core/fetchUtils.js';
16
+ import { downloadFile } from '../core/utils.js';
17
17
  import { logger } from '../../logger.js';
18
18
  const log = logger.withTag('core-resolver');
19
19
  /**
@@ -58,7 +58,7 @@ export async function ensureCorePackage(corePackageSpec) {
58
58
  return candidate;
59
59
  }
60
60
  }
61
- // Not cached — download from registry
61
+ // Not cached — download from registry (streaming to avoid buffering large packages in RAM)
62
62
  ensureCacheDir(configuredCacheDir);
63
63
  const packageDir = path.join(configuredCacheDir, dirName);
64
64
  let downloaded = false;
@@ -67,8 +67,7 @@ export async function ensureCorePackage(corePackageSpec) {
67
67
  const url = `${registry}/${packageName}/${version}`;
68
68
  try {
69
69
  log.info(`Downloading core package ${corePackageSpec} from ${registry}…`);
70
- const response = await fetchArrayBuffer(url);
71
- fs.writeFileSync(tgzPath, Buffer.from(response.data));
70
+ await downloadFile(url, tgzPath);
72
71
  downloaded = true;
73
72
  break;
74
73
  }
@@ -14,7 +14,7 @@
14
14
  import fs from 'fs';
15
15
  import path from 'path';
16
16
  import { getFhirPackagesCacheDir, ensureCacheDir } from '../core/cacheConfig.js';
17
- import { fetchArrayBuffer } from '../core/fetchUtils.js';
17
+ import { downloadFile } from '../core/utils.js';
18
18
  import { logger } from '../../logger.js';
19
19
 
20
20
  const log = logger.withTag('core-resolver');
@@ -88,7 +88,7 @@ export async function ensureCorePackage(corePackageSpec: string): Promise<string
88
88
  }
89
89
  }
90
90
 
91
- // Not cached — download from registry
91
+ // Not cached — download from registry (streaming to avoid buffering large packages in RAM)
92
92
  ensureCacheDir(configuredCacheDir);
93
93
  const packageDir = path.join(configuredCacheDir, dirName);
94
94
 
@@ -98,8 +98,7 @@ export async function ensureCorePackage(corePackageSpec: string): Promise<string
98
98
  const url = `${registry}/${packageName}/${version}`;
99
99
  try {
100
100
  log.info(`Downloading core package ${corePackageSpec} from ${registry}…`);
101
- const response = await fetchArrayBuffer(url);
102
- fs.writeFileSync(tgzPath, Buffer.from(response.data));
101
+ await downloadFile(url, tgzPath);
103
102
  downloaded = true;
104
103
  break;
105
104
  } catch (err) {