@cosyte/x12 0.0.7 → 0.0.9
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 +143 -0
- package/dist/index.cjs +61 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.mjs +61 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
11
|
|
|
12
|
+
- **`requireCallerString` / `makeCallerEscaper`** (internal), the single route a caller-supplied
|
|
13
|
+
element value takes **through a builder's `esc` helper**. Read that scope literally: it is not
|
|
14
|
+
every route into an emitted segment, and the `### Fixed` entry below says which positions bypass
|
|
15
|
+
it. All nine builders now build their `esc` helper through
|
|
16
|
+
`makeCallerEscaper`, which type-checks the value before escaping and refuses through the calling
|
|
17
|
+
module's own `refuse` callback, so a wrong-typed element draws that builder's existing typed error
|
|
18
|
+
and code rather than a new shared one. `buildInterchange`, `build999`, `build271` and `build278`
|
|
19
|
+
each gained the one-line `refuseSpec` thrower they needed for it.
|
|
20
|
+
|
|
12
21
|
- **`renderCallerJson`** (internal), the type-preserving half of the caller-value bound, held to the
|
|
13
22
|
same `BUILD_REFUSAL_VALUE_MAX_RENDERED` ceiling as `renderCallerValue`. It exists because
|
|
14
23
|
`defineProfile()` reports a bad `name` / `id` / `effect` / `fixture` with `JSON.stringify`, and that
|
|
@@ -42,6 +51,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
42
51
|
a warning `message` is a frozen-registry lookup with positional metadata only, but an orphan is
|
|
43
52
|
document content, verbatim, exactly like `tx.rawSegments`. Log `context` and `segmentIndex`.
|
|
44
53
|
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- **`escapeRelease` now throws `TypeError` on a non-string instead of returning `""`.** Previously it
|
|
57
|
+
gave three different wrong answers depending on what arrived: a number, a boolean or a plain object
|
|
58
|
+
returned the empty string silently; `null` and `undefined` threw on the property read; an array or
|
|
59
|
+
an array-like threw on `charAt`. All three now terminate the same way. A `TypeError` rather than a
|
|
60
|
+
code-tagged library error is deliberate: it is a pure text utility with no spec, element or caller
|
|
61
|
+
context to name. Nothing inside the library can reach it, because all nine builders refuse
|
|
62
|
+
first with their own typed, code-tagged error.
|
|
63
|
+
|
|
45
64
|
### Security
|
|
46
65
|
|
|
47
66
|
- **The PHI scanner refuses an in-scope entry that is not a regular file, on both of its enumerating
|
|
@@ -111,6 +130,70 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
111
130
|
|
|
112
131
|
### Fixed
|
|
113
132
|
|
|
133
|
+
- **A number passed where a builder's types say `string` no longer emits an EMPTY element. It is now
|
|
134
|
+
REFUSED, and it is deliberately not coerced.** `escapeRelease` opened with
|
|
135
|
+
`if (value.length === 0) return value;` and then looped to `value.length`. On a number `.length` is
|
|
136
|
+
`undefined`, so the early return did not fire, `i < undefined` was false, the loop body never ran,
|
|
137
|
+
and the function returned its empty accumulator. **The value vanished with no warning and no
|
|
138
|
+
error.** The types say `string`, so a TypeScript caller could not reach it; a JavaScript or
|
|
139
|
+
JSON-driven caller could, and `@cosyte/cli` is such a caller.
|
|
140
|
+
|
|
141
|
+
Measured at `0.0.8` on an otherwise valid `build835` spec with only `patientControlNumber` changed:
|
|
142
|
+
`CLP**1*500.00*450.00*50.00*MB*ICN-9001*11::1`, `ix.warnings.length === 0`, and a frozen interchange
|
|
143
|
+
that looks successful. CLP-01 is required by TR3 005010X221A1 Loop 2100 and is the key that
|
|
144
|
+
reassociates the remittance back to the 837's CLM-01. The builder's own
|
|
145
|
+
`patientControlNumber === ""` guard did not catch it, because the value was not yet a string when it
|
|
146
|
+
was checked.
|
|
147
|
+
|
|
148
|
+
**The same one line reached every escaped slot in all nine builders**, including the 837's own
|
|
149
|
+
CLM-01, the other end of that reassociation link. Measured at base by driving the shipped table
|
|
150
|
+
against a `143a6ea` worktree, one element each: `BPR*A1*450.00` became `BPR**450.00`,
|
|
151
|
+
`AK2*837*A1*005010X222A2` became `AK2*837**005010X222A2`, `NM1*IL*1*DOE*JANE****34*A1` became
|
|
152
|
+
`NM1*IL*1*DOE*JANE****34`, `ENT**2J*34*A1` became `ENT**2J*34`, `NM1*1P*2*A1` became `NM1*1P*2`,
|
|
153
|
+
`UM*HS*I*A1` became `UM*HS*I`, and `CLM*A1*150.00***11:B:1*Y*A*Y*Y` became
|
|
154
|
+
`CLM**150.00***11:B:1*Y*A*Y*Y`. Where the dropped element was trailing, the trailing-empty trim
|
|
155
|
+
removed it outright, so it is not even positionally recoverable.
|
|
156
|
+
|
|
157
|
+
**It refuses rather than coercing, and that choice is the substance of the fix.** Coercion would
|
|
158
|
+
mint a _different_ identifier: a JSON payload that carried `"0012345"` as a number has already lost
|
|
159
|
+
the leading zeros, so `String(12345)` emits a well-formed identifier that is not the one the caller
|
|
160
|
+
sent, and a remittance that reassociates to the wrong claim is worse than one that fails to
|
|
161
|
+
reassociate at all. `String(1e21)` is `"1e+21"`, `String(NaN)` is `"NaN"` and `String(0.1 + 0.2)` is
|
|
162
|
+
`"0.30000000000000004"`, none valid in an `AN`, `ID` or `Nn` element, and `X12Decimal` is already
|
|
163
|
+
the sanctioned route for numeric content. No working caller is broken, because the numeric path did
|
|
164
|
+
not work; it silently lost the field. The refusal message says why, so a caller is not nudged
|
|
165
|
+
straight into `String(value)` at the wrong boundary.
|
|
166
|
+
|
|
167
|
+
This is deliberately the OPPOSITE answer to `renderCallerValue`, which coerces for the same caller
|
|
168
|
+
mistake. A refusal message that throws replaces a typed, code-tagged error with an uncaught
|
|
169
|
+
`TypeError`, so its duty is to survive anything; an emitted document's duty is to invent nothing.
|
|
170
|
+
|
|
171
|
+
**The guard is on values routed through the escape helper, and not every element position goes
|
|
172
|
+
through it.** All of what follows is pre-existing, measured, unchanged here and disclosed in
|
|
173
|
+
`KNOWN-LIMITATIONS.md`. **36 `esc` slots read `.toString()` off what the types say is an
|
|
174
|
+
`X12Decimal`**, so a raw number arrives already a string and is passed through: a
|
|
175
|
+
`patientResponsibilityAmount` of `0.1 + 0.2` still emits `…*0.30000000000000004*…`, `1e21` still
|
|
176
|
+
emits `…*1e+21*…` and `NaN` still emits `…*NaN*…`, each with zero warnings, which are the exact
|
|
177
|
+
three renderings this entry names as disqualifying, and an 837 service-line `units` reaches SV1-04
|
|
178
|
+
the same way. **That is a set of examples too, not a count** - a draft of this entry said the class
|
|
179
|
+
was exactly 36 slots and closed, and adversarial review measured it open. **Some string-typed
|
|
180
|
+
positions never call the escape helper at all** and emit a
|
|
181
|
+
number, or an unescaped delimiter, verbatim: the 999's `groupControlNumber` (GS-06 / GE-02),
|
|
182
|
+
`transactionSetControlNumber` (ST-02 / SE-02) and `disposition` (AK9-01 and IK5-01), the 278's
|
|
183
|
+
`levelCode` (HL-03), `groupDate` / `groupTime` (GS-04 / GS-05), and the 837's `lineNumber`
|
|
184
|
+
(LX-01). **Those are examples and not a census, deliberately:** two drafts of this
|
|
185
|
+
entry published an exhaustive count and adversarial review measured both incomplete, so the claim
|
|
186
|
+
is cut back rather than grown a third time. AK9-01 is an `ID` element bound to X12 code source 715,
|
|
187
|
+
and `build999`'s own accept-with-errors guard compares it against `"A"`, so a number walks past it
|
|
188
|
+
the same way it walked past `patientControlNumber === ""`. **The fixed-width ISA slots** go through
|
|
189
|
+
`pad` / `padControl`, so a number throws an untyped `TypeError` and a numeric
|
|
190
|
+
`interchangeControlNumber` throws a typed refusal whose text misleadingly says "exceeds the 9-char
|
|
191
|
+
spec limit"; `buildTA1` has no escape helper at all.
|
|
192
|
+
|
|
193
|
+
**The "no working caller is broken" claim holds with one measured exception:** a boxed
|
|
194
|
+
`new String("PT-ACCT-001")` built cleanly at `0.0.8` and is refused now, because `typeof` it is
|
|
195
|
+
`"object"`.
|
|
196
|
+
|
|
114
197
|
- **The `attw` publish gate no longer passes a tarball that carries no type declarations.** The
|
|
115
198
|
`attw` script was the bare CLI, and `@arethetypeswrong/cli` returns 0 whenever its analysis found
|
|
116
199
|
no types at all, before it reads the problem list. For a package that ships types, "This package
|
|
@@ -365,6 +448,66 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
365
448
|
|
|
366
449
|
### Tests
|
|
367
450
|
|
|
451
|
+
- **`test/builder-string-type.test.ts`**, the emit gate for the fix above and the third member of the
|
|
452
|
+
builder-gate family (`builder-refusal-bounds` guards what a refusal says, `builder-array-bounds`
|
|
453
|
+
guards whether a refusal happens, this one guards whether the caller's value reaches the document).
|
|
454
|
+
The source scan is the exhaustive half: it requires every builder module's `esc` to be built by
|
|
455
|
+
`makeCallerEscaper` and requires no builder module to call `escapeRelease` itself, so a tenth
|
|
456
|
+
builder writing the old one-liner reds it without anyone adding a case. Negative-controlled by
|
|
457
|
+
putting the defect back: reverting one module's `esc` reds the scan by file and line **and** reds
|
|
458
|
+
the behavioural half, which is a cleaner control than the array gate gets, since there is no loop
|
|
459
|
+
here to wedge the runner.
|
|
460
|
+
|
|
461
|
+
- **The PHI-scanner suite stopped paying 30 of its 32 `tsx` start-ups, and the global `testTimeout`
|
|
462
|
+
now says what it does and does not cover.** No library code, no public surface and no timeout value
|
|
463
|
+
changed; `scripts/phi-scan.ts` and `scripts/attw.mjs` are untouched.
|
|
464
|
+
|
|
465
|
+
Nearly every case in `test/scripts/phi-scan.test.ts` spawns the scanner. Counted at runtime on
|
|
466
|
+
both trees with a `spawnSync` shim: **32 spawns across 32 cases, all under `tsx`**, becoming
|
|
467
|
+
**36 spawns across 33 cases, 34 under `node` and 2 under `tsx`**. So 30 `tsx` start-ups were
|
|
468
|
+
removed and 2 were kept deliberately, in the equivalence case below. The scanner is type-annotated
|
|
469
|
+
Node that needs erasing and nothing more, and Node 22.18 or newer strips types itself, so the
|
|
470
|
+
spawns now use `process.execPath`. Measured on a 12-CPU cgroup quota with
|
|
471
|
+
`availableParallelism()` 12 and other workers running (load average 8.9 to 11.3, a realistic
|
|
472
|
+
condition rather than a quiet one): one scanner start is a 441 ms median under `tsx` against
|
|
473
|
+
149 ms under `node`, seven runs each. Interleaved BASE/HEAD under `pnpm test:coverage`, two rounds
|
|
474
|
+
each so the arms share a load condition, that file went 17.2 s / 17.5 s to 8.6 s / 8.6 s, and
|
|
475
|
+
15.7 s to 6.6 s run on its own. Total CPU across all workers went 58.9 s / 58.4 s to
|
|
476
|
+
50.5 s / 49.5 s. Those medians predict 8.2 s off this file (32 starts converted, less the 2 `node`
|
|
477
|
+
and 2 `tsx` starts the new case adds) against 9.1 s measured, so the model is the right shape and
|
|
478
|
+
about 11% light, not a match.
|
|
479
|
+
|
|
480
|
+
**The substitution is pinned as an equivalence rather than assumed.** The gate consumers actually
|
|
481
|
+
run (`pnpm phi-scan`, the pre-commit hook, CI) still invokes `tsx`, so one new case drives both
|
|
482
|
+
runners over the same violator and the same clean file and requires the same exit code, stdout and
|
|
483
|
+
stderr. It is the only place `tsx` is still spawned, and a simulated divergence reds it. **Scope it
|
|
484
|
+
honestly:** that case drives `paths` mode on one hit and one clean file, so it pins the exit-0 and
|
|
485
|
+
exit-1 verdicts and not the exit-2 refusals, nor all-mode, nor `--staged`. It is aimed at the only
|
|
486
|
+
divergence these two runners plausibly have, which is at module load, and a load-time divergence
|
|
487
|
+
cannot be confined to the routes it does not drive.
|
|
488
|
+
|
|
489
|
+
**What this did not buy, stated because the two figures diverge:** it removed about 8.6 s of CPU
|
|
490
|
+
but barely moved the suite's critical path (17.2 s / 17.5 s to 16.3 s / 16.7 s), which is now
|
|
491
|
+
`test/scripts/attw-gate.test.ts`. That file is deliberately left alone: measured, one `attw --pack`
|
|
492
|
+
on a trivial two-file package is 1,596 ms median, of which the real `npm pack` is 462 ms and the
|
|
493
|
+
rest is attw's own analysis. There is no runner to substitute there, pinning the real binary is the
|
|
494
|
+
point of that gate, and each of its cases already carries its own 60 s ceiling.
|
|
495
|
+
|
|
496
|
+
**`vitest.config.ts` now documents the scope of `testTimeout: 10_000`, which is narrower than it
|
|
497
|
+
looks in both directions.** It is a floor for ordinary tests, not where slow work gets its room:
|
|
498
|
+
the three slowest suites already take per-test ceilings, and the 10 MB+ 834 stream measured
|
|
499
|
+
8.9 s / 10.0 s / 9.3 s / 9.1 s across the four interleaved runs, so it sits AT the 10 s global on a
|
|
500
|
+
merely-loaded box (a 10.0 s reading is not evidence of which side of the bar it fell), and measured
|
|
501
|
+
24.1 s under heavier load on the same box. It is green only on its own 120 s ceiling. Raising the
|
|
502
|
+
global to
|
|
503
|
+
fit it would hand the same leash to all 1,100-odd tests and turn a genuinely hung test from broken
|
|
504
|
+
into merely slow. It is also **not a liveness net**: measured on this tree with vitest 4.1.4, an
|
|
505
|
+
async overrun reds at the ceiling, a finite synchronous overrun reds only after the work returns,
|
|
506
|
+
and an infinite synchronous loop produces no verdict at all, wedging the worker until it is killed
|
|
507
|
+
from outside (45 s, exit 143, no pass/fail line). That is the failure mode
|
|
508
|
+
`X12-CALLER-VALUE-RESIDUALS` hit for real, and the defence against it is the source scan in
|
|
509
|
+
`test/builder-array-bounds.test.ts`, not any timeout value.
|
|
510
|
+
|
|
368
511
|
- **The default emit mode's guarantees are locked against the whole committed corpus, not just the 13
|
|
369
512
|
goldens.** The goldens are already in the serializer's image, so they could only ever demonstrate
|
|
370
513
|
the easy half of the round trip. `test/serialize.test.ts` now discovers every `.edi` fixture from
|
package/dist/index.cjs
CHANGED
|
@@ -426,6 +426,9 @@ function unescapeRelease(input, delimiters, emit, position) {
|
|
|
426
426
|
return out;
|
|
427
427
|
}
|
|
428
428
|
function escapeRelease(value, delimiters) {
|
|
429
|
+
if (typeof value !== "string") {
|
|
430
|
+
throw new TypeError(`escapeRelease: value must be a string, received ${typeof value}.`);
|
|
431
|
+
}
|
|
429
432
|
if (value.length === 0) return value;
|
|
430
433
|
let out = "";
|
|
431
434
|
for (let i = 0; i < value.length; i++) {
|
|
@@ -2508,6 +2511,25 @@ function isRealArray(value) {
|
|
|
2508
2511
|
return Array.isArray(value);
|
|
2509
2512
|
}
|
|
2510
2513
|
|
|
2514
|
+
// src/builder/caller-string.ts
|
|
2515
|
+
function describeCallerValue(value) {
|
|
2516
|
+
if (value === null) return "null";
|
|
2517
|
+
if (value === void 0) return "undefined";
|
|
2518
|
+
const type = typeof value;
|
|
2519
|
+
if (type === "object") return Array.isArray(value) ? "an array" : "an object";
|
|
2520
|
+
if (type === "function") return "a function";
|
|
2521
|
+
return `a ${type} (${renderCallerValue(value)})`;
|
|
2522
|
+
}
|
|
2523
|
+
function requireCallerString(value, at, refuse) {
|
|
2524
|
+
if (typeof value === "string") return value;
|
|
2525
|
+
refuse(
|
|
2526
|
+
`${at}: every element value must be a string, but received ${describeCallerValue(value)}. Values are never coerced - a JavaScript number cannot carry a leading-zero identifier, so converting here could emit a different value than the caller sent. Convert at the call site.`
|
|
2527
|
+
);
|
|
2528
|
+
}
|
|
2529
|
+
function makeCallerEscaper(delimiters, at, refuse) {
|
|
2530
|
+
return (value) => escapeRelease(requireCallerString(value, at, refuse), delimiters);
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2511
2533
|
// src/transactions/remit/build-835.ts
|
|
2512
2534
|
function refuseSpec(message) {
|
|
2513
2535
|
throw new Remit835BuildError(REMIT_835_BUILD_ERROR_CODES.X12_835_BUILD_INVALID_SPEC, message);
|
|
@@ -2533,7 +2555,7 @@ function build835(spec) {
|
|
|
2533
2555
|
component: componentSeparator,
|
|
2534
2556
|
segment: segmentTerminator
|
|
2535
2557
|
};
|
|
2536
|
-
const esc = (
|
|
2558
|
+
const esc = makeCallerEscaper(delimiters, "build835", refuseSpec);
|
|
2537
2559
|
const seg = (parts) => {
|
|
2538
2560
|
let end = parts.length;
|
|
2539
2561
|
while (end > 1 && parts[end - 1] === "") end -= 1;
|
|
@@ -4210,7 +4232,7 @@ function buildClaim837(variant, spec) {
|
|
|
4210
4232
|
component: componentSeparator,
|
|
4211
4233
|
segment: segmentTerminator
|
|
4212
4234
|
};
|
|
4213
|
-
const esc = (
|
|
4235
|
+
const esc = makeCallerEscaper(delimiters, "build837", refuseSpec2);
|
|
4214
4236
|
const seg = (parts) => {
|
|
4215
4237
|
let end = parts.length;
|
|
4216
4238
|
while (end > 1 && parts[end - 1] === "") end -= 1;
|
|
@@ -5351,6 +5373,12 @@ function refuseHierarchy2(message) {
|
|
|
5351
5373
|
message
|
|
5352
5374
|
);
|
|
5353
5375
|
}
|
|
5376
|
+
function refuseSpec3(message) {
|
|
5377
|
+
throw new Eligibility271BuildError(
|
|
5378
|
+
ELIGIBILITY_271_BUILD_ERROR_CODES.X12_271_BUILD_INVALID_SPEC,
|
|
5379
|
+
message
|
|
5380
|
+
);
|
|
5381
|
+
}
|
|
5354
5382
|
var X279A1_VERSION_RELEASE = "005010X279A1";
|
|
5355
5383
|
var X12_271_FUNCTIONAL_ID = "HB";
|
|
5356
5384
|
var X12_AGENCY_CODE3 = "X";
|
|
@@ -5368,7 +5396,7 @@ function build271(spec) {
|
|
|
5368
5396
|
component: componentSeparator,
|
|
5369
5397
|
segment: segmentTerminator
|
|
5370
5398
|
};
|
|
5371
|
-
const esc = (
|
|
5399
|
+
const esc = makeCallerEscaper(delimiters, "build271", refuseSpec3);
|
|
5372
5400
|
const seg = (parts) => {
|
|
5373
5401
|
let end = parts.length;
|
|
5374
5402
|
while (end > 1 && parts[end - 1] === "") end -= 1;
|
|
@@ -6043,7 +6071,7 @@ function refuseHierarchy3(message) {
|
|
|
6043
6071
|
message
|
|
6044
6072
|
);
|
|
6045
6073
|
}
|
|
6046
|
-
function
|
|
6074
|
+
function refuseSpec4(message) {
|
|
6047
6075
|
throw new ClaimStatus277BuildError(
|
|
6048
6076
|
CLAIM_STATUS_277_BUILD_ERROR_CODES.X12_277_BUILD_INVALID_SPEC,
|
|
6049
6077
|
message
|
|
@@ -6077,7 +6105,7 @@ function buildClaimStatus(version, spec) {
|
|
|
6077
6105
|
component: componentSeparator,
|
|
6078
6106
|
segment: segmentTerminator
|
|
6079
6107
|
};
|
|
6080
|
-
const esc = (
|
|
6108
|
+
const esc = makeCallerEscaper(delimiters, "build277", refuseSpec4);
|
|
6081
6109
|
const seg = (parts) => {
|
|
6082
6110
|
let end = parts.length;
|
|
6083
6111
|
while (end > 1 && parts[end - 1] === "") end -= 1;
|
|
@@ -6252,12 +6280,12 @@ function enforceClaim2(claim, locator, isFirst) {
|
|
|
6252
6280
|
const statuses = requireCallerArray(
|
|
6253
6281
|
claim.statuses,
|
|
6254
6282
|
`build277: claim at ${locator}: statuses`,
|
|
6255
|
-
|
|
6283
|
+
refuseSpec4
|
|
6256
6284
|
);
|
|
6257
6285
|
const serviceLines = requireCallerArray(
|
|
6258
6286
|
claim.serviceLines,
|
|
6259
6287
|
`build277: claim at ${locator}: serviceLines`,
|
|
6260
|
-
|
|
6288
|
+
refuseSpec4
|
|
6261
6289
|
);
|
|
6262
6290
|
if (claim.trace === void 0 && statuses.length === 0 && serviceLines.length === 0) {
|
|
6263
6291
|
throw new ClaimStatus277BuildError(
|
|
@@ -6280,7 +6308,7 @@ function enforceClaim2(claim, locator, isFirst) {
|
|
|
6280
6308
|
const lineStatuses = requireCallerArray(
|
|
6281
6309
|
line.statuses,
|
|
6282
6310
|
`build277: claim at ${locator}.line[${String(l)}]: statuses`,
|
|
6283
|
-
|
|
6311
|
+
refuseSpec4
|
|
6284
6312
|
);
|
|
6285
6313
|
for (let i = 0; i < lineStatuses.length; i += 1) {
|
|
6286
6314
|
enforceStatus(lineStatuses[i], `${locator}.line[${String(l)}].status[${String(i)}]`);
|
|
@@ -6831,7 +6859,7 @@ var Premium820BuildError = class extends Error {
|
|
|
6831
6859
|
};
|
|
6832
6860
|
|
|
6833
6861
|
// src/transactions/premium/build-820.ts
|
|
6834
|
-
function
|
|
6862
|
+
function refuseSpec5(message) {
|
|
6835
6863
|
throw new Premium820BuildError(PREMIUM_820_BUILD_ERROR_CODES.X12_820_BUILD_INVALID_SPEC, message);
|
|
6836
6864
|
}
|
|
6837
6865
|
var X218_VERSION_RELEASE = "005010X218";
|
|
@@ -6850,7 +6878,7 @@ function build820(spec) {
|
|
|
6850
6878
|
component: componentSeparator,
|
|
6851
6879
|
segment: segmentTerminator
|
|
6852
6880
|
};
|
|
6853
|
-
const esc = (
|
|
6881
|
+
const esc = makeCallerEscaper(delimiters, "build820", refuseSpec5);
|
|
6854
6882
|
const seg = (parts) => {
|
|
6855
6883
|
let end = parts.length;
|
|
6856
6884
|
while (end > 1 && parts[end - 1] === "") end -= 1;
|
|
@@ -6977,7 +7005,7 @@ function build820(spec) {
|
|
|
6977
7005
|
return parseX12(raw);
|
|
6978
7006
|
}
|
|
6979
7007
|
function enforceStructuralSpec5(spec) {
|
|
6980
|
-
const traces = requireCallerArray(spec.traces, "build820: spec.traces",
|
|
7008
|
+
const traces = requireCallerArray(spec.traces, "build820: spec.traces", refuseSpec5);
|
|
6981
7009
|
if (traces.length === 0) {
|
|
6982
7010
|
throw new Premium820BuildError(
|
|
6983
7011
|
PREMIUM_820_BUILD_ERROR_CODES.X12_820_BUILD_INVALID_SPEC,
|
|
@@ -6987,7 +7015,7 @@ function enforceStructuralSpec5(spec) {
|
|
|
6987
7015
|
const remittances = requireCallerArray(
|
|
6988
7016
|
spec.remittances,
|
|
6989
7017
|
"build820: spec.remittances",
|
|
6990
|
-
|
|
7018
|
+
refuseSpec5
|
|
6991
7019
|
);
|
|
6992
7020
|
if (remittances.length === 0) {
|
|
6993
7021
|
throw new Premium820BuildError(
|
|
@@ -7007,7 +7035,7 @@ function enforceStructuralSpec5(spec) {
|
|
|
7007
7035
|
const openItems = requireCallerArray(
|
|
7008
7036
|
remittance.openItems,
|
|
7009
7037
|
`build820: spec.remittances[${String(r)}].openItems`,
|
|
7010
|
-
|
|
7038
|
+
refuseSpec5
|
|
7011
7039
|
);
|
|
7012
7040
|
if (openItems.length === 0) {
|
|
7013
7041
|
throw new Premium820BuildError(
|
|
@@ -7527,7 +7555,7 @@ var Enrollment834BuildError = class extends Error {
|
|
|
7527
7555
|
};
|
|
7528
7556
|
|
|
7529
7557
|
// src/transactions/enrollment/build-834.ts
|
|
7530
|
-
function
|
|
7558
|
+
function refuseSpec6(message) {
|
|
7531
7559
|
throw new Enrollment834BuildError(
|
|
7532
7560
|
ENROLLMENT_834_BUILD_ERROR_CODES.X12_834_BUILD_INVALID_SPEC,
|
|
7533
7561
|
message
|
|
@@ -7551,7 +7579,7 @@ function build834(spec) {
|
|
|
7551
7579
|
component: componentSeparator,
|
|
7552
7580
|
segment: segmentTerminator
|
|
7553
7581
|
};
|
|
7554
|
-
const esc = (
|
|
7582
|
+
const esc = makeCallerEscaper(delimiters, "build834", refuseSpec6);
|
|
7555
7583
|
const seg = (parts) => {
|
|
7556
7584
|
let end = parts.length;
|
|
7557
7585
|
while (end > 1 && parts[end - 1] === "") end -= 1;
|
|
@@ -7632,7 +7660,7 @@ function build834(spec) {
|
|
|
7632
7660
|
return parseX12(raw);
|
|
7633
7661
|
}
|
|
7634
7662
|
function enforceStructuralSpec6(spec) {
|
|
7635
|
-
const members = requireCallerArray(spec.members, "build834: spec.members",
|
|
7663
|
+
const members = requireCallerArray(spec.members, "build834: spec.members", refuseSpec6);
|
|
7636
7664
|
if (members.length === 0) {
|
|
7637
7665
|
throw new Enrollment834BuildError(
|
|
7638
7666
|
ENROLLMENT_834_BUILD_ERROR_CODES.X12_834_BUILD_INVALID_SPEC,
|
|
@@ -7657,7 +7685,7 @@ function enforceStructuralSpec6(spec) {
|
|
|
7657
7685
|
const coverages = requireCallerArray(
|
|
7658
7686
|
member.healthCoverages,
|
|
7659
7687
|
`build834: spec.members[${String(m)}].healthCoverages`,
|
|
7660
|
-
|
|
7688
|
+
refuseSpec6
|
|
7661
7689
|
);
|
|
7662
7690
|
for (let c = 0; c < coverages.length; c += 1) {
|
|
7663
7691
|
const coverage = coverages[c];
|
|
@@ -8184,6 +8212,12 @@ function refuseHierarchy4(message) {
|
|
|
8184
8212
|
message
|
|
8185
8213
|
);
|
|
8186
8214
|
}
|
|
8215
|
+
function refuseSpec7(message) {
|
|
8216
|
+
throw new ServicesReview278BuildError(
|
|
8217
|
+
AUTH_278_BUILD_ERROR_CODES.X12_278_BUILD_INVALID_SPEC,
|
|
8218
|
+
message
|
|
8219
|
+
);
|
|
8220
|
+
}
|
|
8187
8221
|
var X12_278_FUNCTIONAL_ID = "HI";
|
|
8188
8222
|
var X12_AGENCY_CODE7 = "X";
|
|
8189
8223
|
var HL_LEVEL4 = {
|
|
@@ -8212,7 +8246,7 @@ function buildServicesReview(version, direction, spec) {
|
|
|
8212
8246
|
component: componentSeparator,
|
|
8213
8247
|
segment: segmentTerminator
|
|
8214
8248
|
};
|
|
8215
|
-
const esc = (
|
|
8249
|
+
const esc = makeCallerEscaper(delimiters, "build278", refuseSpec7);
|
|
8216
8250
|
const seg = (parts) => {
|
|
8217
8251
|
let end = parts.length;
|
|
8218
8252
|
while (end > 1 && parts[end - 1] === "") end -= 1;
|
|
@@ -8963,6 +8997,9 @@ function narrowNoteCode(value) {
|
|
|
8963
8997
|
}
|
|
8964
8998
|
|
|
8965
8999
|
// src/transactions/ack/build-999.ts
|
|
9000
|
+
function refuseSpec8(message) {
|
|
9001
|
+
throw new AckBuildError(ACK_BUILD_ERROR_CODES.X12_ACK_INVALID_SPEC, message);
|
|
9002
|
+
}
|
|
8966
9003
|
var X231A1_VERSION_RELEASE = "005010X231A1";
|
|
8967
9004
|
var X12_AGENCY_CODE8 = "X";
|
|
8968
9005
|
function build999(spec) {
|
|
@@ -8979,7 +9016,7 @@ function build999(spec) {
|
|
|
8979
9016
|
component: componentSeparator,
|
|
8980
9017
|
segment: segmentTerminator
|
|
8981
9018
|
};
|
|
8982
|
-
const esc = (
|
|
9019
|
+
const esc = makeCallerEscaper(delimiters, "build999", refuseSpec8);
|
|
8983
9020
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
8984
9021
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
8985
9022
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
@@ -9459,6 +9496,9 @@ var X12BuildError = class extends Error {
|
|
|
9459
9496
|
};
|
|
9460
9497
|
|
|
9461
9498
|
// src/builder/build-interchange.ts
|
|
9499
|
+
function refuseSpec9(message) {
|
|
9500
|
+
throw new X12BuildError(X12_BUILD_ERROR_CODES.X12_BUILD_INVALID_SPEC, message);
|
|
9501
|
+
}
|
|
9462
9502
|
function buildInterchange(spec) {
|
|
9463
9503
|
const elementSeparator = spec.elementSeparator ?? "*";
|
|
9464
9504
|
const repetitionSeparator = spec.repetitionSeparator ?? "^";
|
|
@@ -9470,7 +9510,7 @@ function buildInterchange(spec) {
|
|
|
9470
9510
|
component: componentSeparator,
|
|
9471
9511
|
segment: segmentTerminator
|
|
9472
9512
|
};
|
|
9473
|
-
const esc = (
|
|
9513
|
+
const esc = makeCallerEscaper(delimiters, "buildInterchange", refuseSpec9);
|
|
9474
9514
|
const senderQualifier = spec.senderQualifier ?? "ZZ";
|
|
9475
9515
|
const receiverQualifier = spec.receiverQualifier ?? "ZZ";
|
|
9476
9516
|
const usageIndicator = spec.usageIndicator ?? "P";
|
|
@@ -9892,7 +9932,7 @@ var profiles = Object.freeze({
|
|
|
9892
9932
|
});
|
|
9893
9933
|
|
|
9894
9934
|
// src/index.ts
|
|
9895
|
-
var VERSION = "0.0.
|
|
9935
|
+
var VERSION = "0.0.9";
|
|
9896
9936
|
|
|
9897
9937
|
exports.ACK_BUILD_ERROR_CODES = ACK_BUILD_ERROR_CODES;
|
|
9898
9938
|
exports.ALL_WARNING_MESSAGES = ALL_WARNING_MESSAGES;
|