Skip to main content
Version: v0.0.3

@cosyte/transform

Public entry point for @cosyte/transform - the HL7 v2 → FHIR R4 transformation library.

@cosyte/transform is not a parser; it is a consumer one tier above the parser suite. It takes already-parsed @cosyte/hl7 composites and produces validated @cosyte/fhir model nodes, grounded on the official HL7 Version 2 to FHIR Implementation Guide (hl7.fhir.uv.v2mappings, STU Edition 1). Its whole promise is narrow and honest: IG-grounded, fail-safe transformation with typed, value-free diagnostics - never a confident wrong FHIR value.

This module ships the six safety-critical datatype converters, the immutable OperationOutcome-shaped diagnostic channel and the NamingSystem resolver they consult, the message-level assembly - HL7 v2 ADT → FHIR Patient + Encounter, the ORU^R01 → DiagnosticReport + Observation results graph, the order-entry graph (ORM_O01 / OML_O21 → ServiceRequest and RXO → MedicationRequest), and the thin IG singles (VXU_V04 → Immunization, SIU_S12 → Appointment, MDM_T02 → DocumentReference), all through toFhir(msg) - and the terminology value-translation layer: a $translate-shaped toFhirCodeableConceptVia engine applying the license-clean IG value ConceptMaps to the previously structural-only coded fields (route/site, appointment type, order priority, substitution). Terminology depth beyond these maps, profiles, and the reverse FHIR → v2 direction are not implemented.

Interfaces

CodedTarget

A translated FHIR target coding: the target CodeSystem URI + code, and the IG's target display.

Properties

code

readonly code: string

The FHIR target code.

display?

readonly optional display?: string

The IG map's target display, when it carries one (absent for the identity table maps).

system

readonly system: string

The FHIR target CodeSystem canonical URI.


CodedValueMap

A license-clean v2-table → FHIR value ConceptMap: it translates a source table code to its CodedTarget, or undefined when the code is not in the map's mapped group (the IG's (unmapped) group). Never fabricates a target.

Properties

name

readonly name: string

The IG ConceptMap id this map transcribes (its citation).

sourceMnemonics

readonly sourceMnemonics: ReadonlySet<string>

The CWE.3 (nameOfCodingSystem) mnemonics that denote this map's bound source table - the HL7 forms ("HL70162", "0162", …). Translation applies only when the field's primary coding is from the bound table: CWE.3 absent/empty (a positionally-bound bare code) or CWE.3 ∈ this set. A CWE that declares a different coding system (a local 99…, or SNOMED) is not a source-table code, so the map is not applied to it - the raw coding is carried structurally + its system flagged, never asserted as the standard concept.

sourceSystem

readonly sourceSystem: string

The source table's canonical CodeSystem URI (what the raw v2 code is a member of when mapped).

translate

readonly translate: (code) => CodedTarget | undefined

Translate a source table code to its FHIR target, or undefined when the IG map has no target.

Parameters
code

string

Returns

CodedTarget | undefined


ConvertResult

The result of one datatype conversion: the produced FHIR value (or undefined when the input was empty or un-emittable) plus the diagnostics raised.

Example

import { toFhirHumanName } from "@cosyte/transform";
const { value, issues } = toFhirHumanName({ familyName: "Public" });
// value is a FHIR HumanName node; issues is [] here
void value;
void issues;

Type Parameters

T

T

The produced FHIR value's type (a FhirComplex datatype node, or a lexical string for dateTime).

Properties

issues

readonly issues: readonly TransformIssue[]

The value-free diagnostics raised during the conversion, in emission order.

value

readonly value: T | undefined

The produced FHIR value, or undefined when nothing could be safely emitted.


NamingSystemRegistry

The resolver consulted by the identity- and code-conversion paths.

Properties

resolveAssigningAuthority

readonly resolveAssigningAuthority: (hd) => string | undefined

Resolve an assigning authority (HD) to a FHIR Identifier.system URI, or undefined when it cannot be resolved safely. Never synthesizes a URI from HD.1 alone.

Parameters
hd

HD

Returns

string | undefined

resolveCodeSystem

readonly resolveCodeSystem: (mnemonic) => string | undefined

Resolve a v2 coding-system mnemonic to a canonical URI, or undefined when unrecognized.

Parameters
mnemonic

string

Returns

string | undefined


NamingSystemSeed

A seed for createNamingSystem: extra coding systems and explicit assigning authorities.

Properties

authorities?

readonly optional authorities?: Readonly<Record<string, string>>

Explicit assigning-authority entries, keyed by HD.1 namespace mnemonic and/or HD.2 universal ID (OID) → the Identifier.system URI. This is the safe, caller-vetted path the IG calls for; the registry never derives a system from a mnemonic on its own.

codeSystems?

readonly optional codeSystems?: Readonly<Record<string, string>>

Extra v2 coding-system mnemonic → canonical URI entries (merged over the defaults).


TransformContext

The context a converter consults. Carries the NamingSystemRegistry used to resolve an assigning authority (HD) to an Identifier.system and a v2 coding-system mnemonic to a canonical URI, plus the TransformOptions.

Properties

namingSystem?

readonly optional namingSystem?: NamingSystemRegistry

The registry used to resolve HD → system and v2 mnemonic → canonical URI.

options?

readonly optional options?: TransformOptions

Conversion policy.


TransformIssue

A single value-free diagnostic.

Example

import { ISSUE_CODES } from "@cosyte/transform";
// issue.code === ISSUE_CODES.TRANSFORM_TIMESTAMP_NO_TIMEZONE
// issue.v2Location === "TS.1"; issue.fhirPath === "dateTime"

Properties

code

readonly code: IssueCode

The stable code. One of ISSUE_CODES.

fhirPath?

readonly optional fhirPath?: string

The FHIR path this issue concerns (e.g. Identifier.system), when applicable.

message

readonly message: string

A static, value-free description drawn from ISSUE_REGISTRY.

severity

readonly severity: TransformSeverity

The OperationOutcome-style severity, fixed per code.

v2Location

readonly v2Location: string

The v2 source location - a segment / field / component index, never a value.


TransformOptions

Caller/profile policy for a conversion.

Remarks

assumeTimezoneOffsetMinutes is the only way a naked v2 timestamp acquires a time-of-day in FHIR: the caller asserts the sender's offset (in minutes east of UTC - e.g. -300 for US Eastern standard time). It is a sender-asserted value, flagged as such; absent it, a naked timestamp is reduced to date precision, never assumed to be UTC.

Properties

assumeTimezoneOffsetMinutes?

readonly optional assumeTimezoneOffsetMinutes?: number

The sender's UTC offset in minutes, asserted by the caller to resolve naked timestamps.

generateId?

readonly optional generateId?: () => string

Allocator for the urn:uuid: Bundle.entry.fullUrl / reference identities the assembler mints. Defaults to crypto.randomUUID. Inject a deterministic generator to make bundle output reproducible (e.g. for golden fixtures). It must return a fresh, unique value per call - the assembler relies on uniqueness for intra-bundle reference integrity.

Returns

string

namingSystem?

readonly optional namingSystem?: NamingSystemRegistry

The NamingSystemRegistry the message-level transform threads into every datatype conversion (HD → Identifier.system, v2 mnemonic → canonical URI). When omitted, a default registry (createNamingSystem()) is used - it resolves only the FHIR-core-fixed systems and the two unambiguous HD auto-derivations, so an un-seeded assigning authority surfaces a typed issue rather than a guessed system.


TransformResult

The immutable result of a message-level transform: the FHIR Bundle model and the value-free diagnostics raised assembling it.

Properties

bundle

readonly bundle: FhirComplex

The FHIR R4 Bundle resource node (a message Bundle: MessageHeader first, then focal resources).

issues

readonly issues: readonly TransformIssue[]

The value-free diagnostics raised during assembly, in emission order.

Type Aliases

CodedElement

CodedElement = Pick<CWE, "identifier" | "text" | "nameOfCodingSystem" | "alternateIdentifier" | "alternateText" | "nameOfAlternateCodingSystem" | "codingSystemVersionId" | "alternateCodingSystemVersionId" | "originalText">

The subset of CWE fields a CE also provides - so toFhirCodeableConcept accepts both.


FatalCode

FatalCode = typeof FATAL_CODES[keyof typeof FATAL_CODES]

A value from FATAL_CODES - the type carried by a thrown fatal error.


IssueCode

IssueCode = typeof ISSUE_CODES[keyof typeof ISSUE_CODES]

A value from ISSUE_CODES - the type consumers narrow issue.code against.


TransformSeverity

TransformSeverity = "error" | "warning" | "information"

The severity a TransformIssue carries - an OperationOutcome.issue.severity value.

Variables

ADDRESS_TYPE_MAP

const ADDRESS_TYPE_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0190 address-type code → FHIR address-type, exactly per the IG HL70190→address-type map.


ADDRESS_USE_MAP

const ADDRESS_USE_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0190 address-type code → FHIR address-use, exactly per the IG HL70190→address-use map.


ADMINISTRATIVE_GENDER_MAP

const ADMINISTRATIVE_GENDER_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0001 (Administrative Sex) → FHIR administrative-gender, exactly per the IG Table HL70001 to Administrative Gender ConceptMap (every row "is equivalent to"). A (Ambiguous) and N (Not applicable) both narrow to other - the map's stated equivalence, carried as-is. A code absent here (the map defines no unmapped default) leaves gender absent and is flagged ISSUE_CODES.TRANSFORM_CODE_UNMAPPED - never coerced to unknown.


APPOINTMENT_STATUS_MAP

const APPOINTMENT_STATUS_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0278 (Filler Status Code) → FHIR appointmentstatus (Appointment.status), per the IG Table HL70278 to AppointmentStatus ConceptMap (each is equivalent to). The three source codes the IG leaves unmatched (Discontinued, Blocked, Overbook) are absent here on purpose - an SCH-25 carrying one of them (or any local code) leaves Appointment.status absent + flagged and the required-status emit gate withholds the Appointment.


APPOINTMENT_TYPE_VALUE_MAP

const APPOINTMENT_TYPE_VALUE_MAP: CodedValueMap

SCH-8 Appointment Type - IG ConceptMap/table-hl70277-to-v2-0277. A single identity group of the three v2-0277 codes (Normal, Tentative, Complete → themselves, each equivalent, source and target both v2-0277). Any other code is unmapped → raw coding preserved + flagged.


DEFAULT_V2_CODE_SYSTEMS

const DEFAULT_V2_CODE_SYSTEMS: Readonly<Record<string, string>>

A small, license-clean seed of v2 Table 0396 coding-system mnemonic → canonical URI, for the FHIR-core-fixed systems whose URIs are universally cited (FHIR R4 terminologies-systems.html). The full HL7 THO NamingSystem crosswalk is not bundled; callers extend this via createNamingSystem. No terminology content is bundled - only identity URIs.


DIAGNOSTIC_REPORT_STATUS_MAP

const DIAGNOSTIC_REPORT_STATUS_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0123 (Result Status) → FHIR diagnostic-report-status (DiagnosticReport.status), per the IG Table HL70123 [Queries] to Diagnostic Report Status ConceptMap (each is equivalent to). Only these eight source codes carry a target; the IG leaves A, M, N, Y, Z unmapped (verified firsthand against the published v1.0.0 ConceptMap - N "Procedure completed, results pending" is in the (not mapped) group, and the map declares no unmapped default), so an OBR-25 with one of them leaves status absent + flagged and the report is withheld. In particular a results-pending N is never emitted as the post-final appended. Ccorrected and Xcancelled guarantee a corrected/cancelled report never emits as final.


ENCOUNTER_CLASS_V3_MAP

const ENCOUNTER_CLASS_V3_MAP: Readonly<Record<string, { code: string; display: string; }>>

HL7 v2 Table 0004 (Patient Class) → FHIR v3 ActCode (Encounter.class), per the IG Table HL70004 to V3 ActCode ConceptMap (each "is equivalent to"). Only these four v2 classes have a v3 ActCode equivalent; the remaining classes (R/B/C/N/U) map to themselves and stay in the v2-0004 system (V2_0004_SYSTEM) per the same map's V2→V2 rows.


ENCOUNTER_STATUS_MAP

const ENCOUNTER_STATUS_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0004 (Patient Class) → FHIR Encounter.status, per the IG Table HL70004 to Encounter Status ConceptMap. Applied only when PV1-45 (discharge date) is not valued - a valued discharge sets status = finished per the PV1→Encounter map.


FATAL_CODES

const FATAL_CODES: object

Stable fatal codes - the reserved names for unrecoverable input conditions. Nothing in this library throws one today; every path, datatype and message level alike, fails safe to a value-free issue instead. They are declared so that a future one is an addition rather than a rename.

Type Declaration

EMPTY_INPUT

readonly EMPTY_INPUT: "EMPTY_INPUT" = "EMPTY_INPUT"

The input carried nothing to transform.

TRANSFORM_UNSUPPORTED_INPUT

readonly TRANSFORM_UNSUPPORTED_INPUT: "TRANSFORM_UNSUPPORTED_INPUT" = "TRANSFORM_UNSUPPORTED_INPUT"

The input was not a shape this transform accepts.

Example

import { FATAL_CODES } from "@cosyte/transform";
void FATAL_CODES.EMPTY_INPUT;

HL70078_INTERPRETATION_CODES

const HL70078_INTERPRETATION_CODES: ReadonlySet<string>

HL7 v2 Table 0078 (Abnormal Flags) → FHIR v3 ObservationInterpretation (Observation.interpretation), per the IG Table HL70078 to v3 ObservationInterpretation ConceptMap. Every mapped row is is equivalent to an identically-spelled v3 code (the map is code-preserving), so this is the set of codes that carry a target - a flag absent from this set has no equivalent and is flagged ISSUE_CODES.TRANSFORM_CODE_UNMAPPED, never coerced (the IG leaves AC/HM/OBX/QCF/TOX and any local flag unmapped, and declares no unmapped default).


IG_MAPPED_ADT_TRIGGERS

const IG_MAPPED_ADT_TRIGGERS: ReadonlySet<string>

The ADT trigger events the IG ships a message map for. Other triggers still transform - from the reusable segment maps - but are flagged ISSUE_CODES.TRANSFORM_SEGMENT_ASSEMBLED.


IG_MAPPED_APPOINTMENT_TRIGGERS

const IG_MAPPED_APPOINTMENT_TRIGGERS: ReadonlySet<string>

The scheduling trigger the IG ships a message map for. The IG maps only SIU^S12; other SIU triggers still assemble their Appointment from the reusable SCH/AIS/PID segment maps but are flagged ISSUE_CODES.TRANSFORM_SEGMENT_ASSEMBLED.


IG_MAPPED_DOCUMENT_TRIGGERS

const IG_MAPPED_DOCUMENT_TRIGGERS: ReadonlySet<string>

The medical-document trigger the IG ships a message map for. The IG maps only MDM^T02; other MDM triggers still assemble their DocumentReference from the reusable TXA/OBX segment maps but are flagged ISSUE_CODES.TRANSFORM_SEGMENT_ASSEMBLED.


IG_MAPPED_IMMUNIZATION_TRIGGERS

const IG_MAPPED_IMMUNIZATION_TRIGGERS: ReadonlySet<string>

The immunization trigger the IG ships a message map for. The IG maps only VXU^V04; other VXU triggers still assemble their Immunization graph from the reusable RXA/RXR/ORC segment maps but are flagged ISSUE_CODES.TRANSFORM_SEGMENT_ASSEMBLED.


IG_MAPPED_ORDER_TRIGGERS

const IG_MAPPED_ORDER_TRIGGERS: ReadonlySet<string>

The order-message trigger events the IG ships a message map for, keyed CODE^TRIGGER. Only ORM^O01 and OML^O21 are message-map-grounded; other order families (OMP, OMG, RDE, …) still assemble their request graph from the reusable ORC/OBR/RXO/RXR segment maps but are flagged ISSUE_CODES.TRANSFORM_SEGMENT_ASSEMBLED.


IG_MAPPED_ORU_TRIGGERS

const IG_MAPPED_ORU_TRIGGERS: ReadonlySet<string>

The ORU trigger events the IG ships a message map for. The IG maps only R01; other ORU triggers still assemble their results graph from the reusable OBR/OBX segment maps but are flagged ISSUE_CODES.TRANSFORM_SEGMENT_ASSEMBLED.


IMMUNIZATION_STATUS_MAP

const IMMUNIZATION_STATUS_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0322 (Completion Status) → FHIR Immunization.status, per the IG Table HL70322 to Event Status ConceptMap (each is equivalent to). Table 0322 has exactly these four source codes and every one carries a target; the two distinct targets (completed, not-done) are both valid members of the immunization-status required binding, so applying this map to Immunization.status is faithful. Consulted only for a valued RXA-20 when RXA-21 ≠ "D" (the IG's mappedVia condition on that row); the two other IG status rows assign fixed values directly (a delete → entered-in-error, an unvalued RXA-20 → completed) and do not consult this map. See buildStatus.


ISSUE_CODES

const ISSUE_CODES: object

Stable non-fatal issue codes - the typed diagnostics the fail-safe rule emits.

Type Declaration

TRANSFORM_ADDRESS_USE_UNMAPPED

readonly TRANSFORM_ADDRESS_USE_UNMAPPED: "TRANSFORM_ADDRESS_USE_UNMAPPED" = "TRANSFORM_ADDRESS_USE_UNMAPPED"

An XAD.7 address-type code has no equivalent in the IG's HL70190 → address-use/type ConceptMaps; Address.use/.type are left absent rather than guessed.

TRANSFORM_CODE_SYSTEM_UNRESOLVED

readonly TRANSFORM_CODE_SYSTEM_UNRESOLVED: "TRANSFORM_CODE_SYSTEM_UNRESOLVED" = "TRANSFORM_CODE_SYSTEM_UNRESOLVED"

A coding-system mnemonic (CWE.3 / CWE.6) was not recognized, so no canonical system URI could be emitted. The code is preserved; a URI is never invented.

TRANSFORM_CODE_UNMAPPED

readonly TRANSFORM_CODE_UNMAPPED: "TRANSFORM_CODE_UNMAPPED" = "TRANSFORM_CODE_UNMAPPED"

A coded value could not be mapped to a FHIR concept - either it carried no coding-system context (CWE.3 absent), or it is a table code the IG ConceptMap has no target for (e.g. an OBX-11/ OBR-25 result status the HL70085/HL70123 map does not carry, or an OBX-8 abnormal flag absent from HL70078). The original code is preserved / the FHIR value left absent; never coerced to a neighbor and never guessed to final/normal.

TRANSFORM_ELEMENT_DROPPED

readonly TRANSFORM_ELEMENT_DROPPED: "TRANSFORM_ELEMENT_DROPPED" = "TRANSFORM_ELEMENT_DROPPED"

A populated source element was not carried to its FHIR target and was dropped - either because the IG map defines no target, or because that target's conversion is not implemented (e.g. XTN→ContactPoint telecom, PV1 participants). Surfaced here rather than silently discarded, never a fabricated value.

TRANSFORM_IDENTIFIER_SYSTEM_UNRESOLVED

readonly TRANSFORM_IDENTIFIER_SYSTEM_UNRESOLVED: "TRANSFORM_IDENTIFIER_SYSTEM_UNRESOLVED" = "TRANSFORM_IDENTIFIER_SYSTEM_UNRESOLVED"

The assigning authority (HD) could not be resolved to a FHIR Identifier.system URI via the NamingSystem registry. The identifier is emitted with its value and no system - a system URI is never synthesized from HD.1 alone.

TRANSFORM_NAME_USE_UNMAPPED

readonly TRANSFORM_NAME_USE_UNMAPPED: "TRANSFORM_NAME_USE_UNMAPPED" = "TRANSFORM_NAME_USE_UNMAPPED"

An XPN.7 name-type code has no equivalent in the IG's HL70200 → name-use ConceptMap; HumanName.use is left absent rather than guessed.

TRANSFORM_QUANTITY_VALUE_INVALID

readonly TRANSFORM_QUANTITY_VALUE_INVALID: "TRANSFORM_QUANTITY_VALUE_INVALID" = "TRANSFORM_QUANTITY_VALUE_INVALID"

A v2 numeric value (NM) could not be represented as a FHIR decimal without altering it - e.g. a leading +, a leading zero, or a trailing dot, which FHIR's decimal lexical form forbids. No Quantity value is emitted rather than a canonicalized (and therefore altered) magnitude.

TRANSFORM_REQUIRED_ELEMENT_UNKNOWN

readonly TRANSFORM_REQUIRED_ELEMENT_UNKNOWN: "TRANSFORM_REQUIRED_ELEMENT_UNKNOWN" = "TRANSFORM_REQUIRED_ELEMENT_UNKNOWN"

A FHIR-required element's value could not be faithfully derived from the source, so it was emitted with a data-absent-reason extension (value unknown) rather than fabricated - e.g. MessageHeader.source.endpoint from an MSH-3 application namespace that is not a URL.

TRANSFORM_RESOURCE_INVALID

readonly TRANSFORM_RESOURCE_INVALID: "TRANSFORM_RESOURCE_INVALID" = "TRANSFORM_RESOURCE_INVALID"

A produced FHIR resource failed @cosyte/fhir R4 structural validation and was withheld from the bundle rather than emitted as a silently-invalid resource - the conservative-emit gate.

TRANSFORM_SEGMENT_ASSEMBLED

readonly TRANSFORM_SEGMENT_ASSEMBLED: "TRANSFORM_SEGMENT_ASSEMBLED" = "TRANSFORM_SEGMENT_ASSEMBLED"

The message's trigger event has no IG message map, so its resource graph was assembled from the reusable IG segment maps rather than a message map. The graph is best-effort and flagged as such - never a fabricated message map.

TRANSFORM_TIMESTAMP_INVALID

readonly TRANSFORM_TIMESTAMP_INVALID: "TRANSFORM_TIMESTAMP_INVALID" = "TRANSFORM_TIMESTAMP_INVALID"

A v2 DTM/TS could not be parsed into a valid FHIR date/time; no value was emitted.

TRANSFORM_TIMESTAMP_NO_TIMEZONE

readonly TRANSFORM_TIMESTAMP_NO_TIMEZONE: "TRANSFORM_TIMESTAMP_NO_TIMEZONE" = "TRANSFORM_TIMESTAMP_NO_TIMEZONE"

A v2 DTM/TS carried a time-of-day but no timezone offset. FHIR forbids time-without-zone, so the value was reduced to date precision (or an explicit sender offset applied via options) - never a guessed UTC.

TRANSFORM_UNIT_NOT_UCUM

readonly TRANSFORM_UNIT_NOT_UCUM: "TRANSFORM_UNIT_NOT_UCUM" = "TRANSFORM_UNIT_NOT_UCUM"

A unit was not a valid UCUM code (or was not declared UCUM). It is preserved verbatim in Quantity.unit; Quantity.code/.system are left absent - a UCUM code is never fabricated and a magnitude is never converted.

Example

import { ISSUE_CODES } from "@cosyte/transform";
if (issue.code === ISSUE_CODES.TRANSFORM_TIMESTAMP_NO_TIMEZONE) {
// a v2 timestamp had a time-of-day but no timezone offset - reduced to date precision
}

ISSUE_REGISTRY

const ISSUE_REGISTRY: Readonly<Record<IssueCode, IssueMeta>>

The per-code registry: severity, FHIR issue-type, and a static message. Frozen and exhaustive over ISSUE_CODES (enforced by the Record<IssueCode, …> type - a new code will not compile until it has an entry).


NAME_USE_MAP

const NAME_USE_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0200 name-type code → FHIR name-use, exactly per the IG HL70200 → name-use ConceptMap (every row is "is equivalent to"). Codes absent here (A, B, C, F, I, K, NB, NOUSE, P, REL, S, T, U, …) have no FHIR equivalent and are surfaced, never guessed.


OBSERVATION_STATUS_MAP

const OBSERVATION_STATUS_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0085 (Observation Result Status) → FHIR observation-status (Observation.status), per the IG Table HL70085 to Observation Status ConceptMap (each is equivalent to). Only these seven source codes carry a target; the codes the IG leaves unmapped (B, I, N, O, R, S, U, V) are absent here on purpose - an OBX-11 with one of them (or any local code) leaves Observation.status absent + flagged, and the required-status emit gate withholds the Observation. Ccorrected and Xcancelled guarantee a corrected/cancelled result never emits as final.


REQUEST_STATUS_MAP

const REQUEST_STATUS_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0119 (Order Control Codes) → FHIR request-status (ServiceRequest.status), per the IG Table HL70119 to Request Status ConceptMap (each is equivalent to). Only these 19 source codes carry a target; every other v2-0119 code sits in the IG's explicit (unmapped) group (verified firsthand against the published v1.0.0 ConceptMap - CH/CN/CP/DE/LI/NA/OE/OF/OP/OR/PA/RE/ RF/RP/RR/RU/SC/SN/SR/SS/UA/UC/UD/UF/UH/UM/UN/UR/UX/XO/XR/XX/MC are all unmatched, and the map declares no unmapped default), so an ORC-1 with one of them leaves status absent + flagged and the request is withheld. request-status has no cancelled; the cancel/discontinue codes map to revoked and the hold codes to on-hold, exactly as the IG table specifies.


ROUTE_VALUE_MAP

const ROUTE_VALUE_MAP: CodedValueMap

RXR-1 Route - IG ConceptMap/table-hl70162-to-v2-0162. Two IG groups, transcribed verbatim: a 41-code identity group (source v2-0162 → target v2-0162, each equivalent) and a 6-code remap group into v3-RouteOfAdministration (ID→IDINJ, IM→IM, IV→IVINJ, PO→PO, SC→SQ, TD→TRNSDERM, each equivalent, with the IG target displays). The two source-code sets are disjoint. Any other v2-0162 code (or a non-table code) is unmapped → the raw coding is preserved and flagged, never coerced.


SERVICE_REQUEST_PRIORITY_MAP

const SERVICE_REQUEST_PRIORITY_MAP: Readonly<Record<string, string>>

HL7 v2 Table 0485 (Extended Priority Codes) → FHIR request-priority (ServiceRequest.priority), per the IG Table HL70485 to Request Priority ConceptMap (each is equivalent to; verified firsthand against the published v1.0.0 ConceptMap). Only these three source codes carry a target; every other v2-0485 code - P (Preop), C (Callback), T (Timing critical), the T{S,M,H,D,W,L}<integer> timing-critical family, and PRN (As needed) - sits in the IG's (unmapped) group with no target, so an OBR-5 carrying one leaves priority absent + flagged. All three targets (stat/asap/routine) are valid request-priority members.


SITE_VALUE_MAP

const SITE_VALUE_MAP: CodedValueMap

RXR-2 Administration Site - IG ConceptMap/table-hl70550-to-v2-0550. A single identity group of 443 body-part codes (source v2-0550 → target v2-0550, each equivalent), transcribed verbatim from the published STU1 ConceptMap - including its as-published data-quality artifacts (CHESTÂ, a lone Â, KIDNÂ, where a stray U+00C2 leaked from the IG's source encoding). They are preserved for source-fidelity; they are inert (a clean CHEST/KIDN simply falls through to unmapped). A code not in the table is unmapped → raw coding preserved + flagged.


SUBSTITUTION_VALUE_MAP

const SUBSTITUTION_VALUE_MAP: CodedValueMap

RXO-9 Allow Substitutions - IG ConceptMap/table-hl70161-to-v2-0161. A single identity group of the three v2-0161 codes (N NOT authorized, G generic, T therapeutic → themselves, each equivalent, source and target both v2-0161), the target for MedicationRequest.substitution.allowedCodeableConcept. Any other code is unmapped → the substitution is withheld + flagged, never a fabricated substitution permission.


TRANSFORM_ISSUE_SYSTEM

const TRANSFORM_ISSUE_SYSTEM: "https://cosyte.com/fhir/CodeSystem/transform-issue-codes" = "https://cosyte.com/fhir/CodeSystem/transform-issue-codes"

The code system under which the transform's stable issue codes are carried in details.coding.


V2_0161_SYSTEM

const V2_0161_SYSTEM: "http://terminology.hl7.org/CodeSystem/v2-0161" = "http://terminology.hl7.org/CodeSystem/v2-0161"

HL7 v2 Table 0161 (Allow Substitution) THO CodeSystem URI.


V2_0162_SYSTEM

const V2_0162_SYSTEM: "http://terminology.hl7.org/CodeSystem/v2-0162" = "http://terminology.hl7.org/CodeSystem/v2-0162"

HL7 v2 Table 0162 (Route of Administration) THO CodeSystem URI.


V2_0203_SYSTEM

const V2_0203_SYSTEM: "http://terminology.hl7.org/CodeSystem/v2-0203" = "http://terminology.hl7.org/CodeSystem/v2-0203"

The HL7 v2 Table 0203 identifier-type code system canonical URI - used to build Identifier.type. (FHIR R4 terminologies-systems.html)


V2_0277_SYSTEM

const V2_0277_SYSTEM: "http://terminology.hl7.org/CodeSystem/v2-0277" = "http://terminology.hl7.org/CodeSystem/v2-0277"

HL7 v2 Table 0277 (Appointment Type Codes) THO CodeSystem URI.


V2_0550_SYSTEM

const V2_0550_SYSTEM: "http://terminology.hl7.org/CodeSystem/v2-0550" = "http://terminology.hl7.org/CodeSystem/v2-0550"

HL7 v2 Table 0550 (Body Parts) THO CodeSystem URI.


V3_ROUTE_OF_ADMINISTRATION_SYSTEM

const V3_ROUTE_OF_ADMINISTRATION_SYSTEM: "http://terminology.hl7.org/CodeSystem/v3-RouteOfAdministration" = "http://terminology.hl7.org/CodeSystem/v3-RouteOfAdministration"

HL7 v3 RouteOfAdministration CodeSystem URI (the IG's remap target for the six common routes).


VERSION

const VERSION: "0.0.0" = "0.0.0"

The library version string, synced with package.json#version by the release tooling.

Functions

codeableConceptFromTarget()

codeableConceptFromTarget(target, text?): FhirComplex

Build a FHIR CodeableConcept node for a CodedTarget - the single translated coding, with an optional free-text. Used by translate-or-withhold callers (e.g. substitution) that build the CodeableConcept only on a successful translation.

Parameters

target

CodedTarget

The translated target coding.

text?

string

The original free text (CWE.9) to carry as CodeableConcept.text, if any.

Returns

FhirComplex

Example

import { codeableConceptFromTarget, V2_0161_SYSTEM } from "@cosyte/transform";
const cc = codeableConceptFromTarget({ system: V2_0161_SYSTEM, code: "G" });
void cc;

createNamingSystem()

createNamingSystem(seed?): NamingSystemRegistry

Create a NamingSystemRegistry. With no seed it resolves the built-in FHIR-core code systems and the two unambiguous HD auto-derivations (OID/UUID); a seed adds caller-vetted code systems and explicit assigning-authority URIs.

Parameters

seed?

NamingSystemSeed = {}

Returns

NamingSystemRegistry

Example

import { createNamingSystem } from "@cosyte/transform";
const registry = createNamingSystem({
authorities: { HOSPMRN: "urn:oid:1.2.840.114350.1.13.1" },
});
registry.resolveCodeSystem("LN"); // => "http://loinc.org"

fhirIssueTypeFor()

fhirIssueTypeFor(code): string

The FHIR issue-type code for an IssueCode - used by the OperationOutcome renderer.

Parameters

code

IssueCode

The stable IssueCode.

Returns

string

Example

import { fhirIssueTypeFor, ISSUE_CODES } from "@cosyte/transform";
fhirIssueTypeFor(ISSUE_CODES.TRANSFORM_IDENTIFIER_SYSTEM_UNRESOLVED); // "not-found"

issue()

issue(code, v2Location, fhirPath?): TransformIssue

Construct a value-free TransformIssue. The severity and message come from ISSUE_REGISTRY; the caller supplies only positional metadata, so an issue can carry no PHI.

Parameters

code

IssueCode

The stable IssueCode.

v2Location

string

The v2 source location (segment / field / component index) - never a value.

fhirPath?

string

The FHIR path the issue concerns, when applicable.

Returns

TransformIssue

Example

import { issue, ISSUE_CODES } from "@cosyte/transform";
const i = issue(ISSUE_CODES.TRANSFORM_TIMESTAMP_NO_TIMEZONE, "TS.1", "dateTime");
void i.severity; // "warning"

toFhir()

toFhir(msg, opts?): TransformResult

Transform a parsed HL7 v2 message into a FHIR R4 message Bundle. Never throws for a well-formed Hl7Message; every ambiguity, unmapped code, dropped element, or withheld resource surfaces as a value-free TransformIssue.

Parameters

msg

Hl7Message

A parsed @cosyte/hl7 message.

opts?

TransformOptions = {}

Transform options: the TransformOptions.namingSystem registry, the naked- timestamp TransformOptions.assumeTimezoneOffsetMinutes policy, and a TransformOptions.generateId allocator for reproducible fullUrls.

Returns

TransformResult

Example

import { parseHL7 } from "@cosyte/hl7";
import { toFhir, createNamingSystem } from "@cosyte/transform";
const { bundle, issues } = toFhir(parseHL7(raw), { namingSystem: createNamingSystem() });
void bundle;
void issues;

toFhirAddress()

toFhirAddress(xad): ConvertResult<FhirComplex>

Convert a parsed HL7 v2 XAD to a FHIR Address node. Returns { value: undefined } when the address carries no emittable part.

Parameters

xad

XAD

A parsed @cosyte/hl7 XAD.

Returns

ConvertResult<FhirComplex>

Example

import { toFhirAddress } from "@cosyte/transform";
const { value } = toFhirAddress({ street: "1 Main St", city: "Boston", stateOrProvince: "MA", addressType: "H" });
// value === Address { use: "home", line: ["1 Main St"], city: "Boston", state: "MA" }
void value;

toFhirCodeableConcept()

toFhirCodeableConcept(cwe, ctx?): ConvertResult<FhirComplex>

Convert a parsed HL7 v2 CWE (or CE) to a FHIR CodeableConcept node, fail-safe on the coding system and on unmapped codes. Returns { value: undefined } when the element is empty.

Parameters

cwe

CodedElement

A parsed @cosyte/hl7 CWE (a CE is accepted as its subset).

ctx?

TransformContext = {}

The transform context; ctx.namingSystem resolves the coding-system mnemonic.

Returns

ConvertResult<FhirComplex>

Example

import { toFhirCodeableConcept, createNamingSystem } from "@cosyte/transform";
const { value } = toFhirCodeableConcept(
{ identifier: "789-8", text: "Hemoglobin", nameOfCodingSystem: "LN" },
{ namingSystem: createNamingSystem() },
);
// coding[0] === { system: "http://loinc.org", code: "789-8", display: "Hemoglobin" }
void value;

toFhirCodeableConceptVia()

toFhirCodeableConceptVia(cwe, map, ctx?): ConvertResult<FhirComplex>

Value-translate a coded v2 element to a FHIR CodeableConcept via a license-clean CodedValueMap, additively and fail-safe - never mutating or discarding what the message said:

  • Primary code recognized as a bound-table code (translateBound - CWE.3 absent or names the bound table, and the code is in the IG map's mapped group) → the primary coding is emitted in the recognized source-table system (map.sourceSystem, carrying CWE.7 version) and the derived target coding is appended when it differs (a remap such as SC→SQ); the alternate triplet (CWE.4/5/6, via buildCoding, with its own system resolution + flags) and the original CWE.9 text are preserved. No primary unmapped flag - the value was faithfully recognized.
  • Otherwise - the primary declares a foreign coding system (not the bound table), the code is empty, or it is in the IG's (unmapped) group → this defers entirely to the structural toFhirCodeableConcept, which preserves the raw coding (and its CWE.4/5/6 alternate and CWE.7 version) and flags it (ISSUE_CODES.TRANSFORM_CODE_UNMAPPED / TRANSFORM_CODE_SYSTEM_UNRESOLVED). A target is never fabricated, and a code that declares a foreign system is never asserted to be the standard concept.

Parameters

cwe

CodedElement

The parsed @cosyte/hl7 coded element (its identifier is the candidate table code).

map

CodedValueMap

The license-clean value map to apply (e.g. ROUTE_VALUE_MAP).

ctx?

TransformContext = {}

The transform context (threaded to the structural path + the alternate-triplet resolver).

Returns

ConvertResult<FhirComplex>

Example

import { toFhirCodeableConceptVia, ROUTE_VALUE_MAP } from "@cosyte/transform";
const { value } = toFhirCodeableConceptVia({ identifier: "IM" }, ROUTE_VALUE_MAP);
// coding === [{ system: ".../v2-0162", code: "IM" },
// { system: ".../v3-RouteOfAdministration", code: "IM", display: "Injection, intramuscular" }]
void value;

toFhirDateTime()

toFhirDateTime(ts, options?): ConvertResult<string>

Convert a parsed HL7 v2 timestamp to a FHIR dateTime lexical string, fail-safe on timezone and precision. Returns { value: undefined } only when the timestamp is unparseable.

Parameters

ts

TS

A parsed @cosyte/hl7 TS (DtmParts).

options?

TransformOptions = {}

Conversion policy; assumeTimezoneOffsetMinutes supplies a sender-asserted offset.

Returns

ConvertResult<string>

Example

import { parseDtm } from "@cosyte/hl7";
import { toFhirDateTime } from "@cosyte/transform";
const { value } = toFhirDateTime(parseDtm("20260721"));
// value === "2026-07-21"
void value;

toFhirHumanName()

toFhirHumanName(xpn): ConvertResult<FhirComplex>

Convert a parsed HL7 v2 XPN to a FHIR HumanName node. Returns { value: undefined } when the name carries no emittable part.

Parameters

xpn

XPN

A parsed @cosyte/hl7 XPN.

Returns

ConvertResult<FhirComplex>

Example

import { toFhirHumanName } from "@cosyte/transform";
const { value } = toFhirHumanName({ familyName: "Public", givenName: "Jane", nameTypeCode: "L" });
// value === HumanName { use: "official", family: "Public", given: ["Jane"] }
void value;

toFhirIdentifier()

toFhirIdentifier(cx, ctx?): ConvertResult<FhirComplex>

Convert a parsed HL7 v2 CX to a FHIR Identifier node, fail-safe on the assigning authority. Returns { value: undefined } when the CX carries no identifier value at all.

Parameters

cx

CX

A parsed @cosyte/hl7 CX.

ctx?

TransformContext = {}

The transform context; ctx.namingSystem resolves the assigning authority (HD).

Returns

ConvertResult<FhirComplex>

Example

import { toFhirIdentifier, createNamingSystem } from "@cosyte/transform";
const { value, issues } = toFhirIdentifier(
{ idNumber: "12345", assigningAuthority: { namespaceId: "HOSPMRN" } },
{ namingSystem: createNamingSystem() },
);
// no registry entry for a bare "HOSPMRN" namespace → value emitted, system absent, one issue
void value;
void issues;

toFhirQuantity()

toFhirQuantity(value, units, ctx?): ConvertResult<FhirComplex>

Convert a parsed HL7 v2 numeric value plus its units to a FHIR Quantity node, fail-safe on the unit. Returns { value: undefined } when the numeric magnitude is absent or non-numeric (a Quantity without a value cannot be safely emitted).

Parameters

value

NM

A parsed @cosyte/hl7 NM (its .raw carries the exact lexical value).

units

CWE

The units component (an OBX-6 CWE); its CWE.1 is the candidate UCUM code.

ctx?

TransformContext = {}

The transform context; used to recognize the UCUM coding system.

Returns

ConvertResult<FhirComplex>

Example

import { toFhirQuantity } from "@cosyte/transform";
const { value } = toFhirQuantity(
{ raw: "5.4", value: 5.4 },
{ identifier: "mg/dL", nameOfCodingSystem: "UCUM" },
);
// value === Quantity { value: 5.4, unit: "mg/dL", system: "http://unitsofmeasure.org", code: "mg/dL" }
void value;

toOperationOutcome()

toOperationOutcome(issues): FhirComplex

Build a FHIR OperationOutcome FhirComplex from the given issues. An empty list still produces a structurally-valid OperationOutcome with a single information "all clear" issue (FHIR requires OperationOutcome.issue to be non-empty).

Parameters

issues

readonly TransformIssue[]

The value-free diagnostics to render.

Returns

FhirComplex

Example

import { toOperationOutcome } from "@cosyte/transform";
const oo = toOperationOutcome([]);
// oo is a FhirComplex resource node with resourceType "OperationOutcome"
void oo;

translateBound()

translateBound(cwe, map): CodedTarget | undefined

The bound-table target for a coded element's primary coding, or undefined when the map does not faithfully apply - i.e. the primary declares a coding system that is not this map's bound table (CWE.3 present and not in CodedValueMap.sourceMnemonics), the primary code is empty, or the code is in the IG map's (unmapped) group. Never asserts a standard translation for a foreign coding system, and never fabricates a target.

Parameters

cwe

CodedElement

The parsed coded element (its identifier is the candidate source-table code).

map

CodedValueMap

The license-clean value map to consider applying.

Returns

CodedTarget | undefined

Example

import { translateBound, ROUTE_VALUE_MAP } from "@cosyte/transform";
translateBound({ identifier: "IM" }, ROUTE_VALUE_MAP)?.code; // "IM" (v3 route)
translateBound({ identifier: "IM", nameOfCodingSystem: "99LOCAL" }, ROUTE_VALUE_MAP); // undefined