Skip to main content
Version: v0.1.0

Guides

Task-oriented recipes for @cosyte/transform. Each is a short, copy-pasteable answer to one real transformation question. A guide is written only once the behavior it documents is shipped and its runnable example passes the doc/code-agreement check.

Resolve an assigning authority​

A patient identifier's assigning authority (HD) is resolved through a NamingSystem registry. The registry auto-derives a system URI only for the two unambiguous cases: a valid OID with universalIdType: "ISO" (urn:oid:…) and a valid UUID (urn:uuid:…), and otherwise consults the entries you seed. A bare namespace mnemonic (HD.1) is never turned into a URI on its own.

import { createNamingSystem } from "@cosyte/transform";

const registry = createNamingSystem({
authorities: { HOSPMRN: "urn:oid:1.2.840.114350.1.13.1" },
});

registry.resolveAssigningAuthority({ namespaceId: "HOSPMRN" }); // => "urn:oid:1.2.840.114350.1.13.1"

Supply a sender's timezone for naked timestamps​

By default a v2 timestamp with a time-of-day but no offset is reduced to date precision (FHIR forbids time without a zone). If you know the sending system's offset, assert it, and the value is emitted with that offset and flagged as sender-asserted, never inferred:

import { toFhirDateTime } from "@cosyte/transform";
import { parseDtm } from "@cosyte/hl7";

toFhirDateTime(parseDtm("20260721143000"), { assumeTimezoneOffsetMinutes: -300 });
// => { value: "2026-07-21T14:30:00-05:00", issues: [ TRANSFORM_TIMESTAMP_NO_TIMEZONE ] }

Emit a v2 message from a FHIR resource​

The reverse path is narrow on purpose: a Patient becomes an ADT-shaped message carrying a PID, an Observation becomes an ORU-shaped message carrying an OBX. You supply the trigger. No FHIR resource carries an HL7 v2 message trigger, so there is nothing to infer one from, and an absent one returns no message plus a TRANSFORM_MISSING_TRIGGER diagnostic.

import { toV2Patient, ISSUE_CODES } from "@cosyte/transform";
import { parseResource } from "@cosyte/fhir";

const { resource } = parseResource('{"resourceType":"Patient","gender":"female"}');

const emitted = toV2Patient(resource, "A28");
emitted.value?.toString().includes("ADT^A28"); // => true

const refused = toV2Patient(resource, "");
refused.value; // => undefined
refused.issues[0]?.code === ISSUE_CODES.TRANSFORM_MISSING_TRIGGER; // => true

The direction is lossy by design and not a round-trip. The mapping guide runs v2 to FHIR, and several of its rows are many-to-one, so their inverse is ambiguous: gender other could have come from three different v2 codes, so it is refused rather than resolved to one of them.

import { toV2Patient, ISSUE_CODES } from "@cosyte/transform";
import { parseResource } from "@cosyte/fhir";

const { resource } = parseResource('{"resourceType":"Patient","gender":"other"}');
const { issues } = toV2Patient(resource, "A28");

issues[0]?.code === ISSUE_CODES.TRANSFORM_CODE_NOT_INVERTIBLE; // => true
issues[0]?.v2Location; // => "PID.8"

The same rule covers what v2 requires and your resource does not carry. A PID needs PID-3 (Patient Identifier List) and PID-5 (Patient Name); an OBX needs OBX-11 (Observation Result Status). None of them has a safe default, so the field is left absent rather than padded with an invented value, and its absence is reported: check the issues before you send the message.

import { toV2Patient, ISSUE_CODES } from "@cosyte/transform";
import { parseResource } from "@cosyte/fhir";

const { resource } = parseResource('{"resourceType":"Patient","identifier":[{"value":"MRN1"}]}');
const { value, issues } = toV2Patient(resource, "A28");

// The message is emitted, with the required name field absent rather than fabricated.
value?.toString().includes("PID|||MRN1"); // => true
issues[0]?.code === ISSUE_CODES.TRANSFORM_V2_REQUIRED_FIELD_ABSENT; // => true
issues[0]?.v2Location; // => "PID.5"

If nothing in the resource grounds a single field of the target segment, there is no message at all, and that is reported too rather than returned as an empty success.

import { toV2Patient, ISSUE_CODES } from "@cosyte/transform";
import { parseResource } from "@cosyte/fhir";

const { resource } = parseResource('{"resourceType":"Patient"}');
const { value, issues } = toV2Patient(resource, "A28");

value; // => undefined
issues[0]?.code === ISSUE_CODES.TRANSFORM_NO_V2_MESSAGE_EMITTED; // => true

Planned guides​

Not yet written: assembling a full Patient/Encounter/Observation graph from a message, applying a BYO ConceptMap for local codes, and targeting US Core profiles.