Handle FHIR, X12, C-CDA, JSON and text
A channel's format says how its transform receives each message. The message is stored as it
arrived; it is parsed in the channel's worker, right before the transform runs.
format | The transform receives | Type |
|---|---|---|
hl7v2 (default) | an Hl7Message from @cosyte/hl7 | TransformFor<"hl7v2"> |
fhir | a FHIR R4 resource from @cosyte/fhir's JSON reader | TransformFor<"fhir"> |
x12 | an X12Interchange from @cosyte/x12 | TransformFor<"x12"> |
ccda | a CcdaDocument from @cosyte/ccda | TransformFor<"ccda"> |
json | the value JSON.parse returns | TransformFor<"json"> |
text | the body as a string | TransformFor<"text"> |
FHIR, X12, C-CDA and JSON are read as UTF-8, and a body that is not valid UTF-8 fails to parse rather
than being changed in silence. text turns bytes that are not UTF-8 into U+FFFD. A json body with a
number that a JavaScript number cannot hold exactly (a long id, say) fails with INEXACT_JSON_NUMBER
rather than being rounded; use text to pass it through untouched.
A message that does not parse is marked failed with the parser's stable code, such as
NO_MSH_SEGMENT or X12_NO_ISA_HEADER, and the transform never sees it.
MLLP carries HL7 v2 only, so a channel with an MLLP source or destination keeps format: hl7v2.
Read a FHIR resource
import { resourceType } from "@cosyte/fhir";
import type { TransformFor } from "@cosyte/pathways";
// Patients go on; any other resource is filtered out.
export default ((resource) =>
resourceType(resource) === "Patient" ? resource : null) satisfies TransformFor<"fhir">;
The resource is @cosyte/fhir's immutable model, which keeps every decimal exactly as written. To
call a library's helpers, install it in the project (npm install @cosyte/fhir).
Read an X12 interchange
import type { TransformFor } from "@cosyte/pathways";
// Only interchanges that carry a claim group (GS-01 HC) go on.
export default ((interchange) =>
interchange.groups.some((group) => group.gs.elements[1] === "HC")
? interchange
: null) satisfies TransformFor<"x12">;
Turn one format into another
What a transform returns is written back like this, whatever the channel's format:
- a string is sent as it is, in UTF-8;
- bytes (a
Uint8Array, which aBufferis) are sent exactly as they are, so a body in another character set, such as Latin-1, or a binary one keeps its bytes; - a model from
@cosyte/hl7,@cosyte/fhir,@cosyte/x12or@cosyte/ccdais written by its own library; - on a
jsonchannel, a plain object, an array, a number or a boolean is written withJSON.stringify.
So a transform can take one format in and send another out. This one turns an HL7 v2 admission into a FHIR Patient:
import type { Transform } from "@cosyte/pathways";
export default ((msg) => {
if (!msg.is("ADT^A01")) return null;
const patient = {
resourceType: "Patient",
identifier: [{ value: msg.get("PID.3.1") }],
name: [{ family: msg.get("PID.5.1"), given: [msg.get("PID.5.2")] }],
};
return JSON.stringify(patient);
}) satisfies Transform;
The channel's format still names what comes in, and so it sets the file extension a file destination
writes and the Content-Type an HTTP destination sends. Set the header for what goes out:
format: hl7v2
source:
file: { dir: ../../data/adt-to-fhir/in }
transform: ./transform.ts
destinations:
- http:
url: https://fhir.example.com/Patient
headers:
Content-Type: application/fhir+json
Authorization: { env: FHIR_SERVER_AUTH }
Related
- Transform and filter messages.
- The libraries' own docs: HL7 v2, FHIR, X12 and C-CDA.
- Reference:
MessageTypesandTransformFor.