babelfhir-ts 1.5.15 → 1.5.16

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.
@@ -456,9 +456,9 @@ function generatePatternCodingValidation(slice, relPath, errorPath, sliceLabel,
456
456
  if (isNestedInOptionalSlice) {
457
457
  out.push(`
458
458
  // Required slice validation for ${relPath}:${sliceLabel} (nested in array: ${arrayParentPath}, parent slice is optional)
459
- if ((resource as any).${arrayParentPath} && Array.isArray((resource as any).${arrayParentPath}) && (resource as any).${arrayParentPath}.length > 0) {
459
+ if (resource.${arrayParentPath} && Array.isArray(resource.${arrayParentPath}) && resource.${arrayParentPath}.length > 0) {
460
460
  const ${varName}Elements: Array<{ system?: string; code?: string }> = [];
461
- for (const item of (resource as any).${arrayParentPath}) {
461
+ for (const item of resource.${arrayParentPath}) {
462
462
  const nestedArray = item.${optionalPath};
463
463
  if (nestedArray && Array.isArray(nestedArray)) {
464
464
  for (const coding of nestedArray) { if (${matchExpr.replace(/item\./g, 'coding.')}) ${varName}Elements.push(coding); }
@@ -473,9 +473,9 @@ function generatePatternCodingValidation(slice, relPath, errorPath, sliceLabel,
473
473
  out.push(`
474
474
  // Required slice validation for ${relPath}:${sliceLabel} (nested in array: ${arrayParentPath})
475
475
  // Only check when parent array exists — parent absence is reported by separate required-field checks
476
- if ((resource as any).${arrayParentPath} && Array.isArray((resource as any).${arrayParentPath})) {
476
+ if (resource.${arrayParentPath} && Array.isArray(resource.${arrayParentPath})) {
477
477
  const ${varName}Elements: Array<{ system?: string; code?: string }> = [];
478
- for (const item of (resource as any).${arrayParentPath}) {
478
+ for (const item of resource.${arrayParentPath}) {
479
479
  const nestedArray = item.${optionalPath};
480
480
  if (nestedArray && Array.isArray(nestedArray)) {
481
481
  for (const coding of nestedArray) { if (${matchExpr.replace(/item\./g, 'coding.')}) ${varName}Elements.push(coding); }
@@ -496,9 +496,9 @@ function generatePatternCodingValidation(slice, relPath, errorPath, sliceLabel,
496
496
  out.push(`
497
497
  // Required slice validation for ${relPath}:${sliceLabel}
498
498
  // Only check nested slice if parent field exists (parent absence is already reported separately)
499
- if ((resource as any).${parentPath}) {
500
- if ((resource as any).${optionalPath} && Array.isArray((resource as any).${optionalPath})) {
501
- const ${varName}Elements = ((resource as any).${optionalPath} as Array<{ system?: string; code?: string }>).filter((item) =>
499
+ if (resource.${parentPath}) {
500
+ if (resource.${optionalPath} && Array.isArray(resource.${optionalPath})) {
501
+ const ${varName}Elements = (resource.${optionalPath} as Array<{ system?: string; code?: string }>).filter((item) =>
502
502
  ${matchExpr}
503
503
  );
504
504
  if (${varName}Elements.length < ${min}) {
@@ -512,8 +512,8 @@ function generatePatternCodingValidation(slice, relPath, errorPath, sliceLabel,
512
512
  else {
513
513
  out.push(`
514
514
  // Required slice validation for ${relPath}:${sliceLabel}
515
- if ((resource as any).${optionalPath} && Array.isArray((resource as any).${optionalPath})) {
516
- const ${varName}Elements = ((resource as any).${optionalPath} as Array<{ system?: string; code?: string }>).filter((item) =>
515
+ if (resource.${optionalPath} && Array.isArray(resource.${optionalPath})) {
516
+ const ${varName}Elements = (resource.${optionalPath} as Array<{ system?: string; code?: string }>).filter((item) =>
517
517
  ${matchExpr}
518
518
  );
519
519
  if (${varName}Elements.length < ${min}) {
@@ -627,8 +627,8 @@ function generateProfiledChildDelegation(slice, relPath, childFieldsWithFixedVal
627
627
  out.push(`
628
628
  // Profiled sub-resource delegation for ${relPath}:${sliceLabel}.${childRelPath} → ${delegateName}
629
629
  {
630
- if ((resource as any).${arrayParentPath} && Array.isArray((resource as any).${arrayParentPath})) {
631
- for (const _parentItem of (resource as any).${arrayParentPath}) {
630
+ if (resource.${arrayParentPath} && Array.isArray(resource.${arrayParentPath})) {
631
+ for (const _parentItem of resource.${arrayParentPath}) {
632
632
  const _pi: any = _parentItem;
633
633
  const _nestedArr = _pi?.${remainingPath};
634
634
  if (_nestedArr && Array.isArray(_nestedArr)) {
@@ -775,9 +775,9 @@ function generateProfileDiscriminatorValidation(slice, relPath, errorPath, slice
775
775
  const { resourceType, profileUrls } = match;
776
776
  const max = typeof slice.max === 'number' && slice.max !== Infinity ? slice.max : undefined;
777
777
  const parentPath = relPath.includes('.') ? relPath.split('.').slice(0, -1).join('.') : '';
778
- const accessor = parentPath ? `(resource as any)?.${parentPath.replace(/\./g, '?.')}` : `(resource as any).${relPath}`;
778
+ const accessor = parentPath ? `(resource as any)?.${parentPath.replace(/\./g, '?.')}` : `resource.${relPath}`;
779
779
  // For top-level entry slices, access resource.entry directly
780
- const arrayAccessor = relPath === 'entry' || !relPath.includes('.') ? `(resource as any).${relPath}` : accessor;
780
+ const arrayAccessor = relPath === 'entry' || !relPath.includes('.') ? `resource.${relPath}` : accessor;
781
781
  // Resolve profiled validator for delegation
782
782
  let delegateInterfaceName;
783
783
  if (ctx.profileUrlToName && ctx.validatorImports) {
@@ -102,12 +102,39 @@ function copyFhirAmbientDeclaration(outputDir) {
102
102
  log.warn(`Warning: ${dtsFileName} not found. Run: npm run generate:fhir-module`);
103
103
  }
104
104
  }
105
+ /**
106
+ * Locate the `@types` directory that ships with babelfhir-ts itself (the one
107
+ * containing `@types/fhir`). The generated output imports base FHIR types via the
108
+ * ambient `fhir/r4` module, which aliases `fhir4.*` from `@types/fhir`. Under
109
+ * `--skip-install` the generated package's own dependencies (including
110
+ * `@types/fhir`) are never installed into its `node_modules`, so the output
111
+ * typecheck would resolve `fhir4.Observation` to an empty type and any validator
112
+ * accessing a base-inherited field not restated locally (e.g. `Observation.code`
113
+ * on a profile that only slices `code.coding`) would fail TS2339. Pointing
114
+ * `typeRoots` at babelfhir's own always-present `@types` makes the typecheck
115
+ * robust regardless of the output's install state.
116
+ */
117
+ function resolveGeneratorTypeRoots() {
118
+ let dir = __generatorDir;
119
+ for (let i = 0; i < 6; i++) {
120
+ const atTypes = path.join(dir, 'node_modules', '@types');
121
+ if (fs.existsSync(path.join(atTypes, 'fhir')))
122
+ return [atTypes];
123
+ const parent = path.dirname(dir);
124
+ if (parent === dir)
125
+ break;
126
+ dir = parent;
127
+ }
128
+ return [];
129
+ }
105
130
  /** Compile TypeScript files to JavaScript with declaration files */
106
131
  async function compileTypeScriptToJS(dir) {
107
132
  return new Promise((resolve, reject) => {
108
133
  const tscCmd = process.platform === 'win32' ? 'tsc.cmd' : 'tsc';
109
134
  // Create a temporary tsconfig.json for compilation
110
- // Paths are relative to tsconfig location (which is `dir` itself)
135
+ // Paths are relative to tsconfig location (which is `dir` itself); the
136
+ // generator's own @types (absolute) is appended so `@types/fhir` resolves
137
+ // even when the output's deps were skipped (see resolveGeneratorTypeRoots).
111
138
  const tsconfig = {
112
139
  compilerOptions: {
113
140
  target: 'ES2020',
@@ -121,7 +148,7 @@ async function compileTypeScriptToJS(dir) {
121
148
  allowSyntheticDefaultImports: true,
122
149
  strict: true,
123
150
  resolveJsonModule: true,
124
- typeRoots: ['./node_modules/@types'],
151
+ typeRoots: ['./node_modules/@types', ...resolveGeneratorTypeRoots()],
125
152
  types: ['node']
126
153
  },
127
154
  include: ['./**/*.ts'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babelfhir-ts",
3
- "version": "1.5.15",
3
+ "version": "1.5.16",
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",