babelfhir-ts 1.0.13 → 1.0.14

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.
@@ -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 (/^coverage_de_/.test(baseResource)) {
67
- baseResource = 'Coverage';
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
- console.warn(`No new fields for ${interfaceName}, skipping.`);
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
- // Skip custom German coverage base pseudo-types that we cannot resolve
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 (/^coverage_de_/.test(sanitizedBase)) {
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
@@ -114,48 +114,94 @@ async function downloadPackage(packageSpec, registry) {
114
114
  throw error;
115
115
  }
116
116
  }
117
+ function parseCliArgs(argv) {
118
+ const out = {
119
+ registry: 'https://packages.simplifier.net',
120
+ logLevel: 'none',
121
+ packageSpec: null,
122
+ flags: { noCache: false, noClasses: false, logLevel: 'none' },
123
+ positionals: []
124
+ };
125
+ for (let i = 0; i < argv.length; i++) {
126
+ const arg = argv[i];
127
+ if (arg === '--help' || arg === '-h' || arg === '--version' || arg === '-v' || arg === 'install') {
128
+ // Commands or special flags handled later as positionals to preserve order
129
+ out.positionals.push(arg);
130
+ continue;
131
+ }
132
+ if (arg === '--no-cache') {
133
+ out.flags.noCache = true;
134
+ continue;
135
+ }
136
+ if (arg === '--no-classes') {
137
+ out.flags.noClasses = true;
138
+ continue;
139
+ }
140
+ if (arg === '--log') {
141
+ const val = argv[i + 1];
142
+ if (!val || val.startsWith('-')) {
143
+ throw new Error('Missing value for --log');
144
+ }
145
+ if (!['none', 'console', 'file'].includes(val)) {
146
+ throw new Error(`Invalid --log value: ${val}. Must be: none, console, or file`);
147
+ }
148
+ out.logLevel = val;
149
+ out.flags.logLevel = out.logLevel;
150
+ i++;
151
+ continue;
152
+ }
153
+ if (arg === '--package') {
154
+ const val = argv[i + 1];
155
+ if (!val || val.startsWith('-'))
156
+ throw new Error('Missing value for --package');
157
+ out.packageSpec = val;
158
+ i++;
159
+ continue;
160
+ }
161
+ if (arg === '--registry') {
162
+ const val = argv[i + 1];
163
+ if (!val || val.startsWith('-'))
164
+ throw new Error('Missing value for --registry');
165
+ out.registry = val;
166
+ i++;
167
+ continue;
168
+ }
169
+ // Anything else that doesn't start with -- is positional
170
+ if (!arg.startsWith('--')) {
171
+ out.positionals.push(arg);
172
+ continue;
173
+ }
174
+ // Unknown --flag -> keep as positional to trigger usage error later
175
+ out.positionals.push(arg);
176
+ }
177
+ return out;
178
+ }
117
179
  async function run() {
118
- const args = process.argv.slice(2);
119
- // Parse --registry flag
120
- let registry = 'https://packages.simplifier.net';
121
- const registryIndex = args.indexOf('--registry');
122
- if (registryIndex !== -1 && args[registryIndex + 1]) {
123
- registry = args[registryIndex + 1];
180
+ const argv = process.argv.slice(2);
181
+ let parsed;
182
+ try {
183
+ parsed = parseCliArgs(argv);
124
184
  }
125
- // Parse --log flag
126
- const logIndex = args.indexOf('--log');
127
- const logLevel = logIndex !== -1 && args[logIndex + 1] ? args[logIndex + 1] : 'none';
128
- if (!['none', 'console', 'file'].includes(logLevel)) {
129
- console.error(`Invalid --log value: ${logLevel}. Must be: none, console, or file`);
185
+ catch (e) {
186
+ console.error(`Error: ${e.message}`);
187
+ printUsage();
130
188
  process.exit(1);
131
189
  }
132
- // Parse --package flag
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];
190
+ const { registry, packageSpec, flags, positionals } = parsed;
145
191
  // Check for help flags
146
- if (firstArg === '--help' || firstArg === '-h') {
192
+ if (positionals.includes('--help') || positionals.includes('-h')) {
147
193
  printUsage();
148
194
  process.exit(0);
149
195
  }
150
196
  // Check for version flag
151
- if (firstArg === '--version' || firstArg === '-v') {
197
+ if (positionals.includes('--version') || positionals.includes('-v')) {
152
198
  console.log(`babelfhir-ts version ${packageJson.version}`);
153
199
  process.exit(0);
154
200
  }
155
201
  // Handle install command
156
- if (firstArg === 'install') {
202
+ if (positionals[0] === 'install') {
157
203
  // Package can come from --package flag OR as positional argument after 'install'
158
- const packageToInstall = packageSpec || secondArg;
204
+ const packageToInstall = packageSpec || positionals[1];
159
205
  if (!packageToInstall) {
160
206
  console.error('Error: install command requires a package name');
161
207
  console.error('Example: babelfhir-ts install de.gematik.isik-basismodul@3.1.0');
@@ -212,7 +258,7 @@ async function run() {
212
258
  if (flags.noCache) {
213
259
  cleanupCache();
214
260
  }
215
- console.log(`\n✓ Package ${secondArg} installed and ready to use!`);
261
+ console.log(`\n✓ Package ${packageToInstall} installed and ready to use!`);
216
262
  return;
217
263
  }
218
264
  catch (error) {
@@ -259,12 +305,11 @@ async function run() {
259
305
  process.exit(1);
260
306
  }
261
307
  }
262
- if (!firstArg) {
308
+ if (positionals.length === 0) {
263
309
  // Default: attempt input -> output
264
310
  if (fs.existsSync('input') && fs.lstatSync('input').isDirectory()) {
265
- firstArg = 'input';
266
311
  const outputDir = 'output';
267
- await generateForDirectory(firstArg, outputDir, flags);
312
+ await generateForDirectory('input', outputDir, flags);
268
313
  console.log(`Batch generation complete. Output in: ${outputDir}`);
269
314
  if (flags.noCache) {
270
315
  cleanupCache();
@@ -274,6 +319,8 @@ async function run() {
274
319
  printError();
275
320
  process.exit(1);
276
321
  }
322
+ const firstArg = positionals[0];
323
+ const secondArg = positionals[1];
277
324
  if (!fs.existsSync(firstArg)) {
278
325
  console.error(`Path does not exist: ${firstArg}`);
279
326
  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.13",
3
+ "version": "1.0.14",
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",