Interface: X12OrphanSegment
A segment the envelope grammar has no place for, captured verbatim rather
than discarded. Every segment recorded here also raised exactly one
X12_UNEXPECTED_SEGMENT warning whose position.segmentIndex equals
segmentIndex, and context is that warning's library-owned
discriminant, so the two surfaces can be joined without string matching.
These are structural anomalies, not a normal shape: a stray segment
between GE and IEA, a body segment between an SE and its group's
GE, a body segment between GS and the first ST, an ST with no open
group, an SE closing nothing, a GE closing nothing, or a TA1 inside
an open functional group. The parser cannot place any of them in the typed
tree, but it no longer drops them either, so a segment that used to vanish
is now readable here.
Most of these sit outside every ST..SE transaction set, but the TA1
case does not. TA1 is envelope-level by spec, so a TA1 anywhere
inside an open group is routed here even when it arrives BETWEEN an ST
and its SE - in which case it is lifted out of that transaction's
segments / rawSegments and appears only on this array. That is
long-standing behaviour (it predates this array; the segment simply used
to be discarded), and it is the one case where ix.groups is not the whole
typed model.
serializeX12 re-emits these, at anchor, so an orphan and its
X12_UNEXPECTED_SEGMENT warning both survive a round trip. Placement is by
the structural anchor and NEVER by segmentIndex: that index is an
index into the INPUT stream, and the emit is not in input order (it hoists
ta1Segments ahead of the groups and skips the zero-length segment a
doubled terminator produces), so replaying by index splices an orphan into
whatever occupies that slot - measurably, into an 835's ST..SE body,
where a re-parse reports nothing at all. Use segmentIndex to join
back to the warning, not to place the segment. See KNOWN-LIMITATIONS.md.
Two things are NOT recorded here. A doubled segment terminator delimits a
zero-length segment carrying no elements, so there is nothing to retain.
A segment whose first element is empty (*A*B~) has no id for the
envelope walker to dispatch on and is skipped without a warning; that is
long-standing behaviour this array does not change.
This is document content, so treat it as PHI. Unlike an
X12ParseWarning, whose message is a lookup into a frozen registry and
whose metadata is positional only, an orphan carries the sender's bytes
verbatim, exactly as X12TransactionSet.rawSegments and isa.raw do. A
segment outside a transaction is not required to be PHI-free, so do NOT
log this array wholesale when triaging; log context and segmentIndex,
which name the structural rule and the location without echoing content.
Example
import { parseX12 } from "@cosyte/x12";
const ix = parseX12(raw);
for (const o of ix.orphanSegments) {
console.warn(o.context, o.segmentIndex, o.segment.id);
}
Properties
anchor
readonlyanchor:X12OrphanAnchor
Where the segment sat in the typed tree - the slot serializeX12 puts it
back into. See X12OrphanAnchor for why a structural anchor and not
segmentIndex is what makes re-emission sound.
context
readonlycontext:X12UnexpectedSegmentContext
Which structural rule the segment broke.
raw
readonlyraw:string
The verbatim segment text, segment terminator stripped.
segment
readonlysegment:X12Segment
The decoded segment (id + 1-indexed elements), as for any body segment.
segmentIndex
readonlysegmentIndex:number
Global segment index in the post-ISA stream (ISA itself is index 0) -
identical to the position.segmentIndex of the segment's
X12_UNEXPECTED_SEGMENT warning.