Skip to content

Commit fcabaa1

Browse files
committed
Restrict Long matching to valueString and valueInteger64
A Long result is only allowed to be returned as valueString or valueInteger64, never valueInteger. Drop the numeric match from the Long comparison and add an Integer64Extractor to the extraction chain (FHIR integer64 is serialized as a JSON string). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6fK2KhnNsn28SJfe83Htw
1 parent fbbdb4b commit fcabaa1

5 files changed

Lines changed: 34 additions & 8 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { BaseExtractor } from '../base-extractor.js';
2+
3+
export class Integer64Extractor extends BaseExtractor {
4+
protected _process(parameter: any): any {
5+
if (parameter.hasOwnProperty('valueInteger64')) {
6+
// FHIR integer64 is serialized as a JSON string; normalize in case a
7+
// server sends a JSON number instead.
8+
return String(parameter.valueInteger64);
9+
}
10+
11+
return undefined;
12+
}
13+
}

src/server/extractor-builder.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { UndefinedExtractor } from '../extractors/undefined-extractor.js';
44
import { StringExtractor } from '../extractors/value-type-extractors/string-extractor.js';
55
import { BooleanExtractor } from '../extractors/value-type-extractors/boolean-extractor.js';
66
import { IntegerExtractor } from '../extractors/value-type-extractors/integer-extractor.js';
7+
import { Integer64Extractor } from '../extractors/value-type-extractors/integer64-extractor.js';
78
import { DecimalExtractor } from '../extractors/value-type-extractors/decimal-extractor.js';
89
import { DateExtractor } from '../extractors/value-type-extractors/date-extractor.js';
910
import { DateTimeExtractor } from '../extractors/value-type-extractors/datetime-extractor.js';
@@ -27,6 +28,7 @@ export function buildExtractor(): ResultExtractor {
2728
.setNextExtractor(new StringExtractor())
2829
.setNextExtractor(new BooleanExtractor())
2930
.setNextExtractor(new IntegerExtractor())
31+
.setNextExtractor(new Integer64Extractor())
3032
.setNextExtractor(new DecimalExtractor())
3133
.setNextExtractor(new DateExtractor())
3234
.setNextExtractor(new DateTimeExtractor())

src/shared/results-utils.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Compares an expected CQL Long (parsed to a BigInt by cvl) against the actual value.
3-
* FHIR R4 has no integer64 type, so servers return Long results as valueString
4-
* (or valueInteger when the value fits), and the extracted actual is a string or number.
3+
* A Long result must be returned as valueString (FHIR R4 has no integer64 type) or
4+
* as valueInteger64 (serialized as a JSON string), so the actual is a string either way.
55
*/
66
function longEquals(expected: bigint, actual: any): boolean {
77
if (typeof actual === 'bigint') {
@@ -14,9 +14,6 @@ function longEquals(expected: bigint, actual: any): boolean {
1414
}
1515
return BigInt(actual) === expected;
1616
}
17-
if (typeof actual === 'number' && Number.isInteger(actual)) {
18-
return BigInt(actual) === expected;
19-
}
2017
return false;
2118
}
2219

test/extractResults-cql_operations.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ test('integer response check', () => {
3838
).toBe(1);
3939
});
4040

41+
test('integer64 response check', () => {
42+
expect(
43+
extractor!.extract({
44+
resourceType: 'Parameters',
45+
parameter: [
46+
{
47+
name: 'return',
48+
valueInteger64: '9223372036854775807',
49+
},
50+
],
51+
})
52+
).toBe('9223372036854775807');
53+
});
54+
4155
test('decimal(0.1) response check', () => {
4256
expect(
4357
extractor!.extract({

test/results-utils.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ test('expected Long matches FHIR R4 valueString encoding', () => {
2626
expect(resultsEqual(1n, '2')).toBe(false);
2727
});
2828

29-
test('expected Long matches integer and bigint actuals', () => {
30-
expect(resultsEqual(1n, 1)).toBe(true);
29+
test('expected Long matches bigint actuals but not numbers (valueInteger is not allowed)', () => {
3130
expect(resultsEqual(1n, 1n)).toBe(true);
32-
expect(resultsEqual(1n, 2)).toBe(false);
31+
expect(resultsEqual(1n, 2n)).toBe(false);
32+
expect(resultsEqual(1n, 1)).toBe(false);
3333
expect(resultsEqual(1n, 1.5)).toBe(false);
3434
});
3535

0 commit comments

Comments
 (0)