@cosyte/x12 0.1.0 → 0.1.1

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 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
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.0**, published on npm from a public repository.
34
+ **Version 0.1.1**, 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
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 procedureElement = procedure === void 0 ? "" : trimComponents([
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
- procedureElement,
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 procedureElement = procedure === void 0 ? "" : ctx.comp([
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
- procedureElement,
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.0";
15398
+ var VERSION = "0.1.1";
15364
15399
 
15365
15400
  exports.AAA_CONDITION_LEVELS = AAA_CONDITION_LEVELS;
15366
15401
  exports.AAA_FOLLOW_UP_ACTION_CODES = AAA_FOLLOW_UP_ACTION_CODES;