@cosyte/x12 0.0.15 → 0.0.17
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 +700 -12
- package/KNOWN-LIMITATIONS.md +436 -28
- package/README.md +1 -1
- package/dist/index.cjs +365 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +156 -70
- package/dist/index.d.ts +156 -70
- package/dist/index.mjs +365 -38
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -47,6 +47,12 @@ var DELIMITER_POSITIONS = {
|
|
|
47
47
|
component: 104,
|
|
48
48
|
segment: 105
|
|
49
49
|
};
|
|
50
|
+
function isVisibleDelimiterChar(c) {
|
|
51
|
+
const code = c.charCodeAt(0);
|
|
52
|
+
if (code < 32 || code === 127) return false;
|
|
53
|
+
if (/\s/u.test(c)) return false;
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
50
56
|
function detectDelimiters(raw) {
|
|
51
57
|
const fatalPosition = { segmentIndex: 0, interchangeIndex: 0 };
|
|
52
58
|
const snip = snippet(raw);
|
|
@@ -70,19 +76,13 @@ function detectDelimiters(raw) {
|
|
|
70
76
|
const repetition = raw.charAt(DELIMITER_POSITIONS.repetition);
|
|
71
77
|
const component = raw.charAt(DELIMITER_POSITIONS.component);
|
|
72
78
|
const segment = raw.charAt(DELIMITER_POSITIONS.segment);
|
|
73
|
-
const isValidDelimiterChar = (c) => {
|
|
74
|
-
const code = c.charCodeAt(0);
|
|
75
|
-
if (code < 32 || code === 127) return false;
|
|
76
|
-
if (/\s/u.test(c)) return false;
|
|
77
|
-
return true;
|
|
78
|
-
};
|
|
79
79
|
for (const [name, ch] of [
|
|
80
80
|
["element", element],
|
|
81
81
|
["repetition", repetition],
|
|
82
82
|
["component", component],
|
|
83
83
|
["segment", segment]
|
|
84
84
|
]) {
|
|
85
|
-
if (!
|
|
85
|
+
if (!isVisibleDelimiterChar(ch)) {
|
|
86
86
|
throw new X12ParseError(
|
|
87
87
|
FATAL_CODES.X12_INVALID_DELIMITERS,
|
|
88
88
|
`Delimiter "${name}" at ISA byte ${String(DELIMITER_POSITIONS[name] + 1)} is whitespace, control, or empty.`,
|
|
@@ -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",
|
|
@@ -196,6 +197,7 @@ var WARNING_MESSAGES = {
|
|
|
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
199
|
X12_PRE_005010: 'ISA-12 declares a version other than the HIPAA baseline "00501", so the input may diverge from 005010 semantics. The declared version is preserved verbatim on the model.',
|
|
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 })`.",
|
|
@@ -224,7 +226,7 @@ var WARNING_MESSAGES = {
|
|
|
224
226
|
X12_MISSING_REQUIRED_LOOP_2000B: 'Missing required loop "2000B" (Subscriber HL): no Subscriber HL precedes the CLM.',
|
|
225
227
|
X12_MISSING_REQUIRED_LOOP_2010BA: 'Missing required loop "2010BA" (Subscriber Name): no Subscriber Name follows the Subscriber HL.',
|
|
226
228
|
X12_MISSING_REQUIRED_LOOP_2010BB: 'Missing required loop "2010BB" (Payer Name): no Payer Name follows the Subscriber HL.',
|
|
227
|
-
X12_837_UNKNOWN_VARIANT: "837 variant could not be resolved: ST-03's implementation convention reference is absent, empty, or not an 837 Technical Report Type 3 identifier this reader recognises, and no SVx service-line segment was present to fall back on. The set of references it recognises covers the professional, institutional and dental 837 guides HIPAA adopts at 45 CFR 162.1102 together with their published errata; it is NOT claimed to be exhaustive, and this message deliberately does not enumerate it, because a list here goes stale the moment a guide is added. A reference outside that set is not asserted to be invalid - all this code reports is that this reader could not turn it into a variant and had nothing to fall back on.
|
|
229
|
+
X12_837_UNKNOWN_VARIANT: "837 variant could not be resolved: ST-03's implementation convention reference is absent, empty, or not an 837 Technical Report Type 3 identifier this reader recognises, and no SVx service-line segment was present to fall back on. The set of references it recognises covers the professional, institutional and dental 837 guides HIPAA adopts at 45 CFR 162.1102 together with their published errata; it is NOT claimed to be exhaustive, and this message deliberately does not enumerate it, because a list here goes stale the moment a guide is added. A reference outside that set is not asserted to be invalid - all this code reports is that this reader could not turn it into a variant and had nothing to fall back on.",
|
|
228
230
|
X12_837_AMBIGUOUS_VARIANT: "837 variant resolved from a service segment while the transaction body carries service segments of more than one variant: no caller `type` option was supplied and ST-03's implementation convention reference is absent, empty, or not an 837 Technical Report Type 3 identifier this reader recognises, so this reader fell back to the FIRST SV1 / SV2 / SV3 in the body, and a later one names a different variant. `submission.variant` is therefore a guess between contradictory evidence, and every claim and service line in the submission was read against it. Which service segment is the stray one is NOT decided here and is not derivable from the TR3s: this reader cannot tell a stray service segment from a conformant one, and the fallback takes the first regardless of whether any Loop 2400 was open at it, so an orphan segment decides the variant like any other. Read the bound literally, as a property of the RESOLUTION rather than of the document: this reports the fallback's own ambiguity, so a caller-supplied `type`, or an ST-03 this reader does turn into a variant, means no guess was made and this code is NOT raised however mixed the body is. Whatever else this reader raised on a document that reaches this code, it still raises, at the same position, and this one is added beside them. It is NOT a list of what else you will see, and it does not promise that any particular loss on such a document is reported at all. Re-read with the `type` option to decode the document against a variant you trust. The verbatim segments are preserved on the transaction set; read them there before acting on the submission's type.",
|
|
229
231
|
X12_UNKNOWN_CLAIM_STATUS_CATEGORY: "Unknown claim status category (CSCC): the STC composite's first component is outside the bundled snapshot. The verbatim code is preserved on the status; only its description is unavailable.",
|
|
230
232
|
X12_UNKNOWN_CLAIM_STATUS: "Unknown claim status code (CSC): the STC composite's second component is outside the bundled snapshot. The verbatim code is preserved on the status; only its description is unavailable.",
|
|
@@ -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,
|
|
@@ -868,8 +877,11 @@ function boundSegmentId(first) {
|
|
|
868
877
|
return SEGMENT_ID_SHAPE_RE.test(first) ? first : NON_SPEC_SEGMENT_ID;
|
|
869
878
|
}
|
|
870
879
|
function decodeSegment(raw, delimiters, emit, position) {
|
|
871
|
-
const
|
|
872
|
-
|
|
880
|
+
const degenerate = delimiters.element === RELEASE_CHAR;
|
|
881
|
+
const elements = Object.freeze(
|
|
882
|
+
degenerate ? raw.split(delimiters.element) : splitWithRelease(raw, delimiters.element)
|
|
883
|
+
);
|
|
884
|
+
if (!degenerate && raw.length > 0 && raw.endsWith(RELEASE_CHAR)) {
|
|
873
885
|
let trailingRun = 0;
|
|
874
886
|
for (let j = raw.length - 1; j >= 0 && raw.charAt(j) === RELEASE_CHAR; j -= 1) trailingRun += 1;
|
|
875
887
|
if (trailingRun % 2 === 1) {
|
|
@@ -1045,6 +1057,7 @@ function collectElementValues(seg, start, end, delimiters) {
|
|
|
1045
1057
|
}
|
|
1046
1058
|
|
|
1047
1059
|
// src/parser/envelope.ts
|
|
1060
|
+
var ISA_DECODED_PART_COUNT = 17;
|
|
1048
1061
|
function decodeIsa(raw, delimiters) {
|
|
1049
1062
|
const isaRaw = raw.slice(0, ISA_MIN_LENGTH);
|
|
1050
1063
|
const isaHead = isaRaw.slice(0, ISA_MIN_LENGTH - 1);
|
|
@@ -1111,6 +1124,9 @@ function decodeEnvelope(raw, delimiters) {
|
|
|
1111
1124
|
warnings.push(w);
|
|
1112
1125
|
};
|
|
1113
1126
|
const isa = decodeIsa(raw, delimiters);
|
|
1127
|
+
if (isa.elements.length !== ISA_DECODED_PART_COUNT) {
|
|
1128
|
+
warnings.push(isaExtraElementSeparator({ segmentIndex: 0, interchangeIndex: 0 }));
|
|
1129
|
+
}
|
|
1114
1130
|
const isa12 = el(isa.elements, 12);
|
|
1115
1131
|
if (isa12 !== "00501") {
|
|
1116
1132
|
warnings.push(pre005010({ segmentIndex: 0, interchangeIndex: 0, elementIndex: 12 }));
|
|
@@ -2706,10 +2722,70 @@ function requireCallerString(value, at, refuse) {
|
|
|
2706
2722
|
`${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.`
|
|
2707
2723
|
);
|
|
2708
2724
|
}
|
|
2725
|
+
var DELIMITER_ROLES = [
|
|
2726
|
+
["element", "element separator"],
|
|
2727
|
+
["repetition", "repetition separator"],
|
|
2728
|
+
["component", "component separator"],
|
|
2729
|
+
["segment", "segment terminator"]
|
|
2730
|
+
];
|
|
2731
|
+
function requireEscapableDelimiters(delimiters, at, refuse) {
|
|
2732
|
+
const degenerate = DELIMITER_ROLES.filter(([role]) => delimiters[role] === RELEASE_CHAR).map(
|
|
2733
|
+
([, name]) => name
|
|
2734
|
+
);
|
|
2735
|
+
if (degenerate.length === 0) return;
|
|
2736
|
+
const roles = degenerate.length === 1 ? `the ${degenerate[0] ?? ""}` : `the ${degenerate.slice(0, -1).join(", the ")} and the ${degenerate[degenerate.length - 1] ?? ""}`;
|
|
2737
|
+
refuse(
|
|
2738
|
+
`${at}: "${RELEASE_CHAR}" is the X12 release character and cannot also be ${roles}. An escape is written by prefixing "${RELEASE_CHAR}" to the byte it protects, so on this set the protection is emitted as structure; and a composite or a repetition joined with "${RELEASE_CHAR}" is emitted as an escape. Neither reads back, and no element value avoids it. Declare a delimiter set in which no role is "${RELEASE_CHAR}".`
|
|
2739
|
+
);
|
|
2740
|
+
}
|
|
2741
|
+
function requireWellShapedDelimiters(delimiters, at, refuse) {
|
|
2742
|
+
const REMEDY = `A delimiter occupies ONE fixed position of the ISA (ISA-11, ISA-16 and the position after it), so this set cannot be transmitted and this library's own parser would reject a document declaring it. Declare four distinct, visible, single-character delimiters.`;
|
|
2743
|
+
for (const [role, name] of DELIMITER_ROLES) {
|
|
2744
|
+
const value = delimiters[role];
|
|
2745
|
+
if (typeof value !== "string") {
|
|
2746
|
+
refuse(
|
|
2747
|
+
`${at}: the ${name} must be a string, but received ${describeCallerValue(value)}. Values are never coerced - a coerced delimiter frames the document while the release escape still compares against what you passed, so no element value is protected from it. ${REMEDY}`
|
|
2748
|
+
);
|
|
2749
|
+
}
|
|
2750
|
+
if (value.length !== 1) {
|
|
2751
|
+
refuse(
|
|
2752
|
+
`${at}: the ${name} must be exactly one character, but the declared value is ${value.length === 0 ? "empty" : `${String(value.length)} characters long`}. ${REMEDY}`
|
|
2753
|
+
);
|
|
2754
|
+
}
|
|
2755
|
+
if (!isVisibleDelimiterChar(value)) {
|
|
2756
|
+
refuse(
|
|
2757
|
+
`${at}: the ${name} must be a visible character, but the declared value is whitespace or a control character. ${REMEDY}`
|
|
2758
|
+
);
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
for (const [i, [role, name]] of DELIMITER_ROLES.entries()) {
|
|
2762
|
+
const earlier = DELIMITER_ROLES.slice(0, i).find(([r]) => delimiters[r] === delimiters[role]);
|
|
2763
|
+
if (earlier !== void 0) {
|
|
2764
|
+
refuse(
|
|
2765
|
+
`${at}: the ${name} and the ${earlier[1]} are the same character. A reader cannot tell which role a character is playing. ${REMEDY}`
|
|
2766
|
+
);
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2709
2770
|
function makeCallerEscaper(delimiters, at, refuse) {
|
|
2771
|
+
requireEscapableDelimiters(delimiters, at, refuse);
|
|
2772
|
+
requireWellShapedDelimiters(delimiters, at, refuse);
|
|
2710
2773
|
return (value) => escapeRelease(requireCallerString(value, at, refuse), delimiters);
|
|
2711
2774
|
}
|
|
2712
2775
|
|
|
2776
|
+
// src/builder/caller-control-number.ts
|
|
2777
|
+
function requireControlNumber(value, slot, field, at, refuse) {
|
|
2778
|
+
if (typeof value !== "string") {
|
|
2779
|
+
refuse(
|
|
2780
|
+
`${at}: ${field} must be a string, but received ${describeCallerValue(value)}. ${slot} is a required control number and this builder never coerces one, so nothing is emitted. Convert ${field} at the call site.`
|
|
2781
|
+
);
|
|
2782
|
+
}
|
|
2783
|
+
if (value !== "") return value;
|
|
2784
|
+
refuse(
|
|
2785
|
+
`${at}: ${field} is empty. ${slot} is a required control number and this builder never invents one, so nothing is emitted. Supply ${field}.`
|
|
2786
|
+
);
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2713
2789
|
// src/transactions/remit/build-835.ts
|
|
2714
2790
|
function refuseSpec(message) {
|
|
2715
2791
|
throw new Remit835BuildError(REMIT_835_BUILD_ERROR_CODES.X12_835_BUILD_INVALID_SPEC, message);
|
|
@@ -2754,6 +2830,27 @@ function build835(spec) {
|
|
|
2754
2830
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
2755
2831
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
2756
2832
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
2833
|
+
requireControlNumber(
|
|
2834
|
+
envelope.interchangeControlNumber,
|
|
2835
|
+
"ISA-13 / IEA-02",
|
|
2836
|
+
"interchangeControlNumber",
|
|
2837
|
+
"build835",
|
|
2838
|
+
refuseSpec
|
|
2839
|
+
);
|
|
2840
|
+
requireControlNumber(
|
|
2841
|
+
envelope.groupControlNumber,
|
|
2842
|
+
"GS-06 / GE-02",
|
|
2843
|
+
"groupControlNumber",
|
|
2844
|
+
"build835",
|
|
2845
|
+
refuseSpec
|
|
2846
|
+
);
|
|
2847
|
+
requireControlNumber(
|
|
2848
|
+
envelope.transactionSetControlNumber,
|
|
2849
|
+
"ST-02 / SE-02",
|
|
2850
|
+
"transactionSetControlNumber",
|
|
2851
|
+
"build835",
|
|
2852
|
+
refuseSpec
|
|
2853
|
+
);
|
|
2757
2854
|
const interchangeControlNumber = padControl(envelope.interchangeControlNumber, 9);
|
|
2758
2855
|
const isa = [
|
|
2759
2856
|
"ISA",
|
|
@@ -3331,6 +3428,14 @@ function wireLookup(entries) {
|
|
|
3331
3428
|
return Object.freeze(table);
|
|
3332
3429
|
}
|
|
3333
3430
|
|
|
3431
|
+
// src/transactions/shared/st03.ts
|
|
3432
|
+
var noopWarningSink = (_w) => {
|
|
3433
|
+
};
|
|
3434
|
+
function decodeSt03(raw, delimiters, position) {
|
|
3435
|
+
if (raw === void 0) return void 0;
|
|
3436
|
+
return unescapeRelease(raw, delimiters, noopWarningSink, position);
|
|
3437
|
+
}
|
|
3438
|
+
|
|
3334
3439
|
// src/transactions/claim/address-segments.ts
|
|
3335
3440
|
function emitsStreetLines(address) {
|
|
3336
3441
|
return address.lines.length > 0;
|
|
@@ -3389,9 +3494,14 @@ function get837Claims(delimiters, tx, opts) {
|
|
|
3389
3494
|
if (tx.st.elements[1] !== "837") return void 0;
|
|
3390
3495
|
const warnings = [];
|
|
3391
3496
|
const body = tx.se === void 0 ? tx.segments.slice(1) : tx.segments.slice(1, -1);
|
|
3392
|
-
const
|
|
3497
|
+
const implementationConventionReferenceRaw = tx.st.elements[3];
|
|
3498
|
+
const implementationConventionReference = decodeSt03(
|
|
3499
|
+
implementationConventionReferenceRaw,
|
|
3500
|
+
delimiters,
|
|
3501
|
+
{ segmentIndex: 0, transactionIndex: 0 }
|
|
3502
|
+
);
|
|
3393
3503
|
const explicitType = opts?.type;
|
|
3394
|
-
const variantFromIcr =
|
|
3504
|
+
const variantFromIcr = implementationConventionReferenceRaw !== void 0 && implementationConventionReferenceRaw !== "" ? VARIANT_BY_ICR[implementationConventionReferenceRaw] : void 0;
|
|
3395
3505
|
let variantFromSegment;
|
|
3396
3506
|
let serviceSegmentVariantsConflict = false;
|
|
3397
3507
|
if (explicitType === void 0 && variantFromIcr === void 0) {
|
|
@@ -4642,6 +4752,27 @@ function buildClaim837(variant, spec) {
|
|
|
4642
4752
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
4643
4753
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
4644
4754
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
4755
|
+
requireControlNumber(
|
|
4756
|
+
envelope.interchangeControlNumber,
|
|
4757
|
+
"ISA-13 / IEA-02",
|
|
4758
|
+
"interchangeControlNumber",
|
|
4759
|
+
"build837",
|
|
4760
|
+
refuseSpec2
|
|
4761
|
+
);
|
|
4762
|
+
requireControlNumber(
|
|
4763
|
+
envelope.groupControlNumber,
|
|
4764
|
+
"GS-06 / GE-02",
|
|
4765
|
+
"groupControlNumber",
|
|
4766
|
+
"build837",
|
|
4767
|
+
refuseSpec2
|
|
4768
|
+
);
|
|
4769
|
+
requireControlNumber(
|
|
4770
|
+
envelope.transactionSetControlNumber,
|
|
4771
|
+
"ST-02 / SE-02",
|
|
4772
|
+
"transactionSetControlNumber",
|
|
4773
|
+
"build837",
|
|
4774
|
+
refuseSpec2
|
|
4775
|
+
);
|
|
4645
4776
|
const interchangeControlNumber = padControl2(envelope.interchangeControlNumber, 9);
|
|
4646
4777
|
const isa = [
|
|
4647
4778
|
"ISA",
|
|
@@ -5813,6 +5944,27 @@ function build271(spec) {
|
|
|
5813
5944
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
5814
5945
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
5815
5946
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
5947
|
+
requireControlNumber(
|
|
5948
|
+
envelope.interchangeControlNumber,
|
|
5949
|
+
"ISA-13 / IEA-02",
|
|
5950
|
+
"interchangeControlNumber",
|
|
5951
|
+
"build271",
|
|
5952
|
+
refuseSpec3
|
|
5953
|
+
);
|
|
5954
|
+
requireControlNumber(
|
|
5955
|
+
envelope.groupControlNumber,
|
|
5956
|
+
"GS-06 / GE-02",
|
|
5957
|
+
"groupControlNumber",
|
|
5958
|
+
"build271",
|
|
5959
|
+
refuseSpec3
|
|
5960
|
+
);
|
|
5961
|
+
requireControlNumber(
|
|
5962
|
+
envelope.transactionSetControlNumber,
|
|
5963
|
+
"ST-02 / SE-02",
|
|
5964
|
+
"transactionSetControlNumber",
|
|
5965
|
+
"build271",
|
|
5966
|
+
refuseSpec3
|
|
5967
|
+
);
|
|
5816
5968
|
const interchangeControlNumber = padControl3(envelope.interchangeControlNumber, 9);
|
|
5817
5969
|
const isa = [
|
|
5818
5970
|
"ISA",
|
|
@@ -6183,8 +6335,13 @@ function get277CADisposition(delimiters, tx) {
|
|
|
6183
6335
|
function walk277(delimiters, tx) {
|
|
6184
6336
|
const warnings = [];
|
|
6185
6337
|
const body = tx.se === void 0 ? tx.segments.slice(1) : tx.segments.slice(1, -1);
|
|
6186
|
-
const
|
|
6187
|
-
const
|
|
6338
|
+
const implementationConventionReferenceRaw = tx.st.elements[3];
|
|
6339
|
+
const implementationConventionReference = decodeSt03(
|
|
6340
|
+
implementationConventionReferenceRaw,
|
|
6341
|
+
delimiters,
|
|
6342
|
+
{ segmentIndex: 0, transactionIndex: 0 }
|
|
6343
|
+
);
|
|
6344
|
+
const transactionType = implementationConventionReferenceRaw === ICR_277CA ? "claim-acknowledgment" : "claim-status";
|
|
6188
6345
|
const hierarchies = [];
|
|
6189
6346
|
const hlIndex = /* @__PURE__ */ new Map();
|
|
6190
6347
|
const claims = [];
|
|
@@ -6539,6 +6696,27 @@ function buildClaimStatus(version, spec) {
|
|
|
6539
6696
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
6540
6697
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
6541
6698
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
6699
|
+
requireControlNumber(
|
|
6700
|
+
envelope.interchangeControlNumber,
|
|
6701
|
+
"ISA-13 / IEA-02",
|
|
6702
|
+
"interchangeControlNumber",
|
|
6703
|
+
"build277",
|
|
6704
|
+
refuseSpec4
|
|
6705
|
+
);
|
|
6706
|
+
requireControlNumber(
|
|
6707
|
+
envelope.groupControlNumber,
|
|
6708
|
+
"GS-06 / GE-02",
|
|
6709
|
+
"groupControlNumber",
|
|
6710
|
+
"build277",
|
|
6711
|
+
refuseSpec4
|
|
6712
|
+
);
|
|
6713
|
+
requireControlNumber(
|
|
6714
|
+
envelope.transactionSetControlNumber,
|
|
6715
|
+
"ST-02 / SE-02",
|
|
6716
|
+
"transactionSetControlNumber",
|
|
6717
|
+
"build277",
|
|
6718
|
+
refuseSpec4
|
|
6719
|
+
);
|
|
6542
6720
|
const interchangeControlNumber = padControl4(envelope.interchangeControlNumber, 9);
|
|
6543
6721
|
const isa = [
|
|
6544
6722
|
"ISA",
|
|
@@ -7330,6 +7508,27 @@ function build820(spec) {
|
|
|
7330
7508
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
7331
7509
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
7332
7510
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
7511
|
+
requireControlNumber(
|
|
7512
|
+
envelope.interchangeControlNumber,
|
|
7513
|
+
"ISA-13 / IEA-02",
|
|
7514
|
+
"interchangeControlNumber",
|
|
7515
|
+
"build820",
|
|
7516
|
+
refuseSpec5
|
|
7517
|
+
);
|
|
7518
|
+
requireControlNumber(
|
|
7519
|
+
envelope.groupControlNumber,
|
|
7520
|
+
"GS-06 / GE-02",
|
|
7521
|
+
"groupControlNumber",
|
|
7522
|
+
"build820",
|
|
7523
|
+
refuseSpec5
|
|
7524
|
+
);
|
|
7525
|
+
requireControlNumber(
|
|
7526
|
+
envelope.transactionSetControlNumber,
|
|
7527
|
+
"ST-02 / SE-02",
|
|
7528
|
+
"transactionSetControlNumber",
|
|
7529
|
+
"build820",
|
|
7530
|
+
refuseSpec5
|
|
7531
|
+
);
|
|
7333
7532
|
const interchangeControlNumber = padControl5(envelope.interchangeControlNumber, 9);
|
|
7334
7533
|
const isa = [
|
|
7335
7534
|
"ISA",
|
|
@@ -8037,6 +8236,27 @@ function build834(spec) {
|
|
|
8037
8236
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
8038
8237
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
8039
8238
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
8239
|
+
requireControlNumber(
|
|
8240
|
+
envelope.interchangeControlNumber,
|
|
8241
|
+
"ISA-13 / IEA-02",
|
|
8242
|
+
"interchangeControlNumber",
|
|
8243
|
+
"build834",
|
|
8244
|
+
refuseSpec6
|
|
8245
|
+
);
|
|
8246
|
+
requireControlNumber(
|
|
8247
|
+
envelope.groupControlNumber,
|
|
8248
|
+
"GS-06 / GE-02",
|
|
8249
|
+
"groupControlNumber",
|
|
8250
|
+
"build834",
|
|
8251
|
+
refuseSpec6
|
|
8252
|
+
);
|
|
8253
|
+
requireControlNumber(
|
|
8254
|
+
envelope.transactionSetControlNumber,
|
|
8255
|
+
"ST-02 / SE-02",
|
|
8256
|
+
"transactionSetControlNumber",
|
|
8257
|
+
"build834",
|
|
8258
|
+
refuseSpec6
|
|
8259
|
+
);
|
|
8040
8260
|
const interchangeControlNumber = padControl6(envelope.interchangeControlNumber, 9);
|
|
8041
8261
|
const isa = [
|
|
8042
8262
|
"ISA",
|
|
@@ -8489,7 +8709,10 @@ function walk278(delimiters, tx, direction) {
|
|
|
8489
8709
|
}
|
|
8490
8710
|
}
|
|
8491
8711
|
flushReview();
|
|
8492
|
-
const icr = tx.st.elements[3]
|
|
8712
|
+
const icr = decodeSt03(tx.st.elements[3], delimiters, {
|
|
8713
|
+
segmentIndex: 0,
|
|
8714
|
+
transactionIndex: 0
|
|
8715
|
+
});
|
|
8493
8716
|
return Object.freeze({
|
|
8494
8717
|
direction,
|
|
8495
8718
|
implementationConventionReference: icr === void 0 || icr === "" ? void 0 : icr,
|
|
@@ -8713,6 +8936,27 @@ function buildServicesReview(version, direction, spec) {
|
|
|
8713
8936
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
8714
8937
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
8715
8938
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
8939
|
+
requireControlNumber(
|
|
8940
|
+
envelope.interchangeControlNumber,
|
|
8941
|
+
"ISA-13 / IEA-02",
|
|
8942
|
+
"interchangeControlNumber",
|
|
8943
|
+
"build278",
|
|
8944
|
+
refuseSpec7
|
|
8945
|
+
);
|
|
8946
|
+
requireControlNumber(
|
|
8947
|
+
envelope.groupControlNumber,
|
|
8948
|
+
"GS-06 / GE-02",
|
|
8949
|
+
"groupControlNumber",
|
|
8950
|
+
"build278",
|
|
8951
|
+
refuseSpec7
|
|
8952
|
+
);
|
|
8953
|
+
requireControlNumber(
|
|
8954
|
+
envelope.transactionSetControlNumber,
|
|
8955
|
+
"ST-02 / SE-02",
|
|
8956
|
+
"transactionSetControlNumber",
|
|
8957
|
+
"build278",
|
|
8958
|
+
refuseSpec7
|
|
8959
|
+
);
|
|
8716
8960
|
const interchangeControlNumber = padControl7(envelope.interchangeControlNumber, 9);
|
|
8717
8961
|
const isa = [
|
|
8718
8962
|
"ISA",
|
|
@@ -9420,11 +9664,12 @@ function parseTA1(interchange) {
|
|
|
9420
9664
|
const ta1 = interchange.ta1Segments[0];
|
|
9421
9665
|
if (ta1 === void 0) return void 0;
|
|
9422
9666
|
const elements = ta1.elements;
|
|
9423
|
-
const
|
|
9424
|
-
const
|
|
9425
|
-
const
|
|
9426
|
-
const
|
|
9427
|
-
const
|
|
9667
|
+
const value = (index) => unescapeRelease(elements[index] ?? "", interchange.delimiters, noop3, { segmentIndex: 0 });
|
|
9668
|
+
const interchangeControlNumber = value(1);
|
|
9669
|
+
const interchangeDate = value(2);
|
|
9670
|
+
const interchangeTime = value(3);
|
|
9671
|
+
const ackCodeRaw = value(4);
|
|
9672
|
+
const noteCodeRaw = value(5);
|
|
9428
9673
|
const ackCode = narrowAckCode(ackCodeRaw) ?? TA1_ACK_CODES.R;
|
|
9429
9674
|
const noteCode = narrowNoteCode(noteCodeRaw);
|
|
9430
9675
|
return Object.freeze({
|
|
@@ -9437,6 +9682,8 @@ function parseTA1(interchange) {
|
|
|
9437
9682
|
raw: ta1
|
|
9438
9683
|
});
|
|
9439
9684
|
}
|
|
9685
|
+
var noop3 = (_w) => {
|
|
9686
|
+
};
|
|
9440
9687
|
function narrowAckCode(value) {
|
|
9441
9688
|
switch (value) {
|
|
9442
9689
|
case "A":
|
|
@@ -9478,6 +9725,27 @@ function build999(spec) {
|
|
|
9478
9725
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
9479
9726
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
9480
9727
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
9728
|
+
requireControlNumber(
|
|
9729
|
+
envelope.interchangeControlNumber,
|
|
9730
|
+
"ISA-13 / IEA-02",
|
|
9731
|
+
"interchangeControlNumber",
|
|
9732
|
+
"build999",
|
|
9733
|
+
refuseSpec8
|
|
9734
|
+
);
|
|
9735
|
+
requireControlNumber(
|
|
9736
|
+
envelope.groupControlNumber,
|
|
9737
|
+
"GS-06 / GE-02",
|
|
9738
|
+
"groupControlNumber",
|
|
9739
|
+
"build999",
|
|
9740
|
+
refuseSpec8
|
|
9741
|
+
);
|
|
9742
|
+
requireControlNumber(
|
|
9743
|
+
envelope.transactionSetControlNumber,
|
|
9744
|
+
"ST-02 / SE-02",
|
|
9745
|
+
"transactionSetControlNumber",
|
|
9746
|
+
"build999",
|
|
9747
|
+
refuseSpec8
|
|
9748
|
+
);
|
|
9481
9749
|
const interchangeControlNumber = padControl8(envelope.interchangeControlNumber, 9);
|
|
9482
9750
|
const isa = [
|
|
9483
9751
|
"ISA",
|
|
@@ -9546,6 +9814,13 @@ function build999(spec) {
|
|
|
9546
9814
|
elementSeparator,
|
|
9547
9815
|
segmentTerminator
|
|
9548
9816
|
);
|
|
9817
|
+
requireControlNumber(
|
|
9818
|
+
functionalGroup.groupControlNumber,
|
|
9819
|
+
"AK1-02",
|
|
9820
|
+
"functionalGroup.groupControlNumber",
|
|
9821
|
+
"build999",
|
|
9822
|
+
refuseSpec8
|
|
9823
|
+
);
|
|
9549
9824
|
const ak1 = joinSeg(
|
|
9550
9825
|
[
|
|
9551
9826
|
"AK1",
|
|
@@ -9652,6 +9927,13 @@ function responseHasAnyError(response) {
|
|
|
9652
9927
|
return false;
|
|
9653
9928
|
}
|
|
9654
9929
|
function buildAk2(response, esc, elementSeparator, segmentTerminator) {
|
|
9930
|
+
requireControlNumber(
|
|
9931
|
+
response.transactionSetControlNumber,
|
|
9932
|
+
"AK2-02",
|
|
9933
|
+
"transactionResponses[].transactionSetControlNumber",
|
|
9934
|
+
"build999",
|
|
9935
|
+
refuseSpec8
|
|
9936
|
+
);
|
|
9655
9937
|
const parts = [
|
|
9656
9938
|
"AK2",
|
|
9657
9939
|
esc(response.transactionSetIdCode),
|
|
@@ -9770,13 +10052,29 @@ function buildTA1(spec, options = {}) {
|
|
|
9770
10052
|
segment: options.segmentTerminator ?? "~"
|
|
9771
10053
|
};
|
|
9772
10054
|
const esc = makeCallerEscaper(delimiters, "buildTA1", refuseSpec9);
|
|
10055
|
+
requireControlNumber(
|
|
10056
|
+
spec.interchangeControlNumber,
|
|
10057
|
+
"TA1-01",
|
|
10058
|
+
"interchangeControlNumber",
|
|
10059
|
+
"buildTA1",
|
|
10060
|
+
refuseSpec9
|
|
10061
|
+
);
|
|
10062
|
+
const interchangeControlNumber = esc(spec.interchangeControlNumber);
|
|
10063
|
+
const interchangeDate = esc(spec.interchangeDate);
|
|
10064
|
+
const interchangeTime = esc(spec.interchangeTime);
|
|
10065
|
+
const ackCode = esc(spec.ackCode);
|
|
10066
|
+
const noteCode = esc(spec.noteCode);
|
|
10067
|
+
requireTa1Element(interchangeDate, "TA1-02", "interchangeDate");
|
|
10068
|
+
requireTa1Element(interchangeTime, "TA1-03", "interchangeTime");
|
|
10069
|
+
requireTa1Element(ackCode, "TA1-04", "ackCode");
|
|
10070
|
+
requireTa1Element(noteCode, "TA1-05", "noteCode");
|
|
9773
10071
|
const elements = Object.freeze([
|
|
9774
10072
|
"TA1",
|
|
9775
|
-
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
10073
|
+
interchangeControlNumber,
|
|
10074
|
+
interchangeDate,
|
|
10075
|
+
interchangeTime,
|
|
10076
|
+
ackCode,
|
|
10077
|
+
noteCode
|
|
9780
10078
|
]);
|
|
9781
10079
|
const raw = elements.join(delimiters.element);
|
|
9782
10080
|
return Object.freeze({ raw, elements });
|
|
@@ -9784,6 +10082,12 @@ function buildTA1(spec, options = {}) {
|
|
|
9784
10082
|
function refuseSpec9(message) {
|
|
9785
10083
|
throw new AckBuildError(ACK_BUILD_ERROR_CODES.X12_ACK_INVALID_SPEC, message);
|
|
9786
10084
|
}
|
|
10085
|
+
function requireTa1Element(emitted, slot, field) {
|
|
10086
|
+
if (emitted !== "") return;
|
|
10087
|
+
refuseSpec9(
|
|
10088
|
+
`buildTA1: ${field} is empty. ${slot} is a required element and this builder never invents one, so nothing is emitted. Supply ${field}.`
|
|
10089
|
+
);
|
|
10090
|
+
}
|
|
9787
10091
|
function enforceAcceptIsClean2(spec) {
|
|
9788
10092
|
if (spec.ackCode === TA1_ACK_CODES.A && spec.noteCode !== "000") {
|
|
9789
10093
|
throw new AckBuildError(
|
|
@@ -9991,6 +10295,13 @@ function buildInterchange(spec) {
|
|
|
9991
10295
|
const receiverQualifier = spec.receiverQualifier ?? "ZZ";
|
|
9992
10296
|
const usageIndicator = spec.usageIndicator ?? "P";
|
|
9993
10297
|
const version = spec.version ?? "00501";
|
|
10298
|
+
requireControlNumber(
|
|
10299
|
+
spec.interchangeControlNumber,
|
|
10300
|
+
"ISA-13 / IEA-02",
|
|
10301
|
+
"interchangeControlNumber",
|
|
10302
|
+
"buildInterchange",
|
|
10303
|
+
refuseSpec10
|
|
10304
|
+
);
|
|
9994
10305
|
const interchangeControlNumber = padControl9(spec.interchangeControlNumber, 9);
|
|
9995
10306
|
const isa = [
|
|
9996
10307
|
"ISA",
|
|
@@ -10040,23 +10351,32 @@ function buildInterchange(spec) {
|
|
|
10040
10351
|
return parseX12(raw);
|
|
10041
10352
|
}
|
|
10042
10353
|
function buildGroup(group, spec, esc, elementSeparator, segmentTerminator) {
|
|
10354
|
+
requireControlNumber(
|
|
10355
|
+
group.groupControlNumber,
|
|
10356
|
+
"GS-06 / GE-02",
|
|
10357
|
+
"groupControlNumber",
|
|
10358
|
+
"buildInterchange",
|
|
10359
|
+
refuseSpec10
|
|
10360
|
+
);
|
|
10043
10361
|
const applicationSenderCode = group.applicationSenderCode ?? spec.senderId;
|
|
10044
10362
|
const applicationReceiverCode = group.applicationReceiverCode ?? spec.receiverId;
|
|
10045
10363
|
const groupDate = group.groupDate ?? expandYY9(spec.interchangeDate);
|
|
10046
10364
|
const groupTime = group.groupTime ?? spec.interchangeTime;
|
|
10047
10365
|
const responsibleAgencyCode = group.responsibleAgencyCode ?? "X";
|
|
10366
|
+
const gsParts = [
|
|
10367
|
+
"GS",
|
|
10368
|
+
group.functionalIdCode,
|
|
10369
|
+
applicationSenderCode,
|
|
10370
|
+
applicationReceiverCode,
|
|
10371
|
+
groupDate,
|
|
10372
|
+
groupTime,
|
|
10373
|
+
group.groupControlNumber,
|
|
10374
|
+
responsibleAgencyCode,
|
|
10375
|
+
group.versionRelease
|
|
10376
|
+
];
|
|
10377
|
+
requireCallerSegment(gsParts, "buildInterchange", refuseSpec10);
|
|
10048
10378
|
const gs = joinSeg2(
|
|
10049
|
-
|
|
10050
|
-
"GS",
|
|
10051
|
-
esc(group.functionalIdCode),
|
|
10052
|
-
esc(applicationSenderCode),
|
|
10053
|
-
esc(applicationReceiverCode),
|
|
10054
|
-
groupDate,
|
|
10055
|
-
groupTime,
|
|
10056
|
-
esc(group.groupControlNumber),
|
|
10057
|
-
responsibleAgencyCode,
|
|
10058
|
-
esc(group.versionRelease)
|
|
10059
|
-
],
|
|
10379
|
+
gsParts.map((value, index) => index === 0 ? value : esc(value)),
|
|
10060
10380
|
elementSeparator,
|
|
10061
10381
|
segmentTerminator
|
|
10062
10382
|
);
|
|
@@ -10072,6 +10392,13 @@ function buildGroup(group, spec, esc, elementSeparator, segmentTerminator) {
|
|
|
10072
10392
|
return gs + transactions + ge;
|
|
10073
10393
|
}
|
|
10074
10394
|
function buildTransaction(tx, esc, elementSeparator, segmentTerminator) {
|
|
10395
|
+
requireControlNumber(
|
|
10396
|
+
tx.transactionSetControlNumber,
|
|
10397
|
+
"ST-02 / SE-02",
|
|
10398
|
+
"transactionSetControlNumber",
|
|
10399
|
+
"buildInterchange",
|
|
10400
|
+
refuseSpec10
|
|
10401
|
+
);
|
|
10075
10402
|
const stParts = ["ST", esc(tx.transactionSetIdCode), esc(tx.transactionSetControlNumber)];
|
|
10076
10403
|
if (tx.implementationConventionReference !== void 0) {
|
|
10077
10404
|
stParts.push(esc(tx.implementationConventionReference));
|
|
@@ -10409,7 +10736,7 @@ var profiles = Object.freeze({
|
|
|
10409
10736
|
});
|
|
10410
10737
|
|
|
10411
10738
|
// src/index.ts
|
|
10412
|
-
var VERSION = "0.0.
|
|
10739
|
+
var VERSION = "0.0.17";
|
|
10413
10740
|
|
|
10414
10741
|
exports.ACK_BUILD_ERROR_CODES = ACK_BUILD_ERROR_CODES;
|
|
10415
10742
|
exports.ALL_WARNING_MESSAGES = ALL_WARNING_MESSAGES;
|
|
@@ -10571,6 +10898,7 @@ exports.isAcceptDisposition = isAcceptDisposition;
|
|
|
10571
10898
|
exports.isClaimAdjustmentGroupCode = isClaimAdjustmentGroupCode;
|
|
10572
10899
|
exports.isDiagnosisQualifier = isDiagnosisQualifier;
|
|
10573
10900
|
exports.isProcedureQualifier = isProcedureQualifier;
|
|
10901
|
+
exports.isaExtraElementSeparator = isaExtraElementSeparator;
|
|
10574
10902
|
exports.lookupCarc = lookupCarc;
|
|
10575
10903
|
exports.lookupClaimStatus = lookupClaimStatus;
|
|
10576
10904
|
exports.lookupClaimStatusCategory = lookupClaimStatusCategory;
|