babelfhir-ts 1.0.13 → 1.0.15
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/out/generator/index.js +6 -3
- package/out/generator/interfaceGenerator.js +2 -10
- package/out/main.js +101 -42
- package/package.json +1 -1
package/out/generator/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { generateValidateProfileFunction } from './validatorGenerator';
|
|
|
9
9
|
import { loadExamplesFromPackage, generateTestFile } from './testGenerator';
|
|
10
10
|
import { generateValueSetTypeScript, generateValueSetRegistry } from './valueSetGenerator.js';
|
|
11
11
|
import { logger } from '../logger';
|
|
12
|
+
import fhirInterfaceNames from './fhirInterfaces.json';
|
|
12
13
|
/** Ensure RandomSupport.ts exists in a generation output directory */
|
|
13
14
|
function ensureRandomSupportFile(dir) {
|
|
14
15
|
const filePath = path.join(dir, 'RandomSupport.ts');
|
|
@@ -63,12 +64,14 @@ async function processStructureDefinition(sd, ctx) {
|
|
|
63
64
|
if (profileIdToName?.has(baseResource)) {
|
|
64
65
|
baseResource = profileIdToName.get(baseResource);
|
|
65
66
|
}
|
|
66
|
-
if (
|
|
67
|
-
|
|
67
|
+
// Generic fallback: if baseResource isn't a known FHIR type, prefer the declared SD type (core resource)
|
|
68
|
+
const isFhirType = (name) => !!name && (name === 'FhirResource' || fhirInterfaceNames.includes(name));
|
|
69
|
+
if (!isFhirType(baseResource) && sd.type && isFhirType(sd.type)) {
|
|
70
|
+
baseResource = sd.type;
|
|
68
71
|
}
|
|
69
72
|
const parsed = await parseStructureDefinition(sd, fhirSourceHint, valueSetCodesMap);
|
|
70
73
|
if (!parsed.newFields.length) {
|
|
71
|
-
|
|
74
|
+
logger.log(`No new SD fields for ${interfaceName}, skipping.`);
|
|
72
75
|
return;
|
|
73
76
|
}
|
|
74
77
|
const aligned = alignFields(parsed.newFields, parsed.oldFields);
|
|
@@ -1518,12 +1518,7 @@ export function generateInterfaces(interfaceName, newFields, baseResource, baseF
|
|
|
1518
1518
|
}
|
|
1519
1519
|
if (baseResource && !isPrimitiveType(baseResource) && sanitizeIdentifier(baseResource) !== 'Base') {
|
|
1520
1520
|
const sanitizedBase = sanitizeIdentifier(baseResource);
|
|
1521
|
-
|
|
1522
|
-
if (/^coverage_de_/.test(sanitizedBase)) {
|
|
1523
|
-
// Treat as Coverage
|
|
1524
|
-
imports.add('Coverage');
|
|
1525
|
-
}
|
|
1526
|
-
else if (!isFhirType(sanitizedBase)) {
|
|
1521
|
+
if (!isFhirType(sanitizedBase)) {
|
|
1527
1522
|
// Check if this profile exists in our generated files
|
|
1528
1523
|
if (existingProfiles?.has(sanitizedBase)) {
|
|
1529
1524
|
customImports.add(sanitizedBase);
|
|
@@ -1583,10 +1578,7 @@ export function generateInterfaces(interfaceName, newFields, baseResource, baseF
|
|
|
1583
1578
|
if (baseResource && sanitizeIdentifier(baseResource) !== 'Base') {
|
|
1584
1579
|
const sanitizedBase = sanitizeIdentifier(baseResource);
|
|
1585
1580
|
// Ensure import of the base resource type
|
|
1586
|
-
if (
|
|
1587
|
-
imports.add('Coverage');
|
|
1588
|
-
}
|
|
1589
|
-
else if (!isFhirType(sanitizedBase)) {
|
|
1581
|
+
if (!isFhirType(sanitizedBase)) {
|
|
1590
1582
|
customImports.add(sanitizedBase);
|
|
1591
1583
|
}
|
|
1592
1584
|
else {
|
package/out/main.js
CHANGED
|
@@ -12,7 +12,7 @@ function printUsage() {
|
|
|
12
12
|
console.log("");
|
|
13
13
|
console.log("Usage:");
|
|
14
14
|
console.log(" babelfhir-ts [options] [<input> [output]]");
|
|
15
|
-
console.log(" babelfhir-ts install [--package] <pkg@version> [--registry <url>] [options]");
|
|
15
|
+
console.log(" babelfhir-ts install [--package] <pkg@version|path> [--registry <url>] [options]");
|
|
16
16
|
console.log("");
|
|
17
17
|
console.log("Arguments:");
|
|
18
18
|
console.log(" input Input can be:");
|
|
@@ -35,12 +35,13 @@ function printUsage() {
|
|
|
35
35
|
console.log(" --registry <url> FHIR package registry URL (default: https://packages.simplifier.net)");
|
|
36
36
|
console.log("");
|
|
37
37
|
console.log("Examples:");
|
|
38
|
-
console.log(" babelfhir-ts
|
|
39
|
-
console.log(" babelfhir-ts package.tgz # Process package to
|
|
38
|
+
console.log(" babelfhir-ts # Process ./input to ./output");
|
|
39
|
+
console.log(" babelfhir-ts package.tgz # Process package to current directory");
|
|
40
40
|
console.log(" babelfhir-ts package.tgz modified-package.tgz # Embed interfaces in package");
|
|
41
41
|
console.log(" babelfhir-ts profiles/ generated/ # Process directory to directory");
|
|
42
42
|
console.log(" babelfhir-ts --package hl7.fhir.us.core@8.0.0 # Download and process from default registry");
|
|
43
43
|
console.log(" babelfhir-ts install de.gematik.isik-basismodul@3.1.0 # Download, process, and npm install");
|
|
44
|
+
console.log(" babelfhir-ts install ./package.tgz # Install from local package file");
|
|
44
45
|
console.log(" babelfhir-ts install hl7.fhir.us.core@8.0.0 --registry <url> # Install from custom registry");
|
|
45
46
|
console.log(" babelfhir-ts install --package hl7.fhir.us.core@8.0.0 --registry <url> # Alternative syntax");
|
|
46
47
|
}
|
|
@@ -114,65 +115,122 @@ async function downloadPackage(packageSpec, registry) {
|
|
|
114
115
|
throw error;
|
|
115
116
|
}
|
|
116
117
|
}
|
|
118
|
+
function parseCliArgs(argv) {
|
|
119
|
+
const out = {
|
|
120
|
+
registry: 'https://packages.simplifier.net',
|
|
121
|
+
logLevel: 'none',
|
|
122
|
+
packageSpec: null,
|
|
123
|
+
flags: { noCache: false, noClasses: false, logLevel: 'none' },
|
|
124
|
+
positionals: []
|
|
125
|
+
};
|
|
126
|
+
for (let i = 0; i < argv.length; i++) {
|
|
127
|
+
const arg = argv[i];
|
|
128
|
+
if (arg === '--help' || arg === '-h' || arg === '--version' || arg === '-v' || arg === 'install') {
|
|
129
|
+
// Commands or special flags handled later as positionals to preserve order
|
|
130
|
+
out.positionals.push(arg);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (arg === '--no-cache') {
|
|
134
|
+
out.flags.noCache = true;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (arg === '--no-classes') {
|
|
138
|
+
out.flags.noClasses = true;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (arg === '--log') {
|
|
142
|
+
const val = argv[i + 1];
|
|
143
|
+
if (!val || val.startsWith('-')) {
|
|
144
|
+
throw new Error('Missing value for --log');
|
|
145
|
+
}
|
|
146
|
+
if (!['none', 'console', 'file'].includes(val)) {
|
|
147
|
+
throw new Error(`Invalid --log value: ${val}. Must be: none, console, or file`);
|
|
148
|
+
}
|
|
149
|
+
out.logLevel = val;
|
|
150
|
+
out.flags.logLevel = out.logLevel;
|
|
151
|
+
i++;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (arg === '--package') {
|
|
155
|
+
const val = argv[i + 1];
|
|
156
|
+
if (!val || val.startsWith('-'))
|
|
157
|
+
throw new Error('Missing value for --package');
|
|
158
|
+
out.packageSpec = val;
|
|
159
|
+
i++;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (arg === '--registry') {
|
|
163
|
+
const val = argv[i + 1];
|
|
164
|
+
if (!val || val.startsWith('-'))
|
|
165
|
+
throw new Error('Missing value for --registry');
|
|
166
|
+
out.registry = val;
|
|
167
|
+
i++;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// Anything else that doesn't start with -- is positional
|
|
171
|
+
if (!arg.startsWith('--')) {
|
|
172
|
+
out.positionals.push(arg);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
// Unknown --flag -> keep as positional to trigger usage error later
|
|
176
|
+
out.positionals.push(arg);
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
117
180
|
async function run() {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (registryIndex !== -1 && args[registryIndex + 1]) {
|
|
123
|
-
registry = args[registryIndex + 1];
|
|
181
|
+
const argv = process.argv.slice(2);
|
|
182
|
+
let parsed;
|
|
183
|
+
try {
|
|
184
|
+
parsed = parseCliArgs(argv);
|
|
124
185
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (!['none', 'console', 'file'].includes(logLevel)) {
|
|
129
|
-
console.error(`Invalid --log value: ${logLevel}. Must be: none, console, or file`);
|
|
186
|
+
catch (e) {
|
|
187
|
+
console.error(`Error: ${e.message}`);
|
|
188
|
+
printUsage();
|
|
130
189
|
process.exit(1);
|
|
131
190
|
}
|
|
132
|
-
|
|
133
|
-
const packageIndex = args.indexOf('--package');
|
|
134
|
-
const packageSpec = packageIndex !== -1 && args[packageIndex + 1] ? args[packageIndex + 1] : null;
|
|
135
|
-
// Parse flags
|
|
136
|
-
const flags = {
|
|
137
|
-
noCache: args.includes('--no-cache'),
|
|
138
|
-
noClasses: args.includes('--no-classes'),
|
|
139
|
-
logLevel: logLevel
|
|
140
|
-
};
|
|
141
|
-
// Filter out flags to get positional arguments
|
|
142
|
-
const positionalArgs = args.filter(arg => !arg.startsWith('--') && !arg.startsWith('-'));
|
|
143
|
-
let firstArg = args.find(arg => !arg.startsWith('--') || arg === '--help' || arg === '--version');
|
|
144
|
-
const secondArg = positionalArgs[1];
|
|
191
|
+
const { registry, packageSpec, flags, positionals } = parsed;
|
|
145
192
|
// Check for help flags
|
|
146
|
-
if (
|
|
193
|
+
if (positionals.includes('--help') || positionals.includes('-h')) {
|
|
147
194
|
printUsage();
|
|
148
195
|
process.exit(0);
|
|
149
196
|
}
|
|
150
197
|
// Check for version flag
|
|
151
|
-
if (
|
|
198
|
+
if (positionals.includes('--version') || positionals.includes('-v')) {
|
|
152
199
|
console.log(`babelfhir-ts version ${packageJson.version}`);
|
|
153
200
|
process.exit(0);
|
|
154
201
|
}
|
|
155
202
|
// Handle install command
|
|
156
|
-
if (
|
|
203
|
+
if (positionals[0] === 'install') {
|
|
157
204
|
// Package can come from --package flag OR as positional argument after 'install'
|
|
158
|
-
const packageToInstall = packageSpec ||
|
|
205
|
+
const packageToInstall = packageSpec || positionals[1];
|
|
159
206
|
if (!packageToInstall) {
|
|
160
|
-
console.error('Error: install command requires a package name');
|
|
207
|
+
console.error('Error: install command requires a package name or local .tgz/.zip file');
|
|
161
208
|
console.error('Example: babelfhir-ts install de.gematik.isik-basismodul@3.1.0');
|
|
162
209
|
console.error(' or: babelfhir-ts install --package hl7.fhir.us.core@8.0.0');
|
|
210
|
+
console.error(' or: babelfhir-ts install ./package.tgz');
|
|
163
211
|
process.exit(1);
|
|
164
212
|
}
|
|
165
213
|
try {
|
|
166
|
-
|
|
167
|
-
|
|
214
|
+
let downloadedPath;
|
|
215
|
+
// Check if packageToInstall is a local file path
|
|
216
|
+
if (fs.existsSync(packageToInstall) && (packageToInstall.endsWith('.tgz') || packageToInstall.endsWith('.zip'))) {
|
|
217
|
+
console.log(`Using local package: ${packageToInstall}`);
|
|
218
|
+
downloadedPath = path.resolve(packageToInstall);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// Download from registry
|
|
222
|
+
downloadedPath = await downloadPackage(packageToInstall, registry);
|
|
223
|
+
}
|
|
168
224
|
console.log(`Processing package...`);
|
|
169
225
|
const baseName = path.basename(downloadedPath, path.extname(downloadedPath));
|
|
170
226
|
const outputArchive = path.join(process.cwd(), `${baseName}.with-generated.tgz`);
|
|
171
227
|
await generateIntoPackage(downloadedPath, outputArchive, flags);
|
|
172
|
-
// Clean up temp directory
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
fs.
|
|
228
|
+
// Clean up temp directory only if we downloaded from registry (not for local files)
|
|
229
|
+
if (!fs.existsSync(packageToInstall) || !(packageToInstall.endsWith('.tgz') || packageToInstall.endsWith('.zip'))) {
|
|
230
|
+
const tempDir = path.join(process.cwd(), '.temp-download');
|
|
231
|
+
if (fs.existsSync(tempDir)) {
|
|
232
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
233
|
+
}
|
|
176
234
|
}
|
|
177
235
|
console.log(`✓ Package processed successfully: ${path.basename(outputArchive)}`);
|
|
178
236
|
// Extract the archive to access generated folder
|
|
@@ -212,7 +270,7 @@ async function run() {
|
|
|
212
270
|
if (flags.noCache) {
|
|
213
271
|
cleanupCache();
|
|
214
272
|
}
|
|
215
|
-
console.log(`\n✓ Package ${
|
|
273
|
+
console.log(`\n✓ Package ${packageToInstall} installed and ready to use!`);
|
|
216
274
|
return;
|
|
217
275
|
}
|
|
218
276
|
catch (error) {
|
|
@@ -259,12 +317,11 @@ async function run() {
|
|
|
259
317
|
process.exit(1);
|
|
260
318
|
}
|
|
261
319
|
}
|
|
262
|
-
if (
|
|
320
|
+
if (positionals.length === 0) {
|
|
263
321
|
// Default: attempt input -> output
|
|
264
322
|
if (fs.existsSync('input') && fs.lstatSync('input').isDirectory()) {
|
|
265
|
-
firstArg = 'input';
|
|
266
323
|
const outputDir = 'output';
|
|
267
|
-
await generateForDirectory(
|
|
324
|
+
await generateForDirectory('input', outputDir, flags);
|
|
268
325
|
console.log(`Batch generation complete. Output in: ${outputDir}`);
|
|
269
326
|
if (flags.noCache) {
|
|
270
327
|
cleanupCache();
|
|
@@ -274,6 +331,8 @@ async function run() {
|
|
|
274
331
|
printError();
|
|
275
332
|
process.exit(1);
|
|
276
333
|
}
|
|
334
|
+
const firstArg = positionals[0];
|
|
335
|
+
const secondArg = positionals[1];
|
|
277
336
|
if (!fs.existsSync(firstArg)) {
|
|
278
337
|
console.error(`Path does not exist: ${firstArg}`);
|
|
279
338
|
console.error("Use --help for usage information");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babelfhir-ts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "BabelFHIR-TS: generate TypeScript interfaces, validators, and helper classes from FHIR R4 StructureDefinitions (profiles) directly inside package archives.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "out/main.js",
|