@cosyte/x12 0.1.0 → 0.1.2
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 +31 -8
- package/KNOWN-LIMITATIONS.md +6 -6
- package/README.md +3 -4
- package/TRADEMARKS.md +1 -1
- package/dist/index.cjs +58 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -5
- package/dist/index.d.ts +60 -5
- package/dist/index.mjs +58 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +29 -38
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.1] - 2026-10-07
|
|
11
|
+
|
|
12
|
+
**What 0.1.1 means for you.** The 271 now reads and builds the procedure a benefit line applies to
|
|
13
|
+
(EB-13), which dental payers use for per-procedure coinsurance, frequency, age and maximum limits.
|
|
14
|
+
If you build an `X12EligibilityBenefit` object literal yourself, such as a test double, add
|
|
15
|
+
`procedure: undefined` to it. Code that reads benefits from `get271` needs no change.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **271 EB-13 read.** Each benefit's `procedure` carries the qualifier (EB-13-1), the code
|
|
20
|
+
(EB-13-2), up to four modifiers in transmitted order (EB-13-3 to EB-13-6) and the description
|
|
21
|
+
(EB-13-7) when the sender sent one, and is `undefined` when EB-13 is absent or has no qualifier.
|
|
22
|
+
Components are split on the component separator the interchange declares in ISA-16. New
|
|
23
|
+
package-root type export: `X12EligibilityProcedure`.
|
|
24
|
+
- **271 EB-13 emit.** A 271 benefit takes an optional `procedure` (`Build271ProcedureSpec`, a new
|
|
25
|
+
package-root type export) with a qualifier, a code and modifiers, written as one composite. The
|
|
26
|
+
builder refuses an empty qualifier or code, an empty modifier, and more than four modifiers: a
|
|
27
|
+
fifth would land in the description position, and an empty one would shift later modifiers on
|
|
28
|
+
read. The description is not written.
|
|
29
|
+
- The 270 reader's EQ-02 procedure decodes exactly as before and now shares its decoder with the 271.
|
|
30
|
+
|
|
31
|
+
## [0.1.0] - 2026-09-25
|
|
32
|
+
|
|
10
33
|
**What 0.1 means for you.** This release is the first whose public API we treat as settled: the
|
|
11
34
|
exported readers, builders, types and warning codes are the surface we keep stable, and the warning
|
|
12
35
|
registry only ever gains codes. It covers typed read and typed emit for 270, 271, 276, 277 and
|
|
@@ -1929,7 +1952,7 @@ required control number and this builder never invents one, so nothing is emitte
|
|
|
1929
1952
|
composite. Escaping against a guessed delimiter set is a value corruption rather than a safe
|
|
1930
1953
|
default: `unescapeRelease` preserves `?X` verbatim for any `X` outside the reader's declared set,
|
|
1931
1954
|
so a value released against the wrong delimiter comes back carrying a stray `?`. The defaults are
|
|
1932
|
-
unchanged and are the
|
|
1955
|
+
unchanged and are the Cosyte archetype, which this function cannot verify, so state the separators
|
|
1933
1956
|
if you embed a TA1 in an envelope that declares different ones.
|
|
1934
1957
|
|
|
1935
1958
|
**A non-string element now refuses** with `AckBuildError` and the existing `X12_ACK_INVALID_SPEC`
|
|
@@ -3020,7 +3043,7 @@ string, …` - which `esc` cannot, being unary.
|
|
|
3020
3043
|
|
|
3021
3044
|
- **Em-dash brand gate in CI (`scripts/check-no-emdash.sh`, `pnpm check:no-emdash`,
|
|
3022
3045
|
`.github/workflows/no-emdash.yml`; `EMDASH-CONFORMANCE`).** The founder directive of 2026-07-24
|
|
3023
|
-
(`knowledgebase/06-brand/voice-and-tone.md`) bans `U+2014` outright across every
|
|
3046
|
+
(`knowledgebase/06-brand/voice-and-tone.md`) bans `U+2014` outright across every Cosyte surface
|
|
3024
3047
|
and names commit messages explicitly, and the meta-repo's `documentation/conventions.md` has
|
|
3025
3048
|
described the rule as CI-gated; x12 was one of the repos where it was not. This ports
|
|
3026
3049
|
`knowledgebase`'s scanner (the text-only variant, correct here because x12 tracks no binaries:
|
|
@@ -3115,7 +3138,7 @@ string, …` - which `esc` cannot, being unary.
|
|
|
3115
3138
|
### Added
|
|
3116
3139
|
|
|
3117
3140
|
- **Trademark notice (`TRADEMARKS.md`).** This package names third-party systems to describe what it
|
|
3118
|
-
interoperates with; the notice records that
|
|
3141
|
+
interoperates with; the notice records that Cosyte is not affiliated with, endorsed by, or
|
|
3119
3142
|
sponsored by any of them, that every reference is descriptive, and that the built-in profiles are
|
|
3120
3143
|
authored from public sources only. Added to `files` so it ships inside the published tarball, not
|
|
3121
3144
|
just on GitHub. Documentation only, no runtime or API change.
|
|
@@ -3769,7 +3792,7 @@ EV/SS`), and HL-04 has-child flag from the nested input tree, so an
|
|
|
3769
3792
|
helper). The `X12ClaimNote` JSDoc explicitly flags NTE-02 as
|
|
3770
3793
|
PHI-bearing (provider-supplied free text). Every Phase 5 fixture
|
|
3771
3794
|
is synthetic (test names `TEST PATIENT` / `SUB LAST` / `PATIENT
|
|
3772
|
-
CHILD`; sequential member IDs `MEMBER001
|
|
3795
|
+
CHILD`; sequential member IDs `MEMBER001` to `MEMBER011` etc.; NPI-
|
|
3773
3796
|
shaped sequential numbers; obvious test addresses) and matches
|
|
3774
3797
|
the established 835 fixture conventions.
|
|
3775
3798
|
- **Known limitations after this phase** (deliberate v1 scope; none
|
|
@@ -3957,7 +3980,7 @@ refresh:code-lists` arrives in Phase 10); no per-payer profile
|
|
|
3957
3980
|
|
|
3958
3981
|
- **Phase 3: 999 + TA1 acknowledgments (TR3 005010X231A1).** Two
|
|
3959
3982
|
pure-function ack surfaces ship side-by-side; neither auto-sends, opens
|
|
3960
|
-
a socket, or touches the filesystem. The
|
|
3983
|
+
a socket, or touches the filesystem. The Cosyte ack archetype: the
|
|
3961
3984
|
library MECHANICALLY builds the disposition it is told and REFUSES to
|
|
3962
3985
|
fabricate an Accept against a non-empty error list. Mirrors hl7's
|
|
3963
3986
|
upcoming `buildAck` boundary and mllp's commit-contract pattern.
|
|
@@ -3978,7 +4001,7 @@ refresh:code-lists` arrives in Phase 10); no per-payer profile
|
|
|
3978
4001
|
a TA1 inside an open functional group is still flagged as unexpected
|
|
3979
4002
|
(non-spec). `parseTA1(interchange)` returns the typed `X12AckTA1`
|
|
3980
4003
|
for the first captured TA1 (or `undefined`). `buildTA1(spec)` emits
|
|
3981
|
-
a fixed-position 5-element `Ta1Segment` (`TA101
|
|
4004
|
+
a fixed-position 5-element `Ta1Segment` (`TA101` to `TA105`). Caller
|
|
3982
4005
|
wraps it in their preferred envelope. Both standalone TA1-only
|
|
3983
4006
|
interchanges (ISA → TA1 → IEA, no GS) and embedded TA1s round-trip.
|
|
3984
4007
|
- **Safety guards (refused via `AckBuildError`):** `build999` refuses
|
|
@@ -3997,7 +4020,7 @@ refresh:code-lists` arrives in Phase 10); no per-payer profile
|
|
|
3997
4020
|
`IK3_SYNTAX_ERROR_CODES` (code list 716, 13 codes),
|
|
3998
4021
|
`IK4_SYNTAX_ERROR_CODES` (code list 723, 18 codes),
|
|
3999
4022
|
`TA1_ACK_CODES` (code list I13: `A`/`E`/`R`),
|
|
4000
|
-
`TA1_NOTE_CODES` (code list I18: `000
|
|
4023
|
+
`TA1_NOTE_CODES` (code list I18: `000` to `028`). String-literal
|
|
4001
4024
|
unions are exported for exhaustive narrowing. The helper
|
|
4002
4025
|
`isAcceptDisposition(code)` returns true for `A`/`E`/`P` and false
|
|
4003
4026
|
for the four reject codes.
|
|
@@ -4142,7 +4165,7 @@ safety` test blocks assert no SSN / ISO-date / long-digit-run
|
|
|
4142
4165
|
|
|
4143
4166
|
### Changed
|
|
4144
4167
|
|
|
4145
|
-
- Migrated onto the shared
|
|
4168
|
+
- Migrated onto the shared Cosyte engineering standard (Phase E). The toolchain
|
|
4146
4169
|
is now inherited from the published `@cosyte/*` config packages instead of
|
|
4147
4170
|
per-repo copies: `tsup.config.ts` uses `cosyteTsup`, `vitest.config.ts` uses
|
|
4148
4171
|
`cosyteVitest`, and `eslint.config.js` is the three-line `cosyte` wrapper.
|
package/KNOWN-LIMITATIONS.md
CHANGED
|
@@ -672,7 +672,7 @@ model.
|
|
|
672
672
|
nothing else - `buildTA1` still emits no terminator. Escaping against a guessed set is a value
|
|
673
673
|
corruption rather than a safe default: `unescapeRelease` preserves `?X` verbatim for any `X`
|
|
674
674
|
outside the declared set, so a value released against the wrong delimiter comes back carrying a
|
|
675
|
-
stray `?`. **The defaults are the
|
|
675
|
+
stray `?`. **The defaults are the Cosyte archetype and this function cannot verify them** - if
|
|
676
676
|
you embed a TA1 in an envelope that declares different separators, state them.
|
|
677
677
|
- **A non-string element now REFUSES** with `AckBuildError` / `X12_ACK_INVALID_SPEC`, and that is a
|
|
678
678
|
prerequisite rather than a bonus. Releasing a value means routing it through the escape helper,
|
|
@@ -1555,7 +1555,7 @@ N-char spec limit` refusal, one per emitting module, where the branch fires **be
|
|
|
1555
1555
|
2. **Whether an `X12Decimal` carries the SCALE you meant.** `fromString("0.3")` and
|
|
1556
1556
|
`fromString("0.30")` are both accepted and both emit verbatim. That choice is yours.
|
|
1557
1557
|
3. **The delimiter set `buildTA1` releases against**, per the paragraph above. It defaults to the
|
|
1558
|
-
|
|
1558
|
+
Cosyte archetype and the function cannot verify it; state the separators on `BuildTA1Options`
|
|
1559
1559
|
if you embed a TA1 in an envelope that declares different ones.
|
|
1560
1560
|
4. **`build835`'s balance-equation amounts, which refuse UNTYPED.** `build835` runs its balance
|
|
1561
1561
|
guard before it builds the escape helper, and that guard calls `X12Decimal` methods on your
|
|
@@ -1874,10 +1874,10 @@ N-char spec limit` refusal, one per emitting module, where the branch fires **be
|
|
|
1874
1874
|
applied and this package applies none.
|
|
1875
1875
|
- **No transport.** AS2, SFTP, and MLLP-style delivery are out of scope. This is a parser/serializer,
|
|
1876
1876
|
not a communications stack.
|
|
1877
|
-
- **
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1877
|
+
- **Below 1.0.** The package is published on npm as `@cosyte/x12` from a public repo, at `0.1`. Its
|
|
1878
|
+
exported readers, builders, types and warning codes are the surface we keep stable, and below 1.0
|
|
1879
|
+
a breaking change bumps the minor version and is called out in the changelog with its migration.
|
|
1880
|
+
`npm view @cosyte/x12 version` is the only source of truth for the current version.
|
|
1881
1881
|
- **A 276 hierarchical level whose declared parent does not resolve is left off the returned tree.**
|
|
1882
1882
|
The 276 reader attaches a level by its own HL-02 and by nothing else, so a pointer naming a level
|
|
1883
1883
|
that is not present, a pointer naming a level of the wrong kind, and a parent chain that returns
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ a stable code instead of failing or guessing.
|
|
|
31
31
|
|
|
32
32
|
## Status
|
|
33
33
|
|
|
34
|
-
**Version 0.1.
|
|
34
|
+
**Version 0.1.2**, published on npm from a public repository.
|
|
35
35
|
|
|
36
36
|
From `0.1.0` the public API is settled and safe to depend on: the exported readers, builders,
|
|
37
37
|
types and warning codes are the surface we keep stable, and the warning registry only ever gains
|
|
@@ -179,8 +179,7 @@ Everything ships from one entry point; there are no subpath imports.
|
|
|
179
179
|
transaction set into a typed one (`get835`, `get837Claims`, `get270Inquiry`, `get271Eligibility`,
|
|
180
180
|
`get276StatusInquiry`, `parse999`, `parseTA1`, and the rest).
|
|
181
181
|
- **Emit.** `serializeX12` and `buildInterchange` are the general path, and every transaction set
|
|
182
|
-
with a reader also has a domain builder (`build835`, `build837P`, `build271`, and the rest)
|
|
183
|
-
layers that guide's own invariants on top.
|
|
182
|
+
with a reader also has a domain builder (`build835`, `build837P`, `build271`, and the rest).
|
|
184
183
|
- **Errors and warnings.** Parsing is lenient, and only **four** structural failures are ever fatal
|
|
185
184
|
(`X12_NO_ISA_HEADER`, `X12_ISA_TOO_SHORT`, `X12_INVALID_DELIMITERS`, `X12_EMPTY_INPUT`).
|
|
186
185
|
Everything else arrives on `ix.warnings` as a stable code with positional context, so a tolerated
|
|
@@ -295,7 +294,7 @@ must be synthetic: never open a pull request carrying a real patient's data.
|
|
|
295
294
|
|
|
296
295
|
## Trademarks
|
|
297
296
|
|
|
298
|
-
Availity and Blue Cross Blue Shield are trademarks of their respective owners.
|
|
297
|
+
Availity and Blue Cross Blue Shield are trademarks of their respective owners. Cosyte is not
|
|
299
298
|
affiliated with, endorsed by, or sponsored by any of them. The names identify the trading partners
|
|
300
299
|
whose companion-guide deviations the built-in profiles accommodate. See
|
|
301
300
|
[TRADEMARKS.md](./TRADEMARKS.md).
|
package/TRADEMARKS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Trademarks
|
|
2
2
|
|
|
3
|
-
`@cosyte/x12` is an independent open-source project.
|
|
3
|
+
`@cosyte/x12` is an independent open-source project. Cosyte is **not affiliated with, endorsed by,
|
|
4
4
|
or sponsored by** any company named in this repository or its documentation.
|
|
5
5
|
|
|
6
6
|
## Why these names appear
|
package/dist/index.cjs
CHANGED
|
@@ -6640,6 +6640,26 @@ function validateHl2(hl, index, expectedParentLevel, position, warnings) {
|
|
|
6640
6640
|
}
|
|
6641
6641
|
}
|
|
6642
6642
|
|
|
6643
|
+
// src/transactions/shared/procedure.ts
|
|
6644
|
+
var FIRST_MODIFIER = 3;
|
|
6645
|
+
var LAST_MODIFIER = 6;
|
|
6646
|
+
var DESCRIPTION = 7;
|
|
6647
|
+
function decodeProcedure(seg, elementIndex, delimiters) {
|
|
6648
|
+
const qualifier = componentOptional(seg, elementIndex, 1, delimiters);
|
|
6649
|
+
if (qualifier === void 0) return void 0;
|
|
6650
|
+
const modifiers = [];
|
|
6651
|
+
for (let p = FIRST_MODIFIER; p <= LAST_MODIFIER; p += 1) {
|
|
6652
|
+
const modifier = componentOptional(seg, elementIndex, p, delimiters);
|
|
6653
|
+
if (modifier !== void 0) modifiers.push(modifier);
|
|
6654
|
+
}
|
|
6655
|
+
return Object.freeze({
|
|
6656
|
+
qualifier,
|
|
6657
|
+
code: componentOptional(seg, elementIndex, 2, delimiters),
|
|
6658
|
+
modifiers: Object.freeze(modifiers),
|
|
6659
|
+
description: componentOptional(seg, elementIndex, DESCRIPTION, delimiters)
|
|
6660
|
+
});
|
|
6661
|
+
}
|
|
6662
|
+
|
|
6643
6663
|
// src/transactions/eligibility/get-270.ts
|
|
6644
6664
|
var INQUIRY_270 = "270";
|
|
6645
6665
|
var IMPLEMENTED_GUIDES_270 = implementedGuides(INQUIRY_270);
|
|
@@ -6968,7 +6988,7 @@ function openInquiry(seg, delimiters) {
|
|
|
6968
6988
|
}
|
|
6969
6989
|
return {
|
|
6970
6990
|
serviceTypeCodes,
|
|
6971
|
-
procedure: decodeProcedure(seg, delimiters),
|
|
6991
|
+
procedure: decodeProcedure(seg, 2, delimiters),
|
|
6972
6992
|
coverageLevelCode: elementOptional(seg, 3, delimiters),
|
|
6973
6993
|
insuranceTypeCode: elementOptional(seg, 4, delimiters),
|
|
6974
6994
|
diagnosisCodePointers,
|
|
@@ -6976,21 +6996,6 @@ function openInquiry(seg, delimiters) {
|
|
|
6976
6996
|
dates: []
|
|
6977
6997
|
};
|
|
6978
6998
|
}
|
|
6979
|
-
function decodeProcedure(seg, delimiters) {
|
|
6980
|
-
const qualifier = componentOptional(seg, 2, 1, delimiters);
|
|
6981
|
-
if (qualifier === void 0) return void 0;
|
|
6982
|
-
const modifiers = [];
|
|
6983
|
-
for (let p = 3; p <= 6; p += 1) {
|
|
6984
|
-
const modifier = componentOptional(seg, 2, p, delimiters);
|
|
6985
|
-
if (modifier !== void 0) modifiers.push(modifier);
|
|
6986
|
-
}
|
|
6987
|
-
return Object.freeze({
|
|
6988
|
-
qualifier,
|
|
6989
|
-
code: componentOptional(seg, 2, 2, delimiters),
|
|
6990
|
-
modifiers: Object.freeze(modifiers),
|
|
6991
|
-
description: componentOptional(seg, 2, 7, delimiters)
|
|
6992
|
-
});
|
|
6993
|
-
}
|
|
6994
6999
|
function freezeInquiry(acc) {
|
|
6995
7000
|
return Object.freeze({
|
|
6996
7001
|
serviceTypeCodes: Object.freeze(acc.serviceTypeCodes.slice()),
|
|
@@ -7473,7 +7478,7 @@ function emitInquiry(inquiry, body, ctx, locator) {
|
|
|
7473
7478
|
refuseHierarchy2
|
|
7474
7479
|
).map((s) => ctx.esc(s.code)).join(ctx.repetitionSeparator);
|
|
7475
7480
|
const procedure = absentIfNull(inquiry.procedure);
|
|
7476
|
-
const
|
|
7481
|
+
const procedureElement2 = procedure === void 0 ? "" : trimComponents([
|
|
7477
7482
|
ctx.esc(procedure.qualifier),
|
|
7478
7483
|
ctx.esc(procedure.code ?? ""),
|
|
7479
7484
|
...leafList(procedure.modifiers, `${locator}.procedure.modifiers`).map(ctx.esc),
|
|
@@ -7486,7 +7491,7 @@ function emitInquiry(inquiry, body, ctx, locator) {
|
|
|
7486
7491
|
ctx.seg([
|
|
7487
7492
|
"EQ",
|
|
7488
7493
|
serviceTypeElement,
|
|
7489
|
-
|
|
7494
|
+
procedureElement2,
|
|
7490
7495
|
ctx.esc(inquiry.coverageLevelCode ?? ""),
|
|
7491
7496
|
ctx.esc(inquiry.insuranceTypeCode ?? ""),
|
|
7492
7497
|
pointerElement
|
|
@@ -7997,6 +8002,7 @@ function openBenefit(seg, delimiters, sink) {
|
|
|
7997
8002
|
quantity: elementDecimal(seg, 10, delimiters, sink),
|
|
7998
8003
|
authorizationRequired: elementOptional(seg, 11, delimiters),
|
|
7999
8004
|
inPlanNetwork: elementOptional(seg, 12, delimiters),
|
|
8005
|
+
procedure: decodeProcedure(seg, 13, delimiters),
|
|
8000
8006
|
references: [],
|
|
8001
8007
|
dates: [],
|
|
8002
8008
|
messages: [],
|
|
@@ -8039,6 +8045,7 @@ function freezeBenefit(acc) {
|
|
|
8039
8045
|
quantity: acc.quantity,
|
|
8040
8046
|
authorizationRequired: acc.authorizationRequired,
|
|
8041
8047
|
inPlanNetwork: acc.inPlanNetwork,
|
|
8048
|
+
procedure: acc.procedure,
|
|
8042
8049
|
references: Object.freeze(acc.references.slice()),
|
|
8043
8050
|
dates: Object.freeze(acc.dates.slice()),
|
|
8044
8051
|
messages: Object.freeze(acc.messages.slice()),
|
|
@@ -8104,6 +8111,7 @@ var X279A1_VERSION_RELEASE2 = "005010X279A1";
|
|
|
8104
8111
|
var X12_271_FUNCTIONAL_ID = "HB";
|
|
8105
8112
|
var X12_AGENCY_CODE4 = "X";
|
|
8106
8113
|
var HL_LEVEL3 = { SOURCE: "20", RECEIVER: "21", SUBSCRIBER: "22", DEPENDENT: "23" };
|
|
8114
|
+
var MAX_PROCEDURE_MODIFIERS = 4;
|
|
8107
8115
|
function build271(spec) {
|
|
8108
8116
|
const { envelope } = spec;
|
|
8109
8117
|
enforceStructuralSpec4(spec);
|
|
@@ -8124,7 +8132,7 @@ function build271(spec) {
|
|
|
8124
8132
|
while (end > 1 && parts[end - 1] === "") end -= 1;
|
|
8125
8133
|
return parts.slice(0, end).join(elementSeparator) + segmentTerminator;
|
|
8126
8134
|
};
|
|
8127
|
-
const ctx = { seg, esc, repetitionSeparator };
|
|
8135
|
+
const ctx = { seg, esc, repetitionSeparator, componentSeparator };
|
|
8128
8136
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
8129
8137
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
8130
8138
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
@@ -8354,7 +8362,8 @@ function emitBenefit(benefit, body, ctx) {
|
|
|
8354
8362
|
ctx.esc(benefit.quantityQualifier ?? ""),
|
|
8355
8363
|
benefit.quantity === void 0 ? "" : escDec3(benefit.quantity, ctx.esc),
|
|
8356
8364
|
ctx.esc(benefit.authorizationRequired ?? ""),
|
|
8357
|
-
ctx.esc(benefit.inPlanNetwork ?? "")
|
|
8365
|
+
ctx.esc(benefit.inPlanNetwork ?? ""),
|
|
8366
|
+
benefit.procedure === void 0 ? "" : procedureElement(benefit.procedure, ctx)
|
|
8358
8367
|
])
|
|
8359
8368
|
);
|
|
8360
8369
|
for (const related of benefit.relatedEntities ?? []) emitEntity2(related, body, ctx);
|
|
@@ -8364,6 +8373,32 @@ function emitBenefit(benefit, body, ctx) {
|
|
|
8364
8373
|
body.push(ctx.seg(["MSG", ctx.esc(message)]));
|
|
8365
8374
|
}
|
|
8366
8375
|
}
|
|
8376
|
+
function procedureElement(procedure, ctx) {
|
|
8377
|
+
const qualifier = ctx.esc(procedure.qualifier);
|
|
8378
|
+
const code = ctx.esc(procedure.code);
|
|
8379
|
+
if (qualifier === "" || code === "") {
|
|
8380
|
+
refuseSpec4("build271: a benefit procedure (EB-13) requires a non-empty qualifier and code.");
|
|
8381
|
+
}
|
|
8382
|
+
const modifiers = requireCallerArray(
|
|
8383
|
+
procedure.modifiers,
|
|
8384
|
+
"build271: benefit procedure (EB-13) modifiers",
|
|
8385
|
+
refuseSpec4
|
|
8386
|
+
);
|
|
8387
|
+
if (modifiers.length > MAX_PROCEDURE_MODIFIERS) {
|
|
8388
|
+
refuseSpec4(
|
|
8389
|
+
`build271: a benefit procedure (EB-13) carries at most ${String(MAX_PROCEDURE_MODIFIERS)} modifiers; got ${String(modifiers.length)}.`
|
|
8390
|
+
);
|
|
8391
|
+
}
|
|
8392
|
+
const escapedModifiers = [];
|
|
8393
|
+
for (let i = 0; i < modifiers.length; i += 1) {
|
|
8394
|
+
const modifier = ctx.esc(modifiers[i] ?? "");
|
|
8395
|
+
if (modifier === "") {
|
|
8396
|
+
refuseSpec4(`build271: benefit procedure (EB-13) modifier at index ${String(i)} is empty.`);
|
|
8397
|
+
}
|
|
8398
|
+
escapedModifiers.push(modifier);
|
|
8399
|
+
}
|
|
8400
|
+
return [qualifier, code, ...escapedModifiers].join(ctx.componentSeparator);
|
|
8401
|
+
}
|
|
8367
8402
|
function emitTrace2(trace, body, ctx) {
|
|
8368
8403
|
body.push(
|
|
8369
8404
|
ctx.seg([
|
|
@@ -9347,7 +9382,7 @@ function emitClaim3(claim, body, ctx, locator) {
|
|
|
9347
9382
|
}
|
|
9348
9383
|
function emitServiceLine3(line, body, ctx, locator) {
|
|
9349
9384
|
const procedure = absentIfNull2(line.procedure);
|
|
9350
|
-
const
|
|
9385
|
+
const procedureElement2 = procedure === void 0 ? "" : ctx.comp([
|
|
9351
9386
|
procedure.qualifier,
|
|
9352
9387
|
procedure.code ?? "",
|
|
9353
9388
|
...leafList2(procedure.modifiers, `${locator}.procedure.modifiers`),
|
|
@@ -9356,7 +9391,7 @@ function emitServiceLine3(line, body, ctx, locator) {
|
|
|
9356
9391
|
body.push(
|
|
9357
9392
|
ctx.seg([
|
|
9358
9393
|
"SVC",
|
|
9359
|
-
|
|
9394
|
+
procedureElement2,
|
|
9360
9395
|
line.lineChargeAmount === void 0 ? "" : escDec4(line.lineChargeAmount, ctx.esc),
|
|
9361
9396
|
"",
|
|
9362
9397
|
ctx.esc(line.revenueCode ?? ""),
|
|
@@ -15360,7 +15395,7 @@ var profiles = Object.freeze({
|
|
|
15360
15395
|
});
|
|
15361
15396
|
|
|
15362
15397
|
// src/index.ts
|
|
15363
|
-
var VERSION = "0.1.
|
|
15398
|
+
var VERSION = "0.1.2";
|
|
15364
15399
|
|
|
15365
15400
|
exports.AAA_CONDITION_LEVELS = AAA_CONDITION_LEVELS;
|
|
15366
15401
|
exports.AAA_FOLLOW_UP_ACTION_CODES = AAA_FOLLOW_UP_ACTION_CODES;
|