@cosyte/x12 0.0.14 → 0.0.15
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 +209 -0
- package/KNOWN-LIMITATIONS.md +203 -13
- package/dist/index.cjs +52 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +179 -30
- package/dist/index.d.ts +179 -30
- package/dist/index.mjs +52 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
11
|
|
|
12
|
+
- **🩺 `Build837EnvelopeSpec.implementationConventionReference` - the caller now states the ST-03 /
|
|
13
|
+
GS-08 implementation convention reference `build837P` / `build837I` / `build837D` declares**
|
|
14
|
+
(`X12-837-EMIT-IDENTIFIER-FIXED`). One value, **both elements**; omit it and the builders emit
|
|
15
|
+
exactly what they always have.
|
|
16
|
+
|
|
17
|
+
**What this fixes, and it is a rejected claim rather than a mis-read one.** The builders stamped
|
|
18
|
+
`005010X222A2` / `005010X223A3` / `005010X224A2` with no way to change them. Two of those are not
|
|
19
|
+
what CMS and several state Medicaid companion guides require in ST-03 and GS-08 on production
|
|
20
|
+
professional and institutional claims, which ask for `005010X222A1` and `005010X223A2`, so **a
|
|
21
|
+
partner on one of those guides rejected every 837 this library built and a caller had no remedy.**
|
|
22
|
+
The read side of the same fact was grounded in the release before this one; this is the emit side.
|
|
23
|
+
|
|
24
|
+
**🛑 The defaults are UNCHANGED, on purpose, and that is the whole shape of the fix.** Which
|
|
25
|
+
published guide identifier a trading partner accepts is a **partner fact, not a spec fact**.
|
|
26
|
+
Re-stamping the default would silently change bytes this library already puts on the wire and
|
|
27
|
+
break the partners it works with today, so the default stays and the caller states what its own
|
|
28
|
+
partner asked for. Nothing about an existing call changes.
|
|
29
|
+
|
|
30
|
+
**What it refuses of its own, all `Claim837BuildError` with code `X12_837_BUILD_INVALID_SPEC`, and
|
|
31
|
+
none of them echoes the value you passed.** These sit on top of the element-type guard every string
|
|
32
|
+
slot in every builder already has, which refuses a non-string with the same code, so read the list
|
|
33
|
+
as what this field adds and not as a closed account of everything that can refuse. No total is
|
|
34
|
+
published.
|
|
35
|
+
- **Empty.** A trailing empty element is not emitted at all, so an empty reference would remove
|
|
36
|
+
ST-03 and GS-08 rather than send them empty - a silent structural loss on two required elements.
|
|
37
|
+
- **Carrying an active delimiter or the release character.** The value is refused rather than
|
|
38
|
+
escaped. A trading partner's parser is not obliged to honour the release escape, and a published
|
|
39
|
+
guide identifier has no legitimate use for a delimiter, so the refusal is kept even now that
|
|
40
|
+
this library's own reader would carry it (see the envelope-splitter entry below).
|
|
41
|
+
- **A reference this library's own reader resolves to a DIFFERENT 837 variant** (`005010X223A2`
|
|
42
|
+
handed to `build837P`). The emitted file would declare one variant and carry another's service
|
|
43
|
+
segments, and `get837Claims` would decode none of its service lines. Same class as the existing
|
|
44
|
+
refusal for a service line whose `variant` disagrees with the builder's. The message names the
|
|
45
|
+
variant the builder emits and deliberately not the one the reference belongs to.
|
|
46
|
+
|
|
47
|
+
**A reference outside the read table is emitted as given, and that is deliberate.** Nothing makes
|
|
48
|
+
the published-errata set provably exhaustive, so refusing an unrecognised identifier would claim
|
|
49
|
+
an exhaustiveness this library does not claim when reading either. The honest cost is pinned as a
|
|
50
|
+
test: on such a file this library's own reader falls back to the `SVx` scan, exactly as it does
|
|
51
|
+
for any unrecognised ST-03. The **length** is not bounded either, and the two elements' maxima
|
|
52
|
+
differ: GS-08 is data element 480 (`AN 1/12`), ST-03 is element 1705 (`AN 1/35`).
|
|
53
|
+
|
|
54
|
+
**🩺 A guard on this element cannot make the element trustworthy, and the disclosure above is
|
|
55
|
+
therefore about the whole envelope segment rather than these two elements.** An **unescaped**
|
|
56
|
+
active delimiter in a _different_ `GS` or `ST` element still ends its own element and shifts every
|
|
57
|
+
element after it, so ST-03 and GS-08 are then read out of a neighbour's slot, and no refusal here
|
|
58
|
+
can reach it. A **release-escaped** one no longer does - see the entry below, which landed after
|
|
59
|
+
this one and retracts the part of it that said escaping could not help.
|
|
60
|
+
|
|
12
61
|
- **🩺 `X12_837_SERVICE_SEGMENT_REPEATED`, the 33rd Tier-2 warning code, plus the public factory
|
|
13
62
|
`serviceSegmentRepeated(position)`** (`X12-837-SV1-OVERWRITE`). A **second** `SV1` / `SV2` / `SV3`
|
|
14
63
|
arriving inside an **already-open** Loop 2400 now says so, at that repeated segment. Through
|
|
@@ -901,6 +950,166 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
901
950
|
|
|
902
951
|
### Fixed
|
|
903
952
|
|
|
953
|
+
- **🩺 `buildTA1` now release-escapes its five caller-supplied elements, so an Accept acknowledgment
|
|
954
|
+
this library emits no longer reads back as a Reject** (`X12-TA1-EMIT-NOT-RELEASE-AWARE`).
|
|
955
|
+
Reproduced on the base tree at `e8f34b9`. `buildTA1` joined the five values with the element
|
|
956
|
+
separator and escaped none of them, so a value carrying an active delimiter took a slot of its own
|
|
957
|
+
and shifted every element after it down one. TA1-04 is the disposition, TA1-05 the note, and
|
|
958
|
+
`parseTA1` narrows an out-of-enum TA1-04 to `R`. Measured with `parseX12` + `parseTA1` over
|
|
959
|
+
`ISA … <what buildTA1 returned> … IEA`, `ackCode` `"A"` and `noteCode` `"000"` throughout:
|
|
960
|
+
|
|
961
|
+
| `interchangeControlNumber` | emitted at `0.0.14` | read `ackCode` | read TA1-01 | warnings |
|
|
962
|
+
| -------------------------- | --------------------------------- | -------------- | -------------------- | ------------------------ |
|
|
963
|
+
| `"000000001"` | `TA1*000000001*260601*1200*A*000` | `"A"` | `"000000001"` | none |
|
|
964
|
+
| `"00000001?"` | `TA1*00000001?*260601*1200*A*000` | `"R"` | `"00000001?*260601"` | none |
|
|
965
|
+
| `"0000*0001"` | `TA1*0000*0001*260601*1200*A*000` | `"R"` | `"0000"` | none |
|
|
966
|
+
| `"0000~0001"` | `TA1*0000~0001*260601*1200*A*000` | `"R"` | `"0000"` | `X12_UNEXPECTED_SEGMENT` |
|
|
967
|
+
|
|
968
|
+
**An Accept acknowledgment this library emitted read back as a Reject**, on the element that
|
|
969
|
+
reassociates it, with nothing raised on any channel. The `*` and `~` rows did that on every
|
|
970
|
+
released version; the `?` row is the one the entry below opened. **🩺 The inverse exists and is the
|
|
971
|
+
less safe direction:** the read narrows an out-of-enum TA1-04 to `R`, so a well-typed shift always
|
|
972
|
+
lands on Reject, but `noteCode` is checked by the type system and by nothing at run time, so a
|
|
973
|
+
`noteCode` of literally `"A"` shifted onto TA1-04 and made a **Reject read back as an Accept**, and
|
|
974
|
+
a sender who reads an Accept does not resubmit. All four now read back the disposition emitted.
|
|
975
|
+
|
|
976
|
+
**The grounding is inside this package rather than in a spec clause**, the same tiebreak the entry
|
|
977
|
+
below records: `buildTA1` emitted bytes that this package's own reader decoded into a different
|
|
978
|
+
disposition than the caller asked for, while every other builder already released the same class of
|
|
979
|
+
element through the same helper.
|
|
980
|
+
|
|
981
|
+
**🛑 It changes bytes this library already put on the wire, and that is the cost.** A value
|
|
982
|
+
containing none of the four delimiters and no `?` is emitted byte-for-byte as before, which is
|
|
983
|
+
every conformant TA1: TA1-01 echoes ISA-13, TA1-02 / TA1-03 echo ISA-09 / ISA-10, and TA1-04 /
|
|
984
|
+
TA1-05 are code list values.
|
|
985
|
+
|
|
986
|
+
**🛑 No warning code is added and no case moves onto a new code, but the consumer predicate MOVES
|
|
987
|
+
IN BOTH DIRECTIONS.** `parseTA1` of a `buildTA1` output now reports the disposition and note the
|
|
988
|
+
caller passed; before, it reported whatever element the shift left in TA1-04, which could be the
|
|
989
|
+
caller's, a coincidental in-enum value, or an out-of-enum one narrowed to `"R"`. So
|
|
990
|
+
`ackCode === "R"` **stops** firing where an Accept had been shifted onto it, and **starts** firing
|
|
991
|
+
where a Reject had been shifted off it: `interchangeTime: "12*A"` with `ackCode: "R"` read `"A"`
|
|
992
|
+
before and reads `"R"` now, with every field a valid member of its union. `ackCode === "A"` moves
|
|
993
|
+
the same two ways. What is one-directional is the safety, which is a different statement: nothing
|
|
994
|
+
now reports a disposition the caller did not ask for.
|
|
995
|
+
|
|
996
|
+
**What releasing the rest of the set costs, and where it does not cost.** Only `*`, `~` and a `?`
|
|
997
|
+
immediately before the separator ever shifted the segment's own element framing. **`^` and `:`
|
|
998
|
+
moved the dot-path reader instead, and releasing them is a gain there:**
|
|
999
|
+
`getSegmentValue(ta1, "01")` answered `"0000"` at `0.0.14` for a control number of `"0000^0001"`,
|
|
1000
|
+
silently truncating the reassociation key to the first repetition, and answers `"0000^0001"` now;
|
|
1001
|
+
the composite read `"01-1"` answered `"0000"` for `"0000:0001"` and answers the whole value now.
|
|
1002
|
+
**The measured pure cost is a mid-string `?`, and only on the surfaces documented as raw**: `raw`,
|
|
1003
|
+
`elements` and `parseTA1`'s fields read `"0000??0001"` where they read `"0000?0001"`, while every
|
|
1004
|
+
dot-path read unescapes and answered `"0000?0001"` on both. No total is published: that is what was
|
|
1005
|
+
measured, not a closed account. `getSegmentValue` takes an `X12Segment` and `Ta1Segment` carries no
|
|
1006
|
+
`id`, so add one to read a TA1 through it. If you were escaping the value yourself, as `KNOWN-LIMITATIONS.md`
|
|
1007
|
+
advised while this was open, drop that - you are now escaping twice on both kinds of surface
|
|
1008
|
+
(`"00000001??"` in, `TA1*00000001????*…` out, `getSegmentValue` answering `"00000001??"`).
|
|
1009
|
+
|
|
1010
|
+
**The read half did not move.** `parseTA1` still reads elements RAW, pre-`?`-unescape, exactly as
|
|
1011
|
+
`X12Segment.elements` has always documented, so a control number of `"00000001?"` now reads back as
|
|
1012
|
+
`"00000001??"` rather than as `"00000001?*260601"`. Apply `unescapeRelease` if you need the value
|
|
1013
|
+
rather than the bytes; unescaping on the read side would move every TA1 a consumer already reads
|
|
1014
|
+
and is not done here.
|
|
1015
|
+
|
|
1016
|
+
**`BuildTA1Options` gained `repetitionSeparator`, `componentSeparator` and `segmentTerminator`**
|
|
1017
|
+
beside the existing `elementSeparator`, the same four `build999` already takes. They exist for
|
|
1018
|
+
escaping and nothing else - `buildTA1` still emits no segment terminator, no repetition and no
|
|
1019
|
+
composite. Escaping against a guessed delimiter set is a value corruption rather than a safe
|
|
1020
|
+
default: `unescapeRelease` preserves `?X` verbatim for any `X` outside the reader's declared set,
|
|
1021
|
+
so a value released against the wrong delimiter comes back carrying a stray `?`. The defaults are
|
|
1022
|
+
unchanged and are the cosyte archetype, which this function cannot verify, so state the separators
|
|
1023
|
+
if you embed a TA1 in an envelope that declares different ones.
|
|
1024
|
+
|
|
1025
|
+
**A non-string element now refuses** with `AckBuildError` and the existing `X12_ACK_INVALID_SPEC`
|
|
1026
|
+
code, and that is a prerequisite of the escape rather than a separate guard: releasing a value
|
|
1027
|
+
routes it through the escape helper, and the bare `escapeRelease` underneath it returns its empty
|
|
1028
|
+
accumulator for a `number`, so escaping without the type check would have replaced a shifted TA1-01
|
|
1029
|
+
with a vanished one. A numeric `interchangeControlNumber` emitted `TA1*12345*260601*1200*A*000`
|
|
1030
|
+
before, with the number surviving onto `elements` inside a value typed `readonly string[]`, and an
|
|
1031
|
+
absent one emitted `TA1**250101*1200*A*000`. The accept-with-note refusal still runs first and
|
|
1032
|
+
still reports `X12_TA1_ACCEPT_WITH_NOTE`, so no existing refusal moves code.
|
|
1033
|
+
|
|
1034
|
+
**What this does not close:** `buildTA1` still uses no segment joiner, so its refusal names the
|
|
1035
|
+
builder and never `TA1-01`; `buildInterchange` still does not escape GS-04, GS-05 or GS-07; and an
|
|
1036
|
+
unescaped active delimiter is still not safe anywhere. Measured in `KNOWN-LIMITATIONS.md`.
|
|
1037
|
+
|
|
1038
|
+
- **🩺 A `?` immediately before the element separator inside an envelope segment now frames as ONE
|
|
1039
|
+
element, which fixes a released delimiter and is a SYMMETRIC change**
|
|
1040
|
+
(`X12-ENVELOPE-SPLITTER-NOT-RELEASE-AWARE`). Reproduced on the base
|
|
1041
|
+
tree at `1b71733`. `src/parser/envelope.ts`'s `splitElements` - the splitter for `GS`, `GE`, `ST`,
|
|
1042
|
+
`SE`, `IEA` and `TA1` - was a plain `String.prototype.split` on the element separator, so a `?*`
|
|
1043
|
+
ended the element anyway and every element after it moved down a slot:
|
|
1044
|
+
|
|
1045
|
+
```text
|
|
1046
|
+
GS*HC*S*R*20260601*1200*1*X*005010?*X222A1~ ten elements, GS-08 read "005010?"
|
|
1047
|
+
applicationSenderCode "SEND*ER" GS-08 read "X", the GS-07 agency code
|
|
1048
|
+
groupControlNumber "1*2" GS-08 read "X"; warnings: []
|
|
1049
|
+
transactionSetControlNumber "00*01" ST-03 read "01"; warnings: []
|
|
1050
|
+
CLM*PT?*ACCT*150.00~ three elements - the BODY control, always correct
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
**What made it a defect rather than a tolerance is that this package's own two halves disagreed
|
|
1054
|
+
inside a single call:** `buildInterchange` maps its release escaper over GS-02 / GS-03 / GS-06 /
|
|
1055
|
+
GS-08 and ST-01 / ST-02 / ST-03, then returns `parseX12` of the bytes it just wrote, so
|
|
1056
|
+
`applicationSenderCode: "SEND*ER"` emitted a correct `GS*HC*SEND?*ER*...` and handed back a model
|
|
1057
|
+
whose GS-08 answered `"X"`, with `warnings: []`.
|
|
1058
|
+
|
|
1059
|
+
**🛑 READ THE CHANGE AS SYMMETRIC. IT IS NOT ONLY A CORRECTION.** A `?` before the separator has
|
|
1060
|
+
two readings and 005010 does not transmit which the sender meant. Where the sender **escaped** a
|
|
1061
|
+
delimiter, `0.0.14` framed it wrongly and this release frames it correctly: a correction, the rows
|
|
1062
|
+
above. Where the sender sent a **literal `?`** as the element's last byte, `0.0.14` framed it
|
|
1063
|
+
correctly and this release merges the element with its successor, so **the segment loses its LAST
|
|
1064
|
+
element**: a regression. `GS*HC*SUB1*RCV?*20260601*1200*000000123*X*005010X222A1~` read nine
|
|
1065
|
+
entries and reads **eight** here, GS-06 answering `"X"` and GS-08 gone. Every other release
|
|
1066
|
+
sequence in an envelope element (`??`, `?:`, `?^`, `?~`, `?A`) framed identically before and after
|
|
1067
|
+
and still does, pinned as invariance controls.
|
|
1068
|
+
|
|
1069
|
+
**No warning code is added, and `X12_CONTROL_NUMBER_MISMATCH` moves in BOTH DIRECTIONS.** Where the
|
|
1070
|
+
old shift displaced a control number it stops firing, so **a consumer that rejects on that code
|
|
1071
|
+
will now accept such a document**; where a literal `?` newly displaces one it starts firing, so
|
|
1072
|
+
that same consumer **will now reject a document `0.0.14` accepted**. Both are pinned, alongside a
|
|
1073
|
+
genuine mismatch that raises it on either tree.
|
|
1074
|
+
|
|
1075
|
+
**🩺 The regression direction reaches an 837's variant and its money, by one route.** `ST-03`
|
|
1076
|
+
decides the 837 variant, so an `ST-02` ending in a literal `?` destroys `ST-03` and the document
|
|
1077
|
+
falls back to the `SVx` scan. An 837 declaring `005010X222A1` whose only service segment is an
|
|
1078
|
+
`SV2` read `variant` `"P"`, `charge` `undefined` and `X12_837_SERVICE_LINE_NOT_DECODED` at
|
|
1079
|
+
`0.0.14`, and reads `variant` `"I"` with `charge` `150.00` and that warning silent here. **A warned
|
|
1080
|
+
non-decode becomes a decoded amount.** Re-check any routing driven off `submission.variant` if your
|
|
1081
|
+
partners send envelope elements that can end in a literal `?`.
|
|
1082
|
+
|
|
1083
|
+
**Why it was taken anyway, and it is CONSISTENCY rather than a spec clause.** The two readings are
|
|
1084
|
+
mutually exclusive and nothing in 005010 picks between them. `decodeSegment` has read BODY elements
|
|
1085
|
+
the escape-wins way on every released version (`REF*EA*RCV?*NEXT` has always been two elements), so
|
|
1086
|
+
the envelope now obeys the one rule the rest of the package already obeyed.
|
|
1087
|
+
|
|
1088
|
+
**🩺 The exposure is NOT inbound bytes only.** Envelope slots routed through the builders' release
|
|
1089
|
+
escaper are safe. Not every emit slot is routed through it, and no total is published: what follows
|
|
1090
|
+
is the routes measured to reach the regression direction, not a closed account of what bypasses the
|
|
1091
|
+
escaper. **`buildInterchange` does not escape GS-04, GS-05 or GS-07**: a `groupDate` of
|
|
1092
|
+
`"2026060?"` read nine GS elements at `0.0.14` and reads eight here, GS-08 gone. If you emit one
|
|
1093
|
+
of those, escape or reject a `?` yourself.
|
|
1094
|
+
|
|
1095
|
+
**Values are still RAW, pre-`?`-unescape**, exactly as `X12Segment.elements` has always documented:
|
|
1096
|
+
`gs.elements[2]` reads `"SEND?*ER"`, not `"SEND*ER"`. `elements.join(separator)` therefore still
|
|
1097
|
+
reproduces the segment byte for byte, which is what `serializeX12` relies on when it substitutes a
|
|
1098
|
+
recomputed `SE-01` / `GE-01` / `IEA-01` into a control segment.
|
|
1099
|
+
|
|
1100
|
+
**🩺 The ISA is deliberately exempt.** ASC X12 .5 makes it fixed-width, which is what lets the
|
|
1101
|
+
delimiter set be recovered from it before anything is parsed, so a `?` in an ISA element is content
|
|
1102
|
+
and never an escape; release-splitting it would collapse a well-formed ISA below its 17 entries.
|
|
1103
|
+
A degenerate delimiter set whose element separator IS `?` also falls back to the literal split,
|
|
1104
|
+
the same guard the segment-terminator scanner already carried. Both are pinned, each with a red
|
|
1105
|
+
negative control.
|
|
1106
|
+
|
|
1107
|
+
**🛑 An UNESCAPED delimiter is still not safe and nothing here claims otherwise** - a bare active
|
|
1108
|
+
delimiter ends its element, because that is what a delimiter is. `build837`'s
|
|
1109
|
+
`implementationConventionReference` still refuses a value carrying one, deliberately not relaxed:
|
|
1110
|
+
a partner's parser is not obliged to be release-aware either, and widening an emit surface is its
|
|
1111
|
+
own decision rather than a side effect of a reader fix.
|
|
1112
|
+
|
|
904
1113
|
- **🩺 An `AMT` / `ADX` row whose amount decodes nothing is no longer dropped in silence**
|
|
905
1114
|
(`X12-AMT-ADX-ABSENT-AMOUNT`). Reproduced on the base tree at `9db104b` across all four readers,
|
|
906
1115
|
and the report it now raises is the `X12_AMOUNT_ROW_DROPPED` entry under **Added** above. The
|
package/KNOWN-LIMITATIONS.md
CHANGED
|
@@ -53,14 +53,200 @@ model.
|
|
|
53
53
|
- **The set is not claimed exhaustive and no count of it is published**, here or in any warning
|
|
54
54
|
message. Both variant messages named the three old keys literally and were wrong the moment the
|
|
55
55
|
table was corrected, so neither enumerates the set any more.
|
|
56
|
-
- **🩺
|
|
57
|
-
`
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
- **🩺 CLOSED, in the slice after this one: the emit side takes a caller override**
|
|
57
|
+
(`X12-837-EMIT-IDENTIFIER-FIXED`). `build837P` / `build837I` / `build837D` still DEFAULT to
|
|
58
|
+
`005010X222A2` / `005010X223A3` / `005010X224A2` in ST-03 and GS-08, and
|
|
59
|
+
**`Build837EnvelopeSpec.implementationConventionReference` now states another** - one value,
|
|
60
|
+
both elements. Two of the defaults are not what the companion guides above require, so a partner
|
|
61
|
+
asking for `005010X222A1` or `005010X223A2` used to reject what this builder emitted and there
|
|
62
|
+
was no way to comply. **The default itself was deliberately NOT re-stamped:** which published
|
|
63
|
+
guide identifier a partner accepts is a partner fact rather than a spec fact, and changing bytes
|
|
64
|
+
this library already emitted would break the partners it works with today.
|
|
65
|
+
- **What the override refuses of its own, all `X12_837_BUILD_INVALID_SPEC`, and none of it
|
|
66
|
+
echoes your value back:** an empty reference (a trailing empty element is not emitted, so it
|
|
67
|
+
would delete ST-03 and GS-08 rather than send them empty); one carrying an active delimiter or
|
|
68
|
+
the release character; and one this library's own reader resolves to a **different** 837
|
|
69
|
+
variant, which would emit a file declaring one variant and carrying another's service
|
|
70
|
+
segments. **No total is published**, because those sit on top of the element-type guard every
|
|
71
|
+
string slot in every builder already has, which refuses a non-string with the same code. Take
|
|
72
|
+
the list as what this field adds, never as a closed account of everything that can refuse.
|
|
73
|
+
- **🩺 It bounds the VALUE, not the length, and the two elements' maxima differ.** GS-08 is data
|
|
74
|
+
element 480 (`AN 1/12`) and ST-03 is element 1705 (`AN 1/35`), so "one value, both elements"
|
|
75
|
+
is true of the bytes and not of what each element may legally hold. Nothing here refuses an
|
|
76
|
+
over-length reference, in line with every other envelope field this library takes.
|
|
77
|
+
- **A reference outside the read table is emitted as given, deliberately.** The published-errata
|
|
78
|
+
set is not provably exhaustive, so refusing an unrecognised identifier would claim an
|
|
79
|
+
exhaustiveness nothing here supports. The honest cost, pinned as a test: this library's own
|
|
80
|
+
reader falls back to the `SVx` scan on such a file, exactly as it does for any unrecognised
|
|
81
|
+
ST-03.
|
|
82
|
+
|
|
83
|
+
- **🩺 A `?` immediately before the element separator inside an envelope segment now frames as ONE
|
|
84
|
+
element, and that is a SYMMETRIC behaviour change on already-published decoding**
|
|
85
|
+
(`X12-ENVELOPE-SPLITTER-NOT-RELEASE-AWARE`).
|
|
86
|
+
Through `0.0.14` the envelope segments' element splitter was a plain `String.prototype.split`, so a
|
|
87
|
+
released element separator (`?*`) still ended the element and SHIFTED every element after it down a
|
|
88
|
+
slot. It was a property of the whole envelope segment and never of one element, so the element a
|
|
89
|
+
reader went looking for came back out of its neighbour's slot. Measured then, through `parseX12`:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
GS*HC*S*R*20260601*1200*1*X*005010?*X222A1~ ten elements, GS-08 read "005010?"
|
|
93
|
+
applicationSenderCode "SEND*ER" GS-08 read "X", the GS-07 agency code
|
|
94
|
+
groupControlNumber "1*2" GS-08 read "X"; warnings: []
|
|
95
|
+
transactionSetControlNumber "00*01" ST-03 read "01"; warnings: []
|
|
96
|
+
CLM*PT?*ACCT*150.00~ three elements, CLM-01 held "PT?*ACCT"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The body element was the control and was always correct. `splitElements` now honours the release
|
|
100
|
+
character exactly as `decodeSegment` and the segment-terminator scanner already did, so every row
|
|
101
|
+
above reads one element fewer and the value lands in its own slot.
|
|
102
|
+
- **🛑 READ THE CHANGE AS SYMMETRIC. IT IS NOT ONLY A CORRECTION.** A `?` before the separator has
|
|
103
|
+
two readings and 005010 does not transmit which the sender meant. Where the sender **escaped** a
|
|
104
|
+
delimiter, the release before this one framed it wrongly and this one frames it correctly: a
|
|
105
|
+
correction, the rows above. Where the sender sent a **literal `?`** as the element's last byte,
|
|
106
|
+
the release before this one framed it correctly and this one merges the element with its
|
|
107
|
+
successor, so **the segment loses its LAST element**: a regression.
|
|
108
|
+
`GS*HC*SUB1*RCV?*20260601*1200*000000123*X*005010X222A1~` read nine entries through `0.0.14` and
|
|
109
|
+
reads **eight** here, with GS-06 answering `"X"` and GS-08 gone.
|
|
110
|
+
- **🛑 What this changes for a consumer.** One input class decodes differently: an envelope segment
|
|
111
|
+
(`GS`, `GE`, `ST`, `SE`, `IEA`, `TA1`) carrying a `?` immediately before the element separator.
|
|
112
|
+
Every other release sequence in an envelope element (`??`, `?:`, `?^`, `?~`, `?A`) framed
|
|
113
|
+
identically before and after and still does. **No warning code is added, and
|
|
114
|
+
`X12_CONTROL_NUMBER_MISMATCH` moves in BOTH DIRECTIONS.** Where the old shift displaced a control
|
|
115
|
+
number it STOPS firing, so a consumer that rejects on that code will now **accept** such a
|
|
116
|
+
document; where a literal `?` newly displaces one it STARTS firing, so that same consumer will
|
|
117
|
+
now **reject** a document `0.0.14` accepted. A genuine mismatch still raises it.
|
|
118
|
+
- **🩺 The regression direction reaches an 837's variant and its money, by one route.** `ST-03` is
|
|
119
|
+
what decides the 837 variant, so an `ST-02` ending in a literal `?` destroys `ST-03` and the
|
|
120
|
+
document falls back to the `SVx` scan. An 837 declaring `005010X222A1` whose only service segment
|
|
121
|
+
is an `SV2` read `variant` `"P"`, `charge` `undefined` and `X12_837_SERVICE_LINE_NOT_DECODED`
|
|
122
|
+
through `0.0.14`, and here reads `variant` `"I"` with `charge` `150.00` and that warning silent.
|
|
123
|
+
**A warned non-decode becomes a decoded amount.** If you receive envelope elements that may end
|
|
124
|
+
in a literal `?`, re-check any routing driven off `submission.variant`.
|
|
125
|
+
- **Why it was taken anyway, and it is CONSISTENCY rather than a spec clause.** The two readings
|
|
126
|
+
are mutually exclusive and nothing in 005010 picks between them. `decodeSegment` has read BODY
|
|
127
|
+
elements the escape-wins way on **every released version** (`REF*EA*RCV?*NEXT` has always been
|
|
128
|
+
two elements). The envelope now obeys the one rule the rest of the package already obeyed, and
|
|
129
|
+
`buildInterchange` stops disagreeing with itself: at `0.0.14` it released GS-02 on emit and then
|
|
130
|
+
answered GS-08 as `"X"` from its own return value.
|
|
131
|
+
- **🩺 THE EXPOSURE IS NOT INBOUND BYTES ONLY.** Envelope slots routed through the builders'
|
|
132
|
+
release escaper are safe. **Not every emit slot is routed through it, and no total is published
|
|
133
|
+
here** - what follows is the routes measured to REACH the regression direction, not a closed
|
|
134
|
+
account of what bypasses the escaper.
|
|
135
|
+
|
|
136
|
+
**`buildInterchange` does not escape GS-04, GS-05 or GS-07** (`groupDate`, `groupTime`,
|
|
137
|
+
`responsibleAgencyCode`). A `groupDate` of `"2026060?"` emits
|
|
138
|
+
`GS*HC*SENDER*RECEIVER*2026060?*1200*1*X*005010X222A1`, which its own return value read as nine
|
|
139
|
+
elements with GS-08 intact through `0.0.14` and reads as **eight** here, GS-08 gone, plus
|
|
140
|
+
`X12_CONTROL_NUMBER_MISMATCH`.
|
|
141
|
+
|
|
142
|
+
- **An envelope element ending in a literal `?` is a dangling release character and is NOT warned.**
|
|
143
|
+
`X12_DANGLING_RELEASE_CHAR` fires only for an odd run of `?` at the very END of a segment, so a
|
|
144
|
+
mid-segment one reaches no check. That is true of body elements too and is unchanged here.
|
|
145
|
+
- **Values are still RAW, pre-`?`-unescape**, exactly as `X12Segment.elements` has always
|
|
146
|
+
documented: `gs.elements[2]` on the first row reads `"SEND?*ER"`, not `"SEND*ER"`. Read through
|
|
147
|
+
`getSegmentValue` if you want the logical value. `elements.join(separator)` therefore still
|
|
148
|
+
reproduces the segment byte for byte, which is what `serializeX12` relies on when it substitutes
|
|
149
|
+
a recomputed `SE-01` / `GE-01` / `IEA-01` into a control segment.
|
|
150
|
+
- **🩺 The ISA is deliberately exempt and stays positional.** ASC X12 .5 makes the ISA fixed-width,
|
|
151
|
+
which is what lets the delimiters be recovered from it before anything is parsed, so a `?` in an
|
|
152
|
+
ISA element is content and never an escape. `buildInterchange` states the same rule from the emit
|
|
153
|
+
side: it pads each ISA element and never escapes one.
|
|
154
|
+
- **A degenerate delimiter set whose element separator IS `?` is unchanged.** `?` cannot both
|
|
155
|
+
separate and escape, so the splitter falls back to the literal split, the same guard the
|
|
156
|
+
segment-terminator scanner already carried.
|
|
157
|
+
- **🩺 This does NOT make an UNESCAPED delimiter safe, and nothing here claims it does.** A bare
|
|
158
|
+
active delimiter in an envelope element still ends that element, because that is what a delimiter
|
|
159
|
+
is; only the sender escaping it is now honoured. `build837`'s
|
|
160
|
+
`implementationConventionReference` still REFUSES a value carrying an active delimiter or the
|
|
161
|
+
release character, and is deliberately not relaxed on the strength of this fix: a partner's
|
|
162
|
+
parser is not obliged to be release-aware either. `buildInterchange` applies no domain guard to
|
|
163
|
+
any envelope field and will still emit all of them, though it now reports back what it wrote -
|
|
164
|
+
at `0.0.14` it released GS-02 on emit and then answered GS-08 as `"X"` from its own return value.
|
|
165
|
+
|
|
166
|
+
- **🩺 `buildTA1` now RELEASES its five caller-supplied elements, so an Accept acknowledgment this
|
|
167
|
+
library emits no longer reads back as a Reject, and the bytes it writes for such a value CHANGED**
|
|
168
|
+
(`X12-TA1-EMIT-NOT-RELEASE-AWARE`). Through `0.0.14` `buildTA1` joined the five values with the
|
|
169
|
+
element separator and escaped none of them, so a value carrying an active delimiter took a slot of
|
|
170
|
+
its own and shifted every element after it down one. TA1-04 is the disposition and TA1-05 the note,
|
|
171
|
+
and `parseTA1` narrows an out-of-enum TA1-04 to `R`. Measured with `parseX12` + `parseTA1` over
|
|
172
|
+
`ISA … <what buildTA1 returned> … IEA`, `ackCode` `"A"` and `noteCode` `"000"` throughout:
|
|
173
|
+
|
|
174
|
+
| `interchangeControlNumber` | emitted at `0.0.14` | read `ackCode` | read TA1-01 | warnings |
|
|
175
|
+
| -------------------------- | --------------------------------- | -------------- | -------------------- | ------------------------ |
|
|
176
|
+
| `"000000001"` | `TA1*000000001*260601*1200*A*000` | `"A"` | `"000000001"` | none |
|
|
177
|
+
| `"00000001?"` | `TA1*00000001?*260601*1200*A*000` | `"R"` | `"00000001?*260601"` | none |
|
|
178
|
+
| `"0000*0001"` | `TA1*0000*0001*260601*1200*A*000` | `"R"` | `"0000"` | none |
|
|
179
|
+
| `"0000~0001"` | `TA1*0000~0001*260601*1200*A*000` | `"R"` | `"0000"` | `X12_UNEXPECTED_SEGMENT` |
|
|
180
|
+
|
|
181
|
+
**An Accept acknowledgment this library emitted read back as a Reject, on the element that
|
|
182
|
+
reassociates it, with nothing raised on any channel.** The `*` and `~` rows did that on every
|
|
183
|
+
released version; the `?` row is the one the envelope-splitter entry above opened. **🩺 The inverse
|
|
184
|
+
exists and is the less safe direction:** the read narrows an out-of-enum TA1-04 to `R`, so a
|
|
185
|
+
well-typed shift always lands on Reject, but `noteCode` is checked by the type system and by
|
|
186
|
+
nothing at run time, so a `noteCode` of literally `"A"` shifted onto TA1-04 and made a **Reject
|
|
187
|
+
read back as an Accept** - and a sender who reads an Accept does not resubmit. All four now read
|
|
188
|
+
back the disposition that was emitted.
|
|
189
|
+
- **The grounding is inside this package, not in a spec clause**, the same tiebreak the
|
|
190
|
+
envelope-splitter entry records. `buildTA1` emitted bytes that this package's own reader decoded
|
|
191
|
+
into a different disposition than the caller asked for, while every other builder already
|
|
192
|
+
released the same class of element through the same helper. Nobody here has read a clause that
|
|
193
|
+
settles it, and nothing above claims one.
|
|
194
|
+
- **🛑 It changes bytes this library already put on the wire, which is the cost.** A value
|
|
195
|
+
containing none of the four delimiters and no `?` is emitted byte-for-byte as before, and that
|
|
196
|
+
is every conformant TA1: TA1-01 echoes ISA-13, TA1-02 / TA1-03 echo ISA-09 / ISA-10, and
|
|
197
|
+
TA1-04 / TA1-05 are code list values. A value containing one is now released.
|
|
198
|
+
- **🛑 No warning code is added and no case moves onto a new code, but the consumer predicate
|
|
199
|
+
MOVES IN BOTH DIRECTIONS.** `parseTA1` of a `buildTA1` output now reports the disposition and
|
|
200
|
+
note the caller passed; before, it reported whatever element the shift left in TA1-04, which
|
|
201
|
+
could be the caller's, a coincidental in-enum value, or an out-of-enum one narrowed to `"R"`. So
|
|
202
|
+
`ackCode === "R"` **stops** firing where an Accept had been shifted onto it, and **starts**
|
|
203
|
+
firing where a Reject had been shifted off it: `interchangeTime: "12*A"` with `ackCode: "R"`
|
|
204
|
+
read `"A"` before and reads `"R"` now, with every field a valid member of its union.
|
|
205
|
+
`ackCode === "A"` moves the same two ways. What is one-directional is the safety, which is a
|
|
206
|
+
different statement: nothing now reports a disposition the caller did not ask for.
|
|
207
|
+
- **What releasing the REST of the set costs, and where it does not cost.** Only `*`, `~` and a
|
|
208
|
+
`?` immediately before the separator ever shifted the segment's own element framing. **`^` and
|
|
209
|
+
`:` moved the dot-path reader instead, and releasing them is a gain there:**
|
|
210
|
+
`getSegmentValue(ta1, "01")` answered `"0000"` through `0.0.14` for a control number of
|
|
211
|
+
`"0000^0001"`, silently truncating the reassociation key to the first repetition, and answers
|
|
212
|
+
`"0000^0001"` now; the composite read `"01-1"` answered `"0000"` for `"0000:0001"` and answers
|
|
213
|
+
the whole value now. **The measured pure cost is a mid-string `?`, and only on the surfaces
|
|
214
|
+
documented as raw**: `raw`, `elements` and `parseTA1`'s fields read `"0000??0001"` where they
|
|
215
|
+
read `"0000?0001"`, while every dot-path read unescapes and answered `"0000?0001"` on both.
|
|
216
|
+
No total is published: that is what was measured, not a closed account. (`getSegmentValue`
|
|
217
|
+
takes an `X12Segment` and `Ta1Segment` carries no `id`, so add one to read a TA1 through it.)
|
|
218
|
+
- **A caller who was hand-rolling the escape** (the remedy this file named while the defect was
|
|
219
|
+
open) regresses on both kinds of surface: `"00000001??"` in, `TA1*00000001????*…` out, and
|
|
220
|
+
`getSegmentValue` answering `"00000001??"` where it answered `"00000001?"`. The framing and the
|
|
221
|
+
disposition stay correct, but **drop the hand-rolled escape.**
|
|
222
|
+
- **An EMPTY control number is not refused and never was.** `escapeRelease` early-returns on `""`
|
|
223
|
+
and `buildTA1` carries no required-field guard, so `interchangeControlNumber: ""` emits
|
|
224
|
+
`TA1**260601*1200*A*000` with `warnings: []`, here and at every earlier release. Only a
|
|
225
|
+
NON-string refuses. Unchanged and tracked as its own item.
|
|
226
|
+
- **🩺 The READ half did not move. `parseTA1` still reads elements RAW, pre-`?`-unescape**, exactly
|
|
227
|
+
as `X12Segment.elements` has always documented, so a control number of `"00000001?"` now reads
|
|
228
|
+
back as `"00000001??"` rather than as `"00000001?*260601"`. The disposition is correct where it
|
|
229
|
+
was inverted; apply `unescapeRelease` if you need the value rather than the bytes. Unescaping on
|
|
230
|
+
the read side would move every TA1 a consumer already reads and is not done here.
|
|
231
|
+
- **The release is scoped to the delimiter set the CALLER states.** `BuildTA1Options` gained
|
|
232
|
+
`repetitionSeparator` / `componentSeparator` / `segmentTerminator` beside the existing
|
|
233
|
+
`elementSeparator`, the same four `build999` already takes, and they exist for escaping and
|
|
234
|
+
nothing else - `buildTA1` still emits no terminator. Escaping against a guessed set is a value
|
|
235
|
+
corruption rather than a safe default: `unescapeRelease` preserves `?X` verbatim for any `X`
|
|
236
|
+
outside the declared set, so a value released against the wrong delimiter comes back carrying a
|
|
237
|
+
stray `?`. **The defaults are the cosyte archetype and this function cannot verify them** - if
|
|
238
|
+
you embed a TA1 in an envelope that declares different separators, state them.
|
|
239
|
+
- **A non-string element now REFUSES** with `AckBuildError` / `X12_ACK_INVALID_SPEC`, and that is a
|
|
240
|
+
prerequisite rather than a bonus. Releasing a value means routing it through the escape helper,
|
|
241
|
+
and the bare `escapeRelease` underneath it returns its empty accumulator for a `number`, so
|
|
242
|
+
escaping without the type check would have replaced a shifted TA1-01 with a vanished one. A
|
|
243
|
+
numeric control number emitted `TA1*12345*…` at `0.0.14` (the number surviving onto `elements`,
|
|
244
|
+
inside a value typed `readonly string[]`) and an absent one emitted `TA1**250101*…`; both refuse.
|
|
245
|
+
**No existing refusal moves code:** `ackCode` `"A"` with a non-`000` note still reports
|
|
246
|
+
`X12_TA1_ACCEPT_WITH_NOTE` and still runs first.
|
|
247
|
+
- **What this does NOT close.** `buildTA1` still uses no segment joiner, so its refusal names the
|
|
248
|
+
builder and never the slot; `buildInterchange` still does not escape GS-04 / GS-05 / GS-07; and
|
|
249
|
+
an unescaped active delimiter is still not safe anywhere, because that is what a delimiter is.
|
|
64
250
|
|
|
65
251
|
- **🩺 BREAKING for `build277` callers: a 277 service line now REQUIRES `unitsOfService`, because
|
|
66
252
|
SVC-07 is a required element in `005010X212` and this library was not emitting it at all**
|
|
@@ -913,10 +1099,12 @@ N-char spec limit` refusal, one per emitting module, where the branch fires **be
|
|
|
913
1099
|
than reaching the message.
|
|
914
1100
|
|
|
915
1101
|
**Read the "through a builder's segment joiner" qualifier literally.** `buildTA1` does not use one,
|
|
916
|
-
and is therefore **not covered
|
|
917
|
-
|
|
918
|
-
(`TA1**250101*1200*A*000`)
|
|
919
|
-
|
|
1102
|
+
and is therefore **not covered by the segment guard**. Through `0.0.14` that meant nothing checked
|
|
1103
|
+
its five elements at all, and a numeric or `undefined` `interchangeControlNumber` was emitted
|
|
1104
|
+
silently (`TA1**250101*1200*A*000`); `X12-TA1-EMIT-NOT-RELEASE-AWARE` closed that by routing them
|
|
1105
|
+
through the escape helper, which type-checks first and refuses with `AckBuildError` /
|
|
1106
|
+
`X12_ACK_INVALID_SPEC`. What being outside the segment guard still costs is the **slot** in the
|
|
1107
|
+
refusal message: it names `buildTA1`, never `TA1-01`.
|
|
920
1108
|
|
|
921
1109
|
The monetary slots got their own guard on top of it: a slot typed `X12Decimal` refuses anything that
|
|
922
1110
|
is not one, rather than rendering `number.toString()` into the document.
|
|
@@ -928,7 +1116,9 @@ N-char spec limit` refusal, one per emitting module, where the branch fires **be
|
|
|
928
1116
|
`1?*BOGUS`); the fixed-width ISA slots do not go through it at all.
|
|
929
1117
|
2. **Whether an `X12Decimal` carries the SCALE you meant.** `fromString("0.3")` and
|
|
930
1118
|
`fromString("0.30")` are both accepted and both emit verbatim. That choice is yours.
|
|
931
|
-
3. **
|
|
1119
|
+
3. **The delimiter set `buildTA1` releases against**, per the paragraph above. It defaults to the
|
|
1120
|
+
cosyte archetype and the function cannot verify it; state the separators on `BuildTA1Options`
|
|
1121
|
+
if you embed a TA1 in an envelope that declares different ones.
|
|
932
1122
|
4. **`build835`'s balance-equation amounts, which refuse UNTYPED.** `build835` runs its balance
|
|
933
1123
|
guard before it builds the escape helper, and that guard calls `X12Decimal` methods on your
|
|
934
1124
|
value. So a raw `number` there throws a plain `TypeError` with **no `code`** - some saying the
|
package/dist/index.cjs
CHANGED
|
@@ -1097,7 +1097,10 @@ function splitSegments(text, start, delimiters) {
|
|
|
1097
1097
|
return { segments, endIndex: lastEnd };
|
|
1098
1098
|
}
|
|
1099
1099
|
function splitElements(segment, delimiters) {
|
|
1100
|
-
|
|
1100
|
+
if (delimiters.element === RELEASE_CHAR) {
|
|
1101
|
+
return Object.freeze(segment.split(delimiters.element));
|
|
1102
|
+
}
|
|
1103
|
+
return Object.freeze(splitWithRelease(segment, delimiters.element));
|
|
1101
1104
|
}
|
|
1102
1105
|
function el(elements, index) {
|
|
1103
1106
|
return elements[index] ?? "";
|
|
@@ -4569,6 +4572,29 @@ var VERSION_BY_VARIANT = {
|
|
|
4569
4572
|
I: "005010X223A3",
|
|
4570
4573
|
D: "005010X224A2"
|
|
4571
4574
|
};
|
|
4575
|
+
function resolveVersionRelease(variant, reference, esc) {
|
|
4576
|
+
if (reference === void 0) return VERSION_BY_VARIANT[variant];
|
|
4577
|
+
if (reference === "") {
|
|
4578
|
+
throw new Claim837BuildError(
|
|
4579
|
+
CLAIM_837_BUILD_ERROR_CODES.X12_837_BUILD_INVALID_SPEC,
|
|
4580
|
+
"build837: envelope.implementationConventionReference is empty. ST-03 and GS-08 are required elements and a trailing empty element is not emitted, so an empty reference would remove them rather than send them empty. Omit the field to take the builder's default."
|
|
4581
|
+
);
|
|
4582
|
+
}
|
|
4583
|
+
if (esc(reference) !== reference) {
|
|
4584
|
+
throw new Claim837BuildError(
|
|
4585
|
+
CLAIM_837_BUILD_ERROR_CODES.X12_837_BUILD_INVALID_SPEC,
|
|
4586
|
+
"build837: envelope.implementationConventionReference carries an active delimiter or the release character. Escaping does not make it safe here: the ST and GS segments are read by a splitter that is not release-aware, so a released delimiter still splits the segment and the declaration silently becomes two elements. State a reference that carries neither, or choose different delimiters."
|
|
4587
|
+
);
|
|
4588
|
+
}
|
|
4589
|
+
const named = Object.hasOwn(VARIANT_BY_ICR, reference) ? VARIANT_BY_ICR[reference] : void 0;
|
|
4590
|
+
if (named !== void 0 && named !== variant) {
|
|
4591
|
+
throw new Claim837BuildError(
|
|
4592
|
+
CLAIM_837_BUILD_ERROR_CODES.X12_837_BUILD_INVALID_SPEC,
|
|
4593
|
+
`build837: envelope.implementationConventionReference names an implementation guide this library reads as a DIFFERENT 837 variant, but this is build837${variant}. The emitted file would declare one variant and carry another's service segments, and this library's own reader would then decode none of its service lines. State a reference for the ${variant} 837, or build with the entry point that matches the reference.`
|
|
4594
|
+
);
|
|
4595
|
+
}
|
|
4596
|
+
return reference;
|
|
4597
|
+
}
|
|
4572
4598
|
var X12_837_FUNCTIONAL_ID = "HC";
|
|
4573
4599
|
var X12_AGENCY_CODE2 = "X";
|
|
4574
4600
|
var HL_LEVEL = { BILLING: "20", SUBSCRIBER: "22", PATIENT: "23" };
|
|
@@ -4583,7 +4609,6 @@ function build837D(spec) {
|
|
|
4583
4609
|
}
|
|
4584
4610
|
function buildClaim837(variant, spec) {
|
|
4585
4611
|
const { envelope } = spec;
|
|
4586
|
-
const versionRelease = VERSION_BY_VARIANT[variant];
|
|
4587
4612
|
enforceStructuralSpec2(variant, spec);
|
|
4588
4613
|
const elementSeparator = envelope.elementSeparator ?? "*";
|
|
4589
4614
|
const repetitionSeparator = envelope.repetitionSeparator ?? "^";
|
|
@@ -4609,6 +4634,11 @@ function buildClaim837(variant, spec) {
|
|
|
4609
4634
|
return escaped.slice(0, end).join(componentSeparator);
|
|
4610
4635
|
};
|
|
4611
4636
|
const ctx = { seg, esc, comp };
|
|
4637
|
+
const versionRelease = resolveVersionRelease(
|
|
4638
|
+
variant,
|
|
4639
|
+
envelope.implementationConventionReference,
|
|
4640
|
+
esc
|
|
4641
|
+
);
|
|
4612
4642
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
4613
4643
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
4614
4644
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
@@ -9733,18 +9763,27 @@ function expandYY8(yymmdd) {
|
|
|
9733
9763
|
// src/transactions/ack/build-ta1.ts
|
|
9734
9764
|
function buildTA1(spec, options = {}) {
|
|
9735
9765
|
enforceAcceptIsClean2(spec);
|
|
9736
|
-
const
|
|
9766
|
+
const delimiters = {
|
|
9767
|
+
element: options.elementSeparator ?? "*",
|
|
9768
|
+
repetition: options.repetitionSeparator ?? "^",
|
|
9769
|
+
component: options.componentSeparator ?? ":",
|
|
9770
|
+
segment: options.segmentTerminator ?? "~"
|
|
9771
|
+
};
|
|
9772
|
+
const esc = makeCallerEscaper(delimiters, "buildTA1", refuseSpec9);
|
|
9737
9773
|
const elements = Object.freeze([
|
|
9738
9774
|
"TA1",
|
|
9739
|
-
spec.interchangeControlNumber,
|
|
9740
|
-
spec.interchangeDate,
|
|
9741
|
-
spec.interchangeTime,
|
|
9742
|
-
spec.ackCode,
|
|
9743
|
-
spec.noteCode
|
|
9775
|
+
esc(spec.interchangeControlNumber),
|
|
9776
|
+
esc(spec.interchangeDate),
|
|
9777
|
+
esc(spec.interchangeTime),
|
|
9778
|
+
esc(spec.ackCode),
|
|
9779
|
+
esc(spec.noteCode)
|
|
9744
9780
|
]);
|
|
9745
|
-
const raw = elements.join(
|
|
9781
|
+
const raw = elements.join(delimiters.element);
|
|
9746
9782
|
return Object.freeze({ raw, elements });
|
|
9747
9783
|
}
|
|
9784
|
+
function refuseSpec9(message) {
|
|
9785
|
+
throw new AckBuildError(ACK_BUILD_ERROR_CODES.X12_ACK_INVALID_SPEC, message);
|
|
9786
|
+
}
|
|
9748
9787
|
function enforceAcceptIsClean2(spec) {
|
|
9749
9788
|
if (spec.ackCode === TA1_ACK_CODES.A && spec.noteCode !== "000") {
|
|
9750
9789
|
throw new AckBuildError(
|
|
@@ -9933,7 +9972,7 @@ var X12BuildError = class extends Error {
|
|
|
9933
9972
|
};
|
|
9934
9973
|
|
|
9935
9974
|
// src/builder/build-interchange.ts
|
|
9936
|
-
function
|
|
9975
|
+
function refuseSpec10(message) {
|
|
9937
9976
|
throw new X12BuildError(X12_BUILD_ERROR_CODES.X12_BUILD_INVALID_SPEC, message);
|
|
9938
9977
|
}
|
|
9939
9978
|
function buildInterchange(spec) {
|
|
@@ -9947,7 +9986,7 @@ function buildInterchange(spec) {
|
|
|
9947
9986
|
component: componentSeparator,
|
|
9948
9987
|
segment: segmentTerminator
|
|
9949
9988
|
};
|
|
9950
|
-
const esc = makeCallerEscaper(delimiters, "buildInterchange",
|
|
9989
|
+
const esc = makeCallerEscaper(delimiters, "buildInterchange", refuseSpec10);
|
|
9951
9990
|
const senderQualifier = spec.senderQualifier ?? "ZZ";
|
|
9952
9991
|
const receiverQualifier = spec.receiverQualifier ?? "ZZ";
|
|
9953
9992
|
const usageIndicator = spec.usageIndicator ?? "P";
|
|
@@ -10061,7 +10100,7 @@ function buildTransaction(tx, esc, elementSeparator, segmentTerminator) {
|
|
|
10061
10100
|
return st + bodySegments + se;
|
|
10062
10101
|
}
|
|
10063
10102
|
function joinSeg2(parts, elementSeparator, segmentTerminator) {
|
|
10064
|
-
requireCallerSegment(parts, "buildInterchange",
|
|
10103
|
+
requireCallerSegment(parts, "buildInterchange", refuseSpec10);
|
|
10065
10104
|
return parts.join(elementSeparator) + segmentTerminator;
|
|
10066
10105
|
}
|
|
10067
10106
|
function pad9(value, width) {
|
|
@@ -10370,7 +10409,7 @@ var profiles = Object.freeze({
|
|
|
10370
10409
|
});
|
|
10371
10410
|
|
|
10372
10411
|
// src/index.ts
|
|
10373
|
-
var VERSION = "0.0.
|
|
10412
|
+
var VERSION = "0.0.15";
|
|
10374
10413
|
|
|
10375
10414
|
exports.ACK_BUILD_ERROR_CODES = ACK_BUILD_ERROR_CODES;
|
|
10376
10415
|
exports.ALL_WARNING_MESSAGES = ALL_WARNING_MESSAGES;
|