babelfhir-ts 1.3.8 → 1.3.10
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/README.md +1 -48
- package/out/src/bin.js +11 -0
- package/out/src/cli/installCommand.js +47 -30
- package/out/src/generator/core/cacheConfig.js +4 -4
- package/out/src/generator/core/utils.js +0 -20
- package/out/src/generator/sdProcessor.js +1 -1
- package/out/src/main.js +3 -11
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -202,54 +202,7 @@ const { errors, warnings } = await patient.validate();
|
|
|
202
202
|
|
|
203
203
|
<!-- CLI_HELP_START -->
|
|
204
204
|
```
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
Usage:
|
|
208
|
-
babelfhir-ts [options] [<input> [output]]
|
|
209
|
-
babelfhir-ts install [--package] <pkg@version|path> [--registry <url>] [options]
|
|
210
|
-
|
|
211
|
-
Arguments:
|
|
212
|
-
input Input can be:
|
|
213
|
-
- Canonical URL of a FHIR profile (http://... or https://...)
|
|
214
|
-
- Directory containing FHIR packages (.tgz/.zip files)
|
|
215
|
-
- Single FHIR package (.tgz/.zip file)
|
|
216
|
-
- Single StructureDefinition (.json file)
|
|
217
|
-
- Directory containing StructureDefinition files
|
|
218
|
-
output Output directory or archive name (optional)
|
|
219
|
-
|
|
220
|
-
Commands:
|
|
221
|
-
install Download, process, and npm install package as dependency
|
|
222
|
-
|
|
223
|
-
Options:
|
|
224
|
-
-h, --help Show this help message
|
|
225
|
-
-v, --version Show version number
|
|
226
|
-
--log <dest> Log destination: console (default) or file
|
|
227
|
-
--log-level <level> Log verbosity: error, warn, info (default), or debug
|
|
228
|
-
--cache-dir <path> Custom cache directory (default: ~/.fhir/packages for FHIR packages, .cache for working files)
|
|
229
|
-
--no-cache Delete .cache working folder after generation (does not affect shared ~/.fhir/packages)
|
|
230
|
-
--no-classes Only generate interfaces and types (skip class generation)
|
|
231
|
-
--no-client Skip FHIR client generation (client generated by default)
|
|
232
|
-
--schema <format> Generate schema files alongside outputs (supported: zod)
|
|
233
|
-
--dicomweb Generate DICOMweb helpers typed to ImagingStudy profiles in the IG
|
|
234
|
-
--fhir-version <ver> FHIR version to target: r4, r4b, or r5 (auto-detected from package if omitted)
|
|
235
|
-
--package <pkg@version> Download FHIR package from registry and process it
|
|
236
|
-
--registry <url> FHIR package registry URL (default: https://packages.simplifier.net)
|
|
237
|
-
--tx-server <url> Terminology server URL for ValueSet expansion (e.g., https://tx.fhir.org/r4)
|
|
238
|
-
When set, expands ValueSets without explicit codes using $expand operation
|
|
239
|
-
|
|
240
|
-
Examples:
|
|
241
|
-
babelfhir-ts # Process ./input to ./output
|
|
242
|
-
babelfhir-ts http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient # Generate from profile URL
|
|
243
|
-
babelfhir-ts package.tgz # Process package to current directory
|
|
244
|
-
babelfhir-ts package.tgz modified-package.tgz # Embed interfaces in package
|
|
245
|
-
babelfhir-ts profiles/ generated/ # Process directory to directory
|
|
246
|
-
babelfhir-ts --package hl7.fhir.us.core@8.0.0 # Download and process from default registry
|
|
247
|
-
babelfhir-ts --package hl7.fhir.us.core@8.0.0 output/ # Download and output to directory
|
|
248
|
-
babelfhir-ts --package pkg@version --log console --log-level debug # With verbose logging
|
|
249
|
-
babelfhir-ts install de.gematik.isik-basismodul@3.1.0 # Download, process, and npm install
|
|
250
|
-
babelfhir-ts install ./package.tgz # Install from local package file
|
|
251
|
-
babelfhir-ts install hl7.fhir.us.core@8.0.0 --registry <url> # Install from custom registry
|
|
252
|
-
babelfhir-ts install --package hl7.fhir.us.core@8.0.0 --registry <url> # Alternative syntax
|
|
205
|
+
|
|
253
206
|
```
|
|
254
207
|
<!-- CLI_HELP_END -->
|
|
255
208
|
|
package/out/src/bin.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { run } from './main.js';
|
|
3
|
+
import { logger } from './logger.js';
|
|
4
|
+
run()
|
|
5
|
+
.catch(err => {
|
|
6
|
+
console.error('Generation failed:', err instanceof Error ? err.message : err);
|
|
7
|
+
process.exit(1);
|
|
8
|
+
})
|
|
9
|
+
.finally(() => {
|
|
10
|
+
logger.close();
|
|
11
|
+
});
|
|
@@ -48,42 +48,59 @@ export function detectPackageManager(startDir) {
|
|
|
48
48
|
}
|
|
49
49
|
return { cmd: isWin ? 'npm.cmd' : 'npm', args: ['install'] };
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Build the install arguments for the package manager.
|
|
53
|
+
* Returns `['install']` when the dep already exists, or `[...pmArgs, relativePath]` for new deps.
|
|
54
|
+
* Always uses a relative path (e.g. `./lib/foo.tgz`) — never an absolute path.
|
|
55
|
+
* Exported for testing.
|
|
56
|
+
*/
|
|
57
|
+
export function buildInstallArgs(opts) {
|
|
58
|
+
const { packagePath, pmArgs, cwd, packageJsonContent } = opts;
|
|
59
|
+
const tgzRelPath = './' + path.relative(cwd, packagePath).replace(/\\/g, '/');
|
|
60
|
+
if (packageJsonContent) {
|
|
61
|
+
try {
|
|
62
|
+
const projectPkg = JSON.parse(packageJsonContent);
|
|
63
|
+
const deps = projectPkg.dependencies || {};
|
|
64
|
+
for (const [, value] of Object.entries(deps)) {
|
|
65
|
+
if (typeof value === 'string' && (value === tgzRelPath || value === packagePath)) {
|
|
66
|
+
return { args: ['install'] };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const tgzBaseName = path.basename(packagePath, '.tgz').replace(/^-/, '');
|
|
70
|
+
for (const name of Object.keys(deps)) {
|
|
71
|
+
if (name.replace(/[@/]/g, '-') === tgzBaseName) {
|
|
72
|
+
deps[name] = tgzRelPath;
|
|
73
|
+
projectPkg.dependencies = deps;
|
|
74
|
+
return {
|
|
75
|
+
args: ['install'],
|
|
76
|
+
updatedPackageJson: JSON.stringify(projectPkg, null, 2) + '\n',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch { /* ignore, fall through to normal add */ }
|
|
82
|
+
}
|
|
83
|
+
return { args: [...pmArgs, tgzRelPath] };
|
|
84
|
+
}
|
|
51
85
|
function npmInstall(packagePath) {
|
|
52
86
|
return new Promise((resolve, reject) => {
|
|
53
87
|
const pm = detectPackageManager();
|
|
54
88
|
const pmName = path.basename(pm.cmd).replace(/\.(cmd|exe)$/, '');
|
|
55
|
-
// Check if the package already exists in package.json to avoid dependency loops.
|
|
56
89
|
const projectPkgPath = path.join(process.cwd(), 'package.json');
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
if (!useInstallOnly) {
|
|
71
|
-
const tgzBaseName = path.basename(packagePath, '.tgz').replace(/^-/, '');
|
|
72
|
-
for (const name of Object.keys(deps)) {
|
|
73
|
-
if (name.replace(/[@/]/g, '-') === tgzBaseName) {
|
|
74
|
-
deps[name] = tgzRelPath;
|
|
75
|
-
projectPkg.dependencies = deps;
|
|
76
|
-
fs.writeFileSync(projectPkgPath, JSON.stringify(projectPkg, null, 2) + '\n');
|
|
77
|
-
console.log(`Updated ${name} dependency to ${tgzRelPath}`);
|
|
78
|
-
useInstallOnly = true;
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch { /* ignore, fall through to normal add */ }
|
|
90
|
+
const packageJsonContent = fs.existsSync(projectPkgPath)
|
|
91
|
+
? fs.readFileSync(projectPkgPath, 'utf8')
|
|
92
|
+
: undefined;
|
|
93
|
+
const result = buildInstallArgs({
|
|
94
|
+
packagePath,
|
|
95
|
+
pmArgs: pm.args,
|
|
96
|
+
cwd: process.cwd(),
|
|
97
|
+
packageJsonContent,
|
|
98
|
+
});
|
|
99
|
+
if (result.updatedPackageJson) {
|
|
100
|
+
fs.writeFileSync(projectPkgPath, result.updatedPackageJson);
|
|
101
|
+
console.log(`Updated dependency path in package.json`);
|
|
85
102
|
}
|
|
86
|
-
const args =
|
|
103
|
+
const { args } = result;
|
|
87
104
|
console.log(`Installing package with ${pmName}...`);
|
|
88
105
|
const child = spawn(pm.cmd, args, {
|
|
89
106
|
stdio: 'inherit',
|
|
@@ -67,8 +67,8 @@ export function getCacheConfig() {
|
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Override the cache configuration (useful for testing or CLI options).
|
|
70
|
-
*
|
|
71
|
-
* unless
|
|
70
|
+
* Only rootDir (working cache) is updated; fhirPackagesDir stays at ~/.fhir/packages
|
|
71
|
+
* unless explicitly provided or FHIR_CACHE_ROOT is set.
|
|
72
72
|
*/
|
|
73
73
|
export function setCacheConfig(config) {
|
|
74
74
|
const current = getCacheConfig();
|
|
@@ -77,8 +77,8 @@ export function setCacheConfig(config) {
|
|
|
77
77
|
...current,
|
|
78
78
|
...config,
|
|
79
79
|
rootDir: newRootDir,
|
|
80
|
-
//
|
|
81
|
-
fhirPackagesDir: config.fhirPackagesDir ??
|
|
80
|
+
// Only override fhirPackagesDir if explicitly provided; --cache-dir should NOT move the shared FHIR package cache
|
|
81
|
+
fhirPackagesDir: config.fhirPackagesDir ?? current.fhirPackagesDir,
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
@@ -19,26 +19,6 @@ export function writeInterfaceAndValidatorToFile(outputDir, interfaceName, inter
|
|
|
19
19
|
const content = `${interfaceContent}\n\n${validateFunctionContent}`;
|
|
20
20
|
caseAwareWriteFile(filePath, content);
|
|
21
21
|
}
|
|
22
|
-
export function extractFieldsFromInterface(interfaceDecl) {
|
|
23
|
-
return interfaceDecl.getProperties().map((property) => {
|
|
24
|
-
const name = property.getName();
|
|
25
|
-
const type = property.getType().getText();
|
|
26
|
-
const isOptional = property.hasQuestionToken();
|
|
27
|
-
const isArray = type.endsWith("[]");
|
|
28
|
-
return {
|
|
29
|
-
constraints: [], // Placeholder for constraints
|
|
30
|
-
elements: [], // Placeholder for nested elements
|
|
31
|
-
fromBase: true, // Mark as coming from the base resource
|
|
32
|
-
isForbidden: false, // Interfaces extracted this way cannot infer forbidden state
|
|
33
|
-
isArray,
|
|
34
|
-
isOptional,
|
|
35
|
-
name,
|
|
36
|
-
type: isArray ? type.slice(0, -2) : type,
|
|
37
|
-
// Interfaces parsed from existing code cannot know profiling source
|
|
38
|
-
isProfiled: false,
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
22
|
export function capitalize(str) {
|
|
43
23
|
if (!str)
|
|
44
24
|
return str;
|
|
@@ -250,7 +250,7 @@ export async function processStructureDefinition(sd, ctx) {
|
|
|
250
250
|
if (f.isOptional || f.isForbidden)
|
|
251
251
|
continue;
|
|
252
252
|
const parentFieldName = parts[1].split(':')[0];
|
|
253
|
-
let relativePath = parts.slice(2).map(p => p.split(':')[0]).join('.');
|
|
253
|
+
let relativePath = parts.slice(2).map((p) => p.split(':')[0]).join('.');
|
|
254
254
|
if (relativePath.includes('[x]') && f.type && f.type !== 'any' && f.type !== 'unknown') {
|
|
255
255
|
const fType = f.type;
|
|
256
256
|
relativePath = relativePath.replace(/(\w+)\[x\]/g, (_match, baseName) => {
|
package/out/src/main.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import { generateIntoPackage, generateForDirectory, generateFromJsonFile, generateFromProfileUrl, resetFetchFailureTracking, getFetchFailureWarning, getTimingSummary, formatTimingSummary } from "./generator/index.js";
|
|
3
2
|
import { generateClient } from "./generator/emitters/client/clientGenerator.js";
|
|
4
3
|
import { extractPackage } from "./generator/parser/packageParser.js";
|
|
@@ -9,7 +8,6 @@ import { buildQualityReport, formatReportSummary, resetDiagnostics } from "./gen
|
|
|
9
8
|
import fs from 'fs';
|
|
10
9
|
import path from 'path';
|
|
11
10
|
import { fileURLToPath } from 'url';
|
|
12
|
-
import { logger } from './logger.js';
|
|
13
11
|
// Resolve package.json relative to this file — works from both src/ (dev) and out/src/ (compiled)
|
|
14
12
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
13
|
const _pkgJsonPath = [
|
|
@@ -290,7 +288,7 @@ export function parseCliArgs(argv) {
|
|
|
290
288
|
}
|
|
291
289
|
return out;
|
|
292
290
|
}
|
|
293
|
-
async function run() {
|
|
291
|
+
export async function run() {
|
|
294
292
|
const argv = process.argv.slice(2);
|
|
295
293
|
let parsed;
|
|
296
294
|
try {
|
|
@@ -450,11 +448,5 @@ async function run() {
|
|
|
450
448
|
console.error("Use --help for usage information");
|
|
451
449
|
process.exit(1);
|
|
452
450
|
}
|
|
453
|
-
run()
|
|
454
|
-
|
|
455
|
-
console.error('Generation failed:', err instanceof Error ? err.message : err);
|
|
456
|
-
process.exit(1);
|
|
457
|
-
})
|
|
458
|
-
.finally(() => {
|
|
459
|
-
logger.close();
|
|
460
|
-
});
|
|
451
|
+
// Note: run() is exported and called from bin.ts (the CLI entry point).
|
|
452
|
+
// Do NOT call run() here — importing this module should have no side effects.
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babelfhir-ts",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.10",
|
|
4
4
|
"description": "BabelFHIR-TS: generate TypeScript interfaces, validators, and helper classes from FHIR R4/R4B/R5 StructureDefinitions (profiles) directly inside package archives.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "out/src/main.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"babelfhir-ts": "./out/src/
|
|
8
|
+
"babelfhir-ts": "./out/src/bin.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"out/src/generator/",
|
|
12
12
|
"out/src/cli/",
|
|
13
|
+
"out/src/bin.js",
|
|
13
14
|
"out/src/main.js",
|
|
14
15
|
"out/src/logger.js",
|
|
15
16
|
"out/fhir-r4.d.ts",
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"lint:output": "eslint output || exit 0",
|
|
33
34
|
"typecheck": "tsc --noEmit",
|
|
34
35
|
"typecheck:output": "tsc -p tsconfig.output.json",
|
|
35
|
-
"generate": "tsx src/
|
|
36
|
+
"generate": "tsx src/bin.ts",
|
|
36
37
|
"generate:check": "npm run generate && npm run typecheck && npm run typecheck:output && npm run lint:output",
|
|
37
38
|
"generate:check:package": "tsx scripts/generate-check-package.ts",
|
|
38
39
|
"generate:check:pas": "tsx scripts/generate-check-package.ts hl7.fhir.us.davinci-pas@2.0.1 --list-errors --keep-output",
|
|
@@ -97,7 +98,6 @@
|
|
|
97
98
|
"consola": "^3.4.2",
|
|
98
99
|
"fhirpath": "^4.9.1",
|
|
99
100
|
"tar": "^7.4.3",
|
|
100
|
-
"ts-morph": "^27.0.2",
|
|
101
101
|
"tsx": "^4.19.3",
|
|
102
102
|
"unzipper": "^0.12.3"
|
|
103
103
|
}
|