@cosyte/transform 0.0.9 → 0.1.1
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/CHANGELOG.md +188 -2
- package/README.md +197 -24
- package/dist/index.cjs +2563 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1684 -79
- package/dist/index.d.ts +1684 -79
- package/dist/index.mjs +2499 -38
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -7
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { complex, primitive, list, decimal, UCUM_SYSTEM, validateUcumShape, resourceType, validateResource, UNBOUNDED } from '@cosyte/fhir';
|
|
2
|
-
import { parseDtm } from '@cosyte/hl7';
|
|
1
|
+
import { complex, primitive, list, decimal, UCUM_SYSTEM, validateUcumShape, resourceType, validateResource, isComplex, UNBOUNDED, getProperty, isPrimitive, isList, validatePrimitiveValue } from '@cosyte/fhir';
|
|
3
2
|
import { randomUUID } from 'crypto';
|
|
3
|
+
import { renderText, parseDtm, buildMessage } from '@cosyte/hl7';
|
|
4
4
|
|
|
5
5
|
// src/diagnostics/codes.ts
|
|
6
6
|
var ISSUE_CODES = {
|
|
@@ -52,7 +52,63 @@ var ISSUE_CODES = {
|
|
|
52
52
|
/** A FHIR-required element's value could not be faithfully derived from the source, so it was
|
|
53
53
|
* emitted with a `data-absent-reason` extension (value `unknown`) rather than fabricated, e.g.
|
|
54
54
|
* `MessageHeader.source.endpoint` from an MSH-3 application namespace that is not a URL. */
|
|
55
|
-
TRANSFORM_REQUIRED_ELEMENT_UNKNOWN: "TRANSFORM_REQUIRED_ELEMENT_UNKNOWN"
|
|
55
|
+
TRANSFORM_REQUIRED_ELEMENT_UNKNOWN: "TRANSFORM_REQUIRED_ELEMENT_UNKNOWN",
|
|
56
|
+
/** A reverse (FHIR to v2) conversion was called without the explicit message trigger it requires.
|
|
57
|
+
* No FHIR resource carries a v2 trigger, so it is never inferred from resource content and never
|
|
58
|
+
* defaulted: no message is built and no builder is called. */
|
|
59
|
+
TRANSFORM_MISSING_TRIGGER: "TRANSFORM_MISSING_TRIGGER",
|
|
60
|
+
/** A reverse (FHIR to v2) conversion was handed a resource outside the narrow set of shapes it
|
|
61
|
+
* supports. No v2 message is emitted and no segment layout is guessed. */
|
|
62
|
+
TRANSFORM_UNSUPPORTED_RESOURCE: "TRANSFORM_UNSUPPORTED_RESOURCE",
|
|
63
|
+
/** A resource handed to a reverse (FHIR to v2) conversion is not structurally a FHIR resource of
|
|
64
|
+
* its expected type (not an object, no `resourceType`, or an element carrying the wrong node
|
|
65
|
+
* kind). Nothing is emitted and nothing is thrown. */
|
|
66
|
+
TRANSFORM_RESOURCE_MALFORMED: "TRANSFORM_RESOURCE_MALFORMED",
|
|
67
|
+
/** A populated FHIR element has no v2 field in the narrow reverse map that covers this shape
|
|
68
|
+
* (the IG map defines no source for it, or its inverse is not implemented here). The element is
|
|
69
|
+
* surfaced and left out, never approximated into a neighbouring v2 field. */
|
|
70
|
+
TRANSFORM_NO_V2_TARGET: "TRANSFORM_NO_V2_TARGET",
|
|
71
|
+
/** A FHIR value cannot be carried into its v2 target without altering it (a lexical form v2 has
|
|
72
|
+
* no representation for, or content that exceeds the target's component structure). The v2 field
|
|
73
|
+
* is left absent rather than truncated, rounded, or coerced. */
|
|
74
|
+
TRANSFORM_VALUE_NOT_REPRESENTABLE: "TRANSFORM_VALUE_NOT_REPRESENTABLE",
|
|
75
|
+
/** A FHIR code has no usable inverse in the IG ConceptMap that governs its field: either several
|
|
76
|
+
* v2 source codes map onto it (so the inverse is ambiguous) or the map has no row for it at all.
|
|
77
|
+
* The v2 field is left absent, never resolved to one arbitrary member of the ambiguous set. */
|
|
78
|
+
TRANSFORM_CODE_NOT_INVERTIBLE: "TRANSFORM_CODE_NOT_INVERTIBLE",
|
|
79
|
+
/** A `Coding.system` is not a system this library can name with a v2 coding-system mnemonic, so
|
|
80
|
+
* the coding cannot be written into a v2 coded field. It is flagged rather than emitted with no
|
|
81
|
+
* table context or with a code from an unrelated table. */
|
|
82
|
+
TRANSFORM_CODE_SYSTEM_NOT_V2: "TRANSFORM_CODE_SYSTEM_NOT_V2",
|
|
83
|
+
/** A v2 field the segment's own attribute table marks **required** (usage `R`) is absent from an
|
|
84
|
+
* emitted segment, because the FHIR resource carried no source this reverse map could ground it
|
|
85
|
+
* from, or the source it carried had no faithful v2 form. The field is left absent per v2
|
|
86
|
+
* optionality rules and **declared here**: a placeholder is never written to satisfy v2 structure,
|
|
87
|
+
* and the receiver is never left to discover the gap. Distinct from
|
|
88
|
+
* {@link ISSUE_CODES.TRANSFORM_REQUIRED_ELEMENT_UNKNOWN}, which is the forward direction's
|
|
89
|
+
* FHIR-required element. */
|
|
90
|
+
TRANSFORM_V2_REQUIRED_FIELD_ABSENT: "TRANSFORM_V2_REQUIRED_FIELD_ABSENT",
|
|
91
|
+
/** A reverse (FHIR to v2) conversion produced **no message at all**: nothing in the resource
|
|
92
|
+
* grounded a single field of the target segment, and an empty segment is never emitted. Raised so
|
|
93
|
+
* that an empty-handed conversion is never indistinguishable from a successful one, and separate
|
|
94
|
+
* from the refusals that name their own cause (an absent trigger, an unsupported resource type, a
|
|
95
|
+
* structurally malformed resource). */
|
|
96
|
+
TRANSFORM_NO_V2_MESSAGE_EMITTED: "TRANSFORM_NO_V2_MESSAGE_EMITTED",
|
|
97
|
+
/** A segment the message carried did **not** reach any resource in the returned bundle, and the IG
|
|
98
|
+
* *does* publish a segment map for its name: a **library gap**, fixable here. Raised once per
|
|
99
|
+
* occurrence, located `NAME[k]` with `k` counted 1-based among the occurrences of that name
|
|
100
|
+
* (`DG1[1]`, `DG1[2]`), so a consumer can tell how much of the message the bundle represents
|
|
101
|
+
* without diffing the two by hand. The occurrence may have been read and refused rather than never
|
|
102
|
+
* read: being counted, or already named by another issue, is not the same as reaching a resource. */
|
|
103
|
+
TRANSFORM_SEGMENT_NOT_EMITTED: "TRANSFORM_SEGMENT_NOT_EMITTED",
|
|
104
|
+
/** A segment the message carried did **not** reach any resource in the returned bundle, and its
|
|
105
|
+
* name is **not** one the IG publishes a segment map for: a **standard gap**, not fixable here.
|
|
106
|
+
* Custom Z-segments and `RXE` land on this code, and so does a name this library could not
|
|
107
|
+
* classify at all, because a damaged segment identifier is never re-derived from the line: an
|
|
108
|
+
* `AL1` whose identifier arrived as `AL11` reads as unclassifiable, not as an IG omission. Such an
|
|
109
|
+
* occurrence is located `[#n]` by its 1-based position among the segments of the message, with no
|
|
110
|
+
* name part at all. */
|
|
111
|
+
TRANSFORM_SEGMENT_NO_IG_MAP: "TRANSFORM_SEGMENT_NO_IG_MAP"
|
|
56
112
|
};
|
|
57
113
|
var FATAL_CODES = {
|
|
58
114
|
/** The input carried nothing to transform. */
|
|
@@ -127,6 +183,61 @@ var ISSUE_REGISTRY = Object.freeze({
|
|
|
127
183
|
severity: "information",
|
|
128
184
|
fhirIssueType: "informational",
|
|
129
185
|
message: "required FHIR element could not be derived from the source; emitted with a data-absent-reason extension, never fabricated."
|
|
186
|
+
},
|
|
187
|
+
[ISSUE_CODES.TRANSFORM_MISSING_TRIGGER]: {
|
|
188
|
+
severity: "error",
|
|
189
|
+
fhirIssueType: "required",
|
|
190
|
+
message: "reverse conversion requires an explicit v2 trigger from the caller; no resource carries one, so none was inferred and no message was built."
|
|
191
|
+
},
|
|
192
|
+
[ISSUE_CODES.TRANSFORM_UNSUPPORTED_RESOURCE]: {
|
|
193
|
+
severity: "error",
|
|
194
|
+
fhirIssueType: "not-supported",
|
|
195
|
+
message: "resource type is outside the reverse converter's supported shapes; no v2 message emitted and no segment layout guessed."
|
|
196
|
+
},
|
|
197
|
+
[ISSUE_CODES.TRANSFORM_RESOURCE_MALFORMED]: {
|
|
198
|
+
severity: "error",
|
|
199
|
+
fhirIssueType: "structure",
|
|
200
|
+
message: "input is not a structurally well-shaped FHIR resource for this conversion; nothing emitted, nothing thrown."
|
|
201
|
+
},
|
|
202
|
+
[ISSUE_CODES.TRANSFORM_NO_V2_TARGET]: {
|
|
203
|
+
severity: "information",
|
|
204
|
+
fhirIssueType: "informational",
|
|
205
|
+
message: "populated FHIR element has no v2 field in this reverse map; surfaced and left out, never approximated into a neighbouring field."
|
|
206
|
+
},
|
|
207
|
+
[ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE]: {
|
|
208
|
+
severity: "warning",
|
|
209
|
+
fhirIssueType: "value",
|
|
210
|
+
message: "FHIR value cannot be carried into its v2 target without altering it; the v2 field is left absent, never truncated, rounded, or coerced."
|
|
211
|
+
},
|
|
212
|
+
[ISSUE_CODES.TRANSFORM_CODE_NOT_INVERTIBLE]: {
|
|
213
|
+
severity: "warning",
|
|
214
|
+
fhirIssueType: "code-invalid",
|
|
215
|
+
message: "FHIR code has no usable inverse in the governing IG ConceptMap (ambiguous or absent); v2 field left absent, never resolved arbitrarily."
|
|
216
|
+
},
|
|
217
|
+
[ISSUE_CODES.TRANSFORM_CODE_SYSTEM_NOT_V2]: {
|
|
218
|
+
severity: "warning",
|
|
219
|
+
fhirIssueType: "code-invalid",
|
|
220
|
+
message: "coding system has no v2 coding-system mnemonic here; coding flagged rather than written with no table context or from an unrelated table."
|
|
221
|
+
},
|
|
222
|
+
[ISSUE_CODES.TRANSFORM_V2_REQUIRED_FIELD_ABSENT]: {
|
|
223
|
+
severity: "error",
|
|
224
|
+
fhirIssueType: "required",
|
|
225
|
+
message: "a v2-required field is absent from the emitted segment because the resource carried no source this map could ground it from; left absent per v2 optionality rules and declared here, never filled with a placeholder."
|
|
226
|
+
},
|
|
227
|
+
[ISSUE_CODES.TRANSFORM_NO_V2_MESSAGE_EMITTED]: {
|
|
228
|
+
severity: "error",
|
|
229
|
+
fhirIssueType: "processing",
|
|
230
|
+
message: "no v2 message was emitted: nothing in the resource grounded a single field of the target segment, and an empty segment is never emitted."
|
|
231
|
+
},
|
|
232
|
+
[ISSUE_CODES.TRANSFORM_SEGMENT_NOT_EMITTED]: {
|
|
233
|
+
severity: "information",
|
|
234
|
+
fhirIssueType: "informational",
|
|
235
|
+
message: "segment occurrence reached no resource in the returned bundle, and the IG publishes a segment map for its name; the bundle does not represent what this segment carried."
|
|
236
|
+
},
|
|
237
|
+
[ISSUE_CODES.TRANSFORM_SEGMENT_NO_IG_MAP]: {
|
|
238
|
+
severity: "information",
|
|
239
|
+
fhirIssueType: "informational",
|
|
240
|
+
message: "segment occurrence reached no resource in the returned bundle, and the IG publishes no segment map for its name, or the name could not be classified at all; the bundle does not represent what this segment carried."
|
|
130
241
|
}
|
|
131
242
|
});
|
|
132
243
|
function issue(code, v2Location, fhirPath) {
|
|
@@ -510,6 +621,14 @@ var V3_ROUTE_OF_ADMINISTRATION_SYSTEM = "http://terminology.hl7.org/CodeSystem/v
|
|
|
510
621
|
var V2_0550_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0550";
|
|
511
622
|
var V2_0277_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0277";
|
|
512
623
|
var V2_0161_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0161";
|
|
624
|
+
var V2_0127_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0127";
|
|
625
|
+
var V2_0128_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0128";
|
|
626
|
+
var ALLERGY_INTOLERANCE_CATEGORY_SYSTEM = "http://hl7.org/fhir/allergy-intolerance-category";
|
|
627
|
+
var ALLERGY_INTOLERANCE_TYPE_SYSTEM = "http://hl7.org/fhir/allergy-intolerance-type";
|
|
628
|
+
var ALLERGY_INTOLERANCE_CRITICALITY_SYSTEM = "http://hl7.org/fhir/allergy-intolerance-criticality";
|
|
629
|
+
var V2_0335_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0335";
|
|
630
|
+
var V2_0528_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0528";
|
|
631
|
+
var V3_TIMING_EVENT_SYSTEM = "http://terminology.hl7.org/CodeSystem/v3-TimingEvent";
|
|
513
632
|
function valueMap(name, sourceSystem, sourceMnemonics, targets) {
|
|
514
633
|
return Object.freeze({
|
|
515
634
|
name,
|
|
@@ -1057,6 +1176,121 @@ var SUBSTITUTION_VALUE_MAP = valueMap(
|
|
|
1057
1176
|
["HL70161", "0161"],
|
|
1058
1177
|
identityTargets(V2_0161_SYSTEM, ["N", "G", "T"])
|
|
1059
1178
|
);
|
|
1179
|
+
var IG_ALLERGY_VALUE_MAPS_VERSION = "1.0.0";
|
|
1180
|
+
var IG_ALLERGY_VALUE_MAPS_PUBLISHED = "2025-10-07";
|
|
1181
|
+
var IG_ALLERGY_VALUE_MAPS_RETRIEVED = "2026-08-28";
|
|
1182
|
+
var IG_ALLERGY_VALUE_MAPS_SOURCE = "https://hl7.org/fhir/uv/v2mappings/ConceptMap-segment-al1-to-allergyintolerance.html";
|
|
1183
|
+
var ALLERGY_CATEGORY_VALUE_MAP = valueMap(
|
|
1184
|
+
"table-hl70127-to-allergy-intolerance-category",
|
|
1185
|
+
V2_0127_SYSTEM,
|
|
1186
|
+
["HL70127", "0127"],
|
|
1187
|
+
{
|
|
1188
|
+
DA: { system: ALLERGY_INTOLERANCE_CATEGORY_SYSTEM, code: "medication", display: "Medication" },
|
|
1189
|
+
FA: { system: ALLERGY_INTOLERANCE_CATEGORY_SYSTEM, code: "food", display: "Food" },
|
|
1190
|
+
EA: {
|
|
1191
|
+
system: ALLERGY_INTOLERANCE_CATEGORY_SYSTEM,
|
|
1192
|
+
code: "environment",
|
|
1193
|
+
display: "Environment"
|
|
1194
|
+
},
|
|
1195
|
+
AA: { system: ALLERGY_INTOLERANCE_CATEGORY_SYSTEM, code: "biologic", display: "Biologic" },
|
|
1196
|
+
PA: {
|
|
1197
|
+
system: ALLERGY_INTOLERANCE_CATEGORY_SYSTEM,
|
|
1198
|
+
code: "environment",
|
|
1199
|
+
display: "Environment"
|
|
1200
|
+
},
|
|
1201
|
+
LA: {
|
|
1202
|
+
system: ALLERGY_INTOLERANCE_CATEGORY_SYSTEM,
|
|
1203
|
+
code: "environment",
|
|
1204
|
+
display: "Environment"
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
);
|
|
1208
|
+
var ALLERGY_TYPE_VALUE_MAP = valueMap(
|
|
1209
|
+
"table-hl70127-to-allergy-intolerance-type",
|
|
1210
|
+
V2_0127_SYSTEM,
|
|
1211
|
+
["HL70127", "0127"],
|
|
1212
|
+
{
|
|
1213
|
+
DA: { system: ALLERGY_INTOLERANCE_TYPE_SYSTEM, code: "allergy", display: "Allergy" },
|
|
1214
|
+
FA: { system: ALLERGY_INTOLERANCE_TYPE_SYSTEM, code: "allergy", display: "Allergy" },
|
|
1215
|
+
MA: { system: ALLERGY_INTOLERANCE_TYPE_SYSTEM, code: "allergy", display: "Allergy" },
|
|
1216
|
+
EA: { system: ALLERGY_INTOLERANCE_TYPE_SYSTEM, code: "allergy", display: "Allergy" },
|
|
1217
|
+
AA: { system: ALLERGY_INTOLERANCE_TYPE_SYSTEM, code: "allergy", display: "Allergy" },
|
|
1218
|
+
PA: { system: ALLERGY_INTOLERANCE_TYPE_SYSTEM, code: "allergy", display: "Allergy" },
|
|
1219
|
+
LA: { system: ALLERGY_INTOLERANCE_TYPE_SYSTEM, code: "allergy", display: "Allergy" }
|
|
1220
|
+
}
|
|
1221
|
+
);
|
|
1222
|
+
var ALLERGY_CRITICALITY_VALUE_MAP = valueMap(
|
|
1223
|
+
"table-hl70128-to-allergy-intolerance-criticality",
|
|
1224
|
+
V2_0128_SYSTEM,
|
|
1225
|
+
["HL70128", "0128"],
|
|
1226
|
+
{
|
|
1227
|
+
SV: { system: ALLERGY_INTOLERANCE_CRITICALITY_SYSTEM, code: "high", display: "High Risk" },
|
|
1228
|
+
MI: { system: ALLERGY_INTOLERANCE_CRITICALITY_SYSTEM, code: "low", display: "Low Risk" }
|
|
1229
|
+
}
|
|
1230
|
+
);
|
|
1231
|
+
var ALLERGY_ORIGINAL_CATEGORY_VALUE_MAP = valueMap(
|
|
1232
|
+
"table-hl70127-to-v2-0127",
|
|
1233
|
+
V2_0127_SYSTEM,
|
|
1234
|
+
["HL70127", "0127"],
|
|
1235
|
+
identityTargets(V2_0127_SYSTEM, ["DA", "FA", "MA", "MC", "EA", "AA", "PA", "LA"])
|
|
1236
|
+
);
|
|
1237
|
+
var ALLERGY_ORIGINAL_CRITICALITY_VALUE_MAP = valueMap(
|
|
1238
|
+
"table-hl70128-original-to-v2-0128",
|
|
1239
|
+
V2_0128_SYSTEM,
|
|
1240
|
+
["HL70128", "0128"],
|
|
1241
|
+
identityTargets(V2_0128_SYSTEM, ["SV", "MO", "MI", "U"])
|
|
1242
|
+
);
|
|
1243
|
+
var TIMING_EVENT_VALUE_MAP = valueMap(
|
|
1244
|
+
"table-hl70528-to-v3-timingevent",
|
|
1245
|
+
V2_0528_SYSTEM,
|
|
1246
|
+
["HL70528", "0528"],
|
|
1247
|
+
identityTargets(V3_TIMING_EVENT_SYSTEM, [
|
|
1248
|
+
"HS",
|
|
1249
|
+
"AC",
|
|
1250
|
+
"PC",
|
|
1251
|
+
"ACM",
|
|
1252
|
+
"ACD",
|
|
1253
|
+
"ACV",
|
|
1254
|
+
"PCM",
|
|
1255
|
+
"PCD",
|
|
1256
|
+
"PCV"
|
|
1257
|
+
])
|
|
1258
|
+
);
|
|
1259
|
+
var REPEAT_PATTERN_LITERALS = Object.freeze(
|
|
1260
|
+
/* @__PURE__ */ new Set([
|
|
1261
|
+
"QAM",
|
|
1262
|
+
"QSHIFT",
|
|
1263
|
+
"QHS",
|
|
1264
|
+
"QPM",
|
|
1265
|
+
"C",
|
|
1266
|
+
"PRN",
|
|
1267
|
+
"Once",
|
|
1268
|
+
"A",
|
|
1269
|
+
"P",
|
|
1270
|
+
"I",
|
|
1271
|
+
"M",
|
|
1272
|
+
"D",
|
|
1273
|
+
"V",
|
|
1274
|
+
"BID",
|
|
1275
|
+
"TID",
|
|
1276
|
+
"QID",
|
|
1277
|
+
"QOD"
|
|
1278
|
+
])
|
|
1279
|
+
);
|
|
1280
|
+
var REPEAT_PATTERN_SHAPES = Object.freeze([
|
|
1281
|
+
/^Q[0-9]+[SMHDWL]$/,
|
|
1282
|
+
/^Q[0-9]+J[1-7]$/,
|
|
1283
|
+
/^(?:[5-9]|[1-9][0-9]+)ID$/,
|
|
1284
|
+
/^U .+$/,
|
|
1285
|
+
/^[API]C[MDV]$/
|
|
1286
|
+
]);
|
|
1287
|
+
function isRepeatPatternRow(code) {
|
|
1288
|
+
return REPEAT_PATTERN_LITERALS.has(code) || REPEAT_PATTERN_SHAPES.some((s) => s.test(code));
|
|
1289
|
+
}
|
|
1290
|
+
function isRepeatPatternCode(code) {
|
|
1291
|
+
if (isRepeatPatternRow(code)) return true;
|
|
1292
|
+
return code.startsWith("PRN") && code.length > 3 && isRepeatPatternRow(code.slice(3));
|
|
1293
|
+
}
|
|
1060
1294
|
function codingFrom(system, code, display, version) {
|
|
1061
1295
|
const props = [{ name: "system", value: primitive(system) }];
|
|
1062
1296
|
if (version !== void 0 && version !== "")
|
|
@@ -1159,15 +1393,199 @@ function orderIdentifier(value, typeCode) {
|
|
|
1159
1393
|
{ name: "value", value: primitive(value) }
|
|
1160
1394
|
]);
|
|
1161
1395
|
}
|
|
1396
|
+
function component(field, index) {
|
|
1397
|
+
return field.repetitions[0]?.components[index]?.subcomponents[0] ?? "";
|
|
1398
|
+
}
|
|
1399
|
+
function toFhirEntityIdentifier(field) {
|
|
1400
|
+
const entityId = component(field, 0);
|
|
1401
|
+
const authorityValued = component(field, 1) !== "" || component(field, 2) !== "" || component(field, 3) !== "";
|
|
1402
|
+
return {
|
|
1403
|
+
identifier: entityId === "" ? void 0 : complex([{ name: "value", value: primitive(entityId) }]),
|
|
1404
|
+
authorityValued
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
function withCodeableText(concept, textValue) {
|
|
1408
|
+
return complex([
|
|
1409
|
+
...concept.properties.filter((p) => p.name !== "text"),
|
|
1410
|
+
{ name: "text", value: primitive(textValue) }
|
|
1411
|
+
]);
|
|
1412
|
+
}
|
|
1162
1413
|
function dataAbsent(reasonCode) {
|
|
1163
|
-
|
|
1414
|
+
return primitive(void 0, { extension: [dataAbsentReason(reasonCode)] });
|
|
1415
|
+
}
|
|
1416
|
+
function dataAbsentReason(reasonCode) {
|
|
1417
|
+
return complex([
|
|
1164
1418
|
{ name: "url", value: primitive(DATA_ABSENT_REASON_URL) },
|
|
1165
1419
|
{ name: "valueCode", value: primitive(reasonCode) }
|
|
1166
1420
|
]);
|
|
1167
|
-
|
|
1421
|
+
}
|
|
1422
|
+
function dataAbsentComplex(reasonCode) {
|
|
1423
|
+
return complex([{ name: "extension", value: list([dataAbsentReason(reasonCode)]) }]);
|
|
1168
1424
|
}
|
|
1169
1425
|
|
|
1170
|
-
// src/messages/
|
|
1426
|
+
// src/messages/allergy-intolerance.ts
|
|
1427
|
+
var ALLERGY_CLINICAL_STATUS_SYSTEM = "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical";
|
|
1428
|
+
var ALLERGY_CLINICAL_STATUS_CODE = "active";
|
|
1429
|
+
var ALTERNATE_CODES_EXTENSION_URL = "http://hl7.org/fhir/StructureDefinition/alternate-codes";
|
|
1430
|
+
var AL1_ONSET_WITHDRAWN_AT = Object.freeze([2, 7]);
|
|
1431
|
+
var READABLE_VERSION = /^\d+(?:\.\d+)*$/;
|
|
1432
|
+
function carriesLegacyOnsetDate(version) {
|
|
1433
|
+
if (version === void 0 || !READABLE_VERSION.test(version)) return false;
|
|
1434
|
+
const parts = version.split(".").map(Number);
|
|
1435
|
+
for (let i = 0; i < AL1_ONSET_WITHDRAWN_AT.length; i++) {
|
|
1436
|
+
const part = parts[i] ?? 0;
|
|
1437
|
+
const bound = AL1_ONSET_WITHDRAWN_AT[i] ?? 0;
|
|
1438
|
+
if (part !== bound) return part < bound;
|
|
1439
|
+
}
|
|
1440
|
+
return false;
|
|
1441
|
+
}
|
|
1442
|
+
function collectAllergies(msg) {
|
|
1443
|
+
return msg.allSegments().filter((seg) => seg.type === "AL1");
|
|
1444
|
+
}
|
|
1445
|
+
function alternateCodesExtension(seg, field, map, ctx, issues) {
|
|
1446
|
+
const original = toFhirCodeableConceptVia(seg.field(field).asCwe(), map, ctx);
|
|
1447
|
+
issues.push(...original.issues);
|
|
1448
|
+
if (original.value === void 0) return void 0;
|
|
1449
|
+
return complex([
|
|
1450
|
+
{ name: "url", value: primitive(ALTERNATE_CODES_EXTENSION_URL) },
|
|
1451
|
+
{ name: "valueCodeableConcept", value: original.value }
|
|
1452
|
+
]);
|
|
1453
|
+
}
|
|
1454
|
+
function translatedCodeElement(seg, field, targetMap, originalMap, carryAlternateCodes, v2Location, fhirPath, ctx, issues) {
|
|
1455
|
+
const extension = carryAlternateCodes ? alternateCodesExtension(seg, field, originalMap, ctx, issues) : void 0;
|
|
1456
|
+
const target = translateBound(seg.field(field).asCwe(), targetMap);
|
|
1457
|
+
if (target === void 0) {
|
|
1458
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_UNMAPPED, v2Location, fhirPath));
|
|
1459
|
+
}
|
|
1460
|
+
if (target === void 0 && extension === void 0) return void 0;
|
|
1461
|
+
return extension === void 0 ? primitive(target?.code) : primitive(target?.code, { extension: [extension] });
|
|
1462
|
+
}
|
|
1463
|
+
function buildReaction(al1) {
|
|
1464
|
+
const manifestations = al1.field(5).repetitions.map((rep) => rep.components[0]?.subcomponents[0] ?? "").filter((text2) => text2 !== "").map((text2) => complex([{ name: "text", value: primitive(text2) }]));
|
|
1465
|
+
if (manifestations.length === 0) return void 0;
|
|
1466
|
+
return list([complex([{ name: "manifestation", value: list(manifestations) }])]);
|
|
1467
|
+
}
|
|
1468
|
+
function buildOnset(al1, version, ctx, issues) {
|
|
1469
|
+
if (al1.field(6).value === "") return void 0;
|
|
1470
|
+
if (!carriesLegacyOnsetDate(version)) {
|
|
1471
|
+
issues.push(
|
|
1472
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "AL1.6", "AllergyIntolerance.onsetDateTime")
|
|
1473
|
+
);
|
|
1474
|
+
return void 0;
|
|
1475
|
+
}
|
|
1476
|
+
const onset = toFhirDateTime(al1.field(6).asTs(), ctx.options);
|
|
1477
|
+
issues.push(...onset.issues);
|
|
1478
|
+
return onset.value === void 0 ? void 0 : primitive(onset.value);
|
|
1479
|
+
}
|
|
1480
|
+
function buildAllergyIntolerance(al1, patientFullUrl, version, ctx, options = {}) {
|
|
1481
|
+
const issues = [];
|
|
1482
|
+
const carryAlternateCodes = options.carryAlternateCodes ?? true;
|
|
1483
|
+
const allergen = toFhirCodeableConcept(al1.field(3).asCwe(), ctx);
|
|
1484
|
+
if (allergen.value === void 0) {
|
|
1485
|
+
return {
|
|
1486
|
+
value: void 0,
|
|
1487
|
+
issues: [
|
|
1488
|
+
...allergen.issues,
|
|
1489
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "AL1.3", "AllergyIntolerance.code")
|
|
1490
|
+
]
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
issues.push(...allergen.issues);
|
|
1494
|
+
const allergenTypeValued = al1.field(2).value !== "";
|
|
1495
|
+
const type = allergenTypeValued ? translatedCodeElement(
|
|
1496
|
+
al1,
|
|
1497
|
+
2,
|
|
1498
|
+
ALLERGY_TYPE_VALUE_MAP,
|
|
1499
|
+
ALLERGY_ORIGINAL_CATEGORY_VALUE_MAP,
|
|
1500
|
+
false,
|
|
1501
|
+
"AL1.2",
|
|
1502
|
+
"AllergyIntolerance.type",
|
|
1503
|
+
ctx,
|
|
1504
|
+
issues
|
|
1505
|
+
) : void 0;
|
|
1506
|
+
const category = allergenTypeValued ? translatedCodeElement(
|
|
1507
|
+
al1,
|
|
1508
|
+
2,
|
|
1509
|
+
ALLERGY_CATEGORY_VALUE_MAP,
|
|
1510
|
+
ALLERGY_ORIGINAL_CATEGORY_VALUE_MAP,
|
|
1511
|
+
carryAlternateCodes,
|
|
1512
|
+
"AL1.2",
|
|
1513
|
+
"AllergyIntolerance.category",
|
|
1514
|
+
ctx,
|
|
1515
|
+
issues
|
|
1516
|
+
) : void 0;
|
|
1517
|
+
const criticality = al1.field(4).value !== "" ? translatedCodeElement(
|
|
1518
|
+
al1,
|
|
1519
|
+
4,
|
|
1520
|
+
ALLERGY_CRITICALITY_VALUE_MAP,
|
|
1521
|
+
ALLERGY_ORIGINAL_CRITICALITY_VALUE_MAP,
|
|
1522
|
+
carryAlternateCodes,
|
|
1523
|
+
"AL1.4",
|
|
1524
|
+
"AllergyIntolerance.criticality",
|
|
1525
|
+
ctx,
|
|
1526
|
+
issues
|
|
1527
|
+
) : void 0;
|
|
1528
|
+
const onset = buildOnset(al1, version, ctx, issues);
|
|
1529
|
+
const reaction = buildReaction(al1);
|
|
1530
|
+
const props = [
|
|
1531
|
+
{ name: "resourceType", value: primitive("AllergyIntolerance") },
|
|
1532
|
+
// The IG's fixed assignment: not derived from the message, and the reason is on the row itself.
|
|
1533
|
+
{
|
|
1534
|
+
name: "clinicalStatus",
|
|
1535
|
+
value: complex([
|
|
1536
|
+
{
|
|
1537
|
+
name: "coding",
|
|
1538
|
+
value: list([
|
|
1539
|
+
complex([
|
|
1540
|
+
{ name: "system", value: primitive(ALLERGY_CLINICAL_STATUS_SYSTEM) },
|
|
1541
|
+
{ name: "code", value: primitive(ALLERGY_CLINICAL_STATUS_CODE) }
|
|
1542
|
+
])
|
|
1543
|
+
])
|
|
1544
|
+
}
|
|
1545
|
+
])
|
|
1546
|
+
}
|
|
1547
|
+
];
|
|
1548
|
+
if (type !== void 0) props.push({ name: "type", value: type });
|
|
1549
|
+
if (category !== void 0) props.push({ name: "category", value: list([category]) });
|
|
1550
|
+
if (criticality !== void 0) props.push({ name: "criticality", value: criticality });
|
|
1551
|
+
props.push({ name: "code", value: allergen.value });
|
|
1552
|
+
props.push({ name: "patient", value: reference(patientFullUrl) });
|
|
1553
|
+
if (onset !== void 0) props.push({ name: "onsetDateTime", value: onset });
|
|
1554
|
+
if (reaction !== void 0) props.push({ name: "reaction", value: reaction });
|
|
1555
|
+
return { value: complex(props), issues };
|
|
1556
|
+
}
|
|
1557
|
+
function emitAllergyIntolerance(al1, patientFullUrl, version, ctx, gate, v2Location) {
|
|
1558
|
+
const built = buildAllergyIntolerance(al1, patientFullUrl, version, ctx);
|
|
1559
|
+
if (built.value === void 0) return built;
|
|
1560
|
+
if (gate(built.value)) return built;
|
|
1561
|
+
const issues = [...built.issues];
|
|
1562
|
+
const withoutExtension = buildAllergyIntolerance(al1, patientFullUrl, version, ctx, {
|
|
1563
|
+
carryAlternateCodes: false
|
|
1564
|
+
});
|
|
1565
|
+
if (withoutExtension.value !== void 0 && gate(withoutExtension.value)) {
|
|
1566
|
+
if (al1.field(2).value !== "") {
|
|
1567
|
+
issues.push(
|
|
1568
|
+
issue(
|
|
1569
|
+
ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED,
|
|
1570
|
+
"AL1.2",
|
|
1571
|
+
"AllergyIntolerance.category.extension"
|
|
1572
|
+
)
|
|
1573
|
+
);
|
|
1574
|
+
}
|
|
1575
|
+
if (al1.field(4).value !== "") {
|
|
1576
|
+
issues.push(
|
|
1577
|
+
issue(
|
|
1578
|
+
ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED,
|
|
1579
|
+
"AL1.4",
|
|
1580
|
+
"AllergyIntolerance.criticality.extension"
|
|
1581
|
+
)
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
return { value: withoutExtension.value, issues };
|
|
1585
|
+
}
|
|
1586
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_RESOURCE_INVALID, v2Location, "AllergyIntolerance"));
|
|
1587
|
+
return { value: void 0, issues };
|
|
1588
|
+
}
|
|
1171
1589
|
var APPOINTMENT_STATUS_MAP = Object.freeze({
|
|
1172
1590
|
Pending: "pending",
|
|
1173
1591
|
Waitlist: "waitlist",
|
|
@@ -1265,6 +1683,190 @@ function collectAppointment(msg) {
|
|
|
1265
1683
|
}
|
|
1266
1684
|
return { sch, ais };
|
|
1267
1685
|
}
|
|
1686
|
+
var CONDITION_VERIFICATION_STATUS_SYSTEM = "http://terminology.hl7.org/CodeSystem/condition-ver-status";
|
|
1687
|
+
var CONDITION_ENTERED_IN_ERROR = "entered-in-error";
|
|
1688
|
+
var DG1_RETRACTION_ACTION_CODE = "D";
|
|
1689
|
+
function collectDiagnoses(msg) {
|
|
1690
|
+
return msg.allSegments().filter((seg) => seg.type === "DG1");
|
|
1691
|
+
}
|
|
1692
|
+
function deferredDiagnosisIssues(dg1) {
|
|
1693
|
+
const issues = [];
|
|
1694
|
+
if (dg1.field(16).value !== "") {
|
|
1695
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "DG1.16", "Condition.asserter"));
|
|
1696
|
+
}
|
|
1697
|
+
if (dg1.field(22).value !== "") {
|
|
1698
|
+
issues.push(
|
|
1699
|
+
issue(
|
|
1700
|
+
ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED,
|
|
1701
|
+
"DG1.22",
|
|
1702
|
+
"Condition.extension[condition-dueTo].valueReference"
|
|
1703
|
+
)
|
|
1704
|
+
);
|
|
1705
|
+
}
|
|
1706
|
+
return issues;
|
|
1707
|
+
}
|
|
1708
|
+
function buildVerificationStatus(dg1, issues) {
|
|
1709
|
+
const action = dg1.field(21).value;
|
|
1710
|
+
if (action === "") return void 0;
|
|
1711
|
+
if (action !== DG1_RETRACTION_ACTION_CODE) {
|
|
1712
|
+
issues.push(
|
|
1713
|
+
issue(ISSUE_CODES.TRANSFORM_CODE_UNMAPPED, "DG1.21", "Condition.verificationStatus")
|
|
1714
|
+
);
|
|
1715
|
+
return void 0;
|
|
1716
|
+
}
|
|
1717
|
+
return complex([
|
|
1718
|
+
{
|
|
1719
|
+
name: "coding",
|
|
1720
|
+
value: list([
|
|
1721
|
+
complex([
|
|
1722
|
+
{ name: "system", value: primitive(CONDITION_VERIFICATION_STATUS_SYSTEM) },
|
|
1723
|
+
{ name: "code", value: primitive(CONDITION_ENTERED_IN_ERROR) }
|
|
1724
|
+
])
|
|
1725
|
+
])
|
|
1726
|
+
}
|
|
1727
|
+
]);
|
|
1728
|
+
}
|
|
1729
|
+
function buildCode(dg1, ctx, issues) {
|
|
1730
|
+
const description = dg1.field(4).value;
|
|
1731
|
+
const coded = toFhirCodeableConcept(dg1.field(3).asCwe(), ctx);
|
|
1732
|
+
issues.push(...coded.issues);
|
|
1733
|
+
if (coded.value === void 0) {
|
|
1734
|
+
return description === "" ? void 0 : complex([{ name: "text", value: primitive(description) }]);
|
|
1735
|
+
}
|
|
1736
|
+
return description === "" ? coded.value : withCodeableText(coded.value, description);
|
|
1737
|
+
}
|
|
1738
|
+
function buildDateTime(dg1, field, ctx, issues) {
|
|
1739
|
+
if (dg1.field(field).value === "") return void 0;
|
|
1740
|
+
const converted = toFhirDateTime(dg1.field(field).asTs(), ctx.options);
|
|
1741
|
+
issues.push(...converted.issues);
|
|
1742
|
+
return converted.value === void 0 ? void 0 : primitive(converted.value);
|
|
1743
|
+
}
|
|
1744
|
+
function buildCondition(dg1, patientFullUrl, ctx, v2Location) {
|
|
1745
|
+
const issues = [];
|
|
1746
|
+
const props = [
|
|
1747
|
+
{ name: "resourceType", value: primitive("Condition") }
|
|
1748
|
+
];
|
|
1749
|
+
const entity = toFhirEntityIdentifier(dg1.field(20));
|
|
1750
|
+
if (entity.identifier !== void 0) {
|
|
1751
|
+
props.push({ name: "identifier", value: list([entity.identifier]) });
|
|
1752
|
+
}
|
|
1753
|
+
if (entity.authorityValued) {
|
|
1754
|
+
issues.push(
|
|
1755
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "DG1.20", "Condition.identifier.system")
|
|
1756
|
+
);
|
|
1757
|
+
}
|
|
1758
|
+
const verification = buildVerificationStatus(dg1, issues);
|
|
1759
|
+
if (verification !== void 0) props.push({ name: "verificationStatus", value: verification });
|
|
1760
|
+
const code = buildCode(dg1, ctx, issues);
|
|
1761
|
+
if (code === void 0) {
|
|
1762
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, v2Location, "Condition.code"));
|
|
1763
|
+
} else {
|
|
1764
|
+
props.push({ name: "code", value: code });
|
|
1765
|
+
}
|
|
1766
|
+
props.push({ name: "subject", value: reference(patientFullUrl) });
|
|
1767
|
+
const onset = buildDateTime(dg1, 5, ctx, issues);
|
|
1768
|
+
if (onset !== void 0) props.push({ name: "onsetDateTime", value: onset });
|
|
1769
|
+
const recorded = buildDateTime(dg1, 19, ctx, issues);
|
|
1770
|
+
if (recorded !== void 0) props.push({ name: "recordedDate", value: recorded });
|
|
1771
|
+
return { value: complex(props), issues };
|
|
1772
|
+
}
|
|
1773
|
+
var COVERAGE_SUBSCRIBER_ID_EXTENSION_URL = "http://hl7.org/fhir/5.0/StructureDefinition/extension-subscriberId";
|
|
1774
|
+
var COVERAGE_STATUS_UNKNOWN = "unknown";
|
|
1775
|
+
var IN1_SUBSCRIBER_NUMBER_TYPE = "SN";
|
|
1776
|
+
function collectCoverages(msg) {
|
|
1777
|
+
return msg.allSegments().filter((seg) => seg.type === "IN1");
|
|
1778
|
+
}
|
|
1779
|
+
function insuranceCompanyName(in1) {
|
|
1780
|
+
return in1.field(4).repetitions[0]?.components[0]?.subcomponents[0] ?? "";
|
|
1781
|
+
}
|
|
1782
|
+
function deferredCoverageIssues(in1) {
|
|
1783
|
+
const deferred = [
|
|
1784
|
+
[5, "Coverage.payer"],
|
|
1785
|
+
[10, "Coverage.policyHolder"],
|
|
1786
|
+
[11, "Coverage.policyHolder"],
|
|
1787
|
+
[16, "Coverage.subscriber"],
|
|
1788
|
+
[17, "Coverage.relationship"]
|
|
1789
|
+
];
|
|
1790
|
+
const issues = [];
|
|
1791
|
+
for (const [field, path] of deferred) {
|
|
1792
|
+
if (in1.field(field).value !== "") {
|
|
1793
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, `IN1.${String(field)}`, path));
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
return issues;
|
|
1797
|
+
}
|
|
1798
|
+
function buildIdentifier(in1, issues) {
|
|
1799
|
+
const cwe = in1.field(2).asCwe();
|
|
1800
|
+
const planId = cwe.identifier;
|
|
1801
|
+
if (planId === void 0 || planId === "") return void 0;
|
|
1802
|
+
if (cwe.nameOfCodingSystem !== void 0 && cwe.nameOfCodingSystem !== "") {
|
|
1803
|
+
issues.push(
|
|
1804
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "IN1.2", "Coverage.identifier.system")
|
|
1805
|
+
);
|
|
1806
|
+
}
|
|
1807
|
+
return complex([{ name: "value", value: primitive(planId) }]);
|
|
1808
|
+
}
|
|
1809
|
+
function subscriberIdExtension(in1, field, ctx, issues) {
|
|
1810
|
+
const identifier = toFhirIdentifier(in1.field(field).asCx(), ctx);
|
|
1811
|
+
issues.push(...identifier.issues);
|
|
1812
|
+
if (identifier.value === void 0) return void 0;
|
|
1813
|
+
return complex([
|
|
1814
|
+
{ name: "url", value: primitive(COVERAGE_SUBSCRIBER_ID_EXTENSION_URL) },
|
|
1815
|
+
{ name: "valueIdentifier", value: identifier.value }
|
|
1816
|
+
]);
|
|
1817
|
+
}
|
|
1818
|
+
function buildPeriod(in1, ctx, issues) {
|
|
1819
|
+
const props = [];
|
|
1820
|
+
for (const [field, name] of [
|
|
1821
|
+
[12, "start"],
|
|
1822
|
+
[13, "end"]
|
|
1823
|
+
]) {
|
|
1824
|
+
if (in1.field(field).value === "") continue;
|
|
1825
|
+
const converted = toFhirDateTime(in1.field(field).asTs(), ctx.options);
|
|
1826
|
+
issues.push(...converted.issues);
|
|
1827
|
+
if (converted.value !== void 0) props.push({ name, value: primitive(converted.value) });
|
|
1828
|
+
}
|
|
1829
|
+
return props.length === 0 ? void 0 : complex(props);
|
|
1830
|
+
}
|
|
1831
|
+
function buildCoverage(in1, patientFullUrl, ctx, v2Location) {
|
|
1832
|
+
const issues = [];
|
|
1833
|
+
const payerName = insuranceCompanyName(in1);
|
|
1834
|
+
if (payerName === "") {
|
|
1835
|
+
return {
|
|
1836
|
+
value: void 0,
|
|
1837
|
+
issues: [issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, v2Location, "Coverage.payor")]
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1840
|
+
const props = [
|
|
1841
|
+
{ name: "resourceType", value: primitive("Coverage") }
|
|
1842
|
+
];
|
|
1843
|
+
const extensions = [];
|
|
1844
|
+
if (in1.field(10).asCx().identifierTypeCode === IN1_SUBSCRIBER_NUMBER_TYPE) {
|
|
1845
|
+
const groupId = subscriberIdExtension(in1, 10, ctx, issues);
|
|
1846
|
+
if (groupId !== void 0) extensions.push(groupId);
|
|
1847
|
+
}
|
|
1848
|
+
if (in1.field(49).value !== "") {
|
|
1849
|
+
const insuredId = subscriberIdExtension(in1, 49, ctx, issues);
|
|
1850
|
+
if (insuredId !== void 0) extensions.push(insuredId);
|
|
1851
|
+
}
|
|
1852
|
+
if (extensions.length > 0) props.push({ name: "extension", value: list(extensions) });
|
|
1853
|
+
const identifier = buildIdentifier(in1, issues);
|
|
1854
|
+
if (identifier !== void 0) props.push({ name: "identifier", value: list([identifier]) });
|
|
1855
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_REQUIRED_ELEMENT_UNKNOWN, v2Location, "Coverage.status"));
|
|
1856
|
+
props.push({ name: "status", value: dataAbsent(COVERAGE_STATUS_UNKNOWN) });
|
|
1857
|
+
const type = toFhirCodeableConcept(in1.field(15).asCwe(), ctx);
|
|
1858
|
+
issues.push(...type.issues);
|
|
1859
|
+
if (type.value !== void 0) props.push({ name: "type", value: type.value });
|
|
1860
|
+
props.push({ name: "beneficiary", value: reference(patientFullUrl) });
|
|
1861
|
+
const period = buildPeriod(in1, ctx, issues);
|
|
1862
|
+
if (period !== void 0) props.push({ name: "period", value: period });
|
|
1863
|
+
props.push({
|
|
1864
|
+
name: "payor",
|
|
1865
|
+
value: list([complex([{ name: "display", value: primitive(payerName) }])])
|
|
1866
|
+
});
|
|
1867
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "IN1.4", "Coverage.payor"));
|
|
1868
|
+
return { value: complex(props), issues };
|
|
1869
|
+
}
|
|
1268
1870
|
var V2_0074_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0074";
|
|
1269
1871
|
var DIAGNOSTIC_REPORT_STATUS_MAP = Object.freeze({
|
|
1270
1872
|
O: "registered",
|
|
@@ -1276,7 +1878,7 @@ var DIAGNOSTIC_REPORT_STATUS_MAP = Object.freeze({
|
|
|
1276
1878
|
F: "final",
|
|
1277
1879
|
X: "cancelled"
|
|
1278
1880
|
});
|
|
1279
|
-
function buildDiagnosticReport(obr, resultFullUrls, subjectFullUrl, encounterFullUrl, ctx) {
|
|
1881
|
+
function buildDiagnosticReport(obr, resultFullUrls, subjectFullUrl, encounterFullUrl, ctx, specimenFullUrls = []) {
|
|
1280
1882
|
const issues = [];
|
|
1281
1883
|
const props = [
|
|
1282
1884
|
{ name: "resourceType", value: primitive("DiagnosticReport") }
|
|
@@ -1350,6 +1952,9 @@ function buildDiagnosticReport(obr, resultFullUrls, subjectFullUrl, encounterFul
|
|
|
1350
1952
|
);
|
|
1351
1953
|
}
|
|
1352
1954
|
}
|
|
1955
|
+
if (specimenFullUrls.length > 0) {
|
|
1956
|
+
props.push({ name: "specimen", value: list(specimenFullUrls.map((u) => reference(u))) });
|
|
1957
|
+
}
|
|
1353
1958
|
if (resultFullUrls.length > 0) {
|
|
1354
1959
|
props.push({ name: "result", value: list(resultFullUrls.map((u) => reference(u))) });
|
|
1355
1960
|
}
|
|
@@ -1554,6 +2159,127 @@ function buildEncounter(visit, subjectFullUrl, ctx) {
|
|
|
1554
2159
|
if (props.length === 1) return { value: void 0, issues };
|
|
1555
2160
|
return { value: complex(props), issues };
|
|
1556
2161
|
}
|
|
2162
|
+
function withEncounterDiagnosis(encounter, conditionFullUrls) {
|
|
2163
|
+
if (conditionFullUrls.length === 0) return encounter;
|
|
2164
|
+
const entries = conditionFullUrls.map(
|
|
2165
|
+
(url) => complex([{ name: "condition", value: reference(url) }])
|
|
2166
|
+
);
|
|
2167
|
+
return complex([
|
|
2168
|
+
...encounter.properties.filter((p) => p.name !== "diagnosis"),
|
|
2169
|
+
{ name: "diagnosis", value: list(entries) }
|
|
2170
|
+
]);
|
|
2171
|
+
}
|
|
2172
|
+
function emitEncounterDiagnosis(encounter, conditionFullUrls, gate) {
|
|
2173
|
+
const linked = withEncounterDiagnosis(encounter, conditionFullUrls);
|
|
2174
|
+
if (linked === encounter || gate(linked)) return { value: linked, issues: [] };
|
|
2175
|
+
return {
|
|
2176
|
+
value: encounter,
|
|
2177
|
+
issues: [issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "DG1", "Encounter.diagnosis")]
|
|
2178
|
+
};
|
|
2179
|
+
}
|
|
2180
|
+
var PROCEDURE_STATUS_UNKNOWN = "unknown";
|
|
2181
|
+
var WHOLE_MINUTES = /^\d+$/;
|
|
2182
|
+
var ZONED_DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
|
|
2183
|
+
function collectProcedures(msg) {
|
|
2184
|
+
return msg.allSegments().filter((seg) => seg.type === "PR1");
|
|
2185
|
+
}
|
|
2186
|
+
function addMinutes(start, minutes) {
|
|
2187
|
+
const parts = ZONED_DATE_TIME.exec(start);
|
|
2188
|
+
if (parts === null) return void 0;
|
|
2189
|
+
const [, year, month, day, hour, minute, second, fraction, zone] = parts;
|
|
2190
|
+
const wall = /* @__PURE__ */ new Date(0);
|
|
2191
|
+
wall.setUTCFullYear(Number(year), Number(month) - 1, Number(day));
|
|
2192
|
+
wall.setUTCHours(Number(hour), Number(minute), Number(second), 0);
|
|
2193
|
+
const shifted = new Date(wall.getTime() + minutes * 6e4);
|
|
2194
|
+
if (Number.isNaN(shifted.getTime())) return void 0;
|
|
2195
|
+
const pad2 = (value, width) => String(value).padStart(width, "0");
|
|
2196
|
+
const rendered = `${pad2(shifted.getUTCFullYear(), 4)}-${pad2(shifted.getUTCMonth() + 1, 2)}-${pad2(shifted.getUTCDate(), 2)}T${pad2(shifted.getUTCHours(), 2)}:${pad2(shifted.getUTCMinutes(), 2)}:${pad2(shifted.getUTCSeconds(), 2)}`;
|
|
2197
|
+
return `${rendered}${fraction ?? ""}${zone ?? ""}`;
|
|
2198
|
+
}
|
|
2199
|
+
function deferredProcedureIssues(pr1) {
|
|
2200
|
+
const deferred = [
|
|
2201
|
+
[8, "Procedure.performer.actor"],
|
|
2202
|
+
[11, "Procedure.performer.actor"],
|
|
2203
|
+
[12, "Procedure.performer.actor"],
|
|
2204
|
+
[16, "Procedure.code.value"],
|
|
2205
|
+
[23, "Procedure.location"],
|
|
2206
|
+
[25, "Procedure.partOf"]
|
|
2207
|
+
];
|
|
2208
|
+
const issues = [];
|
|
2209
|
+
for (const [field, path] of deferred) {
|
|
2210
|
+
if (pr1.field(field).value !== "") {
|
|
2211
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, `PR1.${String(field)}`, path));
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
return issues;
|
|
2215
|
+
}
|
|
2216
|
+
function buildCode2(pr1, ctx, issues) {
|
|
2217
|
+
const cne = pr1.field(3).asCwe();
|
|
2218
|
+
const description = pr1.field(4).value;
|
|
2219
|
+
const originalTextValued = cne.originalText !== void 0 && cne.originalText !== "";
|
|
2220
|
+
const coded = toFhirCodeableConcept(cne, ctx);
|
|
2221
|
+
issues.push(...coded.issues);
|
|
2222
|
+
if (description !== "" && originalTextValued) {
|
|
2223
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "PR1.4", "Procedure.code.text"));
|
|
2224
|
+
return coded.value;
|
|
2225
|
+
}
|
|
2226
|
+
if (coded.value === void 0) {
|
|
2227
|
+
return description === "" ? void 0 : complex([{ name: "text", value: primitive(description) }]);
|
|
2228
|
+
}
|
|
2229
|
+
return description === "" ? coded.value : withCodeableText(coded.value, description);
|
|
2230
|
+
}
|
|
2231
|
+
function buildPerformed(pr1, ctx, issues) {
|
|
2232
|
+
if (pr1.field(5).value === "") return void 0;
|
|
2233
|
+
const converted = toFhirDateTime(pr1.field(5).asTs(), ctx.options);
|
|
2234
|
+
issues.push(...converted.issues);
|
|
2235
|
+
if (converted.value === void 0) return void 0;
|
|
2236
|
+
const minutesRaw = pr1.field(7).value;
|
|
2237
|
+
if (minutesRaw === "") {
|
|
2238
|
+
return { name: "performedDateTime", value: primitive(converted.value) };
|
|
2239
|
+
}
|
|
2240
|
+
const end = WHOLE_MINUTES.test(minutesRaw) ? addMinutes(converted.value, Number(minutesRaw)) : void 0;
|
|
2241
|
+
if (end === void 0) {
|
|
2242
|
+
issues.push(
|
|
2243
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "PR1.7", "Procedure.performedPeriod.end")
|
|
2244
|
+
);
|
|
2245
|
+
return { name: "performedDateTime", value: primitive(converted.value) };
|
|
2246
|
+
}
|
|
2247
|
+
return {
|
|
2248
|
+
name: "performedPeriod",
|
|
2249
|
+
value: complex([
|
|
2250
|
+
{ name: "start", value: primitive(converted.value) },
|
|
2251
|
+
{ name: "end", value: primitive(end) }
|
|
2252
|
+
])
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
function buildProcedure(pr1, patientFullUrl, ctx) {
|
|
2256
|
+
const issues = [];
|
|
2257
|
+
const props = [
|
|
2258
|
+
{ name: "resourceType", value: primitive("Procedure") }
|
|
2259
|
+
];
|
|
2260
|
+
const entity = toFhirEntityIdentifier(pr1.field(19));
|
|
2261
|
+
if (entity.identifier !== void 0) {
|
|
2262
|
+
props.push({ name: "identifier", value: list([entity.identifier]) });
|
|
2263
|
+
}
|
|
2264
|
+
if (entity.authorityValued) {
|
|
2265
|
+
issues.push(
|
|
2266
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "PR1.19", "Procedure.identifier.system")
|
|
2267
|
+
);
|
|
2268
|
+
}
|
|
2269
|
+
props.push({ name: "status", value: primitive(PROCEDURE_STATUS_UNKNOWN) });
|
|
2270
|
+
const category = toFhirCodeableConcept(pr1.field(6).asCwe(), ctx);
|
|
2271
|
+
issues.push(...category.issues);
|
|
2272
|
+
if (category.value !== void 0) props.push({ name: "category", value: category.value });
|
|
2273
|
+
const code = buildCode2(pr1, ctx, issues);
|
|
2274
|
+
if (code !== void 0) props.push({ name: "code", value: code });
|
|
2275
|
+
props.push({ name: "subject", value: reference(patientFullUrl) });
|
|
2276
|
+
const performed = buildPerformed(pr1, ctx, issues);
|
|
2277
|
+
if (performed !== void 0) props.push(performed);
|
|
2278
|
+
const reason = toFhirCodeableConcept(pr1.field(15).asCwe(), ctx);
|
|
2279
|
+
issues.push(...reason.issues);
|
|
2280
|
+
if (reason.value !== void 0) props.push({ name: "reasonCode", value: list([reason.value]) });
|
|
2281
|
+
return { value: complex(props), issues };
|
|
2282
|
+
}
|
|
1557
2283
|
var EMIT_SCHEMAS = Object.freeze([
|
|
1558
2284
|
{
|
|
1559
2285
|
type: "Encounter",
|
|
@@ -1618,6 +2344,88 @@ var EMIT_SCHEMAS = Object.freeze([
|
|
|
1618
2344
|
occurrenceDateTime: { min: 1, max: 1, types: ["dateTime"] }
|
|
1619
2345
|
}
|
|
1620
2346
|
},
|
|
2347
|
+
{
|
|
2348
|
+
// Condition: subject (1..1 Reference) is required. A DG1 with no bundle Patient to anchor never
|
|
2349
|
+
// reaches this gate (the assembly withholds it first); the entry is the defence behind that.
|
|
2350
|
+
type: "Condition",
|
|
2351
|
+
elements: {
|
|
2352
|
+
subject: { min: 1, max: 1, types: ["Reference"] }
|
|
2353
|
+
}
|
|
2354
|
+
},
|
|
2355
|
+
{
|
|
2356
|
+
// Procedure: status (1..1 code) and subject (1..1 Reference) are both required. The status
|
|
2357
|
+
// binding is R4's required EventStatus set, so the value the PR1 map's own row directs is
|
|
2358
|
+
// checked rather than trusted, and a Procedure carrying anything else is withheld.
|
|
2359
|
+
type: "Procedure",
|
|
2360
|
+
elements: {
|
|
2361
|
+
status: {
|
|
2362
|
+
min: 1,
|
|
2363
|
+
max: 1,
|
|
2364
|
+
types: ["code"],
|
|
2365
|
+
binding: {
|
|
2366
|
+
strength: "required",
|
|
2367
|
+
codes: [
|
|
2368
|
+
"preparation",
|
|
2369
|
+
"in-progress",
|
|
2370
|
+
"not-done",
|
|
2371
|
+
"on-hold",
|
|
2372
|
+
"stopped",
|
|
2373
|
+
"completed",
|
|
2374
|
+
"entered-in-error",
|
|
2375
|
+
"unknown"
|
|
2376
|
+
]
|
|
2377
|
+
}
|
|
2378
|
+
},
|
|
2379
|
+
subject: { min: 1, max: 1, types: ["Reference"] }
|
|
2380
|
+
}
|
|
2381
|
+
},
|
|
2382
|
+
{
|
|
2383
|
+
// Coverage: status (1..1 code), beneficiary (1..1 Reference) and payor (1..* Reference) are all
|
|
2384
|
+
// required. The status is modelled WITHOUT its required binding on purpose: no published row
|
|
2385
|
+
// grounds a coverage status, so the element ships value-absent with a data-absent-reason
|
|
2386
|
+
// extension, which satisfies the cardinality while asserting no member of the value set.
|
|
2387
|
+
type: "Coverage",
|
|
2388
|
+
elements: {
|
|
2389
|
+
status: { min: 1, max: 1, types: ["code"] },
|
|
2390
|
+
beneficiary: { min: 1, max: 1, types: ["Reference"] },
|
|
2391
|
+
payor: { min: 1, max: UNBOUNDED, types: ["Reference"] }
|
|
2392
|
+
}
|
|
2393
|
+
},
|
|
2394
|
+
{
|
|
2395
|
+
// AllergyIntolerance: patient (1..1 Reference) is required, so an AL1 with no bundle Patient to
|
|
2396
|
+
// anchor is withheld rather than emitted with a dangling reference. The three coded elements carry
|
|
2397
|
+
// their R4 required bindings: an unmapped code leaves its element absent (never a neighbour), and a
|
|
2398
|
+
// value-absent element carrying only the IG's alternate-codes extension is not a code to check.
|
|
2399
|
+
type: "AllergyIntolerance",
|
|
2400
|
+
elements: {
|
|
2401
|
+
clinicalStatus: { min: 0, max: 1, types: ["CodeableConcept"] },
|
|
2402
|
+
type: {
|
|
2403
|
+
min: 0,
|
|
2404
|
+
max: 1,
|
|
2405
|
+
types: ["code"],
|
|
2406
|
+
binding: { strength: "required", codes: ["allergy", "intolerance"] }
|
|
2407
|
+
},
|
|
2408
|
+
category: {
|
|
2409
|
+
min: 0,
|
|
2410
|
+
max: UNBOUNDED,
|
|
2411
|
+
types: ["code"],
|
|
2412
|
+
binding: {
|
|
2413
|
+
strength: "required",
|
|
2414
|
+
codes: ["food", "medication", "environment", "biologic"]
|
|
2415
|
+
}
|
|
2416
|
+
},
|
|
2417
|
+
criticality: {
|
|
2418
|
+
min: 0,
|
|
2419
|
+
max: 1,
|
|
2420
|
+
types: ["code"],
|
|
2421
|
+
binding: { strength: "required", codes: ["low", "high", "unable-to-assess"] }
|
|
2422
|
+
},
|
|
2423
|
+
code: { min: 0, max: 1, types: ["CodeableConcept"] },
|
|
2424
|
+
patient: { min: 1, max: 1, types: ["Reference"] },
|
|
2425
|
+
onsetDateTime: { min: 0, max: 1, types: ["dateTime"] },
|
|
2426
|
+
reaction: { min: 0, max: UNBOUNDED, types: ["BackboneElement"] }
|
|
2427
|
+
}
|
|
2428
|
+
},
|
|
1621
2429
|
{
|
|
1622
2430
|
// Appointment: status (1..1 code) and participant (1..* BackboneElement) are both required, so an
|
|
1623
2431
|
// Appointment whose SCH-25 status could not be grounded via HL70278, or that has no resolvable Patient
|
|
@@ -1770,18 +2578,342 @@ function buildImmunization(rxa, rxr, orc, patientFullUrl, encounterFullUrl, ctx)
|
|
|
1770
2578
|
}
|
|
1771
2579
|
return { value: complex(props), issues };
|
|
1772
2580
|
}
|
|
1773
|
-
var
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
2581
|
+
var UNITS_OF_TIME = Object.freeze(
|
|
2582
|
+
/* @__PURE__ */ new Set(["s", "min", "h", "d", "wk", "mo", "a"])
|
|
2583
|
+
);
|
|
2584
|
+
var UCUM_MNEMONICS = Object.freeze(/* @__PURE__ */ new Set(["UCUM", "ISO+"]));
|
|
2585
|
+
var HL70335_MNEMONICS = Object.freeze(/* @__PURE__ */ new Set(["HL70335", "0335"]));
|
|
2586
|
+
var CONDITION_TEXT_PATH = "MedicationRequest.dosageInstruction.additionalInstruction.text";
|
|
2587
|
+
var INSTRUCTION_TEXT_PATH = "MedicationRequest.text";
|
|
2588
|
+
function timingPath(target) {
|
|
2589
|
+
return target === "MedicationRequest" ? "MedicationRequest.dosageInstruction.timing" : "ServiceRequest.occurrenceTiming";
|
|
1781
2590
|
}
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
2591
|
+
var EXPLICIT_NULL = '""';
|
|
2592
|
+
function carriesValue(sub) {
|
|
2593
|
+
return sub !== "" && sub !== EXPLICIT_NULL;
|
|
2594
|
+
}
|
|
2595
|
+
function repetitionValued(rep) {
|
|
2596
|
+
return rep.components.some((c) => c.subcomponents.some(carriesValue));
|
|
2597
|
+
}
|
|
2598
|
+
function isValued(seg, index) {
|
|
2599
|
+
return seg.field(index).repetitions.some(repetitionValued);
|
|
2600
|
+
}
|
|
2601
|
+
function subcomponents(rep, component3) {
|
|
2602
|
+
return rep.components[component3 - 1]?.subcomponents ?? [];
|
|
2603
|
+
}
|
|
2604
|
+
function componentValued(rep, component3) {
|
|
2605
|
+
return subcomponents(rep, component3).some(carriesValue);
|
|
2606
|
+
}
|
|
2607
|
+
function subcomponent(rep, component3, sub) {
|
|
2608
|
+
return subcomponents(rep, component3)[sub - 1] ?? "";
|
|
2609
|
+
}
|
|
2610
|
+
function restoreStructuralEmpties(text2, repetitions, enc) {
|
|
2611
|
+
const padded = (part, count) => {
|
|
2612
|
+
const subs = part.split(enc.subcomponent);
|
|
2613
|
+
if (subs.length >= count) return part;
|
|
2614
|
+
return [...subs, ...Array.from({ length: count - subs.length }, () => "")].join(
|
|
2615
|
+
enc.subcomponent
|
|
2616
|
+
);
|
|
2617
|
+
};
|
|
2618
|
+
return text2.split(enc.repetition).map((repetition, r) => {
|
|
2619
|
+
const components = repetitions[r]?.components ?? [];
|
|
2620
|
+
const parts = repetition.split(enc.component);
|
|
2621
|
+
const restored = parts.map(
|
|
2622
|
+
(part, c) => padded(part, components[c]?.subcomponents.length ?? 0)
|
|
2623
|
+
);
|
|
2624
|
+
for (const dropped of components.slice(parts.length))
|
|
2625
|
+
restored.push(padded("", dropped.subcomponents.length));
|
|
2626
|
+
return restored.join(enc.component);
|
|
2627
|
+
}).join(enc.repetition);
|
|
2628
|
+
}
|
|
2629
|
+
function freeText(seg, field) {
|
|
2630
|
+
const f = seg.field(field);
|
|
2631
|
+
if (f.repetitions.length === 0) return { kind: "absent" };
|
|
2632
|
+
const rendered = renderText(
|
|
2633
|
+
restoreStructuralEmpties(f.text, f.repetitions, seg.enc),
|
|
2634
|
+
seg.enc
|
|
2635
|
+
).text;
|
|
2636
|
+
return rendered === "" ? { kind: "unplaceable" } : { kind: "text", text: rendered };
|
|
2637
|
+
}
|
|
2638
|
+
function txValued(seg, field) {
|
|
2639
|
+
return freeText(seg, field).kind !== "absent";
|
|
2640
|
+
}
|
|
2641
|
+
var SCHEDULE_NARROWING = Object.freeze([
|
|
2642
|
+
[4, ".event"],
|
|
2643
|
+
[5, ".repeat.offset"],
|
|
2644
|
+
// R4 places every `bounds[x]` on `Timing.repeat`, not on `Timing`, so the element the IG's
|
|
2645
|
+
// TQ1-6 rows would have reached is `...timing.repeat.boundsDuration`: a consumer routing on
|
|
2646
|
+
// `fhirPath` must not be handed a path that resolves to nothing.
|
|
2647
|
+
[6, ".repeat.boundsDuration"],
|
|
2648
|
+
[12, ""],
|
|
2649
|
+
[13, ".repeat.duration"],
|
|
2650
|
+
[14, ".repeat.countMax"]
|
|
2651
|
+
]);
|
|
2652
|
+
var EXPRESSIBLE_RPT_COMPONENTS = Object.freeze(/* @__PURE__ */ new Set([1, 5, 6, 8]));
|
|
2653
|
+
function endPrecedesStart(start, end) {
|
|
2654
|
+
const zoned = (v) => {
|
|
2655
|
+
if (!v.includes("T")) return void 0;
|
|
2656
|
+
const ms = Date.parse(v);
|
|
2657
|
+
return Number.isNaN(ms) ? void 0 : ms;
|
|
2658
|
+
};
|
|
2659
|
+
const startMs = zoned(start);
|
|
2660
|
+
const endMs = zoned(end);
|
|
2661
|
+
if (startMs !== void 0 && endMs !== void 0) return endMs < startMs;
|
|
2662
|
+
const datePart2 = (v) => v.split("T")[0] ?? v;
|
|
2663
|
+
const widen = (v, high) => {
|
|
2664
|
+
const d = datePart2(v);
|
|
2665
|
+
if (d.length === 4) return high ? `${d}-12-31` : `${d}-01-01`;
|
|
2666
|
+
if (d.length === 7) return high ? `${d}-31` : `${d}-01`;
|
|
2667
|
+
return d;
|
|
2668
|
+
};
|
|
2669
|
+
return widen(end, true) < widen(start, false);
|
|
2670
|
+
}
|
|
2671
|
+
function timingCode(code) {
|
|
2672
|
+
return complex([
|
|
2673
|
+
{
|
|
2674
|
+
name: "coding",
|
|
2675
|
+
value: list([
|
|
2676
|
+
complex([
|
|
2677
|
+
{ name: "system", value: primitive(V2_0335_SYSTEM) },
|
|
2678
|
+
{ name: "code", value: primitive(code) }
|
|
2679
|
+
])
|
|
2680
|
+
])
|
|
2681
|
+
}
|
|
2682
|
+
]);
|
|
2683
|
+
}
|
|
2684
|
+
function readRepeatPattern(tq1, base, draft, issues) {
|
|
2685
|
+
const valued = tq1.field(3).repetitions.filter(repetitionValued);
|
|
2686
|
+
const rpt = valued[0];
|
|
2687
|
+
if (rpt === void 0) return;
|
|
2688
|
+
if (valued.length > 1) {
|
|
2689
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.3", base));
|
|
2690
|
+
draft.refused = true;
|
|
2691
|
+
return;
|
|
2692
|
+
}
|
|
2693
|
+
const carried = rpt.components.length;
|
|
2694
|
+
for (let component3 = 1; component3 <= carried; component3 += 1) {
|
|
2695
|
+
if (EXPRESSIBLE_RPT_COMPONENTS.has(component3)) continue;
|
|
2696
|
+
if (!componentValued(rpt, component3)) continue;
|
|
2697
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, `TQ1.3.${String(component3)}`, base));
|
|
2698
|
+
draft.refused = true;
|
|
2699
|
+
}
|
|
2700
|
+
if (componentValued(rpt, 1)) {
|
|
2701
|
+
const code = subcomponent(rpt, 1, 1);
|
|
2702
|
+
const mnemonic = subcomponent(rpt, 1, 3);
|
|
2703
|
+
const fromTable = mnemonic === "" || HL70335_MNEMONICS.has(mnemonic);
|
|
2704
|
+
if (fromTable && isRepeatPatternCode(code)) {
|
|
2705
|
+
draft.code = timingCode(code);
|
|
2706
|
+
} else {
|
|
2707
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_UNMAPPED, "TQ1.3.1", `${base}.code`));
|
|
2708
|
+
draft.refused = true;
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
if (componentValued(rpt, 5)) {
|
|
2712
|
+
const raw = subcomponent(rpt, 5, 1);
|
|
2713
|
+
let period;
|
|
2714
|
+
try {
|
|
2715
|
+
period = primitive(decimal(raw));
|
|
2716
|
+
} catch {
|
|
2717
|
+
period = void 0;
|
|
2718
|
+
}
|
|
2719
|
+
if (period === void 0 || raw.startsWith("-")) {
|
|
2720
|
+
issues.push(
|
|
2721
|
+
issue(ISSUE_CODES.TRANSFORM_QUANTITY_VALUE_INVALID, "TQ1.3.5", `${base}.repeat.period`)
|
|
2722
|
+
);
|
|
2723
|
+
draft.refused = true;
|
|
2724
|
+
} else {
|
|
2725
|
+
draft.period = period;
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
if (componentValued(rpt, 6)) {
|
|
2729
|
+
const unit = subcomponent(rpt, 6, 1);
|
|
2730
|
+
const mnemonic = subcomponent(rpt, 6, 3);
|
|
2731
|
+
const fromUcum = mnemonic === "" || UCUM_MNEMONICS.has(mnemonic);
|
|
2732
|
+
if (fromUcum && UNITS_OF_TIME.has(unit)) {
|
|
2733
|
+
draft.periodUnit = unit;
|
|
2734
|
+
} else {
|
|
2735
|
+
issues.push(
|
|
2736
|
+
issue(ISSUE_CODES.TRANSFORM_CODE_UNMAPPED, "TQ1.3.6", `${base}.repeat.periodUnit`)
|
|
2737
|
+
);
|
|
2738
|
+
draft.refused = true;
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
const periodValued = componentValued(rpt, 5);
|
|
2742
|
+
const unitValued = componentValued(rpt, 6);
|
|
2743
|
+
if (periodValued && !unitValued && draft.period !== void 0) {
|
|
2744
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.3.5", `${base}.repeat.period`));
|
|
2745
|
+
draft.refused = true;
|
|
2746
|
+
}
|
|
2747
|
+
if (unitValued && !periodValued && draft.periodUnit !== void 0) {
|
|
2748
|
+
issues.push(
|
|
2749
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.3.6", `${base}.repeat.periodUnit`)
|
|
2750
|
+
);
|
|
2751
|
+
draft.refused = true;
|
|
2752
|
+
}
|
|
2753
|
+
if (componentValued(rpt, 8)) {
|
|
2754
|
+
const event = subcomponent(rpt, 8, 1);
|
|
2755
|
+
const mnemonic = subcomponent(rpt, 8, 3);
|
|
2756
|
+
const target = translateBound(
|
|
2757
|
+
{ identifier: event, nameOfCodingSystem: mnemonic },
|
|
2758
|
+
TIMING_EVENT_VALUE_MAP
|
|
2759
|
+
);
|
|
2760
|
+
if (target === void 0) {
|
|
2761
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_UNMAPPED, "TQ1.3.8", `${base}.repeat.when`));
|
|
2762
|
+
draft.refused = true;
|
|
2763
|
+
} else {
|
|
2764
|
+
draft.when = target.code;
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
function readBounds(tq1, base, ctx, draft, issues) {
|
|
2769
|
+
const endpoint = (field, name) => {
|
|
2770
|
+
if (!isValued(tq1, field)) return void 0;
|
|
2771
|
+
const converted = toFhirDateTime(tq1.field(field).asTs(), ctx.options);
|
|
2772
|
+
issues.push(...converted.issues);
|
|
2773
|
+
if (converted.value === void 0) {
|
|
2774
|
+
issues.push(
|
|
2775
|
+
issue(
|
|
2776
|
+
ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED,
|
|
2777
|
+
`TQ1.${String(field)}`,
|
|
2778
|
+
`${base}.repeat.boundsPeriod.${name}`
|
|
2779
|
+
)
|
|
2780
|
+
);
|
|
2781
|
+
draft.refused = true;
|
|
2782
|
+
}
|
|
2783
|
+
return converted.value;
|
|
2784
|
+
};
|
|
2785
|
+
draft.boundsStart = endpoint(7, "start");
|
|
2786
|
+
draft.boundsEnd = endpoint(8, "end");
|
|
2787
|
+
if (draft.boundsStart !== void 0 && draft.boundsEnd !== void 0 && endPrecedesStart(draft.boundsStart, draft.boundsEnd)) {
|
|
2788
|
+
issues.push(
|
|
2789
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.8", `${base}.repeat.boundsPeriod.end`)
|
|
2790
|
+
);
|
|
2791
|
+
draft.refused = true;
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
function assembleTiming(draft) {
|
|
2795
|
+
if (draft.refused) return void 0;
|
|
2796
|
+
const bounds = [];
|
|
2797
|
+
if (draft.boundsStart !== void 0)
|
|
2798
|
+
bounds.push({ name: "start", value: primitive(draft.boundsStart) });
|
|
2799
|
+
if (draft.boundsEnd !== void 0)
|
|
2800
|
+
bounds.push({ name: "end", value: primitive(draft.boundsEnd) });
|
|
2801
|
+
const repeat = [];
|
|
2802
|
+
if (bounds.length > 0) repeat.push({ name: "boundsPeriod", value: complex(bounds) });
|
|
2803
|
+
if (draft.period !== void 0) repeat.push({ name: "period", value: draft.period });
|
|
2804
|
+
if (draft.periodUnit !== void 0)
|
|
2805
|
+
repeat.push({ name: "periodUnit", value: primitive(draft.periodUnit) });
|
|
2806
|
+
if (draft.when !== void 0) repeat.push({ name: "when", value: list([primitive(draft.when)]) });
|
|
2807
|
+
const timing = [];
|
|
2808
|
+
if (repeat.length > 0) timing.push({ name: "repeat", value: complex(repeat) });
|
|
2809
|
+
if (draft.code !== void 0) timing.push({ name: "code", value: draft.code });
|
|
2810
|
+
return timing.length === 0 ? void 0 : complex(timing);
|
|
2811
|
+
}
|
|
2812
|
+
function nothing(issues) {
|
|
2813
|
+
return {
|
|
2814
|
+
timing: void 0,
|
|
2815
|
+
conditionText: void 0,
|
|
2816
|
+
instructionText: void 0,
|
|
2817
|
+
issues,
|
|
2818
|
+
contributes: false
|
|
2819
|
+
};
|
|
2820
|
+
}
|
|
2821
|
+
function readTq1(tq1s, target, ctx) {
|
|
2822
|
+
const issues = [];
|
|
2823
|
+
const base = timingPath(target);
|
|
2824
|
+
if (tq1s.length === 0) return nothing(issues);
|
|
2825
|
+
if (tq1s.length > 1) {
|
|
2826
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1", base));
|
|
2827
|
+
return nothing(issues);
|
|
2828
|
+
}
|
|
2829
|
+
const tq1 = tq1s[0];
|
|
2830
|
+
if (tq1 === void 0) return nothing(issues);
|
|
2831
|
+
if (isValued(tq1, 2)) {
|
|
2832
|
+
issues.push(
|
|
2833
|
+
issue(
|
|
2834
|
+
ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED,
|
|
2835
|
+
"TQ1.2",
|
|
2836
|
+
target === "MedicationRequest" ? "MedicationRequest.dosageInstruction.doseAndRate.doseQuantity" : "ServiceRequest.quantityQuantity"
|
|
2837
|
+
)
|
|
2838
|
+
);
|
|
2839
|
+
}
|
|
2840
|
+
if (isValued(tq1, 9)) {
|
|
2841
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.9", `${target}.priority`));
|
|
2842
|
+
}
|
|
2843
|
+
const draft = {
|
|
2844
|
+
refused: false,
|
|
2845
|
+
code: void 0,
|
|
2846
|
+
period: void 0,
|
|
2847
|
+
periodUnit: void 0,
|
|
2848
|
+
when: void 0,
|
|
2849
|
+
boundsStart: void 0,
|
|
2850
|
+
boundsEnd: void 0
|
|
2851
|
+
};
|
|
2852
|
+
for (const [field, suffix] of SCHEDULE_NARROWING) {
|
|
2853
|
+
if (!isValued(tq1, field)) continue;
|
|
2854
|
+
issues.push(
|
|
2855
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, `TQ1.${String(field)}`, `${base}${suffix}`)
|
|
2856
|
+
);
|
|
2857
|
+
draft.refused = true;
|
|
2858
|
+
}
|
|
2859
|
+
readRepeatPattern(tq1, base, draft, issues);
|
|
2860
|
+
readBounds(tq1, base, ctx, draft, issues);
|
|
2861
|
+
const timing = assembleTiming(draft);
|
|
2862
|
+
let conditionText;
|
|
2863
|
+
let instructionText;
|
|
2864
|
+
if (target === "MedicationRequest") {
|
|
2865
|
+
const condition = freeText(tq1, 10);
|
|
2866
|
+
if (condition.kind === "text") conditionText = condition.text;
|
|
2867
|
+
else if (condition.kind === "unplaceable")
|
|
2868
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.10", CONDITION_TEXT_PATH));
|
|
2869
|
+
const instruction = freeText(tq1, 11);
|
|
2870
|
+
if (instruction.kind === "unplaceable") {
|
|
2871
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.11", INSTRUCTION_TEXT_PATH));
|
|
2872
|
+
} else if (instruction.kind === "text") {
|
|
2873
|
+
if (instruction.text.trim() === "")
|
|
2874
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.11", INSTRUCTION_TEXT_PATH));
|
|
2875
|
+
else instructionText = instruction.text;
|
|
2876
|
+
}
|
|
2877
|
+
} else {
|
|
2878
|
+
if (txValued(tq1, 10))
|
|
2879
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.10", "ServiceRequest"));
|
|
2880
|
+
if (txValued(tq1, 11))
|
|
2881
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "TQ1.11", "ServiceRequest.note"));
|
|
2882
|
+
}
|
|
2883
|
+
return {
|
|
2884
|
+
timing,
|
|
2885
|
+
conditionText,
|
|
2886
|
+
instructionText,
|
|
2887
|
+
issues,
|
|
2888
|
+
contributes: timing !== void 0 || conditionText !== void 0 || instructionText !== void 0
|
|
2889
|
+
};
|
|
2890
|
+
}
|
|
2891
|
+
function escapeXml(value) {
|
|
2892
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2893
|
+
}
|
|
2894
|
+
function narrative(value) {
|
|
2895
|
+
return complex([
|
|
2896
|
+
{ name: "status", value: primitive("additional") },
|
|
2897
|
+
{
|
|
2898
|
+
name: "div",
|
|
2899
|
+
value: primitive(`<div xmlns="http://www.w3.org/1999/xhtml">${escapeXml(value)}</div>`)
|
|
2900
|
+
}
|
|
2901
|
+
]);
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
// src/messages/medication-request.ts
|
|
2905
|
+
var STATUS_UNKNOWN = "unknown";
|
|
2906
|
+
var ORDER_INTENT = "order";
|
|
2907
|
+
var UNSIGNED_INT = /^(0|[1-9][0-9]*)$/;
|
|
2908
|
+
function codeableFrom(seg, index, ctx, issues) {
|
|
2909
|
+
if (seg.field(index).value === "") return void 0;
|
|
2910
|
+
const cc = toFhirCodeableConcept(seg.field(index).asCwe(), ctx);
|
|
2911
|
+
issues.push(...cc.issues);
|
|
2912
|
+
return cc.value;
|
|
2913
|
+
}
|
|
2914
|
+
function translatedFrom2(seg, index, map, ctx, issues) {
|
|
2915
|
+
if (seg.field(index).value === "") return void 0;
|
|
2916
|
+
const cc = toFhirCodeableConceptVia(seg.field(index).asCwe(), map, ctx);
|
|
1785
2917
|
issues.push(...cc.issues);
|
|
1786
2918
|
return cc.value;
|
|
1787
2919
|
}
|
|
@@ -1799,8 +2931,17 @@ function doseEndpoint(rxo, amountIndex, units, ctx, issues) {
|
|
|
1799
2931
|
issues.push(...q.issues);
|
|
1800
2932
|
return q.value;
|
|
1801
2933
|
}
|
|
1802
|
-
function buildDosageInstruction(rxo, rxr, ctx, issues) {
|
|
2934
|
+
function buildDosageInstruction(rxo, rxr, tq1, ctx, issues) {
|
|
1803
2935
|
const props = [];
|
|
2936
|
+
if (tq1?.conditionText !== void 0) {
|
|
2937
|
+
props.push({
|
|
2938
|
+
name: "additionalInstruction",
|
|
2939
|
+
value: list([complex([{ name: "text", value: primitive(tq1.conditionText) }])])
|
|
2940
|
+
});
|
|
2941
|
+
}
|
|
2942
|
+
if (tq1?.timing !== void 0) {
|
|
2943
|
+
props.push({ name: "timing", value: tq1.timing });
|
|
2944
|
+
}
|
|
1804
2945
|
if (rxr !== void 0) {
|
|
1805
2946
|
const route = translatedFrom2(rxr, 1, ROUTE_VALUE_MAP, ctx, issues);
|
|
1806
2947
|
if (route !== void 0) props.push({ name: "route", value: route });
|
|
@@ -1856,8 +2997,9 @@ function buildDispenseRequest(rxo, ctx, issues) {
|
|
|
1856
2997
|
}
|
|
1857
2998
|
return props.length === 0 ? void 0 : complex(props);
|
|
1858
2999
|
}
|
|
1859
|
-
function buildMedicationRequest(rxo, rxr, orc, subjectFullUrl, encounterFullUrl, ctx) {
|
|
3000
|
+
function buildMedicationRequest(rxo, rxr, orc, tq1, subjectFullUrl, encounterFullUrl, ctx) {
|
|
1860
3001
|
const issues = [];
|
|
3002
|
+
if (tq1 !== void 0) issues.push(...tq1.issues);
|
|
1861
3003
|
if (rxo === void 0 || rxo.field(1).value === "") return { value: void 0, issues };
|
|
1862
3004
|
const medication = toFhirCodeableConcept(rxo.field(1).asCwe(), ctx);
|
|
1863
3005
|
issues.push(...medication.issues);
|
|
@@ -1865,6 +3007,9 @@ function buildMedicationRequest(rxo, rxr, orc, subjectFullUrl, encounterFullUrl,
|
|
|
1865
3007
|
const props = [
|
|
1866
3008
|
{ name: "resourceType", value: primitive("MedicationRequest") }
|
|
1867
3009
|
];
|
|
3010
|
+
if (tq1?.instructionText !== void 0) {
|
|
3011
|
+
props.push({ name: "text", value: narrative(tq1.instructionText) });
|
|
3012
|
+
}
|
|
1868
3013
|
props.push({ name: "status", value: primitive(STATUS_UNKNOWN) });
|
|
1869
3014
|
issues.push(
|
|
1870
3015
|
issue(ISSUE_CODES.TRANSFORM_REQUIRED_ELEMENT_UNKNOWN, "RXO", "MedicationRequest.status")
|
|
@@ -1881,7 +3026,7 @@ function buildMedicationRequest(rxo, rxr, orc, subjectFullUrl, encounterFullUrl,
|
|
|
1881
3026
|
if (authored.value !== void 0)
|
|
1882
3027
|
props.push({ name: "authoredOn", value: primitive(authored.value) });
|
|
1883
3028
|
}
|
|
1884
|
-
const dosage = buildDosageInstruction(rxo, rxr, ctx, issues);
|
|
3029
|
+
const dosage = buildDosageInstruction(rxo, rxr, tq1, ctx, issues);
|
|
1885
3030
|
if (dosage !== void 0) props.push({ name: "dosageInstruction", value: list([dosage]) });
|
|
1886
3031
|
const dispense = buildDispenseRequest(rxo, ctx, issues);
|
|
1887
3032
|
if (dispense !== void 0) props.push({ name: "dispenseRequest", value: dispense });
|
|
@@ -1936,6 +3081,40 @@ function buildMessageHeader(meta, focusFullUrls) {
|
|
|
1936
3081
|
}
|
|
1937
3082
|
return { value: complex(props), issues };
|
|
1938
3083
|
}
|
|
3084
|
+
var DEFERRED_NOTE_ROWS = Object.freeze([
|
|
3085
|
+
[4, "Annotation.extension"],
|
|
3086
|
+
[5, "Annotation.authorReference"]
|
|
3087
|
+
]);
|
|
3088
|
+
function annotationTime(nte, ctx, issues) {
|
|
3089
|
+
if (nte.field(6).value === "") return void 0;
|
|
3090
|
+
const entered = toFhirDateTime(nte.field(6).asTs(), ctx.options);
|
|
3091
|
+
issues.push(...entered.issues);
|
|
3092
|
+
return entered.value === void 0 ? void 0 : primitive(entered.value);
|
|
3093
|
+
}
|
|
3094
|
+
function buildAnnotations(notes, ctx, issues) {
|
|
3095
|
+
const annotations = [];
|
|
3096
|
+
for (const nte of notes) {
|
|
3097
|
+
for (const [field, path] of DEFERRED_NOTE_ROWS) {
|
|
3098
|
+
if (nte.field(field).value !== "") {
|
|
3099
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, `NTE.${String(field)}`, path));
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
const comment = nte.field(3);
|
|
3103
|
+
if (comment.repetitions.length === 0) continue;
|
|
3104
|
+
const time = annotationTime(nte, ctx, issues);
|
|
3105
|
+
for (const repetition of comment.text.split(nte.enc.repetition)) {
|
|
3106
|
+
const rendered = renderText(repetition, nte.enc).text;
|
|
3107
|
+
if (rendered === "") continue;
|
|
3108
|
+
const props = [];
|
|
3109
|
+
if (time !== void 0) props.push({ name: "time", value: time });
|
|
3110
|
+
props.push({ name: "text", value: primitive(rendered) });
|
|
3111
|
+
annotations.push(complex(props));
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
return annotations.length === 0 ? void 0 : list(annotations);
|
|
3115
|
+
}
|
|
3116
|
+
|
|
3117
|
+
// src/messages/observation.ts
|
|
1939
3118
|
var V3_OBSERVATION_INTERPRETATION_SYSTEM = "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation";
|
|
1940
3119
|
var HL70078_INTERPRETATION_CODES = /* @__PURE__ */ new Set([
|
|
1941
3120
|
"<",
|
|
@@ -1987,6 +3166,10 @@ var OBSERVATION_STATUS_MAP = Object.freeze({
|
|
|
1987
3166
|
W: "entered-in-error",
|
|
1988
3167
|
X: "cancelled"
|
|
1989
3168
|
});
|
|
3169
|
+
var OBSERVATION_VALUE_ATTACHMENT_EXTENSION_URL = "https://hl7.org/fhir/5.0/StructureDefinition/extension-Observation.valueAttachment";
|
|
3170
|
+
var ED_BASE64_ENCODING = "Base64";
|
|
3171
|
+
var SAMPLED_DATA_ABSENT_POINT = "E";
|
|
3172
|
+
var SAMPLED_DATA_UNGROUNDED = "unknown";
|
|
1990
3173
|
var SN_COMPARATORS = /* @__PURE__ */ new Set([">", "<", ">=", "<="]);
|
|
1991
3174
|
var CODED_VALUE_TYPES = /* @__PURE__ */ new Set(["CWE", "CE", "CF", "CNE", "IS"]);
|
|
1992
3175
|
var DATETIME_VALUE_TYPES = /* @__PURE__ */ new Set(["DT", "DTM", "TS"]);
|
|
@@ -1995,6 +3178,117 @@ function rawComponent2(field, index) {
|
|
|
1995
3178
|
const c = field.repetitions[0]?.components[index]?.subcomponents[0];
|
|
1996
3179
|
return c === void 0 || c === "" ? void 0 : c;
|
|
1997
3180
|
}
|
|
3181
|
+
function fieldEmpty(field) {
|
|
3182
|
+
return field.repetitions.every(
|
|
3183
|
+
(r) => r.components.every((c) => c.subcomponents.every((s) => s === ""))
|
|
3184
|
+
);
|
|
3185
|
+
}
|
|
3186
|
+
function buildPeriodValue(field, ctx, issues) {
|
|
3187
|
+
const props = [];
|
|
3188
|
+
for (const [index, name] of [
|
|
3189
|
+
[0, "start"],
|
|
3190
|
+
[1, "end"]
|
|
3191
|
+
]) {
|
|
3192
|
+
const raw = rawComponent2(field, index);
|
|
3193
|
+
if (raw === void 0) continue;
|
|
3194
|
+
const converted = toFhirDateTime(parseDtm(raw), ctx.options);
|
|
3195
|
+
issues.push(...converted.issues);
|
|
3196
|
+
if (converted.value !== void 0) props.push({ name, value: primitive(converted.value) });
|
|
3197
|
+
}
|
|
3198
|
+
return props.length === 0 ? void 0 : complex(props);
|
|
3199
|
+
}
|
|
3200
|
+
function rangeBound(raw, fhirPath, issues) {
|
|
3201
|
+
if (raw === void 0) return void 0;
|
|
3202
|
+
try {
|
|
3203
|
+
return complex([{ name: "value", value: primitive(decimal(raw)) }]);
|
|
3204
|
+
} catch {
|
|
3205
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_QUANTITY_VALUE_INVALID, "OBX.5", fhirPath));
|
|
3206
|
+
return void 0;
|
|
3207
|
+
}
|
|
3208
|
+
}
|
|
3209
|
+
function buildRangeValue(field, issues) {
|
|
3210
|
+
const low = rangeBound(rawComponent2(field, 0), "Range.low.value", issues);
|
|
3211
|
+
const high = rangeBound(rawComponent2(field, 1), "Range.high.value", issues);
|
|
3212
|
+
const props = [];
|
|
3213
|
+
if (low !== void 0) props.push({ name: "low", value: low });
|
|
3214
|
+
if (high !== void 0) props.push({ name: "high", value: high });
|
|
3215
|
+
return props.length === 0 ? void 0 : complex(props);
|
|
3216
|
+
}
|
|
3217
|
+
function timeValue(raw) {
|
|
3218
|
+
const parts = /^(\d{2})(\d{2})(\d{2})(\.\d{1,4})?$/.exec(raw);
|
|
3219
|
+
if (parts === null) return void 0;
|
|
3220
|
+
const candidate = `${parts[1] ?? ""}:${parts[2] ?? ""}:${parts[3] ?? ""}${parts[4] ?? ""}`;
|
|
3221
|
+
return validatePrimitiveValue(candidate, "time") === "ok" ? candidate : void 0;
|
|
3222
|
+
}
|
|
3223
|
+
function buildSampledData(field, issues) {
|
|
3224
|
+
const rows = field.repetitions.map((r) => r.components.map((c) => c.subcomponents[0] ?? ""));
|
|
3225
|
+
if (rows.length === 0) return void 0;
|
|
3226
|
+
const width = Math.max(...rows.map((r) => r.length));
|
|
3227
|
+
const dimensions = rows.length === 1 ? 1 : width;
|
|
3228
|
+
const points = [];
|
|
3229
|
+
for (const row of rows) {
|
|
3230
|
+
for (let i = 0; i < width; i++) {
|
|
3231
|
+
const cell = row[i] ?? "";
|
|
3232
|
+
if (cell === "") {
|
|
3233
|
+
points.push(SAMPLED_DATA_ABSENT_POINT);
|
|
3234
|
+
continue;
|
|
3235
|
+
}
|
|
3236
|
+
try {
|
|
3237
|
+
decimal(cell);
|
|
3238
|
+
points.push(cell);
|
|
3239
|
+
} catch {
|
|
3240
|
+
issues.push(
|
|
3241
|
+
issue(ISSUE_CODES.TRANSFORM_QUANTITY_VALUE_INVALID, "OBX.5", "SampledData.data")
|
|
3242
|
+
);
|
|
3243
|
+
return void 0;
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
for (const path of ["SampledData.origin", "SampledData.period"]) {
|
|
3248
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_REQUIRED_ELEMENT_UNKNOWN, "OBX.5", path));
|
|
3249
|
+
}
|
|
3250
|
+
return complex([
|
|
3251
|
+
{ name: "origin", value: dataAbsentComplex(SAMPLED_DATA_UNGROUNDED) },
|
|
3252
|
+
{ name: "period", value: dataAbsent(SAMPLED_DATA_UNGROUNDED) },
|
|
3253
|
+
{ name: "dimensions", value: primitive(decimal(String(dimensions))) },
|
|
3254
|
+
{ name: "data", value: primitive(points.join(" ")) }
|
|
3255
|
+
]);
|
|
3256
|
+
}
|
|
3257
|
+
function buildAttachmentExtension(field, issues) {
|
|
3258
|
+
const payload = rawComponent2(field, 4);
|
|
3259
|
+
if (payload === void 0) return void 0;
|
|
3260
|
+
const attachment = [];
|
|
3261
|
+
const subtype = rawComponent2(field, 2);
|
|
3262
|
+
const typeOfData = rawComponent2(field, 1);
|
|
3263
|
+
if (subtype === void 0 && typeOfData !== void 0) {
|
|
3264
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_UNMAPPED, "OBX.5", "Attachment.contentType"));
|
|
3265
|
+
attachment.push({
|
|
3266
|
+
name: "extension",
|
|
3267
|
+
value: list([
|
|
3268
|
+
complex([
|
|
3269
|
+
{ name: "url", value: primitive(ALTERNATE_CODES_EXTENSION_URL) },
|
|
3270
|
+
{
|
|
3271
|
+
name: "valueCodeableConcept",
|
|
3272
|
+
value: complex([
|
|
3273
|
+
{
|
|
3274
|
+
name: "coding",
|
|
3275
|
+
value: list([complex([{ name: "code", value: primitive(typeOfData) }])])
|
|
3276
|
+
}
|
|
3277
|
+
])
|
|
3278
|
+
}
|
|
3279
|
+
])
|
|
3280
|
+
])
|
|
3281
|
+
});
|
|
3282
|
+
}
|
|
3283
|
+
if (subtype !== void 0) attachment.push({ name: "contentType", value: primitive(subtype) });
|
|
3284
|
+
attachment.push({ name: "data", value: primitive(payload) });
|
|
3285
|
+
return list([
|
|
3286
|
+
complex([
|
|
3287
|
+
{ name: "url", value: primitive(OBSERVATION_VALUE_ATTACHMENT_EXTENSION_URL) },
|
|
3288
|
+
{ name: "valueAttachment", value: complex(attachment) }
|
|
3289
|
+
])
|
|
3290
|
+
]);
|
|
3291
|
+
}
|
|
1998
3292
|
function snText(field) {
|
|
1999
3293
|
return [0, 1, 2, 3].map((i) => rawComponent2(field, i) ?? "").join("");
|
|
2000
3294
|
}
|
|
@@ -2050,10 +3344,39 @@ function buildSnValue(field, units, ctx, issues) {
|
|
|
2050
3344
|
}
|
|
2051
3345
|
return valueStringProp(snText(field));
|
|
2052
3346
|
}
|
|
3347
|
+
var COMPOSITE_VALUE_TYPES = /* @__PURE__ */ new Set(["DR", "NR", "TM", "NA", "ED"]);
|
|
3348
|
+
function buildMappedValue(field, vt, ctx, issues) {
|
|
3349
|
+
if (vt === "DR") {
|
|
3350
|
+
const period = buildPeriodValue(field, ctx, issues);
|
|
3351
|
+
return period === void 0 ? void 0 : { name: "valuePeriod", value: period };
|
|
3352
|
+
}
|
|
3353
|
+
if (vt === "NR") {
|
|
3354
|
+
const range = buildRangeValue(field, issues);
|
|
3355
|
+
return range === void 0 ? void 0 : { name: "valueRange", value: range };
|
|
3356
|
+
}
|
|
3357
|
+
if (vt === "TM") {
|
|
3358
|
+
const time = timeValue(field.text);
|
|
3359
|
+
return time === void 0 ? void 0 : { name: "valueTime", value: primitive(time) };
|
|
3360
|
+
}
|
|
3361
|
+
if (vt === "NA") {
|
|
3362
|
+
const sampled = buildSampledData(field, issues);
|
|
3363
|
+
return sampled === void 0 ? void 0 : { name: "valueSampledData", value: sampled };
|
|
3364
|
+
}
|
|
3365
|
+
if (rawComponent2(field, 3) !== ED_BASE64_ENCODING) return void 0;
|
|
3366
|
+
const extension = buildAttachmentExtension(field, issues);
|
|
3367
|
+
return extension === void 0 ? void 0 : { name: "extension", value: extension };
|
|
3368
|
+
}
|
|
2053
3369
|
function buildValue(obx, valueType, ctx, issues) {
|
|
2054
3370
|
const field = obx.field(5);
|
|
2055
3371
|
const rawValue = field.value;
|
|
2056
3372
|
const vt = valueType.toUpperCase();
|
|
3373
|
+
if (COMPOSITE_VALUE_TYPES.has(vt)) {
|
|
3374
|
+
if (fieldEmpty(field)) return void 0;
|
|
3375
|
+
const mapped = buildMappedValue(field, vt, ctx, issues);
|
|
3376
|
+
if (mapped !== void 0) return mapped;
|
|
3377
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "OBX.5", "Observation.value[x]"));
|
|
3378
|
+
return valueStringProp(field.text);
|
|
3379
|
+
}
|
|
2057
3380
|
if (vt === "NM") {
|
|
2058
3381
|
const q = quantityFromRawMagnitude(field.asNm().raw, obx.field(6).asCwe(), ctx);
|
|
2059
3382
|
issues.push(...q.issues);
|
|
@@ -2106,7 +3429,7 @@ function buildInterpretation(obx, issues) {
|
|
|
2106
3429
|
}
|
|
2107
3430
|
return codings.length === 0 ? void 0 : list(codings);
|
|
2108
3431
|
}
|
|
2109
|
-
function buildObservation(obx, subjectFullUrl, encounterFullUrl, ctx) {
|
|
3432
|
+
function buildObservation(obx, subjectFullUrl, encounterFullUrl, ctx, notes = []) {
|
|
2110
3433
|
const issues = [];
|
|
2111
3434
|
const props = [
|
|
2112
3435
|
{ name: "resourceType", value: primitive("Observation") }
|
|
@@ -2140,6 +3463,8 @@ function buildObservation(obx, subjectFullUrl, encounterFullUrl, ctx) {
|
|
|
2140
3463
|
if (value !== void 0) props.push(value);
|
|
2141
3464
|
const interpretation = buildInterpretation(obx, issues);
|
|
2142
3465
|
if (interpretation !== void 0) props.push({ name: "interpretation", value: interpretation });
|
|
3466
|
+
const note = buildAnnotations(notes, ctx, issues);
|
|
3467
|
+
if (note !== void 0) props.push({ name: "note", value: note });
|
|
2143
3468
|
const refRange = obx.field(7).value;
|
|
2144
3469
|
if (refRange !== "") {
|
|
2145
3470
|
props.push({
|
|
@@ -2156,7 +3481,13 @@ function collectOrderGroups(msg) {
|
|
|
2156
3481
|
let current;
|
|
2157
3482
|
let rxeCount = 0;
|
|
2158
3483
|
const open = () => {
|
|
2159
|
-
const g = {
|
|
3484
|
+
const g = {
|
|
3485
|
+
orc: void 0,
|
|
3486
|
+
obr: void 0,
|
|
3487
|
+
rxo: void 0,
|
|
3488
|
+
rxrs: [],
|
|
3489
|
+
tq1s: []
|
|
3490
|
+
};
|
|
2160
3491
|
groups.push(g);
|
|
2161
3492
|
current = g;
|
|
2162
3493
|
return g;
|
|
@@ -2177,13 +3508,22 @@ function collectOrderGroups(msg) {
|
|
|
2177
3508
|
case "RXR":
|
|
2178
3509
|
if (current !== void 0) current.rxrs.push(seg);
|
|
2179
3510
|
break;
|
|
3511
|
+
case "TQ1":
|
|
3512
|
+
if (current !== void 0) current.tq1s.push(seg);
|
|
3513
|
+
break;
|
|
2180
3514
|
case "RXE":
|
|
2181
3515
|
rxeCount += 1;
|
|
2182
3516
|
break;
|
|
2183
3517
|
}
|
|
2184
3518
|
}
|
|
2185
3519
|
return {
|
|
2186
|
-
groups: groups.map((g) => ({
|
|
3520
|
+
groups: groups.map((g) => ({
|
|
3521
|
+
orc: g.orc,
|
|
3522
|
+
obr: g.obr,
|
|
3523
|
+
rxo: g.rxo,
|
|
3524
|
+
rxrs: g.rxrs,
|
|
3525
|
+
tq1s: g.tq1s
|
|
3526
|
+
})),
|
|
2187
3527
|
rxeCount
|
|
2188
3528
|
};
|
|
2189
3529
|
}
|
|
@@ -2192,14 +3532,29 @@ function collectOrderGroups(msg) {
|
|
|
2192
3532
|
function collectReportGroups(msg) {
|
|
2193
3533
|
const groups = [];
|
|
2194
3534
|
let current;
|
|
3535
|
+
let openObservation;
|
|
2195
3536
|
let orphanObxCount = 0;
|
|
2196
3537
|
for (const seg of msg.allSegments()) {
|
|
3538
|
+
if (seg.type === "NTE") {
|
|
3539
|
+
if (openObservation !== void 0) openObservation.notes.push(seg);
|
|
3540
|
+
continue;
|
|
3541
|
+
}
|
|
3542
|
+
if (seg.type === "OBX") {
|
|
3543
|
+
if (current === void 0) {
|
|
3544
|
+
orphanObxCount += 1;
|
|
3545
|
+
openObservation = void 0;
|
|
3546
|
+
continue;
|
|
3547
|
+
}
|
|
3548
|
+
openObservation = { obx: seg, notes: [] };
|
|
3549
|
+
current.observations.push(openObservation);
|
|
3550
|
+
continue;
|
|
3551
|
+
}
|
|
3552
|
+
openObservation = void 0;
|
|
2197
3553
|
if (seg.type === "OBR") {
|
|
2198
|
-
current = { obr: seg, observations: [] };
|
|
3554
|
+
current = { obr: seg, observations: [], specimens: [] };
|
|
2199
3555
|
groups.push(current);
|
|
2200
|
-
} else if (seg.type === "
|
|
2201
|
-
|
|
2202
|
-
else current.observations.push(seg);
|
|
3556
|
+
} else if (seg.type === "SPM" && current !== void 0) {
|
|
3557
|
+
current.specimens.push(seg);
|
|
2203
3558
|
}
|
|
2204
3559
|
}
|
|
2205
3560
|
return { groups, orphanObxCount };
|
|
@@ -2301,6 +3656,131 @@ function buildRelatedPerson(nk1, patientFullUrl, ctx, setIndex) {
|
|
|
2301
3656
|
if (!hasContent) return { value: void 0, issues };
|
|
2302
3657
|
return { value: complex(props), issues };
|
|
2303
3658
|
}
|
|
3659
|
+
|
|
3660
|
+
// src/messages/ig-segment-maps.ts
|
|
3661
|
+
var IG_SEGMENT_MAPS_VERSION = "1.0.0";
|
|
3662
|
+
var IG_SEGMENT_MAPS_PUBLISHED = "2025-10-07";
|
|
3663
|
+
var IG_SEGMENT_MAPS_RETRIEVED = "2026-08-22";
|
|
3664
|
+
var IG_SEGMENT_MAPS_SOURCE = "https://hl7.org/fhir/uv/v2mappings/segment_maps.html";
|
|
3665
|
+
var IG_MAPPED_SEGMENT_NAMES = Object.freeze(
|
|
3666
|
+
/* @__PURE__ */ new Set([
|
|
3667
|
+
"AIG",
|
|
3668
|
+
"AIL",
|
|
3669
|
+
"AIP",
|
|
3670
|
+
"AIS",
|
|
3671
|
+
"AL1",
|
|
3672
|
+
"DG1",
|
|
3673
|
+
"EVN",
|
|
3674
|
+
"IAM",
|
|
3675
|
+
"IN1",
|
|
3676
|
+
"IN3",
|
|
3677
|
+
"MRG",
|
|
3678
|
+
"MSA",
|
|
3679
|
+
"MSH",
|
|
3680
|
+
"NK1",
|
|
3681
|
+
"NTE",
|
|
3682
|
+
"OBR",
|
|
3683
|
+
"OBX",
|
|
3684
|
+
"ORC",
|
|
3685
|
+
"PD1",
|
|
3686
|
+
"PID",
|
|
3687
|
+
"PR1",
|
|
3688
|
+
"PRT",
|
|
3689
|
+
"PV1",
|
|
3690
|
+
"PV2",
|
|
3691
|
+
"ROL",
|
|
3692
|
+
"RXA",
|
|
3693
|
+
"RXO",
|
|
3694
|
+
"RXR",
|
|
3695
|
+
"SCH",
|
|
3696
|
+
"SFT",
|
|
3697
|
+
"SPM",
|
|
3698
|
+
"TQ1",
|
|
3699
|
+
"TXA"
|
|
3700
|
+
])
|
|
3701
|
+
);
|
|
3702
|
+
function isIgMappedSegmentName(name) {
|
|
3703
|
+
return IG_MAPPED_SEGMENT_NAMES.has(name);
|
|
3704
|
+
}
|
|
3705
|
+
|
|
3706
|
+
// src/messages/segment-completeness.ts
|
|
3707
|
+
var SEGMENT_IDENTIFIER_SHAPE = /^[A-Z][A-Za-z0-9]{2}$/;
|
|
3708
|
+
function isWellFormedSegmentName(name) {
|
|
3709
|
+
return SEGMENT_IDENTIFIER_SHAPE.test(name);
|
|
3710
|
+
}
|
|
3711
|
+
function enumerateSegmentOccurrences(msg) {
|
|
3712
|
+
const occurrences = [];
|
|
3713
|
+
const seenPerName = /* @__PURE__ */ new Map();
|
|
3714
|
+
for (const [i, segment] of msg.allSegments().entries()) {
|
|
3715
|
+
if (segment.type === "" && segment.fields.length === 0) continue;
|
|
3716
|
+
if (isWellFormedSegmentName(segment.type)) {
|
|
3717
|
+
const nameIndex = (seenPerName.get(segment.type) ?? 0) + 1;
|
|
3718
|
+
seenPerName.set(segment.type, nameIndex);
|
|
3719
|
+
occurrences.push({ segment, ordinal: i + 1, name: segment.type, nameIndex });
|
|
3720
|
+
} else {
|
|
3721
|
+
occurrences.push({ segment, ordinal: i + 1, name: void 0, nameIndex: void 0 });
|
|
3722
|
+
}
|
|
3723
|
+
}
|
|
3724
|
+
return occurrences;
|
|
3725
|
+
}
|
|
3726
|
+
function segmentOccurrenceLocation(occurrence) {
|
|
3727
|
+
return occurrence.name !== void 0 && occurrence.nameIndex !== void 0 ? `${occurrence.name}[${String(occurrence.nameIndex)}]` : `[#${String(occurrence.ordinal)}]`;
|
|
3728
|
+
}
|
|
3729
|
+
var SegmentReachLedger = class {
|
|
3730
|
+
occurrences;
|
|
3731
|
+
reached = /* @__PURE__ */ new Set();
|
|
3732
|
+
/**
|
|
3733
|
+
* @param msg - The parsed message whose occurrences are being tracked.
|
|
3734
|
+
*/
|
|
3735
|
+
constructor(msg) {
|
|
3736
|
+
this.occurrences = enumerateSegmentOccurrences(msg);
|
|
3737
|
+
}
|
|
3738
|
+
/**
|
|
3739
|
+
* Record that each given segment contributed to a resource now present in the bundle. `undefined`
|
|
3740
|
+
* entries are ignored, so a call site can pass an optional part of a group without branching.
|
|
3741
|
+
*/
|
|
3742
|
+
mark(...segments) {
|
|
3743
|
+
for (const segment of segments) {
|
|
3744
|
+
if (segment !== void 0) this.reached.add(segment);
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
/**
|
|
3748
|
+
* Record that the FIRST occurrence of `type` contributed. The parser's derived views (`patient`,
|
|
3749
|
+
* `visit`, `meta`) are built from the first segment of their type, so this is how a resource built
|
|
3750
|
+
* from a view marks the occurrence it came from.
|
|
3751
|
+
*/
|
|
3752
|
+
markFirstOfType(type) {
|
|
3753
|
+
const found = this.occurrences.find((o) => o.name === type);
|
|
3754
|
+
if (found !== void 0) this.reached.add(found.segment);
|
|
3755
|
+
}
|
|
3756
|
+
/**
|
|
3757
|
+
* Record that the `index`-th (0-based) occurrence of `type` contributed: the counterpart of
|
|
3758
|
+
* {@link SegmentReachLedger.markFirstOfType} for the repeating views (`nextOfKin()`), whose
|
|
3759
|
+
* entries are in document order.
|
|
3760
|
+
*/
|
|
3761
|
+
markNthOfType(type, index) {
|
|
3762
|
+
const matching = this.occurrences.filter((o) => o.name === type);
|
|
3763
|
+
const found = matching[index];
|
|
3764
|
+
if (found !== void 0) this.reached.add(found.segment);
|
|
3765
|
+
}
|
|
3766
|
+
/** The occurrences that contributed to no resource present in the bundle, in message order. */
|
|
3767
|
+
reportable() {
|
|
3768
|
+
return this.occurrences.filter((o) => !this.reached.has(o.segment));
|
|
3769
|
+
}
|
|
3770
|
+
/**
|
|
3771
|
+
* One value-free issue per reportable occurrence, in message order: the library-gap code when the
|
|
3772
|
+
* IG publishes a segment map for the name, the standard-gap code otherwise, and the standard-gap
|
|
3773
|
+
* code for every name that could not be classified at all.
|
|
3774
|
+
*/
|
|
3775
|
+
issues() {
|
|
3776
|
+
return this.reportable().map(
|
|
3777
|
+
(occurrence) => issue(
|
|
3778
|
+
occurrence.name !== void 0 && isIgMappedSegmentName(occurrence.name) ? ISSUE_CODES.TRANSFORM_SEGMENT_NOT_EMITTED : ISSUE_CODES.TRANSFORM_SEGMENT_NO_IG_MAP,
|
|
3779
|
+
segmentOccurrenceLocation(occurrence)
|
|
3780
|
+
)
|
|
3781
|
+
);
|
|
3782
|
+
}
|
|
3783
|
+
};
|
|
2304
3784
|
var REQUEST_STATUS_MAP = Object.freeze({
|
|
2305
3785
|
AF: "active",
|
|
2306
3786
|
CA: "active",
|
|
@@ -2331,8 +3811,9 @@ var ORDER_INTENT2 = "order";
|
|
|
2331
3811
|
function fieldValue(seg, index) {
|
|
2332
3812
|
return seg === void 0 ? "" : seg.field(index).value;
|
|
2333
3813
|
}
|
|
2334
|
-
function buildServiceRequest(orc, obr, subjectFullUrl, encounterFullUrl, ctx) {
|
|
3814
|
+
function buildServiceRequest(orc, obr, tq1, subjectFullUrl, encounterFullUrl, ctx) {
|
|
2335
3815
|
const issues = [];
|
|
3816
|
+
if (tq1 !== void 0) issues.push(...tq1.issues);
|
|
2336
3817
|
if (orc === void 0 && obr === void 0) return { value: void 0, issues };
|
|
2337
3818
|
const props = [
|
|
2338
3819
|
{ name: "resourceType", value: primitive("ServiceRequest") }
|
|
@@ -2386,8 +3867,16 @@ function buildServiceRequest(orc, obr, subjectFullUrl, encounterFullUrl, ctx) {
|
|
|
2386
3867
|
if (obr !== void 0 && obr.field(6).value !== "") {
|
|
2387
3868
|
const occurrence = toFhirDateTime(obr.field(6).asTs(), ctx.options);
|
|
2388
3869
|
issues.push(...occurrence.issues);
|
|
2389
|
-
if (occurrence.value !== void 0)
|
|
3870
|
+
if (occurrence.value !== void 0 && tq1?.timing === void 0) {
|
|
2390
3871
|
props.push({ name: "occurrenceDateTime", value: primitive(occurrence.value) });
|
|
3872
|
+
} else if (occurrence.value !== void 0) {
|
|
3873
|
+
issues.push(
|
|
3874
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "OBR.6", "ServiceRequest.occurrenceDateTime")
|
|
3875
|
+
);
|
|
3876
|
+
}
|
|
3877
|
+
}
|
|
3878
|
+
if (tq1?.timing !== void 0) {
|
|
3879
|
+
props.push({ name: "occurrenceTiming", value: tq1.timing });
|
|
2391
3880
|
}
|
|
2392
3881
|
if (obr !== void 0 && obr.field(31).value !== "") {
|
|
2393
3882
|
const reason = toFhirCodeableConcept(obr.field(31).asCwe(), ctx);
|
|
@@ -2396,6 +3885,122 @@ function buildServiceRequest(orc, obr, subjectFullUrl, encounterFullUrl, ctx) {
|
|
|
2396
3885
|
}
|
|
2397
3886
|
return { value: complex(props), issues };
|
|
2398
3887
|
}
|
|
3888
|
+
var SPM_SHIPMENT_IDENTIFIER_TYPE = "SHIP";
|
|
3889
|
+
var DEFERRED_SPECIMEN_ROWS = Object.freeze([
|
|
3890
|
+
[3, "Specimen.parent"],
|
|
3891
|
+
[12, "Specimen.collection.quantity"],
|
|
3892
|
+
[20, "Specimen.status"]
|
|
3893
|
+
]);
|
|
3894
|
+
function subcomponent2(spm, field, component3, sub) {
|
|
3895
|
+
return spm.field(field).repetitions[0]?.components[component3 - 1]?.subcomponents[sub - 1] ?? "";
|
|
3896
|
+
}
|
|
3897
|
+
function codeable(spm, field, ctx, issues) {
|
|
3898
|
+
const converted = toFhirCodeableConcept(spm.field(field).asCwe(), ctx);
|
|
3899
|
+
issues.push(...converted.issues);
|
|
3900
|
+
return converted.value;
|
|
3901
|
+
}
|
|
3902
|
+
function identifierFrom(spm, field, ctx, issues) {
|
|
3903
|
+
const converted = toFhirIdentifier(spm.field(field).asCx(), ctx);
|
|
3904
|
+
issues.push(...converted.issues);
|
|
3905
|
+
return converted.value;
|
|
3906
|
+
}
|
|
3907
|
+
function buildIdentifiers(spm, ctx, issues) {
|
|
3908
|
+
const identifiers = [];
|
|
3909
|
+
for (const component3 of [1, 2]) {
|
|
3910
|
+
const entityId = subcomponent2(spm, 2, component3, 1);
|
|
3911
|
+
if (entityId !== "") {
|
|
3912
|
+
identifiers.push(complex([{ name: "value", value: primitive(entityId) }]));
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3915
|
+
const other = identifierFrom(spm, 31, ctx, issues);
|
|
3916
|
+
if (other !== void 0) identifiers.push(other);
|
|
3917
|
+
const shipment = orderIdentifier(spm.field(32).value, SPM_SHIPMENT_IDENTIFIER_TYPE);
|
|
3918
|
+
if (shipment !== void 0) identifiers.push(shipment);
|
|
3919
|
+
return identifiers;
|
|
3920
|
+
}
|
|
3921
|
+
function buildCollection(spm, ctx, issues) {
|
|
3922
|
+
const props = [];
|
|
3923
|
+
const method = codeable(spm, 7, ctx, issues);
|
|
3924
|
+
if (method !== void 0) props.push({ name: "method", value: method });
|
|
3925
|
+
const bodySite = codeable(spm, 8, ctx, issues);
|
|
3926
|
+
if (bodySite !== void 0) props.push({ name: "bodySite", value: bodySite });
|
|
3927
|
+
const start = subcomponent2(spm, 17, 1, 1);
|
|
3928
|
+
const end = subcomponent2(spm, 17, 2, 1);
|
|
3929
|
+
const bounds = [];
|
|
3930
|
+
for (const [raw, name] of [
|
|
3931
|
+
[start, "start"],
|
|
3932
|
+
[end, "end"]
|
|
3933
|
+
]) {
|
|
3934
|
+
if (raw === "") continue;
|
|
3935
|
+
const converted = toFhirDateTime(parseDtm(raw), ctx.options);
|
|
3936
|
+
issues.push(...converted.issues);
|
|
3937
|
+
if (converted.value !== void 0) bounds.push({ name, value: primitive(converted.value) });
|
|
3938
|
+
}
|
|
3939
|
+
if (end !== "" && bounds.length > 0) {
|
|
3940
|
+
props.push({ name: "collectedPeriod", value: complex(bounds) });
|
|
3941
|
+
} else if (bounds[0] !== void 0) {
|
|
3942
|
+
props.push({ name: "collectedDateTime", value: bounds[0].value });
|
|
3943
|
+
}
|
|
3944
|
+
return props.length === 0 ? void 0 : complex(props);
|
|
3945
|
+
}
|
|
3946
|
+
function buildContainer(spm, ctx, issues) {
|
|
3947
|
+
const props = [];
|
|
3948
|
+
const type = codeable(spm, 27, ctx, issues);
|
|
3949
|
+
if (type !== void 0) props.push({ name: "type", value: type });
|
|
3950
|
+
const additive = codeable(spm, 6, ctx, issues);
|
|
3951
|
+
if (additive !== void 0) props.push({ name: "additiveCodeableConcept", value: additive });
|
|
3952
|
+
return props.length === 0 ? void 0 : list([complex(props)]);
|
|
3953
|
+
}
|
|
3954
|
+
function buildDescriptionNotes(spm) {
|
|
3955
|
+
const annotations = [];
|
|
3956
|
+
for (const repetition of spm.field(14).repetitions) {
|
|
3957
|
+
const text2 = repetition.components[0]?.subcomponents[0] ?? "";
|
|
3958
|
+
if (text2 === "") continue;
|
|
3959
|
+
annotations.push(complex([{ name: "text", value: primitive(text2) }]));
|
|
3960
|
+
}
|
|
3961
|
+
return annotations.length === 0 ? void 0 : list(annotations);
|
|
3962
|
+
}
|
|
3963
|
+
function buildSpecimen(spm, subjectFullUrl, ctx) {
|
|
3964
|
+
const issues = [];
|
|
3965
|
+
for (const [field, path] of DEFERRED_SPECIMEN_ROWS) {
|
|
3966
|
+
if (spm.field(field).value !== "") {
|
|
3967
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, `SPM.${String(field)}`, path));
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
const props = [];
|
|
3971
|
+
const identifiers = buildIdentifiers(spm, ctx, issues);
|
|
3972
|
+
if (identifiers.length > 0) props.push({ name: "identifier", value: list(identifiers) });
|
|
3973
|
+
const accession = identifierFrom(spm, 30, ctx, issues);
|
|
3974
|
+
if (accession !== void 0) props.push({ name: "accessionIdentifier", value: accession });
|
|
3975
|
+
const type = codeable(spm, 4, ctx, issues);
|
|
3976
|
+
if (type !== void 0) props.push({ name: "type", value: type });
|
|
3977
|
+
if (subjectFullUrl !== void 0) {
|
|
3978
|
+
props.push({
|
|
3979
|
+
name: "subject",
|
|
3980
|
+
value: complex([{ name: "reference", value: primitive(subjectFullUrl) }])
|
|
3981
|
+
});
|
|
3982
|
+
}
|
|
3983
|
+
if (spm.field(18).value !== "") {
|
|
3984
|
+
const received = toFhirDateTime(spm.field(18).asTs(), ctx.options);
|
|
3985
|
+
issues.push(...received.issues);
|
|
3986
|
+
if (received.value !== void 0) {
|
|
3987
|
+
props.push({ name: "receivedTime", value: primitive(received.value) });
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
const collection = buildCollection(spm, ctx, issues);
|
|
3991
|
+
if (collection !== void 0) props.push({ name: "collection", value: collection });
|
|
3992
|
+
const container = buildContainer(spm, ctx, issues);
|
|
3993
|
+
if (container !== void 0) props.push({ name: "container", value: container });
|
|
3994
|
+
const condition = codeable(spm, 24, ctx, issues);
|
|
3995
|
+
if (condition !== void 0) props.push({ name: "condition", value: list([condition]) });
|
|
3996
|
+
const note = buildDescriptionNotes(spm);
|
|
3997
|
+
if (note !== void 0) props.push({ name: "note", value: note });
|
|
3998
|
+
if (props.every((p) => p.name === "subject")) return { value: void 0, issues };
|
|
3999
|
+
return {
|
|
4000
|
+
value: complex([{ name: "resourceType", value: primitive("Specimen") }, ...props]),
|
|
4001
|
+
issues
|
|
4002
|
+
};
|
|
4003
|
+
}
|
|
2399
4004
|
|
|
2400
4005
|
// src/messages/to-fhir.ts
|
|
2401
4006
|
var IG_MAPPED_ADT_TRIGGERS = /* @__PURE__ */ new Set([
|
|
@@ -2412,9 +4017,12 @@ var IG_MAPPED_ORDER_TRIGGERS = /* @__PURE__ */ new Set(["ORM^O01", "OML^O21"]);
|
|
|
2412
4017
|
var IG_MAPPED_IMMUNIZATION_TRIGGERS = /* @__PURE__ */ new Set(["V04"]);
|
|
2413
4018
|
var IG_MAPPED_APPOINTMENT_TRIGGERS = /* @__PURE__ */ new Set(["S12"]);
|
|
2414
4019
|
var IG_MAPPED_DOCUMENT_TRIGGERS = /* @__PURE__ */ new Set(["T02"]);
|
|
2415
|
-
function
|
|
4020
|
+
function clearsEmitGate(resource) {
|
|
2416
4021
|
const result = resourceType(resource) === "Patient" ? validateResource(resource, { mode: "strict" }) : validateResource(resource, { mode: "lenient", schemas: EMIT_SCHEMAS });
|
|
2417
|
-
|
|
4022
|
+
return result.valid;
|
|
4023
|
+
}
|
|
4024
|
+
function passesEmitGate(resource, v2Location, fhirPath, issues) {
|
|
4025
|
+
if (clearsEmitGate(resource)) return true;
|
|
2418
4026
|
issues.push(issue(ISSUE_CODES.TRANSFORM_RESOURCE_INVALID, v2Location, fhirPath));
|
|
2419
4027
|
return false;
|
|
2420
4028
|
}
|
|
@@ -2453,6 +4061,7 @@ function toFhir(msg, opts = {}) {
|
|
|
2453
4061
|
const namingSystem = opts.namingSystem ?? createNamingSystem();
|
|
2454
4062
|
const ctx = { namingSystem, options: opts };
|
|
2455
4063
|
const ids = new IdAllocator(opts);
|
|
4064
|
+
const reach = new SegmentReachLedger(msg);
|
|
2456
4065
|
const code = msg.meta.messageCode;
|
|
2457
4066
|
const trigger = msg.meta.triggerEvent;
|
|
2458
4067
|
const messageMapGrounded = trigger !== void 0 && (code === "ADT" && IG_MAPPED_ADT_TRIGGERS.has(trigger) || code === "ORU" && IG_MAPPED_ORU_TRIGGERS.has(trigger) || code === "VXU" && IG_MAPPED_IMMUNIZATION_TRIGGERS.has(trigger) || code === "SIU" && IG_MAPPED_APPOINTMENT_TRIGGERS.has(trigger) || code === "MDM" && IG_MAPPED_DOCUMENT_TRIGGERS.has(trigger) || IG_MAPPED_ORDER_TRIGGERS.has(`${code ?? ""}^${trigger}`));
|
|
@@ -2468,16 +4077,20 @@ function toFhir(msg, opts = {}) {
|
|
|
2468
4077
|
if (built.value !== void 0 && passesEmitGate(built.value, "PID", "Patient", issues)) {
|
|
2469
4078
|
patientFullUrl = ids.next();
|
|
2470
4079
|
focalEntries.push({ fullUrl: patientFullUrl, resource: built.value });
|
|
4080
|
+
reach.markFirstOfType("PID");
|
|
2471
4081
|
}
|
|
2472
4082
|
}
|
|
2473
4083
|
let encounterFullUrl;
|
|
4084
|
+
let encounterEntryIndex = -1;
|
|
2474
4085
|
const visitView = msg.visit;
|
|
2475
4086
|
if (visitView !== void 0) {
|
|
2476
4087
|
const built = buildEncounter(visitView, patientFullUrl, ctx);
|
|
2477
4088
|
issues.push(...built.issues);
|
|
2478
4089
|
if (built.value !== void 0 && passesEmitGate(built.value, "PV1", "Encounter", issues)) {
|
|
2479
4090
|
encounterFullUrl = ids.next();
|
|
4091
|
+
encounterEntryIndex = focalEntries.length;
|
|
2480
4092
|
focalEntries.push({ fullUrl: encounterFullUrl, resource: built.value });
|
|
4093
|
+
reach.markFirstOfType("PV1");
|
|
2481
4094
|
}
|
|
2482
4095
|
}
|
|
2483
4096
|
const nextOfKin = msg.nextOfKin();
|
|
@@ -2489,11 +4102,116 @@ function toFhir(msg, opts = {}) {
|
|
|
2489
4102
|
issues.push(...built.issues);
|
|
2490
4103
|
if (built.value !== void 0 && passesEmitGate(built.value, `NK1[${String(i)}]`, "RelatedPerson", issues)) {
|
|
2491
4104
|
focalEntries.push({ fullUrl: ids.next(), resource: built.value });
|
|
4105
|
+
reach.markNthOfType("NK1", i);
|
|
2492
4106
|
}
|
|
2493
4107
|
}
|
|
2494
4108
|
} else if (nextOfKin.length > 0) {
|
|
2495
4109
|
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "NK1", "RelatedPerson.patient"));
|
|
2496
4110
|
}
|
|
4111
|
+
const allergyFullUrls = [];
|
|
4112
|
+
const allergies = collectAllergies(msg);
|
|
4113
|
+
for (let i = 0; i < allergies.length; i++) {
|
|
4114
|
+
const al1 = allergies[i];
|
|
4115
|
+
if (al1 === void 0) continue;
|
|
4116
|
+
const location = `AL1[${String(i)}]`;
|
|
4117
|
+
if (patientFullUrl === void 0) {
|
|
4118
|
+
issues.push(
|
|
4119
|
+
issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, location, "AllergyIntolerance.patient")
|
|
4120
|
+
);
|
|
4121
|
+
continue;
|
|
4122
|
+
}
|
|
4123
|
+
const emitted = emitAllergyIntolerance(
|
|
4124
|
+
al1,
|
|
4125
|
+
patientFullUrl,
|
|
4126
|
+
msg.meta.version,
|
|
4127
|
+
ctx,
|
|
4128
|
+
clearsEmitGate,
|
|
4129
|
+
location
|
|
4130
|
+
);
|
|
4131
|
+
issues.push(...emitted.issues);
|
|
4132
|
+
if (emitted.value === void 0) continue;
|
|
4133
|
+
const url = ids.next();
|
|
4134
|
+
allergyFullUrls.push(url);
|
|
4135
|
+
focalEntries.push({ fullUrl: url, resource: emitted.value });
|
|
4136
|
+
reach.mark(al1);
|
|
4137
|
+
}
|
|
4138
|
+
const conditionFullUrls = [];
|
|
4139
|
+
const diagnoses = collectDiagnoses(msg);
|
|
4140
|
+
for (let i = 0; i < diagnoses.length; i++) {
|
|
4141
|
+
const dg1 = diagnoses[i];
|
|
4142
|
+
if (dg1 === void 0) continue;
|
|
4143
|
+
const location = `DG1[${String(i)}]`;
|
|
4144
|
+
issues.push(...deferredDiagnosisIssues(dg1));
|
|
4145
|
+
if (patientFullUrl === void 0) {
|
|
4146
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, location, "Condition.subject"));
|
|
4147
|
+
continue;
|
|
4148
|
+
}
|
|
4149
|
+
const built = buildCondition(dg1, patientFullUrl, ctx, location);
|
|
4150
|
+
issues.push(...built.issues);
|
|
4151
|
+
if (built.value === void 0) continue;
|
|
4152
|
+
if (!passesEmitGate(built.value, location, "Condition", issues)) continue;
|
|
4153
|
+
const url = ids.next();
|
|
4154
|
+
conditionFullUrls.push(url);
|
|
4155
|
+
focalEntries.push({ fullUrl: url, resource: built.value });
|
|
4156
|
+
reach.mark(dg1);
|
|
4157
|
+
}
|
|
4158
|
+
if (diagnoses.length > 0) {
|
|
4159
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "DG1", "EpisodeOfCare"));
|
|
4160
|
+
}
|
|
4161
|
+
if (conditionFullUrls.length > 0 && encounterEntryIndex >= 0) {
|
|
4162
|
+
const emitted = focalEntries[encounterEntryIndex];
|
|
4163
|
+
if (emitted !== void 0) {
|
|
4164
|
+
const linked = emitEncounterDiagnosis(emitted.resource, conditionFullUrls, clearsEmitGate);
|
|
4165
|
+
issues.push(...linked.issues);
|
|
4166
|
+
if (linked.value !== void 0) {
|
|
4167
|
+
focalEntries[encounterEntryIndex] = { fullUrl: emitted.fullUrl, resource: linked.value };
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
}
|
|
4171
|
+
const procedureFullUrls = [];
|
|
4172
|
+
const procedures = collectProcedures(msg);
|
|
4173
|
+
for (let i = 0; i < procedures.length; i++) {
|
|
4174
|
+
const pr1 = procedures[i];
|
|
4175
|
+
if (pr1 === void 0) continue;
|
|
4176
|
+
const location = `PR1[${String(i)}]`;
|
|
4177
|
+
issues.push(...deferredProcedureIssues(pr1));
|
|
4178
|
+
if (patientFullUrl === void 0) {
|
|
4179
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, location, "Procedure.subject"));
|
|
4180
|
+
continue;
|
|
4181
|
+
}
|
|
4182
|
+
const built = buildProcedure(pr1, patientFullUrl, ctx);
|
|
4183
|
+
issues.push(...built.issues);
|
|
4184
|
+
if (built.value === void 0) continue;
|
|
4185
|
+
if (!passesEmitGate(built.value, location, "Procedure", issues)) continue;
|
|
4186
|
+
const url = ids.next();
|
|
4187
|
+
procedureFullUrls.push(url);
|
|
4188
|
+
focalEntries.push({ fullUrl: url, resource: built.value });
|
|
4189
|
+
reach.mark(pr1);
|
|
4190
|
+
}
|
|
4191
|
+
const coverages = collectCoverages(msg);
|
|
4192
|
+
const visitSegment = msg.allSegments().find((seg) => seg.type === "PV1");
|
|
4193
|
+
if (coverages.length > 0 && visitSegment !== void 0 && visitSegment.field(20).value !== "") {
|
|
4194
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, "PV1.20", "Coverage"));
|
|
4195
|
+
}
|
|
4196
|
+
const coverageFullUrls = [];
|
|
4197
|
+
for (let i = 0; i < coverages.length; i++) {
|
|
4198
|
+
const in1 = coverages[i];
|
|
4199
|
+
if (in1 === void 0) continue;
|
|
4200
|
+
const location = `IN1[${String(i)}]`;
|
|
4201
|
+
issues.push(...deferredCoverageIssues(in1));
|
|
4202
|
+
if (patientFullUrl === void 0) {
|
|
4203
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_ELEMENT_DROPPED, location, "Coverage.beneficiary"));
|
|
4204
|
+
continue;
|
|
4205
|
+
}
|
|
4206
|
+
const built = buildCoverage(in1, patientFullUrl, ctx, location);
|
|
4207
|
+
issues.push(...built.issues);
|
|
4208
|
+
if (built.value === void 0) continue;
|
|
4209
|
+
if (!passesEmitGate(built.value, location, "Coverage", issues)) continue;
|
|
4210
|
+
const url = ids.next();
|
|
4211
|
+
coverageFullUrls.push(url);
|
|
4212
|
+
focalEntries.push({ fullUrl: url, resource: built.value });
|
|
4213
|
+
reach.mark(in1);
|
|
4214
|
+
}
|
|
2497
4215
|
const diagnosticReportFullUrls = [];
|
|
2498
4216
|
if (code === "ORU") {
|
|
2499
4217
|
const { groups, orphanObxCount } = collectReportGroups(msg);
|
|
@@ -2504,28 +4222,54 @@ function toFhir(msg, opts = {}) {
|
|
|
2504
4222
|
const resultFullUrls = [];
|
|
2505
4223
|
const observationEntries = [];
|
|
2506
4224
|
for (let i = 0; i < group.observations.length; i++) {
|
|
2507
|
-
const
|
|
2508
|
-
if (
|
|
2509
|
-
const built = buildObservation(
|
|
4225
|
+
const observation = group.observations[i];
|
|
4226
|
+
if (observation === void 0) continue;
|
|
4227
|
+
const built = buildObservation(
|
|
4228
|
+
observation.obx,
|
|
4229
|
+
patientFullUrl,
|
|
4230
|
+
encounterFullUrl,
|
|
4231
|
+
ctx,
|
|
4232
|
+
observation.notes
|
|
4233
|
+
);
|
|
2510
4234
|
issues.push(...built.issues);
|
|
2511
4235
|
if (built.value !== void 0 && passesEmitGate(built.value, `OBX[${String(i)}]`, "Observation", issues)) {
|
|
2512
4236
|
const url = ids.next();
|
|
2513
4237
|
resultFullUrls.push(url);
|
|
2514
4238
|
observationEntries.push({ fullUrl: url, resource: built.value });
|
|
4239
|
+
reach.mark(observation.obx, ...observation.notes);
|
|
2515
4240
|
}
|
|
2516
4241
|
}
|
|
4242
|
+
const specimenFullUrls = [];
|
|
4243
|
+
const specimenEntries = [];
|
|
4244
|
+
const emittedSpecimens = [];
|
|
4245
|
+
for (let i = 0; i < group.specimens.length; i++) {
|
|
4246
|
+
const spm = group.specimens[i];
|
|
4247
|
+
if (spm === void 0) continue;
|
|
4248
|
+
const built = buildSpecimen(spm, patientFullUrl, ctx);
|
|
4249
|
+
issues.push(...built.issues);
|
|
4250
|
+
if (built.value === void 0) continue;
|
|
4251
|
+
if (!passesEmitGate(built.value, `SPM[${String(i)}]`, "Specimen", issues)) continue;
|
|
4252
|
+
const url = ids.next();
|
|
4253
|
+
specimenFullUrls.push(url);
|
|
4254
|
+
specimenEntries.push({ fullUrl: url, resource: built.value });
|
|
4255
|
+
emittedSpecimens.push(spm);
|
|
4256
|
+
}
|
|
2517
4257
|
const report = buildDiagnosticReport(
|
|
2518
4258
|
group.obr,
|
|
2519
4259
|
resultFullUrls,
|
|
2520
4260
|
patientFullUrl,
|
|
2521
4261
|
encounterFullUrl,
|
|
2522
|
-
ctx
|
|
4262
|
+
ctx,
|
|
4263
|
+
specimenFullUrls
|
|
2523
4264
|
);
|
|
2524
4265
|
issues.push(...report.issues);
|
|
2525
4266
|
if (report.value !== void 0 && passesEmitGate(report.value, "OBR", "DiagnosticReport", issues)) {
|
|
2526
4267
|
const reportUrl = ids.next();
|
|
2527
4268
|
diagnosticReportFullUrls.push(reportUrl);
|
|
2528
4269
|
focalEntries.push({ fullUrl: reportUrl, resource: report.value });
|
|
4270
|
+
reach.mark(group.obr);
|
|
4271
|
+
focalEntries.push(...specimenEntries);
|
|
4272
|
+
reach.mark(...emittedSpecimens);
|
|
2529
4273
|
}
|
|
2530
4274
|
focalEntries.push(...observationEntries);
|
|
2531
4275
|
}
|
|
@@ -2538,9 +4282,11 @@ function toFhir(msg, opts = {}) {
|
|
|
2538
4282
|
}
|
|
2539
4283
|
for (const group of groups) {
|
|
2540
4284
|
if (group.obr !== void 0 || group.orc !== void 0 && group.rxo === void 0) {
|
|
4285
|
+
const tq1 = readTq1(group.tq1s, "ServiceRequest", ctx);
|
|
2541
4286
|
const built = buildServiceRequest(
|
|
2542
4287
|
group.orc,
|
|
2543
4288
|
group.obr,
|
|
4289
|
+
tq1,
|
|
2544
4290
|
patientFullUrl,
|
|
2545
4291
|
encounterFullUrl,
|
|
2546
4292
|
ctx
|
|
@@ -2551,13 +4297,16 @@ function toFhir(msg, opts = {}) {
|
|
|
2551
4297
|
const url = ids.next();
|
|
2552
4298
|
orderResourceFullUrls.push(url);
|
|
2553
4299
|
focalEntries.push({ fullUrl: url, resource: built.value });
|
|
4300
|
+
reach.mark(group.orc, group.obr, tq1.contributes ? group.tq1s[0] : void 0);
|
|
2554
4301
|
}
|
|
2555
4302
|
}
|
|
2556
4303
|
if (group.rxo !== void 0) {
|
|
4304
|
+
const tq1 = readTq1(group.tq1s, "MedicationRequest", ctx);
|
|
2557
4305
|
const built = buildMedicationRequest(
|
|
2558
4306
|
group.rxo,
|
|
2559
4307
|
group.rxrs[0],
|
|
2560
4308
|
group.orc,
|
|
4309
|
+
tq1,
|
|
2561
4310
|
patientFullUrl,
|
|
2562
4311
|
encounterFullUrl,
|
|
2563
4312
|
ctx
|
|
@@ -2567,6 +4316,12 @@ function toFhir(msg, opts = {}) {
|
|
|
2567
4316
|
const url = ids.next();
|
|
2568
4317
|
orderResourceFullUrls.push(url);
|
|
2569
4318
|
focalEntries.push({ fullUrl: url, resource: built.value });
|
|
4319
|
+
reach.mark(
|
|
4320
|
+
group.rxo,
|
|
4321
|
+
group.rxrs[0],
|
|
4322
|
+
group.orc,
|
|
4323
|
+
tq1.contributes ? group.tq1s[0] : void 0
|
|
4324
|
+
);
|
|
2570
4325
|
}
|
|
2571
4326
|
}
|
|
2572
4327
|
}
|
|
@@ -2587,6 +4342,7 @@ function toFhir(msg, opts = {}) {
|
|
|
2587
4342
|
const url = ids.next();
|
|
2588
4343
|
immunizationFullUrls.push(url);
|
|
2589
4344
|
focalEntries.push({ fullUrl: url, resource: built.value });
|
|
4345
|
+
reach.mark(group.rxa, group.rxr, group.orc);
|
|
2590
4346
|
}
|
|
2591
4347
|
}
|
|
2592
4348
|
for (const seg of msg.allSegments()) {
|
|
@@ -2595,6 +4351,7 @@ function toFhir(msg, opts = {}) {
|
|
|
2595
4351
|
issues.push(...built.issues);
|
|
2596
4352
|
if (built.value !== void 0 && passesEmitGate(built.value, "OBX", "Observation", issues)) {
|
|
2597
4353
|
focalEntries.push({ fullUrl: ids.next(), resource: built.value });
|
|
4354
|
+
reach.mark(seg);
|
|
2598
4355
|
}
|
|
2599
4356
|
}
|
|
2600
4357
|
}
|
|
@@ -2608,6 +4365,7 @@ function toFhir(msg, opts = {}) {
|
|
|
2608
4365
|
const url = ids.next();
|
|
2609
4366
|
appointmentFullUrls.push(url);
|
|
2610
4367
|
focalEntries.push({ fullUrl: url, resource: built.value });
|
|
4368
|
+
reach.mark(sch, ais);
|
|
2611
4369
|
}
|
|
2612
4370
|
}
|
|
2613
4371
|
}
|
|
@@ -2621,12 +4379,17 @@ function toFhir(msg, opts = {}) {
|
|
|
2621
4379
|
const url = ids.next();
|
|
2622
4380
|
documentFullUrls.push(url);
|
|
2623
4381
|
focalEntries.push({ fullUrl: url, resource: built.value });
|
|
4382
|
+
reach.mark(txa, ...obxs);
|
|
2624
4383
|
}
|
|
2625
4384
|
}
|
|
2626
4385
|
}
|
|
2627
4386
|
const focus = [
|
|
2628
4387
|
patientFullUrl,
|
|
2629
4388
|
encounterFullUrl,
|
|
4389
|
+
...allergyFullUrls,
|
|
4390
|
+
...conditionFullUrls,
|
|
4391
|
+
...procedureFullUrls,
|
|
4392
|
+
...coverageFullUrls,
|
|
2630
4393
|
...diagnosticReportFullUrls,
|
|
2631
4394
|
...orderResourceFullUrls,
|
|
2632
4395
|
...immunizationFullUrls,
|
|
@@ -2638,15 +4401,713 @@ function toFhir(msg, opts = {}) {
|
|
|
2638
4401
|
const entries = [];
|
|
2639
4402
|
if (header.value !== void 0 && passesEmitGate(header.value, "MSH", "MessageHeader", issues)) {
|
|
2640
4403
|
entries.push({ fullUrl: ids.next(), resource: header.value });
|
|
4404
|
+
reach.markFirstOfType("MSH");
|
|
2641
4405
|
}
|
|
2642
4406
|
entries.push(...focalEntries);
|
|
2643
4407
|
const bundle = buildBundle(msg, entries, ctx, issues);
|
|
4408
|
+
issues.push(...reach.issues());
|
|
2644
4409
|
return { bundle, issues };
|
|
2645
4410
|
}
|
|
4411
|
+
function itemsOf(node) {
|
|
4412
|
+
if (node === void 0) return [];
|
|
4413
|
+
return isList(node) ? node.items : [node];
|
|
4414
|
+
}
|
|
4415
|
+
function at(node, name) {
|
|
4416
|
+
return getProperty(node, name);
|
|
4417
|
+
}
|
|
4418
|
+
function readString(node, location, fhirPath, issues) {
|
|
4419
|
+
if (node === void 0) return void 0;
|
|
4420
|
+
if (!isPrimitive(node) || typeof node.value !== "string") {
|
|
4421
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_RESOURCE_MALFORMED, location, fhirPath));
|
|
4422
|
+
return void 0;
|
|
4423
|
+
}
|
|
4424
|
+
return node.value === "" ? void 0 : node.value;
|
|
4425
|
+
}
|
|
4426
|
+
function readStrings(node, location, fhirPath, issues) {
|
|
4427
|
+
const out = [];
|
|
4428
|
+
for (const item of itemsOf(node)) {
|
|
4429
|
+
const value = readString(item, location, fhirPath, issues);
|
|
4430
|
+
if (value !== void 0) out.push(value);
|
|
4431
|
+
}
|
|
4432
|
+
return out;
|
|
4433
|
+
}
|
|
4434
|
+
function readComplexes(node, location, fhirPath, issues) {
|
|
4435
|
+
const out = [];
|
|
4436
|
+
for (const item of itemsOf(node)) {
|
|
4437
|
+
if (isComplex(item)) out.push(item);
|
|
4438
|
+
else issues.push(issue(ISSUE_CODES.TRANSFORM_RESOURCE_MALFORMED, location, fhirPath));
|
|
4439
|
+
}
|
|
4440
|
+
return out;
|
|
4441
|
+
}
|
|
4442
|
+
function readNumberText(node, location, fhirPath, issues) {
|
|
4443
|
+
if (node === void 0) return void 0;
|
|
4444
|
+
const value = isPrimitive(node) ? node.value : void 0;
|
|
4445
|
+
if (value === void 0 || typeof value === "boolean") {
|
|
4446
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_RESOURCE_MALFORMED, location, fhirPath));
|
|
4447
|
+
return void 0;
|
|
4448
|
+
}
|
|
4449
|
+
return typeof value === "string" ? value : value.raw;
|
|
4450
|
+
}
|
|
4451
|
+
|
|
4452
|
+
// src/reverse/v2.ts
|
|
4453
|
+
function component2(value) {
|
|
4454
|
+
return { subcomponents: value === void 0 || value === "" ? [] : [value] };
|
|
4455
|
+
}
|
|
4456
|
+
function v2Field(repetitions) {
|
|
4457
|
+
const present = repetitions.filter(
|
|
4458
|
+
(components) => components.some((value) => value !== void 0 && value !== "")
|
|
4459
|
+
);
|
|
4460
|
+
if (present.length === 0) return void 0;
|
|
4461
|
+
return {
|
|
4462
|
+
isNull: false,
|
|
4463
|
+
repetitions: present.map((components) => {
|
|
4464
|
+
let last = components.length;
|
|
4465
|
+
while (last > 0 && (components[last - 1] === void 0 || components[last - 1] === ""))
|
|
4466
|
+
last--;
|
|
4467
|
+
return { components: components.slice(0, last).map(component2) };
|
|
4468
|
+
})
|
|
4469
|
+
};
|
|
4470
|
+
}
|
|
4471
|
+
function segmentFields(byPosition) {
|
|
4472
|
+
const positions = [...byPosition.keys()];
|
|
4473
|
+
const highest = positions.length === 0 ? 0 : Math.max(...positions);
|
|
4474
|
+
const out = [];
|
|
4475
|
+
for (let position = 1; position <= highest; position++) {
|
|
4476
|
+
out.push(byPosition.get(position) ?? "");
|
|
4477
|
+
}
|
|
4478
|
+
return out;
|
|
4479
|
+
}
|
|
4480
|
+
var FHIR_DATETIME = /^(\d{4})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})(\.\d{1,4})?(Z|[+-]\d{2}:\d{2}))?)?)?$/;
|
|
4481
|
+
function v2Timestamp(value) {
|
|
4482
|
+
const parts = FHIR_DATETIME.exec(value);
|
|
4483
|
+
if (parts === null) return void 0;
|
|
4484
|
+
const [, year, month, day, hour, minute, second, fraction, zone] = parts;
|
|
4485
|
+
let out = year ?? "";
|
|
4486
|
+
if (month !== void 0) out += month;
|
|
4487
|
+
if (day !== void 0) out += day;
|
|
4488
|
+
if (hour === void 0) return out;
|
|
4489
|
+
out += `${hour}${minute ?? ""}${second ?? ""}${fraction ?? ""}`;
|
|
4490
|
+
return out + (zone === "Z" ? "+0000" : (zone ?? "").replace(":", ""));
|
|
4491
|
+
}
|
|
4492
|
+
function v2Date(value) {
|
|
4493
|
+
return value.includes("T") ? void 0 : v2Timestamp(value);
|
|
4494
|
+
}
|
|
4495
|
+
var V2_NUMBER = /^-?(0|[1-9]\d*)(\.\d+)?$/;
|
|
4496
|
+
function v2Number(raw) {
|
|
4497
|
+
return V2_NUMBER.test(raw) ? raw : void 0;
|
|
4498
|
+
}
|
|
4499
|
+
function invertCodeMap(forward) {
|
|
4500
|
+
const sources = /* @__PURE__ */ new Map();
|
|
4501
|
+
for (const [v2Code, fhirCode] of Object.entries(forward)) {
|
|
4502
|
+
const seen = sources.get(fhirCode);
|
|
4503
|
+
if (seen === void 0) sources.set(fhirCode, [v2Code]);
|
|
4504
|
+
else seen.push(v2Code);
|
|
4505
|
+
}
|
|
4506
|
+
const inverse = {};
|
|
4507
|
+
for (const [fhirCode, v2Codes] of sources) {
|
|
4508
|
+
const only = v2Codes[0];
|
|
4509
|
+
if (v2Codes.length === 1 && only !== void 0) inverse[fhirCode] = only;
|
|
4510
|
+
}
|
|
4511
|
+
return Object.freeze(inverse);
|
|
4512
|
+
}
|
|
4513
|
+
|
|
4514
|
+
// src/reverse/coding.ts
|
|
4515
|
+
function reverseContext(options = {}) {
|
|
4516
|
+
const mnemonics = invertCodeMap({ ...DEFAULT_V2_CODE_SYSTEMS, ...options.codeSystems });
|
|
4517
|
+
const authorities = options.assigningAuthorities ?? {};
|
|
4518
|
+
return {
|
|
4519
|
+
mnemonicFor: (system) => Object.hasOwn(mnemonics, system) ? mnemonics[system] : void 0,
|
|
4520
|
+
namespaceFor: (system) => Object.hasOwn(authorities, system) ? authorities[system] : void 0,
|
|
4521
|
+
envelope: options.envelope ?? {}
|
|
4522
|
+
};
|
|
4523
|
+
}
|
|
4524
|
+
function readCoding(coding2, ctx, location, fhirPath, issues) {
|
|
4525
|
+
const code = readString(at(coding2, "code"), location, `${fhirPath}.code`, issues);
|
|
4526
|
+
const display = readString(at(coding2, "display"), location, `${fhirPath}.display`, issues);
|
|
4527
|
+
const system = readString(at(coding2, "system"), location, `${fhirPath}.system`, issues);
|
|
4528
|
+
if (code === void 0) return void 0;
|
|
4529
|
+
const mnemonic = system === void 0 ? void 0 : ctx.mnemonicFor(system);
|
|
4530
|
+
if (mnemonic === void 0) {
|
|
4531
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_SYSTEM_NOT_V2, location, `${fhirPath}.system`));
|
|
4532
|
+
return void 0;
|
|
4533
|
+
}
|
|
4534
|
+
return { code, display, mnemonic };
|
|
4535
|
+
}
|
|
4536
|
+
function codeableToCwe(concept, ctx, location, fhirPath, issues) {
|
|
4537
|
+
const codings = [];
|
|
4538
|
+
for (const coding2 of readComplexes(
|
|
4539
|
+
at(concept, "coding"),
|
|
4540
|
+
location,
|
|
4541
|
+
`${fhirPath}.coding`,
|
|
4542
|
+
issues
|
|
4543
|
+
)) {
|
|
4544
|
+
const read = readCoding(coding2, ctx, location, `${fhirPath}.coding`, issues);
|
|
4545
|
+
if (read !== void 0) codings.push(read);
|
|
4546
|
+
}
|
|
4547
|
+
const text2 = readString(at(concept, "text"), location, `${fhirPath}.text`, issues);
|
|
4548
|
+
if (codings.length === 0 && text2 === void 0) return void 0;
|
|
4549
|
+
if (codings.length > 2) {
|
|
4550
|
+
issues.push(
|
|
4551
|
+
issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, location, `${fhirPath}.coding`)
|
|
4552
|
+
);
|
|
4553
|
+
}
|
|
4554
|
+
const primary = codings[0];
|
|
4555
|
+
const alternate = codings[1];
|
|
4556
|
+
return [
|
|
4557
|
+
primary?.code,
|
|
4558
|
+
primary?.display,
|
|
4559
|
+
primary?.mnemonic,
|
|
4560
|
+
alternate?.code,
|
|
4561
|
+
alternate?.display,
|
|
4562
|
+
alternate?.mnemonic,
|
|
4563
|
+
void 0,
|
|
4564
|
+
void 0,
|
|
4565
|
+
text2
|
|
4566
|
+
];
|
|
4567
|
+
}
|
|
4568
|
+
function codeInSystem(concept, system, location, fhirPath, issues) {
|
|
4569
|
+
let found;
|
|
4570
|
+
let foreign = false;
|
|
4571
|
+
for (const coding2 of readComplexes(
|
|
4572
|
+
at(concept, "coding"),
|
|
4573
|
+
location,
|
|
4574
|
+
`${fhirPath}.coding`,
|
|
4575
|
+
issues
|
|
4576
|
+
)) {
|
|
4577
|
+
const codingSystem = readString(at(coding2, "system"), location, `${fhirPath}.system`, issues);
|
|
4578
|
+
const code = readString(at(coding2, "code"), location, `${fhirPath}.code`, issues);
|
|
4579
|
+
if (code === void 0) continue;
|
|
4580
|
+
if (codingSystem === system) found ??= code;
|
|
4581
|
+
else foreign = true;
|
|
4582
|
+
}
|
|
4583
|
+
if (found === void 0 && foreign) {
|
|
4584
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_SYSTEM_NOT_V2, location, `${fhirPath}.system`));
|
|
4585
|
+
}
|
|
4586
|
+
return found;
|
|
4587
|
+
}
|
|
4588
|
+
var NAMED_RESOURCES = /* @__PURE__ */ new Set([
|
|
4589
|
+
"Appointment",
|
|
4590
|
+
"Bundle",
|
|
4591
|
+
"DiagnosticReport",
|
|
4592
|
+
"DocumentReference",
|
|
4593
|
+
"Encounter",
|
|
4594
|
+
"Immunization",
|
|
4595
|
+
"MedicationRequest",
|
|
4596
|
+
"MessageHeader",
|
|
4597
|
+
"Observation",
|
|
4598
|
+
"OperationOutcome",
|
|
4599
|
+
"Patient",
|
|
4600
|
+
"RelatedPerson",
|
|
4601
|
+
"ServiceRequest"
|
|
4602
|
+
]);
|
|
4603
|
+
function isNonEmptyString(value) {
|
|
4604
|
+
return typeof value === "string" && value.trim() !== "";
|
|
4605
|
+
}
|
|
4606
|
+
var BARE_TRIGGER = /^[^\s|^~\\&\r\n]+$/;
|
|
4607
|
+
function hasTrigger(trigger, issues) {
|
|
4608
|
+
if (!isNonEmptyString(trigger)) {
|
|
4609
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_MISSING_TRIGGER, "MSH.9.2", "trigger"));
|
|
4610
|
+
return false;
|
|
4611
|
+
}
|
|
4612
|
+
if (!BARE_TRIGGER.test(trigger)) {
|
|
4613
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, "MSH.9.2", "trigger"));
|
|
4614
|
+
return false;
|
|
4615
|
+
}
|
|
4616
|
+
return true;
|
|
4617
|
+
}
|
|
4618
|
+
function readResource(input, expected, location, issues) {
|
|
4619
|
+
if (!isComplex(input)) {
|
|
4620
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_RESOURCE_MALFORMED, location, "Resource"));
|
|
4621
|
+
return void 0;
|
|
4622
|
+
}
|
|
4623
|
+
const type = resourceType(input);
|
|
4624
|
+
if (type === void 0) {
|
|
4625
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_RESOURCE_MALFORMED, location, "Resource.resourceType"));
|
|
4626
|
+
return void 0;
|
|
4627
|
+
}
|
|
4628
|
+
if (type !== expected) {
|
|
4629
|
+
const named = NAMED_RESOURCES.has(type) ? type : "Resource";
|
|
4630
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_UNSUPPORTED_RESOURCE, location, named));
|
|
4631
|
+
return void 0;
|
|
4632
|
+
}
|
|
4633
|
+
return input;
|
|
4634
|
+
}
|
|
4635
|
+
function flagUnmapped(resource, mapped, targets, resourceName, segment, issues) {
|
|
4636
|
+
for (const property of resource.properties) {
|
|
4637
|
+
if (mapped.has(property.name)) continue;
|
|
4638
|
+
const known = Object.hasOwn(targets, property.name);
|
|
4639
|
+
issues.push(
|
|
4640
|
+
issue(
|
|
4641
|
+
ISSUE_CODES.TRANSFORM_NO_V2_TARGET,
|
|
4642
|
+
known ? targets[property.name] ?? segment : segment,
|
|
4643
|
+
known ? `${resourceName}.${property.name}` : resourceName
|
|
4644
|
+
)
|
|
4645
|
+
);
|
|
4646
|
+
}
|
|
4647
|
+
}
|
|
4648
|
+
function emitMessage(shape, trigger, byPosition, ctx, issues) {
|
|
4649
|
+
if (byPosition.size === 0) {
|
|
4650
|
+
issues.push(
|
|
4651
|
+
issue(ISSUE_CODES.TRANSFORM_NO_V2_MESSAGE_EMITTED, shape.segment, shape.resourceName)
|
|
4652
|
+
);
|
|
4653
|
+
return void 0;
|
|
4654
|
+
}
|
|
4655
|
+
for (const field of shape.required) {
|
|
4656
|
+
if (byPosition.has(field.position)) continue;
|
|
4657
|
+
issues.push(
|
|
4658
|
+
issue(ISSUE_CODES.TRANSFORM_V2_REQUIRED_FIELD_ABSENT, field.location, field.fhirPath)
|
|
4659
|
+
);
|
|
4660
|
+
}
|
|
4661
|
+
return buildMessage({ ...ctx.envelope, type: `${shape.messageCode}^${trigger}` }).addSegment(
|
|
4662
|
+
shape.segment,
|
|
4663
|
+
segmentFields(byPosition)
|
|
4664
|
+
);
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4667
|
+
// src/reverse/patient.ts
|
|
4668
|
+
var GENDER_TO_V2 = invertCodeMap(ADMINISTRATIVE_GENDER_MAP);
|
|
4669
|
+
var NAME_USE_TO_V2 = invertCodeMap(NAME_USE_MAP);
|
|
4670
|
+
var ADDRESS_USE_TO_V2 = invertCodeMap(ADDRESS_USE_MAP);
|
|
4671
|
+
var PATIENT_MAPPED = /* @__PURE__ */ new Set([
|
|
4672
|
+
"resourceType",
|
|
4673
|
+
"identifier",
|
|
4674
|
+
"name",
|
|
4675
|
+
"birthDate",
|
|
4676
|
+
"gender",
|
|
4677
|
+
"address"
|
|
4678
|
+
]);
|
|
4679
|
+
var PID_REQUIRED = [
|
|
4680
|
+
// PID-3 Patient Identifier List, v2.5.1 item 00106.
|
|
4681
|
+
{ position: 3, location: "PID.3", fhirPath: "Patient.identifier" },
|
|
4682
|
+
// PID-5 Patient Name, v2.5.1 item 00108.
|
|
4683
|
+
{ position: 5, location: "PID.5", fhirPath: "Patient.name" }
|
|
4684
|
+
];
|
|
4685
|
+
var PATIENT_SHAPE = {
|
|
4686
|
+
messageCode: "ADT",
|
|
4687
|
+
segment: "PID",
|
|
4688
|
+
resourceName: "Patient",
|
|
4689
|
+
required: PID_REQUIRED
|
|
4690
|
+
};
|
|
4691
|
+
var PATIENT_UNMAPPED = Object.freeze({
|
|
4692
|
+
telecom: "PID.13",
|
|
4693
|
+
communication: "PID.15",
|
|
4694
|
+
maritalStatus: "PID.16",
|
|
4695
|
+
multipleBirthBoolean: "PID.24",
|
|
4696
|
+
multipleBirthInteger: "PID.25",
|
|
4697
|
+
deceasedDateTime: "PID.29",
|
|
4698
|
+
deceasedBoolean: "PID.30",
|
|
4699
|
+
contact: "NK1"
|
|
4700
|
+
});
|
|
4701
|
+
function invertible(inverse, code, location, fhirPath, issues) {
|
|
4702
|
+
if (Object.hasOwn(inverse, code)) return inverse[code];
|
|
4703
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_NOT_INVERTIBLE, location, fhirPath));
|
|
4704
|
+
return void 0;
|
|
4705
|
+
}
|
|
4706
|
+
function identifierComponents(identifier, ctx, issues) {
|
|
4707
|
+
const value = readString(at(identifier, "value"), "CX.1", "Patient.identifier.value", issues);
|
|
4708
|
+
if (value === void 0) {
|
|
4709
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_NO_V2_TARGET, "CX.1", "Patient.identifier"));
|
|
4710
|
+
return void 0;
|
|
4711
|
+
}
|
|
4712
|
+
const system = readString(at(identifier, "system"), "CX.4", "Patient.identifier.system", issues);
|
|
4713
|
+
let namespace;
|
|
4714
|
+
if (system !== void 0) {
|
|
4715
|
+
namespace = ctx.namespaceFor(system);
|
|
4716
|
+
if (namespace === void 0) {
|
|
4717
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_NO_V2_TARGET, "CX.4", "Patient.identifier.system"));
|
|
4718
|
+
}
|
|
4719
|
+
}
|
|
4720
|
+
const typeConcept = readComplexes(
|
|
4721
|
+
at(identifier, "type"),
|
|
4722
|
+
"CX.5",
|
|
4723
|
+
"Patient.identifier.type",
|
|
4724
|
+
issues
|
|
4725
|
+
)[0];
|
|
4726
|
+
const typeCode = typeConcept === void 0 ? void 0 : codeInSystem(typeConcept, V2_0203_SYSTEM, "CX.5", "Patient.identifier.type", issues);
|
|
4727
|
+
return [value, void 0, void 0, namespace, typeCode];
|
|
4728
|
+
}
|
|
4729
|
+
function nameComponents(name, issues) {
|
|
4730
|
+
const family = readString(at(name, "family"), "XPN.1", "Patient.name.family", issues);
|
|
4731
|
+
const given = readStrings(at(name, "given"), "XPN.2", "Patient.name.given", issues);
|
|
4732
|
+
const prefix = readStrings(at(name, "prefix"), "XPN.5", "Patient.name.prefix", issues);
|
|
4733
|
+
const suffix = readStrings(at(name, "suffix"), "XPN.4", "Patient.name.suffix", issues);
|
|
4734
|
+
const use = readString(at(name, "use"), "XPN.7", "Patient.name.use", issues);
|
|
4735
|
+
if (given.length > 2) {
|
|
4736
|
+
issues.push(
|
|
4737
|
+
issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, "XPN.3", "Patient.name.given")
|
|
4738
|
+
);
|
|
4739
|
+
}
|
|
4740
|
+
if (prefix.length > 1) {
|
|
4741
|
+
issues.push(
|
|
4742
|
+
issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, "XPN.5", "Patient.name.prefix")
|
|
4743
|
+
);
|
|
4744
|
+
}
|
|
4745
|
+
if (suffix.length > 1) {
|
|
4746
|
+
issues.push(
|
|
4747
|
+
issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, "XPN.4", "Patient.name.suffix")
|
|
4748
|
+
);
|
|
4749
|
+
}
|
|
4750
|
+
const nameType = use === void 0 ? void 0 : invertible(NAME_USE_TO_V2, use, "XPN.7", "Patient.name.use", issues);
|
|
4751
|
+
return [family, given[0], given[1], suffix[0], prefix[0], void 0, nameType];
|
|
4752
|
+
}
|
|
4753
|
+
function addressComponents(address, issues) {
|
|
4754
|
+
const line = readStrings(at(address, "line"), "XAD.1", "Patient.address.line", issues);
|
|
4755
|
+
const city = readString(at(address, "city"), "XAD.3", "Patient.address.city", issues);
|
|
4756
|
+
const state = readString(at(address, "state"), "XAD.4", "Patient.address.state", issues);
|
|
4757
|
+
const postal = readString(
|
|
4758
|
+
at(address, "postalCode"),
|
|
4759
|
+
"XAD.5",
|
|
4760
|
+
"Patient.address.postalCode",
|
|
4761
|
+
issues
|
|
4762
|
+
);
|
|
4763
|
+
const country = readString(at(address, "country"), "XAD.6", "Patient.address.country", issues);
|
|
4764
|
+
const district = readString(at(address, "district"), "XAD.9", "Patient.address.district", issues);
|
|
4765
|
+
const use = readString(at(address, "use"), "XAD.7", "Patient.address.use", issues);
|
|
4766
|
+
const type = readString(at(address, "type"), "XAD.7", "Patient.address.type", issues);
|
|
4767
|
+
if (line.length > 2) {
|
|
4768
|
+
issues.push(
|
|
4769
|
+
issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, "XAD.2", "Patient.address.line")
|
|
4770
|
+
);
|
|
4771
|
+
}
|
|
4772
|
+
const addressType = use === void 0 ? void 0 : invertible(ADDRESS_USE_TO_V2, use, "XAD.7", "Patient.address.use", issues);
|
|
4773
|
+
if (type !== void 0) {
|
|
4774
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_NOT_INVERTIBLE, "XAD.7", "Patient.address.type"));
|
|
4775
|
+
}
|
|
4776
|
+
return [line[0], line[1], city, state, postal, country, addressType, void 0, district];
|
|
4777
|
+
}
|
|
4778
|
+
function pidFields(patient, ctx, issues) {
|
|
4779
|
+
const fields = /* @__PURE__ */ new Map();
|
|
4780
|
+
const identifiers = [];
|
|
4781
|
+
for (const identifier of readComplexes(
|
|
4782
|
+
at(patient, "identifier"),
|
|
4783
|
+
"PID.3",
|
|
4784
|
+
"Patient.identifier",
|
|
4785
|
+
issues
|
|
4786
|
+
)) {
|
|
4787
|
+
const components = identifierComponents(identifier, ctx, issues);
|
|
4788
|
+
if (components !== void 0) identifiers.push(components);
|
|
4789
|
+
}
|
|
4790
|
+
const pid3 = v2Field(identifiers);
|
|
4791
|
+
if (pid3 !== void 0) fields.set(3, pid3);
|
|
4792
|
+
const names = readComplexes(at(patient, "name"), "PID.5", "Patient.name", issues).map(
|
|
4793
|
+
(name) => nameComponents(name, issues)
|
|
4794
|
+
);
|
|
4795
|
+
const pid5 = v2Field(names);
|
|
4796
|
+
if (pid5 !== void 0) fields.set(5, pid5);
|
|
4797
|
+
const birthDate = readString(at(patient, "birthDate"), "PID.7", "Patient.birthDate", issues);
|
|
4798
|
+
if (birthDate !== void 0) {
|
|
4799
|
+
const dtm = v2Date(birthDate);
|
|
4800
|
+
if (dtm === void 0) {
|
|
4801
|
+
issues.push(
|
|
4802
|
+
issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, "PID.7", "Patient.birthDate")
|
|
4803
|
+
);
|
|
4804
|
+
} else {
|
|
4805
|
+
const pid7 = v2Field([[dtm]]);
|
|
4806
|
+
if (pid7 !== void 0) fields.set(7, pid7);
|
|
4807
|
+
}
|
|
4808
|
+
}
|
|
4809
|
+
const gender = readString(at(patient, "gender"), "PID.8", "Patient.gender", issues);
|
|
4810
|
+
const sex = gender === void 0 ? void 0 : invertible(GENDER_TO_V2, gender, "PID.8", "Patient.gender", issues);
|
|
4811
|
+
const pid8 = sex === void 0 ? void 0 : v2Field([[sex]]);
|
|
4812
|
+
if (pid8 !== void 0) fields.set(8, pid8);
|
|
4813
|
+
const addresses = readComplexes(at(patient, "address"), "PID.11", "Patient.address", issues).map(
|
|
4814
|
+
(address) => addressComponents(address, issues)
|
|
4815
|
+
);
|
|
4816
|
+
const pid11 = v2Field(addresses);
|
|
4817
|
+
if (pid11 !== void 0) fields.set(11, pid11);
|
|
4818
|
+
return fields;
|
|
4819
|
+
}
|
|
4820
|
+
function toV2Patient(resource, trigger, options = {}) {
|
|
4821
|
+
const issues = [];
|
|
4822
|
+
const triggerOk = hasTrigger(trigger, issues);
|
|
4823
|
+
const patient = readResource(resource, "Patient", "PID", issues);
|
|
4824
|
+
if (!triggerOk || patient === void 0) return { value: void 0, issues };
|
|
4825
|
+
flagUnmapped(patient, PATIENT_MAPPED, PATIENT_UNMAPPED, "Patient", "PID", issues);
|
|
4826
|
+
const ctx = reverseContext(options);
|
|
4827
|
+
const fields = pidFields(patient, ctx, issues);
|
|
4828
|
+
const value = emitMessage(PATIENT_SHAPE, trigger, fields, ctx, issues);
|
|
4829
|
+
return { value, issues };
|
|
4830
|
+
}
|
|
4831
|
+
|
|
4832
|
+
// src/reverse/observation.ts
|
|
4833
|
+
var OBSERVATION_STATUS_TO_V2 = invertCodeMap(OBSERVATION_STATUS_MAP);
|
|
4834
|
+
var SN_COMPARATORS2 = /* @__PURE__ */ new Set(["<", "<=", ">=", ">"]);
|
|
4835
|
+
var OBSERVATION_MAPPED = /* @__PURE__ */ new Set([
|
|
4836
|
+
"resourceType",
|
|
4837
|
+
"code",
|
|
4838
|
+
"status",
|
|
4839
|
+
"effectiveDateTime",
|
|
4840
|
+
"interpretation",
|
|
4841
|
+
"referenceRange",
|
|
4842
|
+
"valueQuantity",
|
|
4843
|
+
"valueCodeableConcept",
|
|
4844
|
+
"valueString",
|
|
4845
|
+
"valueDateTime"
|
|
4846
|
+
]);
|
|
4847
|
+
var OBX_REQUIRED = [
|
|
4848
|
+
// OBX-3 Observation Identifier. UNREACHABLE TODAY BY CONSTRUCTION, and kept
|
|
4849
|
+
// anyway: `obxFields` returns no field at all when it cannot build OBX-3, so an
|
|
4850
|
+
// emitted OBX always carries one and this row can only fire if that early return
|
|
4851
|
+
// is ever relaxed. It guards the next edit rather than changing this one.
|
|
4852
|
+
{ position: 3, location: "OBX.3", fhirPath: "Observation.code" },
|
|
4853
|
+
// OBX-11 Observation Result Status.
|
|
4854
|
+
{ position: 11, location: "OBX.11", fhirPath: "Observation.status" }
|
|
4855
|
+
];
|
|
4856
|
+
var OBSERVATION_SHAPE = {
|
|
4857
|
+
messageCode: "ORU",
|
|
4858
|
+
segment: "OBX",
|
|
4859
|
+
resourceName: "Observation",
|
|
4860
|
+
required: OBX_REQUIRED
|
|
4861
|
+
};
|
|
4862
|
+
var OBSERVATION_UNMAPPED = Object.freeze({
|
|
4863
|
+
valueBoolean: "OBX.5",
|
|
4864
|
+
valueInteger: "OBX.5",
|
|
4865
|
+
valueRange: "OBX.5",
|
|
4866
|
+
valueRatio: "OBX.5",
|
|
4867
|
+
valueTime: "OBX.5",
|
|
4868
|
+
valuePeriod: "OBX.5",
|
|
4869
|
+
valueSampledData: "OBX.5",
|
|
4870
|
+
valueAttachment: "OBX.5",
|
|
4871
|
+
dataAbsentReason: "OBX.5",
|
|
4872
|
+
effectivePeriod: "OBX.14",
|
|
4873
|
+
effectiveInstant: "OBX.14",
|
|
4874
|
+
issued: "OBX.19",
|
|
4875
|
+
performer: "OBX.16",
|
|
4876
|
+
method: "OBX.17",
|
|
4877
|
+
specimen: "OBX.18",
|
|
4878
|
+
device: "OBX.18",
|
|
4879
|
+
bodySite: "OBX.20",
|
|
4880
|
+
identifier: "OBX.21",
|
|
4881
|
+
note: "NTE",
|
|
4882
|
+
subject: "PID",
|
|
4883
|
+
encounter: "PV1",
|
|
4884
|
+
basedOn: "OBR",
|
|
4885
|
+
category: "OBR",
|
|
4886
|
+
component: "OBX",
|
|
4887
|
+
hasMember: "OBX",
|
|
4888
|
+
derivedFrom: "OBX"
|
|
4889
|
+
});
|
|
4890
|
+
function unitComponents(quantity, ctx, issues) {
|
|
4891
|
+
const unit = readString(at(quantity, "unit"), "OBX.6", "Observation.valueQuantity.unit", issues);
|
|
4892
|
+
const code = readString(at(quantity, "code"), "OBX.6", "Observation.valueQuantity.code", issues);
|
|
4893
|
+
const system = readString(
|
|
4894
|
+
at(quantity, "system"),
|
|
4895
|
+
"OBX.6",
|
|
4896
|
+
"Observation.valueQuantity.system",
|
|
4897
|
+
issues
|
|
4898
|
+
);
|
|
4899
|
+
const mnemonic = system === void 0 ? void 0 : ctx.mnemonicFor(system);
|
|
4900
|
+
if (code !== void 0 && mnemonic !== void 0) return [code, unit, mnemonic];
|
|
4901
|
+
if (code !== void 0) {
|
|
4902
|
+
issues.push(
|
|
4903
|
+
issue(ISSUE_CODES.TRANSFORM_CODE_SYSTEM_NOT_V2, "OBX.6", "Observation.valueQuantity.system")
|
|
4904
|
+
);
|
|
4905
|
+
}
|
|
4906
|
+
return unit === void 0 ? void 0 : [void 0, unit];
|
|
4907
|
+
}
|
|
4908
|
+
function quantityValue(quantity, ctx, issues) {
|
|
4909
|
+
const raw = readNumberText(
|
|
4910
|
+
at(quantity, "value"),
|
|
4911
|
+
"OBX.5",
|
|
4912
|
+
"Observation.valueQuantity.value",
|
|
4913
|
+
issues
|
|
4914
|
+
);
|
|
4915
|
+
const magnitude = raw === void 0 ? void 0 : v2Number(raw);
|
|
4916
|
+
if (magnitude === void 0) {
|
|
4917
|
+
if (raw !== void 0) {
|
|
4918
|
+
issues.push(
|
|
4919
|
+
issue(
|
|
4920
|
+
ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE,
|
|
4921
|
+
"OBX.5",
|
|
4922
|
+
"Observation.valueQuantity.value"
|
|
4923
|
+
)
|
|
4924
|
+
);
|
|
4925
|
+
}
|
|
4926
|
+
return void 0;
|
|
4927
|
+
}
|
|
4928
|
+
const units = unitComponents(quantity, ctx, issues);
|
|
4929
|
+
const comparator = readString(
|
|
4930
|
+
at(quantity, "comparator"),
|
|
4931
|
+
"OBX.5",
|
|
4932
|
+
"Observation.valueQuantity.comparator",
|
|
4933
|
+
issues
|
|
4934
|
+
);
|
|
4935
|
+
if (comparator === void 0) return { valueType: "NM", value: [magnitude], units };
|
|
4936
|
+
if (!SN_COMPARATORS2.has(comparator)) {
|
|
4937
|
+
issues.push(
|
|
4938
|
+
issue(
|
|
4939
|
+
ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE,
|
|
4940
|
+
"OBX.5",
|
|
4941
|
+
"Observation.valueQuantity.comparator"
|
|
4942
|
+
)
|
|
4943
|
+
);
|
|
4944
|
+
return void 0;
|
|
4945
|
+
}
|
|
4946
|
+
return { valueType: "SN", value: [comparator, magnitude], units };
|
|
4947
|
+
}
|
|
4948
|
+
function observationValue(observation, ctx, issues) {
|
|
4949
|
+
const quantity = readComplexes(
|
|
4950
|
+
at(observation, "valueQuantity"),
|
|
4951
|
+
"OBX.5",
|
|
4952
|
+
"Observation.valueQuantity",
|
|
4953
|
+
issues
|
|
4954
|
+
)[0];
|
|
4955
|
+
if (quantity !== void 0) return quantityValue(quantity, ctx, issues);
|
|
4956
|
+
const concept = readComplexes(
|
|
4957
|
+
at(observation, "valueCodeableConcept"),
|
|
4958
|
+
"OBX.5",
|
|
4959
|
+
"Observation.valueCodeableConcept",
|
|
4960
|
+
issues
|
|
4961
|
+
)[0];
|
|
4962
|
+
if (concept !== void 0) {
|
|
4963
|
+
const cwe = codeableToCwe(concept, ctx, "OBX.5", "Observation.valueCodeableConcept", issues);
|
|
4964
|
+
return cwe === void 0 ? void 0 : { valueType: "CWE", value: cwe, units: void 0 };
|
|
4965
|
+
}
|
|
4966
|
+
const text2 = readString(
|
|
4967
|
+
at(observation, "valueString"),
|
|
4968
|
+
"OBX.5",
|
|
4969
|
+
"Observation.valueString",
|
|
4970
|
+
issues
|
|
4971
|
+
);
|
|
4972
|
+
if (text2 !== void 0) return { valueType: "ST", value: [text2], units: void 0 };
|
|
4973
|
+
const instant = readString(
|
|
4974
|
+
at(observation, "valueDateTime"),
|
|
4975
|
+
"OBX.5",
|
|
4976
|
+
"Observation.valueDateTime",
|
|
4977
|
+
issues
|
|
4978
|
+
);
|
|
4979
|
+
if (instant !== void 0) {
|
|
4980
|
+
const dtm = v2Timestamp(instant);
|
|
4981
|
+
if (dtm === void 0) {
|
|
4982
|
+
issues.push(
|
|
4983
|
+
issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, "OBX.5", "Observation.valueDateTime")
|
|
4984
|
+
);
|
|
4985
|
+
return void 0;
|
|
4986
|
+
}
|
|
4987
|
+
return { valueType: "DTM", value: [dtm], units: void 0 };
|
|
4988
|
+
}
|
|
4989
|
+
return void 0;
|
|
4990
|
+
}
|
|
4991
|
+
function interpretationField(observation, issues) {
|
|
4992
|
+
const flags = [];
|
|
4993
|
+
for (const concept of readComplexes(
|
|
4994
|
+
at(observation, "interpretation"),
|
|
4995
|
+
"OBX.8",
|
|
4996
|
+
"Observation.interpretation",
|
|
4997
|
+
issues
|
|
4998
|
+
)) {
|
|
4999
|
+
const code = codeInSystem(
|
|
5000
|
+
concept,
|
|
5001
|
+
V3_OBSERVATION_INTERPRETATION_SYSTEM,
|
|
5002
|
+
"OBX.8",
|
|
5003
|
+
"Observation.interpretation",
|
|
5004
|
+
issues
|
|
5005
|
+
);
|
|
5006
|
+
if (code === void 0) continue;
|
|
5007
|
+
if (HL70078_INTERPRETATION_CODES.has(code)) flags.push([code]);
|
|
5008
|
+
else {
|
|
5009
|
+
issues.push(
|
|
5010
|
+
issue(ISSUE_CODES.TRANSFORM_CODE_NOT_INVERTIBLE, "OBX.8", "Observation.interpretation")
|
|
5011
|
+
);
|
|
5012
|
+
}
|
|
5013
|
+
}
|
|
5014
|
+
return v2Field(flags);
|
|
5015
|
+
}
|
|
5016
|
+
function referenceRangeField(observation, issues) {
|
|
5017
|
+
const ranges = readComplexes(
|
|
5018
|
+
at(observation, "referenceRange"),
|
|
5019
|
+
"OBX.7",
|
|
5020
|
+
"Observation.referenceRange",
|
|
5021
|
+
issues
|
|
5022
|
+
);
|
|
5023
|
+
if (ranges.length > 1) {
|
|
5024
|
+
issues.push(
|
|
5025
|
+
issue(ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE, "OBX.7", "Observation.referenceRange")
|
|
5026
|
+
);
|
|
5027
|
+
}
|
|
5028
|
+
const first = ranges[0];
|
|
5029
|
+
if (first === void 0) return void 0;
|
|
5030
|
+
const text2 = readString(at(first, "text"), "OBX.7", "Observation.referenceRange.text", issues);
|
|
5031
|
+
if (text2 === void 0) {
|
|
5032
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_NO_V2_TARGET, "OBX.7", "Observation.referenceRange"));
|
|
5033
|
+
return void 0;
|
|
5034
|
+
}
|
|
5035
|
+
return v2Field([[text2]]);
|
|
5036
|
+
}
|
|
5037
|
+
function obxFields(observation, ctx, issues) {
|
|
5038
|
+
const fields = /* @__PURE__ */ new Map();
|
|
5039
|
+
const concept = readComplexes(at(observation, "code"), "OBX.3", "Observation.code", issues)[0];
|
|
5040
|
+
if (concept === void 0) {
|
|
5041
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_RESOURCE_MALFORMED, "OBX.3", "Observation.code"));
|
|
5042
|
+
return fields;
|
|
5043
|
+
}
|
|
5044
|
+
const cwe = codeableToCwe(concept, ctx, "OBX.3", "Observation.code", issues);
|
|
5045
|
+
const obx3 = cwe === void 0 ? void 0 : v2Field([cwe]);
|
|
5046
|
+
if (obx3 === void 0) return fields;
|
|
5047
|
+
fields.set(3, obx3);
|
|
5048
|
+
const value = observationValue(observation, ctx, issues);
|
|
5049
|
+
if (value !== void 0) {
|
|
5050
|
+
const obx2 = v2Field([[value.valueType]]);
|
|
5051
|
+
const obx5 = v2Field([value.value]);
|
|
5052
|
+
if (obx2 !== void 0 && obx5 !== void 0) {
|
|
5053
|
+
fields.set(2, obx2);
|
|
5054
|
+
fields.set(5, obx5);
|
|
5055
|
+
}
|
|
5056
|
+
const obx6 = value.units === void 0 ? void 0 : v2Field([value.units]);
|
|
5057
|
+
if (obx6 !== void 0) fields.set(6, obx6);
|
|
5058
|
+
}
|
|
5059
|
+
const referenceRange = referenceRangeField(observation, issues);
|
|
5060
|
+
if (referenceRange !== void 0) fields.set(7, referenceRange);
|
|
5061
|
+
const interpretation = interpretationField(observation, issues);
|
|
5062
|
+
if (interpretation !== void 0) fields.set(8, interpretation);
|
|
5063
|
+
const status = readString(at(observation, "status"), "OBX.11", "Observation.status", issues);
|
|
5064
|
+
if (status !== void 0) {
|
|
5065
|
+
const code = Object.hasOwn(OBSERVATION_STATUS_TO_V2, status) ? OBSERVATION_STATUS_TO_V2[status] : void 0;
|
|
5066
|
+
if (code === void 0) {
|
|
5067
|
+
issues.push(issue(ISSUE_CODES.TRANSFORM_CODE_NOT_INVERTIBLE, "OBX.11", "Observation.status"));
|
|
5068
|
+
} else {
|
|
5069
|
+
const obx11 = v2Field([[code]]);
|
|
5070
|
+
if (obx11 !== void 0) fields.set(11, obx11);
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
const effective = readString(
|
|
5074
|
+
at(observation, "effectiveDateTime"),
|
|
5075
|
+
"OBX.14",
|
|
5076
|
+
"Observation.effectiveDateTime",
|
|
5077
|
+
issues
|
|
5078
|
+
);
|
|
5079
|
+
if (effective !== void 0) {
|
|
5080
|
+
const dtm = v2Timestamp(effective);
|
|
5081
|
+
if (dtm === void 0) {
|
|
5082
|
+
issues.push(
|
|
5083
|
+
issue(
|
|
5084
|
+
ISSUE_CODES.TRANSFORM_VALUE_NOT_REPRESENTABLE,
|
|
5085
|
+
"OBX.14",
|
|
5086
|
+
"Observation.effectiveDateTime"
|
|
5087
|
+
)
|
|
5088
|
+
);
|
|
5089
|
+
} else {
|
|
5090
|
+
const obx14 = v2Field([[dtm]]);
|
|
5091
|
+
if (obx14 !== void 0) fields.set(14, obx14);
|
|
5092
|
+
}
|
|
5093
|
+
}
|
|
5094
|
+
return fields;
|
|
5095
|
+
}
|
|
5096
|
+
function toV2Observation(resource, trigger, options = {}) {
|
|
5097
|
+
const issues = [];
|
|
5098
|
+
const triggerOk = hasTrigger(trigger, issues);
|
|
5099
|
+
const observation = readResource(resource, "Observation", "OBX", issues);
|
|
5100
|
+
if (!triggerOk || observation === void 0) return { value: void 0, issues };
|
|
5101
|
+
flagUnmapped(observation, OBSERVATION_MAPPED, OBSERVATION_UNMAPPED, "Observation", "OBX", issues);
|
|
5102
|
+
const ctx = reverseContext(options);
|
|
5103
|
+
const fields = obxFields(observation, ctx, issues);
|
|
5104
|
+
const value = emitMessage(OBSERVATION_SHAPE, trigger, fields, ctx, issues);
|
|
5105
|
+
return { value, issues };
|
|
5106
|
+
}
|
|
2646
5107
|
|
|
2647
5108
|
// src/index.ts
|
|
2648
|
-
var VERSION = "0.
|
|
5109
|
+
var VERSION = "0.1.1";
|
|
2649
5110
|
|
|
2650
|
-
export { ADDRESS_TYPE_MAP, ADDRESS_USE_MAP, ADMINISTRATIVE_GENDER_MAP, APPOINTMENT_STATUS_MAP, APPOINTMENT_TYPE_VALUE_MAP, DEFAULT_V2_CODE_SYSTEMS, DIAGNOSTIC_REPORT_STATUS_MAP, ENCOUNTER_CLASS_V3_MAP, ENCOUNTER_STATUS_MAP, FATAL_CODES, HL70078_INTERPRETATION_CODES, IG_MAPPED_ADT_TRIGGERS, IG_MAPPED_APPOINTMENT_TRIGGERS, IG_MAPPED_DOCUMENT_TRIGGERS, IG_MAPPED_IMMUNIZATION_TRIGGERS, IG_MAPPED_ORDER_TRIGGERS, IG_MAPPED_ORU_TRIGGERS, IMMUNIZATION_STATUS_MAP, ISSUE_CODES, ISSUE_REGISTRY, NAME_USE_MAP, OBSERVATION_STATUS_MAP, REQUEST_STATUS_MAP, ROUTE_VALUE_MAP, SERVICE_REQUEST_PRIORITY_MAP, SITE_VALUE_MAP, SUBSTITUTION_VALUE_MAP, TRANSFORM_ISSUE_SYSTEM, V2_0161_SYSTEM, V2_0162_SYSTEM, V2_0203_SYSTEM, V2_0277_SYSTEM, V2_0550_SYSTEM, V3_ROUTE_OF_ADMINISTRATION_SYSTEM, VERSION, codeableConceptFromTarget, createNamingSystem, fhirIssueTypeFor, issue, toFhir, toFhirAddress, toFhirCodeableConcept, toFhirCodeableConceptVia, toFhirDateTime, toFhirHumanName, toFhirIdentifier, toFhirQuantity, toOperationOutcome, translateBound };
|
|
5111
|
+
export { ADDRESS_TYPE_MAP, ADDRESS_USE_MAP, ADDRESS_USE_TO_V2, ADMINISTRATIVE_GENDER_MAP, AL1_ONSET_WITHDRAWN_AT, ALLERGY_CATEGORY_VALUE_MAP, ALLERGY_CLINICAL_STATUS_CODE, ALLERGY_CLINICAL_STATUS_SYSTEM, ALLERGY_CRITICALITY_VALUE_MAP, ALLERGY_INTOLERANCE_CATEGORY_SYSTEM, ALLERGY_INTOLERANCE_CRITICALITY_SYSTEM, ALLERGY_INTOLERANCE_TYPE_SYSTEM, ALLERGY_ORIGINAL_CATEGORY_VALUE_MAP, ALLERGY_ORIGINAL_CRITICALITY_VALUE_MAP, ALLERGY_TYPE_VALUE_MAP, ALTERNATE_CODES_EXTENSION_URL, APPOINTMENT_STATUS_MAP, APPOINTMENT_TYPE_VALUE_MAP, CONDITION_ENTERED_IN_ERROR, CONDITION_VERIFICATION_STATUS_SYSTEM, COVERAGE_STATUS_UNKNOWN, COVERAGE_SUBSCRIBER_ID_EXTENSION_URL, DEFAULT_V2_CODE_SYSTEMS, DG1_RETRACTION_ACTION_CODE, DIAGNOSTIC_REPORT_STATUS_MAP, ED_BASE64_ENCODING, ENCOUNTER_CLASS_V3_MAP, ENCOUNTER_STATUS_MAP, FATAL_CODES, GENDER_TO_V2, HL70078_INTERPRETATION_CODES, IG_ALLERGY_VALUE_MAPS_PUBLISHED, IG_ALLERGY_VALUE_MAPS_RETRIEVED, IG_ALLERGY_VALUE_MAPS_SOURCE, IG_ALLERGY_VALUE_MAPS_VERSION, IG_MAPPED_ADT_TRIGGERS, IG_MAPPED_APPOINTMENT_TRIGGERS, IG_MAPPED_DOCUMENT_TRIGGERS, IG_MAPPED_IMMUNIZATION_TRIGGERS, IG_MAPPED_ORDER_TRIGGERS, IG_MAPPED_ORU_TRIGGERS, IG_MAPPED_SEGMENT_NAMES, IG_SEGMENT_MAPS_PUBLISHED, IG_SEGMENT_MAPS_RETRIEVED, IG_SEGMENT_MAPS_SOURCE, IG_SEGMENT_MAPS_VERSION, IMMUNIZATION_STATUS_MAP, IN1_SUBSCRIBER_NUMBER_TYPE, ISSUE_CODES, ISSUE_REGISTRY, NAME_USE_MAP, NAME_USE_TO_V2, OBSERVATION_STATUS_MAP, OBSERVATION_STATUS_TO_V2, OBSERVATION_VALUE_ATTACHMENT_EXTENSION_URL, PROCEDURE_STATUS_UNKNOWN, REQUEST_STATUS_MAP, ROUTE_VALUE_MAP, SAMPLED_DATA_ABSENT_POINT, SAMPLED_DATA_UNGROUNDED, SEGMENT_IDENTIFIER_SHAPE, SERVICE_REQUEST_PRIORITY_MAP, SITE_VALUE_MAP, SPM_SHIPMENT_IDENTIFIER_TYPE, SUBSTITUTION_VALUE_MAP, SegmentReachLedger, TRANSFORM_ISSUE_SYSTEM, V2_0127_SYSTEM, V2_0128_SYSTEM, V2_0161_SYSTEM, V2_0162_SYSTEM, V2_0203_SYSTEM, V2_0277_SYSTEM, V2_0550_SYSTEM, V3_OBSERVATION_INTERPRETATION_SYSTEM, V3_ROUTE_OF_ADMINISTRATION_SYSTEM, VERSION, addMinutes, buildAnnotations, buildCondition, buildCoverage, buildProcedure, buildSpecimen, carriesLegacyOnsetDate, codeableConceptFromTarget, collectAllergies, collectCoverages, collectDiagnoses, collectProcedures, createNamingSystem, deferredCoverageIssues, deferredDiagnosisIssues, deferredProcedureIssues, emitEncounterDiagnosis, enumerateSegmentOccurrences, fhirIssueTypeFor, insuranceCompanyName, invertCodeMap, isIgMappedSegmentName, isWellFormedSegmentName, issue, segmentOccurrenceLocation, toFhir, toFhirAddress, toFhirCodeableConcept, toFhirCodeableConceptVia, toFhirDateTime, toFhirEntityIdentifier, toFhirHumanName, toFhirIdentifier, toFhirQuantity, toOperationOutcome, toV2Observation, toV2Patient, translateBound, withCodeableText, withEncounterDiagnosis };
|
|
2651
5112
|
//# sourceMappingURL=index.mjs.map
|
|
2652
5113
|
//# sourceMappingURL=index.mjs.map
|