@atomic-ehr/fhirpath 0.0.5 → 0.0.6-canary.20260203154724.387b5fc

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.
@@ -1,8 +1,8 @@
1
- import { F as FHIRModelProviderBase, R as Resource } from './model-provider.common-oir-zg7r.js';
2
- export { q as ASTMetadata, i as ASTNode, h as AnalysisResult, A as Analyzer, N as AnyCursorNode, w as CompletionItem, C as CompletionKind, x as CompletionOptions, J as CursorArgumentNode, y as CursorContext, H as CursorIdentifierNode, K as CursorIndexNode, B as CursorNode, G as CursorOperatorNode, L as CursorTypeNode, f as Diagnostic, D as DiagnosticSeverity, u as ErrorCodes, t as Errors, E as EvaluateOptions, l as EvaluationResult, a as FHIRModelContext, s as FHIRPathError, k as FunctionDefinition, n as InspectOptions, o as InspectResult, I as Interpreter, M as ModelTypeProvider, O as OperatorDefinition, d as ParseResult, P as Parser, c as Registry, T as TypeInfo, j as TypeName, b as analyze, e as evaluate, g as getVersion, m as inspect, z as isCursorNode, p as parse, v as provideCompletions, r as registry } from './model-provider.common-oir-zg7r.js';
1
+ import { F as FHIRModelProviderBase, R as Resource } from './model-provider.common-BULsr92N.js';
2
+ export { q as ASTMetadata, i as ASTNode, h as AnalysisResult, A as Analyzer, N as AnyCursorNode, w as CompletionItem, C as CompletionKind, x as CompletionOptions, J as CursorArgumentNode, y as CursorContext, H as CursorIdentifierNode, K as CursorIndexNode, B as CursorNode, G as CursorOperatorNode, L as CursorTypeNode, f as Diagnostic, D as DiagnosticSeverity, u as ErrorCodes, t as Errors, E as EvaluateOptions, l as EvaluationResult, a as FHIRModelContext, s as FHIRPathError, k as FunctionDefinition, n as InspectOptions, o as InspectResult, I as Interpreter, M as ModelTypeProvider, O as OperatorDefinition, d as ParseResult, P as Parser, c as Registry, T as TypeInfo, j as TypeName, b as analyze, e as evaluate, g as getVersion, m as inspect, z as isCursorNode, p as parse, v as provideCompletions, r as registry } from './model-provider.common-BULsr92N.js';
3
3
  import '@atomic-ehr/fhirschema';
4
4
 
5
- type Resolver = (canonicalUrl: string) => Promise<Resource | null>;
5
+ type Resolver = (typeName: string) => Promise<Resource | null>;
6
6
  type Searcher = (kind: 'primitive-type' | 'complex-type' | 'resource') => Promise<Resource[]>;
7
7
  type Options = {
8
8
  resolve: Resolver;
@@ -11,7 +11,7 @@ type Options = {
11
11
  declare class FHIRModelProvider extends FHIRModelProviderBase {
12
12
  private _resolve;
13
13
  private _search;
14
- resolve(canonicalUrl: string): Promise<Resource | null>;
14
+ resolve(typeName: string): Promise<Resource | null>;
15
15
  search(params: {
16
16
  kind: 'primitive-type' | 'complex-type' | 'resource';
17
17
  }): Promise<Resource[]>;
@@ -2267,6 +2267,8 @@ __export(operations_exports, {
2267
2267
  extensionFunction: () => extensionFunction,
2268
2268
  firstFunction: () => firstFunction,
2269
2269
  floorFunction: () => floorFunction,
2270
+ getReferenceKeyFunction: () => getReferenceKeyFunction,
2271
+ getResourceKeyFunction: () => getResourceKeyFunction,
2270
2272
  greaterOperator: () => greaterOperator,
2271
2273
  greaterOrEqualOperator: () => greaterOrEqualOperator,
2272
2274
  hasValueFunction: () => hasValueFunction,
@@ -11581,6 +11583,133 @@ var expFunction = {
11581
11583
  evaluate: evaluate105
11582
11584
  };
11583
11585
 
11586
+ // src/operations/getResourceKey-function.ts
11587
+ var evaluate106 = async (input, context, args, evaluator) => {
11588
+ const results = [];
11589
+ for (const boxedItem of input) {
11590
+ const item = unbox(boxedItem);
11591
+ if (item && typeof item === "object") {
11592
+ if ("id" in item && item.id !== void 0) {
11593
+ results.push(box(String(item.id), { type: "String", singleton: true }));
11594
+ }
11595
+ }
11596
+ }
11597
+ return { value: results, context };
11598
+ };
11599
+ var getResourceKeyFunction = {
11600
+ name: "getResourceKey",
11601
+ category: ["SQL on FHIR", "navigation"],
11602
+ description: "Returns a unique key identifying this resource for use in database joins. The returned value can be used with getReferenceKey() to join resources. This is typically the resource id, but the exact format is implementation-dependent.",
11603
+ examples: [
11604
+ "getResourceKey()",
11605
+ "Patient.getResourceKey()"
11606
+ ],
11607
+ signatures: [{
11608
+ name: "getResourceKey",
11609
+ input: { type: "Any", singleton: false, name: "Resource" },
11610
+ parameters: [],
11611
+ result: { type: "String", singleton: false }
11612
+ }],
11613
+ evaluate: evaluate106
11614
+ };
11615
+
11616
+ // src/operations/getReferenceKey-function.ts
11617
+ init_errors();
11618
+ init_types();
11619
+ function parseReference(reference) {
11620
+ if (!reference) return null;
11621
+ if (reference.startsWith("urn:")) {
11622
+ return { id: reference };
11623
+ }
11624
+ if (reference.includes("://")) {
11625
+ const url = reference.split("?")[0];
11626
+ const segments = url.split("/").filter((s) => s);
11627
+ if (segments.length >= 2) {
11628
+ const id = segments[segments.length - 1];
11629
+ const resourceType = segments[segments.length - 2];
11630
+ return { resourceType, id };
11631
+ }
11632
+ return null;
11633
+ }
11634
+ const parts = reference.split("/");
11635
+ if (parts.length === 2) {
11636
+ return { resourceType: parts[0], id: parts[1] };
11637
+ }
11638
+ if (reference.startsWith("#")) {
11639
+ return { id: reference.substring(1) };
11640
+ }
11641
+ return null;
11642
+ }
11643
+ function extractTypeName(typeArg) {
11644
+ if (isIdentifierNode(typeArg)) {
11645
+ return typeArg.name;
11646
+ } else if (isFunctionNode(typeArg) && isIdentifierNode(typeArg.name)) {
11647
+ return typeArg.name.name;
11648
+ }
11649
+ throw Errors.invalidOperation(`getReferenceKey() requires a type name as argument, got ${typeArg.type}`);
11650
+ }
11651
+ var evaluate107 = async (input, context, args, evaluator) => {
11652
+ let targetResourceType;
11653
+ if (args.length > 0) {
11654
+ targetResourceType = extractTypeName(args[0]);
11655
+ }
11656
+ const results = [];
11657
+ for (const boxedItem of input) {
11658
+ const item = unbox(boxedItem);
11659
+ if (!item || typeof item !== "object") {
11660
+ continue;
11661
+ }
11662
+ let referenceString;
11663
+ if ("reference" in item && typeof item.reference === "string") {
11664
+ referenceString = item.reference;
11665
+ } else if (typeof item === "string") {
11666
+ referenceString = item;
11667
+ }
11668
+ if (!referenceString) {
11669
+ continue;
11670
+ }
11671
+ const parsed = parseReference(referenceString);
11672
+ if (!parsed || !parsed.id) {
11673
+ continue;
11674
+ }
11675
+ if (targetResourceType) {
11676
+ if (!parsed.resourceType || parsed.resourceType !== targetResourceType) {
11677
+ continue;
11678
+ }
11679
+ }
11680
+ results.push(box(parsed.id, { type: "String", singleton: true }));
11681
+ }
11682
+ return { value: results, context };
11683
+ };
11684
+ var getReferenceKeyFunction = {
11685
+ name: "getReferenceKey",
11686
+ category: ["SQL on FHIR", "navigation"],
11687
+ description: "Returns a foreign key from a Reference element for joining to another resource. The returned value equals getResourceKey() on the referenced resource. If resourceType is provided, returns empty if the reference is not of that type.",
11688
+ examples: [
11689
+ "subject.getReferenceKey()",
11690
+ "subject.getReferenceKey(Patient)",
11691
+ "Observation.subject.getReferenceKey(Patient)"
11692
+ ],
11693
+ signatures: [
11694
+ {
11695
+ name: "getReferenceKey",
11696
+ input: { type: "Any", singleton: false, name: "Reference" },
11697
+ parameters: [
11698
+ {
11699
+ name: "resourceType",
11700
+ type: { type: "Any", singleton: true },
11701
+ optional: true,
11702
+ expression: true,
11703
+ typeReference: true
11704
+ // Expects a type name like Patient, Observation
11705
+ }
11706
+ ],
11707
+ result: { type: "String", singleton: false }
11708
+ }
11709
+ ],
11710
+ evaluate: evaluate107
11711
+ };
11712
+
11584
11713
  // src/registry.ts
11585
11714
  var Registry = class {
11586
11715
  constructor() {
@@ -13064,11 +13193,11 @@ function specificity(actual, required) {
13064
13193
  if (numeric.has(actual.type) && numeric.has(required.type)) return 2;
13065
13194
  return 1;
13066
13195
  }
13067
- function matchFunctionSignature(input, args, def) {
13196
+ function matchFunctionSignature(input, args, def, resourceTypes) {
13068
13197
  if (!def || !def.signatures || def.signatures.length === 0) return void 0;
13069
13198
  let best;
13070
13199
  for (const sig of def.signatures) {
13071
- if (sig.input && !isFunctionTypeCompatible(input, sig.input)) {
13200
+ if (sig.input && !isFunctionTypeCompatible(input, sig.input, resourceTypes)) {
13072
13201
  continue;
13073
13202
  }
13074
13203
  let ok = true;
@@ -13105,8 +13234,16 @@ function matchFunctionSignature(input, args, def) {
13105
13234
  }
13106
13235
  return best?.sig;
13107
13236
  }
13108
- function isFunctionTypeCompatible(actual, expected) {
13237
+ function isFunctionTypeCompatible(actual, expected, resourceTypes) {
13109
13238
  if (expected.singleton && !actual.singleton) return false;
13239
+ if (expected.name && actual.name) {
13240
+ if (expected.name === "Resource") {
13241
+ if (actual.name === "Resource") return true;
13242
+ if (resourceTypes) return resourceTypes.has(actual.name);
13243
+ return true;
13244
+ }
13245
+ if (expected.name !== actual.name) return false;
13246
+ }
13110
13247
  if (expected.type === "Any") return true;
13111
13248
  if (actual.type === expected.type) return true;
13112
13249
  if (expected.type === "Decimal" && actual.type === "Integer") return true;
@@ -13213,6 +13350,7 @@ function checkParamTypes(sig, argTypes, nodes, opts) {
13213
13350
  init_errors();
13214
13351
  var Analyzer = class _Analyzer {
13215
13352
  constructor(modelProvider) {
13353
+ this.resourceTypesCache = null;
13216
13354
  this.cursorMode = false;
13217
13355
  this.stoppedAtCursor = false;
13218
13356
  this.modelProvider = modelProvider;
@@ -13558,7 +13696,12 @@ var Analyzer = class _Analyzer {
13558
13696
  const diagnostics = [];
13559
13697
  let match = null;
13560
13698
  if (!hasArityError && funcDef.signatures && funcDef.signatures.length > 0) {
13561
- match = matchFunctionSignature(actualInput, argTypes, funcDef) || null;
13699
+ match = matchFunctionSignature(
13700
+ actualInput,
13701
+ argTypes,
13702
+ funcDef,
13703
+ this.resourceTypesCache ?? void 0
13704
+ ) || null;
13562
13705
  if (!match) {
13563
13706
  const inputIsEmpty = isEmptyCollection(actualInput);
13564
13707
  if (inputIsEmpty && !funcDef.doesNotPropagateEmpty) {
@@ -13581,7 +13724,11 @@ var Analyzer = class _Analyzer {
13581
13724
  const expectedInput = sig.input;
13582
13725
  const singletonMatch = !expectedInput.singleton || actualInput.singleton === true;
13583
13726
  const typeMatch = expectedInput.type === "Any" || actualInput.type === "Any" || expectedInput.type === actualInput.type || expectedInput.type === "Decimal" && actualInput.type === "Integer";
13584
- inputMatches = singletonMatch && typeMatch;
13727
+ let nameMatch = !expectedInput.name || !actualInput.name || expectedInput.name === actualInput.name;
13728
+ if (expectedInput.name === "Resource" && actualInput.name) {
13729
+ nameMatch = actualInput.name === "Resource" || (this.resourceTypesCache?.has(actualInput.name) ?? true);
13730
+ }
13731
+ inputMatches = singletonMatch && typeMatch && nameMatch;
13585
13732
  }
13586
13733
  if (inputMatches) {
13587
13734
  inputMatchingSignature = sig;
@@ -13597,7 +13744,8 @@ var Analyzer = class _Analyzer {
13597
13744
  })
13598
13745
  );
13599
13746
  } else {
13600
- const actualTypeStr = actualInput.singleton ? actualInput.type : `${actualInput.type}[]`;
13747
+ const actualTypeName = actualInput.name || actualInput.type;
13748
+ const actualTypeStr = actualInput.singleton ? actualTypeName : `${actualTypeName}[]`;
13601
13749
  const hasSingletonSignature = funcDef.signatures.some((sig) => sig.input?.singleton && sig.input.type === actualInput.type);
13602
13750
  const permissive = ["anyFalse", "anyTrue"];
13603
13751
  if (hasSingletonSignature && !actualInput.singleton) {
@@ -13609,7 +13757,11 @@ var Analyzer = class _Analyzer {
13609
13757
  )
13610
13758
  );
13611
13759
  } else if (!permissive.includes(functionName)) {
13612
- const expectedTypes = funcDef.signatures.map((sig) => sig.input ? sig.input.singleton ? sig.input.type : `${sig.input.type}[]` : "Any").filter((v, i, a) => a.indexOf(v) === i).join(" or ");
13760
+ const expectedTypes = funcDef.signatures.map((sig) => {
13761
+ if (!sig.input) return "Any";
13762
+ const name = sig.input.name || sig.input.type;
13763
+ return sig.input.singleton ? name : `${name}[]`;
13764
+ }).filter((v, i, a) => a.indexOf(v) === i).join(" or ");
13613
13765
  diagnostics.push(
13614
13766
  this.createError(
13615
13767
  node,
@@ -14021,6 +14173,10 @@ var Analyzer = class _Analyzer {
14021
14173
  this.cursorMode = options?.cursorMode ?? false;
14022
14174
  this.stoppedAtCursor = false;
14023
14175
  this.cursorContext = void 0;
14176
+ if (this.modelProvider && this.resourceTypesCache === null) {
14177
+ const list = await this.modelProvider.getResourceTypes();
14178
+ this.resourceTypesCache = new Set(list);
14179
+ }
14024
14180
  const systemVars = /* @__PURE__ */ new Map();
14025
14181
  systemVars.set("$this", inputType || { type: "Any", singleton: false });
14026
14182
  systemVars.set("$index", { type: "Integer", singleton: true });
@@ -14937,10 +15093,33 @@ async function provideCompletions(expression, cursorPosition, options = {}) {
14937
15093
  return [];
14938
15094
  }
14939
15095
  }
14940
- function isFunctionApplicable(funcDef, typeInfo) {
15096
+ async function isFunctionApplicable(funcDef, typeInfo, modelProvider) {
14941
15097
  if (!typeInfo || !typeInfo.type) return true;
14942
15098
  const typeForRegistry = typeInfo.singleton === false ? `${typeInfo.type}[]` : typeInfo.type;
14943
- return registry.isFunctionApplicableToType(funcDef.name, typeForRegistry);
15099
+ if (!registry.isFunctionApplicableToType(funcDef.name, typeForRegistry)) {
15100
+ return false;
15101
+ }
15102
+ if (funcDef.signatures) {
15103
+ const hasNameConstraint = funcDef.signatures.some(
15104
+ (sig) => sig.input && sig.input.name
15105
+ );
15106
+ if (hasNameConstraint && typeInfo.name) {
15107
+ const resourceTypes = modelProvider ? await modelProvider.getResourceTypes() : [];
15108
+ const nameMatches = funcDef.signatures.some((sig) => {
15109
+ if (!sig.input?.name) return true;
15110
+ if (sig.input.name === typeInfo.name) return true;
15111
+ if (sig.input.name === "Resource") {
15112
+ const name = typeInfo.name;
15113
+ return name === "Resource" || name !== void 0 && resourceTypes.includes(name);
15114
+ }
15115
+ return false;
15116
+ });
15117
+ if (!nameMatches) {
15118
+ return false;
15119
+ }
15120
+ }
15121
+ }
15122
+ return true;
14944
15123
  }
14945
15124
  function isOperatorApplicable(opDef, typeInfo) {
14946
15125
  if (!typeInfo || !typeInfo.type) return true;
@@ -14984,7 +15163,7 @@ async function getIdentifierCompletions(typeBeforeCursor, modelProvider) {
14984
15163
  for (const name of functionNames) {
14985
15164
  const funcDef = registry.getFunction(name);
14986
15165
  if (funcDef) {
14987
- const isApplicable = !typeBeforeCursor || isFunctionApplicable(funcDef, typeBeforeCursor);
15166
+ const isApplicable = !typeBeforeCursor || await isFunctionApplicable(funcDef, typeBeforeCursor, modelProvider);
14988
15167
  if (isApplicable) {
14989
15168
  const hasParams = funcDef.signatures?.some((sig) => (sig.parameters?.length ?? 0) > 0) ?? false;
14990
15169
  const funcDescription = funcDef.description || `FHIRPath ${name} function`;
@@ -15001,7 +15180,7 @@ async function getIdentifierCompletions(typeBeforeCursor, modelProvider) {
15001
15180
  const typeForRegistry = typeBeforeCursor.singleton === false ? `${typeBeforeCursor.type}[]` : typeBeforeCursor.type;
15002
15181
  const typeFunctions = registry.getFunctionsForType(typeForRegistry);
15003
15182
  for (const func of typeFunctions) {
15004
- if (!completions.some((c) => c.label === func.name)) {
15183
+ if (!completions.some((c) => c.label === func.name) && await isFunctionApplicable(func, typeBeforeCursor, modelProvider)) {
15005
15184
  const hasParams = func.signatures?.some((sig) => (sig.parameters?.length ?? 0) > 0) ?? false;
15006
15185
  completions.push({
15007
15186
  label: func.name,
@@ -15244,7 +15423,7 @@ function rankCompletions(completions) {
15244
15423
  }
15245
15424
 
15246
15425
  // src/index.common.ts
15247
- async function evaluate106(expression, options = {}) {
15426
+ async function evaluate108(expression, options = {}) {
15248
15427
  const interpreter = new Interpreter(void 0, options.modelProvider);
15249
15428
  return interpreter.evaluateExpression(expression, {
15250
15429
  input: options.input,
@@ -15264,7 +15443,7 @@ async function analyze(expression, options = {}) {
15264
15443
  return analysisResult;
15265
15444
  }
15266
15445
  function getVersion() {
15267
- return "0.0.5";
15446
+ return "0.0.6-canary.20260203154724.387b5fc";
15268
15447
  }
15269
15448
  var FHIRModelProviderBase = class _FHIRModelProviderBase {
15270
15449
  constructor() {
@@ -15346,23 +15525,19 @@ var FHIRModelProviderBase = class _FHIRModelProviderBase {
15346
15525
  this.initialized = true;
15347
15526
  }
15348
15527
  }
15349
- async resolve(_canonicalUrl) {
15528
+ async resolve(_typeName) {
15350
15529
  throw new Error("Resolve not implemented.");
15351
15530
  }
15352
15531
  async search(_params) {
15353
15532
  throw new Error("Search not implemented.");
15354
15533
  }
15355
- buildCanonicalUrl(typeName) {
15356
- return `http://hl7.org/fhir/StructureDefinition/${typeName}`;
15357
- }
15358
15534
  // Public method to get schema with automatic caching
15359
15535
  async getSchema(typeName) {
15360
15536
  if (this.schemaCache.has(typeName)) {
15361
15537
  return this.schemaCache.get(typeName);
15362
15538
  }
15363
15539
  try {
15364
- const canonicalUrl = this.buildCanonicalUrl(typeName);
15365
- const resource = await this.resolve(canonicalUrl);
15540
+ const resource = await this.resolve(typeName);
15366
15541
  if (!resource || resource.resourceType !== "StructureDefinition") {
15367
15542
  return void 0;
15368
15543
  }
@@ -15736,8 +15911,8 @@ var FHIRModelProviderBase = class _FHIRModelProviderBase {
15736
15911
 
15737
15912
  // src/model-provider.browser.ts
15738
15913
  var FHIRModelProvider = class extends FHIRModelProviderBase {
15739
- async resolve(canonicalUrl) {
15740
- return await this._resolve(canonicalUrl);
15914
+ async resolve(typeName) {
15915
+ return await this._resolve(typeName);
15741
15916
  }
15742
15917
  async search(params) {
15743
15918
  return await this._search(params.kind);
@@ -15753,6 +15928,6 @@ var FHIRModelProvider = class extends FHIRModelProviderBase {
15753
15928
  }
15754
15929
  };
15755
15930
 
15756
- export { Analyzer, CompletionKind, CursorContext, DiagnosticSeverity, ErrorCodes, Errors, FHIRModelProvider, FHIRPathError, Interpreter, Parser, Registry, analyze, evaluate106 as evaluate, getVersion, inspect, isCursorNode, parse, provideCompletions, registry };
15931
+ export { Analyzer, CompletionKind, CursorContext, DiagnosticSeverity, ErrorCodes, Errors, FHIRModelProvider, FHIRPathError, Interpreter, Parser, Registry, analyze, evaluate108 as evaluate, getVersion, inspect, isCursorNode, parse, provideCompletions, registry };
15757
15932
  //# sourceMappingURL=index.browser.js.map
15758
15933
  //# sourceMappingURL=index.browser.js.map