@cosyte/x12 0.0.16 → 0.0.18
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 +232 -0
- package/KNOWN-LIMITATIONS.md +100 -37
- package/dist/index.cjs +16 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +212 -144
- package/dist/index.d.ts +212 -144
- package/dist/index.mjs +16 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,8 +7,240 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`pnpm check:no-internal-refs` - a gate on internal project bookkeeping reaching a consumer**
|
|
13
|
+
(`X12-NO-INTERNAL-REFS-GATE`), with `.github/workflows/no-internal-refs.yml` running it on every
|
|
14
|
+
push and PR. Documentation and tooling only: the `src/` half of the diff is comment-only and
|
|
15
|
+
`dist/index.mjs` / `dist/index.cjs` are byte-identical base to head.
|
|
16
|
+
|
|
17
|
+
It scans `README.md`, `TRADEMARKS.md`, `LICENSE`, `KNOWN-LIMITATIONS.md`, `docs-content/`, the npm
|
|
18
|
+
`description` and `keywords`, and the `/** */` doc comments under `src/` (which tsup compiles into
|
|
19
|
+
`dist/index.d.ts` and `dist/index.d.cts`), against six rules: item identifiers, phase and wave
|
|
20
|
+
language, ADR references, "slice" as our word for a unit of work, meta-repo paths, and bracketed
|
|
21
|
+
traceability markers. Every rule runs line by line and again over paragraph-joined text, because
|
|
22
|
+
this repo hard-wraps and a multi-token violation that straddles a wrap is invisible to a line
|
|
23
|
+
scan: on the sweep this shipped with, 52 of 124 phase-rule hits and 29 of 76 identifier hits in
|
|
24
|
+
`src/` were visible only to the reflowed pass. `CHANGELOG.md`, `.changeset/`, `CLAUDE.md`,
|
|
25
|
+
`documentation/`, `scripts/`, `test/` and `//` comments are deliberately out of scope: the
|
|
26
|
+
convention names those as where the identifiers belong.
|
|
27
|
+
|
|
28
|
+
**It is derived from the sibling parsers' copy, not transcribed from it.** Every sibling excludes
|
|
29
|
+
`X12-\d{3}[A-Z]?` and `X12-\d{6}` as standards designations to protect. In this repo `X12` is also
|
|
30
|
+
our own project prefix. Counted here with two independent tools that agreed exactly, that pattern
|
|
31
|
+
matches 141 times across tracked files and **every one of the 141 is an internal identifier**, in
|
|
32
|
+
eight spellings, with no standards designation among them; the hyphenated standards spelling it
|
|
33
|
+
exists to protect occurs zero times, because this corpus writes transaction sets and guides bare
|
|
34
|
+
(`837P`, `005010X222A1`). Carrying the sibling line verbatim reported OK over six live violations
|
|
35
|
+
on shipping carriers. Both the item spellings and the hyphenated forms are now asserted
|
|
36
|
+
individually in the self-test, each on its own, after a control run showed a shared positive
|
|
37
|
+
sample was satisfied by its first entry and covered none of the rest.
|
|
38
|
+
|
|
39
|
+
`KNOWN-LIMITATIONS.md` is scanned and is the entry no sibling copy has: this package ships it in
|
|
40
|
+
`files`, and it held most of what the gate first found.
|
|
41
|
+
|
|
42
|
+
**What it cannot do**, stated so a green run is not over-read: it reads the `src/` doc comments
|
|
43
|
+
that are the SOURCE of the published declarations, never `dist/` itself, which is untracked build
|
|
44
|
+
output this script does not build. It catches identifiers and named patterns, not ordinary English
|
|
45
|
+
sentences about how the software came to exist, so the reviewer still owns half the rule. It reads
|
|
46
|
+
file contents and never file names. It is not yet a required check on this repo, so it reds
|
|
47
|
+
visibly without blocking a merge.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- **`WARNING_MESSAGES.X12_PRE_005010` stops asserting what ISA-12 declares.** The message a consumer
|
|
52
|
+
reads off `w.message` said _"ISA-12 declares a version other than the HIPAA baseline `00501`, so
|
|
53
|
+
the input may diverge from 005010 semantics. The declared version is preserved verbatim on the
|
|
54
|
+
model."_ The guard behind it tests the twelfth element of the ISA split, so both the assertion
|
|
55
|
+
about ISA-12 and the phrase "the declared version" presuppose a header that framed. **This is a
|
|
56
|
+
runtime value, not a comment: `dist/index.mjs` and `dist/index.cjs` change here, and that is the
|
|
57
|
+
difference from the comment-only slice above.** No guard, no code, no position and no control flow
|
|
58
|
+
moved: the same interchanges raise the same codes at the same positions as before.
|
|
59
|
+
|
|
60
|
+
Measured on one interchange per row, reading ISA-12 at its own fixed byte offset and
|
|
61
|
+
again off the split:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
construction ISA-12 at its fixed offset elements[12] X12_PRE_005010 other codes
|
|
65
|
+
spec-clean "00501" "00501" silent -
|
|
66
|
+
ISA-12 declares 00401 "00401" "00401" FIRES -
|
|
67
|
+
ISA-05 carries `*` "00501" "^" FIRES X12_ISA_EXTRA_ELEMENT_SEPARATOR, X12_CONTROL_NUMBER_MISMATCH
|
|
68
|
+
ISA-06 carries `*` "00501" "^" FIRES X12_ISA_EXTRA_ELEMENT_SEPARATOR, X12_CONTROL_NUMBER_MISMATCH
|
|
69
|
+
ISA-08 carries `*` "00501" "^" FIRES X12_ISA_EXTRA_ELEMENT_SEPARATOR, X12_CONTROL_NUMBER_MISMATCH
|
|
70
|
+
ISA-13 carries `*` "00501" "00501" silent X12_ISA_EXTRA_ELEMENT_SEPARATOR
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The replacement names the element the guard read, states that raising the code does not establish
|
|
74
|
+
that the header split into `ISA` plus 16 elements, and points at `isa.raw`. It echoes no value, so
|
|
75
|
+
the message stays a static table lookup with no consumer bytes in it. `pre005010`'s docblock twin
|
|
76
|
+
of the same clause moves with it, which is why the two were left in agreement rather than
|
|
77
|
+
corrected one at a time. The shipped troubleshooting table carried a third spelling of the same
|
|
78
|
+
assertion ("ISA-12 declares a version family other than `00501`") and is corrected too.
|
|
79
|
+
|
|
80
|
+
- **Internal project bookkeeping removed from the markdown surface, the npm metadata and the
|
|
81
|
+
shipped doc comments.** Deliberately not "from every surface a consumer reads": source string
|
|
82
|
+
literals are outside this gate, and five bundled code-list snapshots still carry build-order
|
|
83
|
+
framing in an exported `note` field, which reaches `dist/index.mjs` and `dist/index.cjs` as a
|
|
84
|
+
runtime value. That is a different carrier with a different review path, it reproduces on the base,
|
|
85
|
+
and it is filed rather than folded in here. Item identifiers, "phase" build-order framing and
|
|
86
|
+
"slice" as a unit of work were translated into what the software does and what changed, in
|
|
87
|
+
`KNOWN-LIMITATIONS.md`, `docs-content/cookbook.md`, `docs-content/troubleshooting.md` and the doc
|
|
88
|
+
comments across `src/`. Nothing was deleted to
|
|
89
|
+
satisfy the gate: a doc comment removed rather than reworded would be a regression, since JSDoc
|
|
90
|
+
with `@example` on every public export is a guardrail neither lint nor coverage protects. Two
|
|
91
|
+
pages sent the reader to the package's `CLAUDE.md`, which the tarball does not ship; they now
|
|
92
|
+
point at `README.md` and the Cookbook. Measured on a local build of base commit `a3e081d`,
|
|
93
|
+
`dist/index.d.ts` carried 13 lines of item identifiers, 64 of phase and wave framing, 2 of
|
|
94
|
+
"slice" jargon and 1 meta-repo path, with `dist/index.d.cts` byte-identical to it; at head all
|
|
95
|
+
four counts are zero and the two twins remain byte-identical to each other. Zero on the rules is
|
|
96
|
+
the weaker statement: six lines of phase framing survived the first sweep while every rule read
|
|
97
|
+
zero, four ending in punctuation and two using the PLURAL `Phases`, which rule 2 cannot see because
|
|
98
|
+
it requires `phase` followed by an alphanumeric. All six were then translated, so the built
|
|
99
|
+
declaration file now contains no occurrence of the word at all. The plural form remains ungated and
|
|
100
|
+
is disclosed as such.
|
|
101
|
+
|
|
102
|
+
- **🩺 `X12_ISA_EXTRA_ELEMENT_SEPARATOR` - the ISA element split now has an arity check**
|
|
103
|
+
(`X12-ISA-ELEMENT-ARITY`). Additions-only: no decoding moved, no existing warning was suppressed or
|
|
104
|
+
narrowed, and nothing is re-framed.
|
|
105
|
+
|
|
106
|
+
`decodeIsa` splits the 105-byte ISA element area on the element separator, and the comment above it
|
|
107
|
+
asserted the result was "exactly 17 entries by construction because the element-separator-position
|
|
108
|
+
guard in `delimiters.ts` already verified the layout". That guard verifies the separator at all 16
|
|
109
|
+
fixed 005010 positions, which bounds the split from BELOW - it can never come out short. It was
|
|
110
|
+
never bounded from above. An ISA element value carrying that same byte splits again, so the element
|
|
111
|
+
comes back a prefix and everything after it is displaced. **How far is not derivable from
|
|
112
|
+
`isa.elements`**: more than one element can carry an extra separator, and one sitting between two
|
|
113
|
+
of them is displaced less than one sitting after both. `isa.raw` plus the ISA's fixed widths is the
|
|
114
|
+
only route back.
|
|
115
|
+
|
|
116
|
+
Planting the element separator inside each of the 16 fixed elements of one conformant interchange,
|
|
117
|
+
measured at `0.0.16`:
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
planted in split parts warnings at 0.0.16
|
|
121
|
+
ISA-01..10 18 X12_PRE_005010, X12_CONTROL_NUMBER_MISMATCH
|
|
122
|
+
ISA-11 - X12_INVALID_DELIMITERS (Tier-3, reached first)
|
|
123
|
+
ISA-12 18 X12_PRE_005010, X12_CONTROL_NUMBER_MISMATCH
|
|
124
|
+
ISA-13 18 X12_CONTROL_NUMBER_MISMATCH
|
|
125
|
+
ISA-14 18 (none)
|
|
126
|
+
ISA-15 18 (none)
|
|
127
|
+
ISA-16 - X12_INVALID_DELIMITERS (Tier-3, reached first)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
ISA-11 and ISA-16 ARE the in-band repetition and component separator declarations, so the plant
|
|
131
|
+
collides with them and the Tier-3 refusal reaches it before any of this. That is a boundary of the
|
|
132
|
+
probe, not a property of those two elements.
|
|
133
|
+
|
|
134
|
+
On the `ISA-01..10` and `ISA-12` rows the document declares `00501` at ISA-12's own fixed offset and
|
|
135
|
+
`X12_PRE_005010` fires anyway; `elements[13]`, the interchange control number and the reassociation
|
|
136
|
+
key, answers `"00501"`; and `elements[15]`, the test/production usage indicator, answers `"0"` on a
|
|
137
|
+
document whose ISA-15 says `P`. The `ISA-14` and `ISA-15` rows were reported on no channel at all.
|
|
138
|
+
|
|
139
|
+
`parseX12` raises the new warning BEFORE the ISA-derived checks that read `elements[12]` and
|
|
140
|
+
`elements[13]` by index, because when it fires those two may be reading a displaced element rather
|
|
141
|
+
than the one they name. `{ strict: true }` therefore escalates on it rather than on the warning that
|
|
142
|
+
follows. **That is a statement about `ix.warnings` and `onWarning` only.** `serializeX12(ix,
|
|
143
|
+
{ specClean: true })` reconciles ISA-13 against IEA-02 off `isa.elements[13]` with no arity
|
|
144
|
+
awareness and never raises this code, so on that channel a lone `X12_CONTROL_NUMBER_MISMATCH` can be
|
|
145
|
+
a displaced read of a control number that matches byte for byte at its fixed span, and the absence
|
|
146
|
+
of this warning there is not evidence the header framed. Pre-existing, disclosed, not fixed.
|
|
147
|
+
|
|
148
|
+
**It is a report, not a repair.** A byte that is both an element's content under the ISA's fixed
|
|
149
|
+
widths and the separator that same segment declares in-band has two readings; the interchange is
|
|
150
|
+
not 005010-conformant either way, and nothing anyone here has read settles which reading to take,
|
|
151
|
+
so `isa.elements` is left exactly as the split produced it and `isa.raw` still carries all 106
|
|
152
|
+
bytes, which is the route back.
|
|
153
|
+
|
|
154
|
+
**The emit side is untouched, and this is not a build-side guard.** The fixed-width ISA slots go
|
|
155
|
+
through `pad` / `padControl` and never through the caller escaper, so `buildInterchange` still
|
|
156
|
+
writes such a caller value straight onto the wire. It does now surface there, because
|
|
157
|
+
`buildInterchange` returns `parseX12` of the bytes it just wrote:
|
|
158
|
+
`interchangeControlNumber: "0000*0001"` came back with ISA-13 reading `"0000"`, ISA-15 reading
|
|
159
|
+
`"0"` instead of `"P"`, IEA-02 displaced the same way so the control-number reconciliation agreed
|
|
160
|
+
with the misreading, and `warnings: []`.
|
|
161
|
+
|
|
10
162
|
### Documentation
|
|
11
163
|
|
|
164
|
+
- **`IsaSegment` and the `X12_PRE_005010` warning factory no longer document a raw ISA element as the
|
|
165
|
+
value it holds** (`X12-ISA-VALUE-POINTERS`). **Documentation only: the diff is comment-only, and
|
|
166
|
+
`dist/index.mjs` and `dist/index.cjs` are byte-identical before and after, so no behaviour moved.**
|
|
167
|
+
The corrected text ships in `dist/index.d.ts` and `dist/index.d.cts`.
|
|
168
|
+
|
|
169
|
+
`isa.elements` holds raw byte text. `IsaSegment` called it "the 16 ISA values" and its `@example`
|
|
170
|
+
handed out `isa.elements[12]; // ISA-12 - version, expected "00501"` and
|
|
171
|
+
`isa.elements[13]; // ISA-13 - interchange control number`, while `pre005010`'s JSDoc said "The
|
|
172
|
+
declared version stays on `isa.elements[12]`". Measured on 005010 interchanges, one per row, plus
|
|
173
|
+
two rows this library emitted and read back:
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
construction cell stated / at that ISA offset elements[n] warnings
|
|
177
|
+
spec-clean elements[12] "00501" "00501" []
|
|
178
|
+
spec-clean elements[13] "000000001" "000000001" []
|
|
179
|
+
ISA-12 declares 00401 elements[12] "00401" "00401" X12_PRE_005010
|
|
180
|
+
ISA-06 carries `*` elements[12] "00501" "^" X12_ISA_EXTRA_ELEMENT_SEPARATOR, X12_PRE_005010, X12_CONTROL_NUMBER_MISMATCH
|
|
181
|
+
ISA-06 carries `*` elements[13] "000000001" "00501" X12_ISA_EXTRA_ELEMENT_SEPARATOR, X12_PRE_005010, X12_CONTROL_NUMBER_MISMATCH
|
|
182
|
+
ISA-13 carries `*` elements[12] "00501" "00501" X12_ISA_EXTRA_ELEMENT_SEPARATOR
|
|
183
|
+
ISA-13 carries `*` elements[13] "0000*0001" "0000" X12_ISA_EXTRA_ELEMENT_SEPARATOR
|
|
184
|
+
ISA-13 carries `?` elements[13] "00000001?" "00000001?" X12_CONTROL_NUMBER_MISMATCH
|
|
185
|
+
this library's own emit, stated " " elements[13] " " "00000000 " []
|
|
186
|
+
this library's own emit, stated "1" elements[13] "1" "000000001" []
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
On the `ISA-06` rows the interchange declares `00501` at ISA-12's own fixed offset,
|
|
190
|
+
`X12_PRE_005010` fires anyway, and the sentence the consumer was holding sent them to an element
|
|
191
|
+
that answers `"^"`. On the `ISA-13 carries ?` row the `?` is content, because the ISA split is
|
|
192
|
+
deliberately not release-aware; its `X12_CONTROL_NUMBER_MISMATCH` is the fixture and not a finding.
|
|
193
|
+
|
|
194
|
+
**Two mechanisms falsify a cell on their own** - fixed-width padding, which needs no `?` and no
|
|
195
|
+
anomaly at all, and the arity displacement `X12_ISA_EXTRA_ELEMENT_SEPARATOR` reports - **so no
|
|
196
|
+
mechanism is named as the reason, the set of them is not published as closed, and nothing here says
|
|
197
|
+
which ISA element is special.**
|
|
198
|
+
|
|
199
|
+
The `pre005010` pointer is deleted outright, with nothing put back. `IsaSegment` gains the raw
|
|
200
|
+
label, keeps ISA-12's and ISA-13's semantics restated at segment level where they are true, and its
|
|
201
|
+
`@example` keeps one indexed pointer plus `.raw`, the same shape the four sibling envelope types
|
|
202
|
+
already carry. **The label is NOT the siblings' label**: theirs reads "pre-`?`-unescape", which is
|
|
203
|
+
false on the ISA. **The 1-indexed mapping onto ISA-01..ISA-16 is scoped to a 17-entry split rather
|
|
204
|
+
than deleted, and no shift is quantified.** No accessor, guard or test was added, and no route is
|
|
205
|
+
named as the route for reading an ISA element.
|
|
206
|
+
|
|
207
|
+
- **`IeaSegment`, `GsSegment`, `GeSegment`, `Ta1Segment` and `X12FunctionalGroup` no longer document
|
|
208
|
+
a raw envelope element as the value it holds** (`X12-ENVELOPE-VALUE-EXAMPLES`). **Documentation
|
|
209
|
+
only: the diff is comment-only, and `dist/index.mjs` and `dist/index.cjs` are byte-identical
|
|
210
|
+
before and after, so no behaviour moved.** The corrected text ships in `dist/index.d.ts`.
|
|
211
|
+
|
|
212
|
+
**Element values on those segment types are stored RAW, pre-`?`-unescape.** Their JSDoc named the
|
|
213
|
+
index and then named the value it holds - "IEA-02 interchange control number - must match ISA-13",
|
|
214
|
+
"GS-06 group control number", "TA1-01 (echoes the prior interchange's ISA-13 control number)" -
|
|
215
|
+
and repeated the promise inside an `@example` fence, which is the form a consumer copies. Measured
|
|
216
|
+
on one interchange where each documented non-ISA slot carries the sender-intended value `A*B`,
|
|
217
|
+
written on the wire in released form `A?*B`, **every one of those cells reads back `"A?*B"` and
|
|
218
|
+
not `"A*B"`.**
|
|
219
|
+
|
|
220
|
+
The same correction is applied to `parseX12`'s own `@example`, which handed out `// "HC"` at
|
|
221
|
+
`gs.elements[1]`.
|
|
222
|
+
|
|
223
|
+
On a `TA1` that `buildTA1` emitted and `parseX12` read back:
|
|
224
|
+
|
|
225
|
+
```text
|
|
226
|
+
stated TA1-01 emitted TA1 elements[1] parseTA1()
|
|
227
|
+
"000000001" TA1*000000001*260601*1200*A*000 "000000001" "000000001"
|
|
228
|
+
"0000*0001" TA1*0000?*0001*260601*1200*A*000 "0000?*0001" "0000*0001"
|
|
229
|
+
"0000~0001" TA1*0000?~0001*260601*1200*A*000 "0000?~0001" "0000~0001"
|
|
230
|
+
"00000001?" TA1*00000001??*260601*1200*A*000 "00000001??" "00000001?"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Every row `warnings: []`. TA1-01 is the reassociation key, so a consumer following the shipped
|
|
234
|
+
`@example` compared framed bytes against the ISA-13 it was acknowledging. `parseTA1` already read
|
|
235
|
+
the same bytes correctly, so the package disagreed with itself.
|
|
236
|
+
|
|
237
|
+
**Each block now carries the label `X12Segment` has always carried** - "Element values are stored
|
|
238
|
+
RAW, pre-`?`-unescape" - and the `@example` pointers keep their index and lose the promise. The
|
|
239
|
+
slot mapping (`elements[2]` = IEA-02) was true and is kept, and so are the element names, the
|
|
240
|
+
formats and the code-list citations, restated where they are true: as facts about the segment's
|
|
241
|
+
fields rather than about a raw element. No accessor, guard or test was added, and **no route is
|
|
242
|
+
named as the route.**
|
|
243
|
+
|
|
12
244
|
- **The documentation carriers that told you to read an envelope element's logical value through
|
|
13
245
|
`getSegmentValue` are corrected** (`X12-ENVELOPE-VALUE-ROUTES`). **Documentation and tests only: no
|
|
14
246
|
runtime line changed and the emitted JS is byte-identical, so no behaviour moved.**
|
package/KNOWN-LIMITATIONS.md
CHANGED
|
@@ -16,13 +16,77 @@ model.
|
|
|
16
16
|
|
|
17
17
|
## Data / decode boundaries
|
|
18
18
|
|
|
19
|
+
- **🩺 An ISA element carrying the element separator makes the header split into more than
|
|
20
|
+
`ISA` + 16 elements. Through `0.0.16` no check saw that at all; it is now reported as
|
|
21
|
+
`X12_ISA_EXTRA_ELEMENT_SEPARATOR`.** **Nothing is
|
|
22
|
+
re-framed: this is a report, not a repair, and no existing warning was suppressed or narrowed.**
|
|
23
|
+
|
|
24
|
+
`detectDelimiters` verifies the element separator at all 16 fixed 005010 byte positions, so the
|
|
25
|
+
ISA split can never come out SHORT. It was never bounded from ABOVE. An element value carrying
|
|
26
|
+
that same byte splits again, so that element comes back a **prefix** and everything after it is
|
|
27
|
+
**displaced**. **🛑 How far is NOT derivable from `isa.elements`, and no arithmetic on it works.**
|
|
28
|
+
More than one element can carry an extra separator, and an element sitting between two of them is
|
|
29
|
+
displaced less than one sitting after both; `isa.raw` plus the ISA's fixed widths is the only route
|
|
30
|
+
back. Measured on one conformant interchange, planting the element separator inside each of the 16
|
|
31
|
+
fixed elements in turn:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
planted in split parts warnings through 0.0.16
|
|
35
|
+
ISA-01..10 18 X12_PRE_005010, X12_CONTROL_NUMBER_MISMATCH
|
|
36
|
+
ISA-11 - X12_INVALID_DELIMITERS (Tier-3, thrown before any of this)
|
|
37
|
+
ISA-12 18 X12_PRE_005010, X12_CONTROL_NUMBER_MISMATCH
|
|
38
|
+
ISA-13 18 X12_CONTROL_NUMBER_MISMATCH
|
|
39
|
+
ISA-14 18 (none)
|
|
40
|
+
ISA-15 18 (none)
|
|
41
|
+
ISA-16 - X12_INVALID_DELIMITERS (Tier-3, thrown before any of this)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
ISA-11 and ISA-16 **are** the in-band repetition and component separator declarations, so planting
|
|
45
|
+
the element separator there collides with them and the Tier-3 refusal reaches it first. That is a
|
|
46
|
+
boundary of the probe, not a claim that those two elements are special.
|
|
47
|
+
|
|
48
|
+
**What the displaced reads cost, on the rows that had a warning as much as on the rows that had
|
|
49
|
+
none.** On the `ISA-01..10` and `ISA-12` rows the interchange declares `00501` at ISA-12's own
|
|
50
|
+
fixed offset and `X12_PRE_005010` fires anyway, because `elements[12]` has become the repetition
|
|
51
|
+
separator; `elements[13]`, the interchange control number and the reassociation key, answers
|
|
52
|
+
`"00501"`; and `elements[15]`, the test/production usage indicator, answers `"0"` on a document
|
|
53
|
+
whose ISA-15 says `P`. On the `ISA-13` row the control number is a prefix. **The `ISA-14` and
|
|
54
|
+
`ISA-15` rows carried `warnings: []`** while the usage indicator read empty.
|
|
55
|
+
|
|
56
|
+
**The route back is `isa.raw`**, which still carries all 106 bytes verbatim, and the ISA's fixed
|
|
57
|
+
widths make the transmitted span of any element recoverable from it. Recovering it is **your**
|
|
58
|
+
decision, not this library's: a byte that is both an element's content under those fixed widths and
|
|
59
|
+
the separator the same segment declares in-band has two readings, the interchange is not
|
|
60
|
+
005010-conformant either way, and nothing anyone here has read says which reading to take. So the
|
|
61
|
+
parser reports that the header did not frame and leaves `isa.elements` exactly as the split
|
|
62
|
+
produced it.
|
|
63
|
+
|
|
64
|
+
**When this warning is present, treat every other ISA-derived diagnostic on that interchange as
|
|
65
|
+
provisional.** `parseX12` raises it ahead of the ones it raises after it for that reason, which
|
|
66
|
+
also means `{ strict: true }` escalates on it rather than on the displaced-value warning that
|
|
67
|
+
follows. **🩺 Read that as a statement about `ix.warnings` and `onWarning`, and about nothing
|
|
68
|
+
else.** `serializeX12(ix, { specClean: true })` reconciles ISA-13 against IEA-02 off
|
|
69
|
+
`isa.elements[13]` with no arity awareness and **never raises this code at all**, so on that
|
|
70
|
+
channel a lone `X12_CONTROL_NUMBER_MISMATCH` can be a displaced read of a control number that in
|
|
71
|
+
fact matches byte for byte at its fixed span, and **the absence of this warning there is not
|
|
72
|
+
evidence the header framed**. Pre-existing, disclosed, not fixed here.
|
|
73
|
+
|
|
74
|
+
**The emit side is unchanged and is NOT guarded by this.** The fixed-width ISA slots go through
|
|
75
|
+
`pad` / `padControl` and never through the caller escaper, so `buildInterchange` still writes a
|
|
76
|
+
caller value carrying the element separator straight onto the wire. What changed is that
|
|
77
|
+
`buildInterchange` returns `parseX12` of the bytes it just wrote, so the report now reaches that
|
|
78
|
+
path too: `interchangeControlNumber: "0000*0001"` used to come back with ISA-13 reading `"0000"`,
|
|
79
|
+
ISA-15 reading `"0"` instead of `"P"`, IEA-02 displaced the same way so the control-number
|
|
80
|
+
reconciliation **agreed with the misreading**, and `warnings: []`. Refusing such a value on emit is
|
|
81
|
+
a decision about the build side and is not taken here.
|
|
82
|
+
|
|
19
83
|
- **🩺 `parseTA1`'s five decoded fields are POST-`?`-unescape as of this release, and an EMPTY
|
|
20
|
-
TA1-02 / TA1-03 / TA1-04 / TA1-05 is REFUSED on emit. Both are behaviour changes
|
|
21
|
-
|
|
84
|
+
TA1-02 / TA1-03 / TA1-04 / TA1-05 is REFUSED on emit. Both are behaviour changes.**
|
|
85
|
+
They are one change because they are the two ends of the same disagreement:
|
|
22
86
|
this package's emit half releases a TA1 element and its read half decoded the escape rather than
|
|
23
87
|
the value.
|
|
24
88
|
|
|
25
|
-
**The read half.**
|
|
89
|
+
**The read half.** An earlier release made `buildTA1` release all five caller
|
|
26
90
|
elements, and `parseTA1` kept reading `elements` verbatim, so a round trip through this package's
|
|
27
91
|
own halves was not an identity for any value carrying a delimiter or the release character.
|
|
28
92
|
Measured at `0.0.15`, over `parseX12` + `parseTA1` of what `buildTA1` had just emitted:
|
|
@@ -69,12 +133,12 @@ model.
|
|
|
69
133
|
first, so an `ackCode: "A"` with an empty note still reports `X12_TA1_ACCEPT_WITH_NOTE`; TA1-01
|
|
70
134
|
still draws the control-number refusal; and every wrong-TYPED element still draws the escape
|
|
71
135
|
helper's refusal, because all five escapes run before any emptiness test. **No spec that was
|
|
72
|
-
refused before this
|
|
73
|
-
- **No census of other builders' required elements is published here.** This
|
|
136
|
+
refused before this change is refused differently by it.**
|
|
137
|
+
- **No census of other builders' required elements is published here.** This change measured TA1.
|
|
74
138
|
|
|
75
139
|
- **🩺 `implementationConventionReference` is POST-`?`-unescape as of this release, in every typed
|
|
76
140
|
reader that publishes it, and that is a behaviour change on documents whose `ST-03` carries a
|
|
77
|
-
release escape
|
|
141
|
+
release escape.** `tx.st.elements` is the ST segment as framed:
|
|
78
142
|
post-element-split and PRE-unescape. Five public
|
|
79
143
|
readers were handing one of those strings straight back on the model - `get837Claims`,
|
|
80
144
|
`get277Status`, `get277CADisposition`, `get278Request` and `get278Response` - so a sender that
|
|
@@ -119,8 +183,8 @@ model.
|
|
|
119
183
|
`unescapeRelease` to `submission.implementationConventionReference` yourself, drop that call.
|
|
120
184
|
|
|
121
185
|
- **🩺 An EMPTY control number is REFUSED on emit as of this release, where it used to be
|
|
122
|
-
FABRICATED, and that is a behaviour change for any caller passing one
|
|
123
|
-
|
|
186
|
+
FABRICATED, and that is a behaviour change for any caller passing one.**
|
|
187
|
+
Every builder that assembles an ISA zero-pads its control
|
|
124
188
|
number to the nine characters ASC X12 .5 fixes ISA-13 at. `padControl("1", 9)` answering
|
|
125
189
|
`"000000001"` is the point of that; `padControl("", 9)` answering `"000000000"` was not, and
|
|
126
190
|
nothing stood in front of it, so `interchangeControlNumber: ""` produced a frozen, well-formed
|
|
@@ -173,7 +237,7 @@ model.
|
|
|
173
237
|
`X12_ACK_INVALID_SPEC` now. If you branch on a specific builder error code, that pairing moved.
|
|
174
238
|
|
|
175
239
|
- **🩺 Which `ST-03` implementation-convention references resolve to an 837 variant CHANGED in this
|
|
176
|
-
release, and some already-published files therefore decode differently
|
|
240
|
+
release, and some already-published files therefore decode differently.**
|
|
177
241
|
Through `0.0.13` `get837Claims` recognised exactly three references: `005010X222A2`, `005010X223A3`
|
|
178
242
|
and `005010X224A2`. **That set contained none of the identifiers HIPAA adopts at 45 CFR 162.1102**
|
|
179
243
|
(`005010X222`, `005010X223` + `005010X223A1`, `005010X224` + `005010X224A1`), **and it was missing
|
|
@@ -209,8 +273,8 @@ model.
|
|
|
209
273
|
- **The set is not claimed exhaustive and no count of it is published**, here or in any warning
|
|
210
274
|
message. Both variant messages named the three old keys literally and were wrong the moment the
|
|
211
275
|
table was corrected, so neither enumerates the set any more.
|
|
212
|
-
- **🩺 CLOSED, in the
|
|
213
|
-
|
|
276
|
+
- **🩺 CLOSED, in the change after this one: the emit side takes a caller override.**
|
|
277
|
+
`build837P` / `build837I` / `build837D` still DEFAULT to
|
|
214
278
|
`005010X222A2` / `005010X223A3` / `005010X224A2` in ST-03 and GS-08, and
|
|
215
279
|
**`Build837EnvelopeSpec.implementationConventionReference` now states another** - one value,
|
|
216
280
|
both elements. Two of the defaults are not what the companion guides above require, so a partner
|
|
@@ -237,8 +301,7 @@ model.
|
|
|
237
301
|
ST-03.
|
|
238
302
|
|
|
239
303
|
- **🩺 A `?` immediately before the element separator inside an envelope segment now frames as ONE
|
|
240
|
-
element, and that is a SYMMETRIC behaviour change on already-published decoding
|
|
241
|
-
(`X12-ENVELOPE-SPLITTER-NOT-RELEASE-AWARE`).
|
|
304
|
+
element, and that is a SYMMETRIC behaviour change on already-published decoding.**
|
|
242
305
|
Through `0.0.14` the envelope segments' element splitter was a plain `String.prototype.split`, so a
|
|
243
306
|
released element separator (`?*`) still ended the element and SHIFTED every element after it down a
|
|
244
307
|
slot. It was a property of the whole envelope segment and never of one element, so the element a
|
|
@@ -293,7 +356,7 @@ model.
|
|
|
293
356
|
`responsibleAgencyCode`) at this release. A `groupDate` of `"2026060?"` emitted
|
|
294
357
|
`GS*HC*SENDER*RECEIVER*2026060?*1200*1*X*005010X222A1`, which its own return value read as nine
|
|
295
358
|
elements with GS-08 intact through `0.0.14` and read as **eight** at `0.0.15`, GS-08 gone, plus
|
|
296
|
-
`X12_CONTROL_NUMBER_MISMATCH`. **Closed by
|
|
359
|
+
`X12_CONTROL_NUMBER_MISMATCH`. **Closed by a later release** - that
|
|
297
360
|
entry is at the top of this section and it is the one that describes the current tree.
|
|
298
361
|
|
|
299
362
|
- **An envelope element ending in a literal `?` is a dangling release character and is NOT warned.**
|
|
@@ -329,8 +392,8 @@ model.
|
|
|
329
392
|
at `0.0.14` it released GS-02 on emit and then answered GS-08 as `"X"` from its own return value.
|
|
330
393
|
|
|
331
394
|
- **🩺 A BODY segment in an interchange whose ELEMENT SEPARATOR is `?` now frames its elements,
|
|
332
|
-
where it used to come back as ONE element with an id of `(non-spec)
|
|
333
|
-
|
|
395
|
+
where it used to come back as ONE element with an id of `(non-spec)`.**
|
|
396
|
+
`detectDelimiters` reads the element separator
|
|
334
397
|
positionally out of ISA byte 4 and rejects only control characters, whitespace and a non-distinct
|
|
335
398
|
set, so a sender may declare `?` there, and `buildInterchange` accepted `elementSeparator: "?"`
|
|
336
399
|
from a caller when this was measured (it refuses now - see the emit-side entry below).
|
|
@@ -367,8 +430,8 @@ model.
|
|
|
367
430
|
of them. Splitting those two roles literally would re-frame that as two empty components, so it
|
|
368
431
|
would stop reading a value this library itself wrote. **That reason survives the emit-side
|
|
369
432
|
refusal below - those documents exist**, which is why the read side did not move with it.
|
|
370
|
-
- **🟢 CLOSED, in the
|
|
371
|
-
|
|
433
|
+
- **🟢 CLOSED, in the change after this one, and WIDER than it was filed:
|
|
434
|
+
every builder REFUSES a delimiter set in which any of
|
|
372
435
|
the four roles is `?`.** The entry as filed named the element separator and one mechanism - a
|
|
373
436
|
caller VALUE the escape cannot protect, because the protecting `?` is itself the separator. Two
|
|
374
437
|
things were measured wrong about that:
|
|
@@ -433,7 +496,7 @@ model.
|
|
|
433
496
|
terminator.** `findUnescapedTerminator` guards its own role only, so with `?` as the element
|
|
434
497
|
separator a segment that ends in an EMPTY LAST ELEMENT puts a `?` immediately before the
|
|
435
498
|
terminator and the scanner reads it as an escape: `PER?IC?NAME?TE?5551234?EX?~SE?3?0001~` frames
|
|
436
|
-
as ONE segment and raises `X12_MISSING_SE`. This
|
|
499
|
+
as ONE segment and raises `X12_MISSING_SE`. This change does not touch framing. But **the READ of
|
|
437
500
|
that merged blob did move, so do not take "framing is untouched" as "nothing about this residual
|
|
438
501
|
moved"**: at `0.0.15` the merge produced one `(non-spec)` element no walker looked at, and here
|
|
439
502
|
it frames, so `~SE` and the SE's own control number land in `PER`'s communication-number slots.
|
|
@@ -446,8 +509,8 @@ model.
|
|
|
446
509
|
gives: it is fixed-width, which is what lets the delimiters be recovered from it at all.
|
|
447
510
|
|
|
448
511
|
- **🩺 `buildInterchange` now RELEASES GS-04, GS-05 and GS-07, so the interchange it hands back
|
|
449
|
-
reports the values you passed, and the bytes it writes for such a value CHANGED
|
|
450
|
-
|
|
512
|
+
reports the values you passed, and the bytes it writes for such a value CHANGED.**
|
|
513
|
+
Through `0.0.15` it mapped its release escaper over
|
|
451
514
|
GS-01, GS-02, GS-03, GS-06 and GS-08 and wrote `groupDate` (GS-04), `groupTime` (GS-05) and
|
|
452
515
|
`responsibleAgencyCode` (GS-07) raw. It returns `parseX12` of the bytes it just wrote, so a value
|
|
453
516
|
carrying an active delimiter in one of those three took a slot of its own and shifted every element
|
|
@@ -508,8 +571,8 @@ model.
|
|
|
508
571
|
active delimiter is still not safe anywhere, because that is what a delimiter is.
|
|
509
572
|
|
|
510
573
|
- **🩺 `buildTA1` now RELEASES its five caller-supplied elements, so an Accept acknowledgment this
|
|
511
|
-
library emits no longer reads back as a Reject, and the bytes it writes for such a value CHANGED
|
|
512
|
-
|
|
574
|
+
library emits no longer reads back as a Reject, and the bytes it writes for such a value CHANGED.**
|
|
575
|
+
Through `0.0.14` `buildTA1` joined the five values with the
|
|
513
576
|
element separator and escaped none of them, so a value carrying an active delimiter took a slot of
|
|
514
577
|
its own and shifted every element after it down one. TA1-04 is the disposition and TA1-05 the note,
|
|
515
578
|
and `parseTA1` narrows an out-of-enum TA1-04 to `R`. Measured with `parseX12` + `parseTA1` over
|
|
@@ -560,19 +623,19 @@ model.
|
|
|
560
623
|
No total is published: that is what was measured, not a closed account. (`getSegmentValue`
|
|
561
624
|
takes an `X12Segment` and `Ta1Segment` carries no `id`, so add one to read a TA1 through it.)
|
|
562
625
|
**🩺 A clause naming `parseTA1`'s fields as a third such surface stood here and is DELETED, not
|
|
563
|
-
reworded** -
|
|
626
|
+
reworded** - a later release made those fields post-unescape, so it is measured false.
|
|
564
627
|
- **A caller who was hand-rolling the escape** (the remedy this file named while the defect was
|
|
565
628
|
open) regresses on both kinds of surface: `"00000001??"` in, `TA1*00000001????*…` out, and
|
|
566
629
|
`getSegmentValue` answering `"00000001??"` where it answered `"00000001?"`. The framing and the
|
|
567
630
|
disposition stay correct, but **drop the hand-rolled escape.**
|
|
568
|
-
- **An EMPTY control number was not refused by this
|
|
631
|
+
- **An EMPTY control number was not refused by this change, and is refused by the NEXT one.**
|
|
569
632
|
`escapeRelease` early-returns on `""` and `buildTA1` carried no required-field guard, so
|
|
570
633
|
`interchangeControlNumber: ""` emitted `TA1**260601*1200*A*000` with `warnings: []`, here and at
|
|
571
|
-
every earlier release.
|
|
634
|
+
every earlier release. A later release closed it across every builder; see
|
|
572
635
|
the entry at the top of this file, including the whitespace-only residual it leaves open.
|
|
573
|
-
- **🩺 The READ half did not move IN THIS
|
|
636
|
+
- **🩺 The READ half did not move IN THIS CHANGE, and a later release is the one that moved
|
|
574
637
|
it** - see the entry at the top of this file. A control number of `"00000001?"` read back as
|
|
575
|
-
`"00000001?*260601"` before
|
|
638
|
+
`"00000001?*260601"` before the EMIT half moved and as `"00000001??"` after it; the clause that stood
|
|
576
639
|
here telling callers to apply `unescapeRelease` themselves is **deleted, not reworded**, because
|
|
577
640
|
the library now does it.
|
|
578
641
|
- **The release is scoped to the delimiter set the CALLER states.** `BuildTA1Options` gained
|
|
@@ -593,12 +656,12 @@ model.
|
|
|
593
656
|
`X12_TA1_ACCEPT_WITH_NOTE` and still runs first.
|
|
594
657
|
- **What this does NOT close.** `buildTA1` still uses no segment joiner, so its refusal names the
|
|
595
658
|
builder and never the slot; `buildInterchange` did not escape GS-04 / GS-05 / GS-07 at this
|
|
596
|
-
release, which
|
|
659
|
+
release, which a later one then closed; and an unescaped active
|
|
597
660
|
delimiter is still not safe anywhere, because that is what a delimiter is.
|
|
598
661
|
|
|
599
662
|
- **🩺 BREAKING for `build277` callers: a 277 service line now REQUIRES `unitsOfService`, because
|
|
600
|
-
SVC-07 is a required element in `005010X212` and this library was not emitting it at all
|
|
601
|
-
|
|
663
|
+
SVC-07 is a required element in `005010X212` and this library was not emitting it at all.**
|
|
664
|
+
Through the release before this one `get277Status` read SVC-01
|
|
602
665
|
through SVC-04 and stopped, and `build277` emitted exactly those four, so **every X212 277 this
|
|
603
666
|
library produced with a Loop 2220 service line was short a required element** and every 277 it read
|
|
604
667
|
silently discarded the submitted units. Both sides are fixed: `X12ServiceLineStatus.unitsOfService`
|
|
@@ -632,7 +695,7 @@ model.
|
|
|
632
695
|
string** - at base the same spec emitted a bare `SVC~`, because the SVC-07 slot did not exist. `SVC-03` (Line Item Payment
|
|
633
696
|
Amount) is usage **R** in X212 and usage **N** in X214 and is optional in both builders. And the
|
|
634
697
|
read side is unchanged and still lenient: an X212 277 arriving with no SVC-07 raises **no
|
|
635
|
-
warning**, because that would need a new Tier-2 registry code and the defect this
|
|
698
|
+
warning**, because that would need a new Tier-2 registry code and the defect this change closes is
|
|
636
699
|
on the emit side. All of it is pre-existing and reproduces at `e3cdf49`; widening the guard would
|
|
637
700
|
have turned this into that audit, which is its own item.
|
|
638
701
|
|
|
@@ -1178,7 +1241,7 @@ Code"`, `SVC05 / 380 / "Units of Service Paid Count"`, `SVC06 / C003`,
|
|
|
1178
1241
|
|
|
1179
1242
|
**`undefined` on either quantity still means "not decoded", not "absent".** The element may have
|
|
1180
1243
|
been missing, or present and unparseable as a decimal; the two share one `undefined` on the model.
|
|
1181
|
-
They no longer share a silence: as of
|
|
1244
|
+
They no longer share a silence: as of an earlier release the unparseable case raises
|
|
1182
1245
|
`X12_UNPARSEABLE_DECIMAL` at that `position.elementIndex` and the absent case raises nothing, so a
|
|
1183
1246
|
warning at the element is what tells them apart. The verbatim element is still on `tx.segments`.
|
|
1184
1247
|
|
|
@@ -1188,7 +1251,7 @@ Code"`, `SVC05 / 380 / "Units of Service Paid Count"`, `SVC06 / C003`,
|
|
|
1188
1251
|
no warning. Re-emitting from the model with this release produces conformant bytes.
|
|
1189
1252
|
|
|
1190
1253
|
**The 277's SVC-07 is a different element in a different TR3 and is now decoded and emitted in its
|
|
1191
|
-
own right** (
|
|
1254
|
+
own right** (see the 277 entry below). Do not read either field off the other.
|
|
1192
1255
|
|
|
1193
1256
|
- **Bundled code-list snapshots are pre-launch initial subsets, not the full WPC-published lists.**
|
|
1194
1257
|
CARC, RARC, Claim-Status-Category (CSCC), Claim-Status (CSC), service-type, CLP-status, and
|
|
@@ -1445,7 +1508,7 @@ N-char spec limit` refusal, one per emitting module, where the branch fires **be
|
|
|
1445
1508
|
**Read the "through a builder's segment joiner" qualifier literally.** `buildTA1` does not use one,
|
|
1446
1509
|
and is therefore **not covered by the segment guard**. Through `0.0.14` that meant nothing checked
|
|
1447
1510
|
its five elements at all, and a numeric or `undefined` `interchangeControlNumber` was emitted
|
|
1448
|
-
silently (`TA1**250101*1200*A*000`);
|
|
1511
|
+
silently (`TA1**250101*1200*A*000`); a later release closed that by routing them
|
|
1449
1512
|
through the escape helper, which type-checks first and refuses with `AckBuildError` /
|
|
1450
1513
|
`X12_ACK_INVALID_SPEC`. What being outside the segment guard still costs is the **slot** in the
|
|
1451
1514
|
refusal message: it names `buildTA1`, never `TA1-01`.
|
|
@@ -1617,5 +1680,5 @@ the maintainers have not reviewed.
|
|
|
1617
1680
|
|
|
1618
1681
|
---
|
|
1619
1682
|
|
|
1620
|
-
For the
|
|
1621
|
-
[`
|
|
1683
|
+
For the per-transaction read and emit surface, and the exact fields each helper decodes, see
|
|
1684
|
+
[`README.md`](./README.md) and the Cookbook on the documentation site.
|
package/dist/index.cjs
CHANGED
|
@@ -121,6 +121,7 @@ function detectDelimiters(raw) {
|
|
|
121
121
|
var WARNING_CODES = {
|
|
122
122
|
X12_CONTROL_NUMBER_MISMATCH: "X12_CONTROL_NUMBER_MISMATCH",
|
|
123
123
|
X12_PRE_005010: "X12_PRE_005010",
|
|
124
|
+
X12_ISA_EXTRA_ELEMENT_SEPARATOR: "X12_ISA_EXTRA_ELEMENT_SEPARATOR",
|
|
124
125
|
X12_GROUP_COUNT_MISMATCH: "X12_GROUP_COUNT_MISMATCH",
|
|
125
126
|
X12_TRANSACTION_COUNT_MISMATCH: "X12_TRANSACTION_COUNT_MISMATCH",
|
|
126
127
|
X12_SEGMENT_COUNT_MISMATCH: "X12_SEGMENT_COUNT_MISMATCH",
|
|
@@ -195,7 +196,8 @@ var WARNING_MESSAGES = {
|
|
|
195
196
|
X12_CONTROL_NUMBER_MISMATCH_INTERCHANGE: "Control number mismatch: ISA-13 (header) and IEA-02 (trailer) disagree. Both values are preserved verbatim on the model; neither is echoed here.",
|
|
196
197
|
X12_CONTROL_NUMBER_MISMATCH_GROUP: "Control number mismatch: GS-06 (header) and GE-02 (trailer) disagree. Both values are preserved verbatim on the model; neither is echoed here.",
|
|
197
198
|
X12_CONTROL_NUMBER_MISMATCH_TRANSACTION: "Control number mismatch: ST-02 (header) and SE-02 (trailer) disagree. Both values are preserved verbatim on the model; neither is echoed here.",
|
|
198
|
-
X12_PRE_005010: 'ISA
|
|
199
|
+
X12_PRE_005010: 'The twelfth element of the ISA split does not read "00501", the HIPAA baseline interchange control version number, so the input may diverge from 005010 semantics. Whether that element is ISA-12 is NOT established here: where `X12_ISA_EXTRA_ELEMENT_SEPARATOR` is also present on this interchange the header did not split into `ISA` plus 16 elements, so the element read may be a displaced one. All 106 ISA bytes are preserved verbatim on `isa.raw`, which with the ISA fixed widths is the route back. Nothing is echoed here.',
|
|
200
|
+
X12_ISA_EXTRA_ELEMENT_SEPARATOR: "The ISA element area carries at least one element separator beyond the 16 sitting at their fixed 005010 byte positions, so the header does not split into `ISA` plus 16 elements. `isa.elements` is that split as it came out: an element containing an extra separator comes back a prefix and everything after it is displaced. How far is NOT derivable from `isa.elements`, so any other ISA-derived diagnostic on this interchange may be reporting a displaced value. All 106 bytes are preserved verbatim on `isa.raw`, which with the ISA's fixed widths is the route back. Which reading is correct - the byte as data under the ISA's fixed widths, or as a separator - is NOT decided here, and nothing is re-framed.",
|
|
199
201
|
X12_GROUP_COUNT_MISMATCH: "IEA-01 does not equal the number of GS..GE groups actually present in the interchange. The declared count is preserved verbatim on the model and is NEVER silently corrected.",
|
|
200
202
|
X12_TRANSACTION_COUNT_MISMATCH: "GE-01 does not equal the number of ST..SE transaction sets actually present in the group. The declared count is preserved verbatim on the model and is NEVER silently corrected.",
|
|
201
203
|
X12_SEGMENT_COUNT_MISMATCH: "SE-01 does not equal the number of segments actually present in the transaction set it closes. The declared count is preserved verbatim and is corrected only on `serializeX12(ix, { specClean: true, recomputeCounts: true })`.",
|
|
@@ -284,6 +286,13 @@ function pre005010(position) {
|
|
|
284
286
|
position
|
|
285
287
|
};
|
|
286
288
|
}
|
|
289
|
+
function isaExtraElementSeparator(position) {
|
|
290
|
+
return {
|
|
291
|
+
code: WARNING_CODES.X12_ISA_EXTRA_ELEMENT_SEPARATOR,
|
|
292
|
+
message: WARNING_MESSAGES.X12_ISA_EXTRA_ELEMENT_SEPARATOR,
|
|
293
|
+
position
|
|
294
|
+
};
|
|
295
|
+
}
|
|
287
296
|
function groupCountMismatch(position) {
|
|
288
297
|
return {
|
|
289
298
|
code: WARNING_CODES.X12_GROUP_COUNT_MISMATCH,
|
|
@@ -1048,6 +1057,7 @@ function collectElementValues(seg, start, end, delimiters) {
|
|
|
1048
1057
|
}
|
|
1049
1058
|
|
|
1050
1059
|
// src/parser/envelope.ts
|
|
1060
|
+
var ISA_DECODED_PART_COUNT = 17;
|
|
1051
1061
|
function decodeIsa(raw, delimiters) {
|
|
1052
1062
|
const isaRaw = raw.slice(0, ISA_MIN_LENGTH);
|
|
1053
1063
|
const isaHead = isaRaw.slice(0, ISA_MIN_LENGTH - 1);
|
|
@@ -1114,6 +1124,9 @@ function decodeEnvelope(raw, delimiters) {
|
|
|
1114
1124
|
warnings.push(w);
|
|
1115
1125
|
};
|
|
1116
1126
|
const isa = decodeIsa(raw, delimiters);
|
|
1127
|
+
if (isa.elements.length !== ISA_DECODED_PART_COUNT) {
|
|
1128
|
+
warnings.push(isaExtraElementSeparator({ segmentIndex: 0, interchangeIndex: 0 }));
|
|
1129
|
+
}
|
|
1117
1130
|
const isa12 = el(isa.elements, 12);
|
|
1118
1131
|
if (isa12 !== "00501") {
|
|
1119
1132
|
warnings.push(pre005010({ segmentIndex: 0, interchangeIndex: 0, elementIndex: 12 }));
|
|
@@ -10723,7 +10736,7 @@ var profiles = Object.freeze({
|
|
|
10723
10736
|
});
|
|
10724
10737
|
|
|
10725
10738
|
// src/index.ts
|
|
10726
|
-
var VERSION = "0.0.
|
|
10739
|
+
var VERSION = "0.0.18";
|
|
10727
10740
|
|
|
10728
10741
|
exports.ACK_BUILD_ERROR_CODES = ACK_BUILD_ERROR_CODES;
|
|
10729
10742
|
exports.ALL_WARNING_MESSAGES = ALL_WARNING_MESSAGES;
|
|
@@ -10885,6 +10898,7 @@ exports.isAcceptDisposition = isAcceptDisposition;
|
|
|
10885
10898
|
exports.isClaimAdjustmentGroupCode = isClaimAdjustmentGroupCode;
|
|
10886
10899
|
exports.isDiagnosisQualifier = isDiagnosisQualifier;
|
|
10887
10900
|
exports.isProcedureQualifier = isProcedureQualifier;
|
|
10901
|
+
exports.isaExtraElementSeparator = isaExtraElementSeparator;
|
|
10888
10902
|
exports.lookupCarc = lookupCarc;
|
|
10889
10903
|
exports.lookupClaimStatus = lookupClaimStatus;
|
|
10890
10904
|
exports.lookupClaimStatusCategory = lookupClaimStatusCategory;
|