@cosyte/synth 0.0.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 +414 -0
- package/LICENSE +21 -0
- package/README.md +325 -0
- package/dist/astm/index.cjs +847 -0
- package/dist/astm/index.cjs.map +1 -0
- package/dist/astm/index.d.cts +418 -0
- package/dist/astm/index.d.ts +418 -0
- package/dist/astm/index.mjs +828 -0
- package/dist/astm/index.mjs.map +1 -0
- package/dist/ccda/index.cjs +1103 -0
- package/dist/ccda/index.cjs.map +1 -0
- package/dist/ccda/index.d.cts +380 -0
- package/dist/ccda/index.d.ts +380 -0
- package/dist/ccda/index.mjs +1077 -0
- package/dist/ccda/index.mjs.map +1 -0
- package/dist/deid/index.cjs +2809 -0
- package/dist/deid/index.cjs.map +1 -0
- package/dist/deid/index.d.cts +464 -0
- package/dist/deid/index.d.ts +464 -0
- package/dist/deid/index.mjs +2793 -0
- package/dist/deid/index.mjs.map +1 -0
- package/dist/example-codes-DeXcnCSK.d.cts +105 -0
- package/dist/example-codes-DeXcnCSK.d.ts +105 -0
- package/dist/fhir/index.cjs +1429 -0
- package/dist/fhir/index.cjs.map +1 -0
- package/dist/fhir/index.d.cts +772 -0
- package/dist/fhir/index.d.ts +772 -0
- package/dist/fhir/index.mjs +1384 -0
- package/dist/fhir/index.mjs.map +1 -0
- package/dist/hl7/index.cjs +1012 -0
- package/dist/hl7/index.cjs.map +1 -0
- package/dist/hl7/index.d.cts +548 -0
- package/dist/hl7/index.d.ts +548 -0
- package/dist/hl7/index.mjs +990 -0
- package/dist/hl7/index.mjs.map +1 -0
- package/dist/index.cjs +535 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +407 -0
- package/dist/index.d.ts +407 -0
- package/dist/index.mjs +488 -0
- package/dist/index.mjs.map +1 -0
- package/dist/ncpdp/index.cjs +714 -0
- package/dist/ncpdp/index.cjs.map +1 -0
- package/dist/ncpdp/index.d.cts +432 -0
- package/dist/ncpdp/index.d.ts +432 -0
- package/dist/ncpdp/index.mjs +695 -0
- package/dist/ncpdp/index.mjs.map +1 -0
- package/dist/providers-OLz3zAc-.d.cts +343 -0
- package/dist/providers-OLz3zAc-.d.ts +343 -0
- package/dist/quirk-DmkgoZdh.d.cts +239 -0
- package/dist/quirk-JLyO1Ncj.d.ts +239 -0
- package/dist/x12/index.cjs +920 -0
- package/dist/x12/index.cjs.map +1 -0
- package/dist/x12/index.d.cts +484 -0
- package/dist/x12/index.d.ts +484 -0
- package/dist/x12/index.mjs +892 -0
- package/dist/x12/index.mjs.map +1 -0
- package/package.json +210 -0
|
@@ -0,0 +1,920 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var x12 = require('@cosyte/x12');
|
|
4
|
+
|
|
5
|
+
// src/rng/splitmix32.ts
|
|
6
|
+
function splitmix32(seed) {
|
|
7
|
+
let a = seed | 0;
|
|
8
|
+
return function next() {
|
|
9
|
+
a = a + 2654435769 | 0;
|
|
10
|
+
let t = a ^ a >>> 16;
|
|
11
|
+
t = Math.imul(t, 569420461);
|
|
12
|
+
t = t ^ t >>> 15;
|
|
13
|
+
t = Math.imul(t, 1935289751);
|
|
14
|
+
t = t ^ t >>> 15;
|
|
15
|
+
return t >>> 0;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/rng/sfc32.ts
|
|
20
|
+
function sfc32Next(s) {
|
|
21
|
+
s.a |= 0;
|
|
22
|
+
s.b |= 0;
|
|
23
|
+
s.c |= 0;
|
|
24
|
+
s.d |= 0;
|
|
25
|
+
const t = (s.a + s.b | 0) + s.d | 0;
|
|
26
|
+
s.d = s.d + 1 | 0;
|
|
27
|
+
s.a = s.b ^ s.b >>> 9;
|
|
28
|
+
s.b = s.c + (s.c << 3) | 0;
|
|
29
|
+
s.c = s.c << 21 | s.c >>> 11;
|
|
30
|
+
s.c = s.c + t | 0;
|
|
31
|
+
return t >>> 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/rng/rng.ts
|
|
35
|
+
var Sfc32Rng = class {
|
|
36
|
+
seed;
|
|
37
|
+
#state;
|
|
38
|
+
constructor(seed) {
|
|
39
|
+
this.seed = seed | 0;
|
|
40
|
+
const mix = splitmix32(this.seed);
|
|
41
|
+
this.#state = { a: mix(), b: mix(), c: mix(), d: mix() };
|
|
42
|
+
for (let i = 0; i < 8; i += 1) sfc32Next(this.#state);
|
|
43
|
+
}
|
|
44
|
+
nextUint32() {
|
|
45
|
+
return sfc32Next(this.#state);
|
|
46
|
+
}
|
|
47
|
+
float() {
|
|
48
|
+
return this.nextUint32() / 4294967296;
|
|
49
|
+
}
|
|
50
|
+
int(min, max) {
|
|
51
|
+
if (max < min) throw new RangeError(`Rng.int: max (${String(max)}) < min (${String(min)})`);
|
|
52
|
+
const span = max - min + 1;
|
|
53
|
+
return min + Math.floor(this.float() * span);
|
|
54
|
+
}
|
|
55
|
+
bool(p = 0.5) {
|
|
56
|
+
return this.float() < p;
|
|
57
|
+
}
|
|
58
|
+
pick(items) {
|
|
59
|
+
if (items.length === 0) throw new RangeError("Rng.pick: empty array");
|
|
60
|
+
return items[this.int(0, items.length - 1)];
|
|
61
|
+
}
|
|
62
|
+
digits(n) {
|
|
63
|
+
let out = "";
|
|
64
|
+
for (let i = 0; i < n; i += 1) out += String(this.int(0, 9));
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
function createRng(seed) {
|
|
69
|
+
return new Sfc32Rng(seed);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/corpus.ts
|
|
73
|
+
function makeCorpus(seed, artifacts, quirks = []) {
|
|
74
|
+
const counts = {};
|
|
75
|
+
const formats = /* @__PURE__ */ new Set();
|
|
76
|
+
const frozenArtifacts = artifacts.map((a) => {
|
|
77
|
+
counts[a.kind] = (counts[a.kind] ?? 0) + 1;
|
|
78
|
+
formats.add(a.format);
|
|
79
|
+
return Object.freeze({ ...a, warnings: Object.freeze([...a.warnings]) });
|
|
80
|
+
});
|
|
81
|
+
const manifest = Object.freeze({
|
|
82
|
+
formats: Object.freeze([...formats]),
|
|
83
|
+
counts: Object.freeze(counts),
|
|
84
|
+
quirks: Object.freeze([...quirks])
|
|
85
|
+
});
|
|
86
|
+
return Object.freeze({
|
|
87
|
+
seed,
|
|
88
|
+
manifest,
|
|
89
|
+
artifacts: Object.freeze(frozenArtifacts)
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function dec(value) {
|
|
93
|
+
const d = x12.X12Decimal.fromString(value);
|
|
94
|
+
if (d === void 0) throw new Error(`invalid synthetic decimal: ${value}`);
|
|
95
|
+
return d;
|
|
96
|
+
}
|
|
97
|
+
function money(n) {
|
|
98
|
+
return `${String(n)}.00`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/safe/reserved.ts
|
|
102
|
+
var SYNTHETIC_ASSIGNING_AUTHORITY = Object.freeze({
|
|
103
|
+
/** The human-readable assigning-authority namespace id (HL7 HD.1). */
|
|
104
|
+
namespaceId: "COSYTE-SYNTH",
|
|
105
|
+
/** The universal id — an OID under HL7's example arc `2.16.840.1.113883.19` (HD.2). */
|
|
106
|
+
universalId: "2.16.840.1.113883.19.999",
|
|
107
|
+
/** The universal id type (HD.3). */
|
|
108
|
+
universalIdType: "ISO"
|
|
109
|
+
});
|
|
110
|
+
var RESERVED_EMAIL_DOMAINS = Object.freeze([
|
|
111
|
+
"example.com",
|
|
112
|
+
"example.org",
|
|
113
|
+
"example.net"
|
|
114
|
+
]);
|
|
115
|
+
var TEST_NET_V4_PREFIXES = Object.freeze([
|
|
116
|
+
"192.0.2",
|
|
117
|
+
// TEST-NET-1
|
|
118
|
+
"198.51.100",
|
|
119
|
+
// TEST-NET-2
|
|
120
|
+
"203.0.113"
|
|
121
|
+
// TEST-NET-3
|
|
122
|
+
]);
|
|
123
|
+
var DOC_V6_PREFIX = "2001:db8";
|
|
124
|
+
var NPI_LUHN_PREFIX = "80840";
|
|
125
|
+
function luhnMod10(digits) {
|
|
126
|
+
let sum = 0;
|
|
127
|
+
let double = false;
|
|
128
|
+
for (let i = digits.length - 1; i >= 0; i -= 1) {
|
|
129
|
+
let d = digits.charCodeAt(i) - 48;
|
|
130
|
+
if (d < 0 || d > 9) continue;
|
|
131
|
+
if (double) {
|
|
132
|
+
d *= 2;
|
|
133
|
+
if (d > 9) d -= 9;
|
|
134
|
+
}
|
|
135
|
+
sum += d;
|
|
136
|
+
double = !double;
|
|
137
|
+
}
|
|
138
|
+
return sum % 10;
|
|
139
|
+
}
|
|
140
|
+
function npiCheckDigit(base9) {
|
|
141
|
+
const partial = luhnMod10(`${NPI_LUHN_PREFIX}${base9}0`);
|
|
142
|
+
return (10 - partial) % 10;
|
|
143
|
+
}
|
|
144
|
+
var DEA_REGISTRANT_TYPES = Object.freeze([
|
|
145
|
+
"A",
|
|
146
|
+
"B",
|
|
147
|
+
"F",
|
|
148
|
+
"G",
|
|
149
|
+
"M",
|
|
150
|
+
"P",
|
|
151
|
+
"R",
|
|
152
|
+
"X"
|
|
153
|
+
]);
|
|
154
|
+
function deaCheckDigit(base6) {
|
|
155
|
+
let odd = 0;
|
|
156
|
+
let even = 0;
|
|
157
|
+
for (let i = 0; i < 6; i += 1) {
|
|
158
|
+
const digit = base6.charCodeAt(i) - 48;
|
|
159
|
+
if (i % 2 === 0) odd += digit;
|
|
160
|
+
else even += digit;
|
|
161
|
+
}
|
|
162
|
+
return (odd + 2 * even) % 10;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/safe/names-pool.ts
|
|
166
|
+
var SYNTHETIC_GIVEN_NAMES = Object.freeze([
|
|
167
|
+
"Testina",
|
|
168
|
+
"Fixtura",
|
|
169
|
+
"Synthos",
|
|
170
|
+
"Placeholda",
|
|
171
|
+
"Sampleton",
|
|
172
|
+
"Prototius",
|
|
173
|
+
"Stubbina",
|
|
174
|
+
"Exampla",
|
|
175
|
+
"Quilliam",
|
|
176
|
+
"Fabrica",
|
|
177
|
+
"Simula",
|
|
178
|
+
"Testry",
|
|
179
|
+
"Seedwin",
|
|
180
|
+
"Corpora",
|
|
181
|
+
"Reprodo",
|
|
182
|
+
"Mocktavia",
|
|
183
|
+
"Dummett",
|
|
184
|
+
"Voidwin",
|
|
185
|
+
"Deteria",
|
|
186
|
+
"Randomir"
|
|
187
|
+
]);
|
|
188
|
+
var SYNTHETIC_FAMILY_NAMES = Object.freeze([
|
|
189
|
+
"Testerson",
|
|
190
|
+
"Fauxman",
|
|
191
|
+
"Placeholt",
|
|
192
|
+
"Mockridge",
|
|
193
|
+
"Fixtingham",
|
|
194
|
+
"Synthwell",
|
|
195
|
+
"Dummerton",
|
|
196
|
+
"Examplewood",
|
|
197
|
+
"Fabricant",
|
|
198
|
+
"Simulacre",
|
|
199
|
+
"Nonesuch",
|
|
200
|
+
"Seedman",
|
|
201
|
+
"Corpusworth",
|
|
202
|
+
"Reprodus",
|
|
203
|
+
"Voidmark",
|
|
204
|
+
"Deterwood",
|
|
205
|
+
"Randomson",
|
|
206
|
+
"Quillfeather",
|
|
207
|
+
"Notreal",
|
|
208
|
+
"Genfield"
|
|
209
|
+
]);
|
|
210
|
+
var SYNTHETIC_STREET_NAMES = Object.freeze([
|
|
211
|
+
"Fixture Lane",
|
|
212
|
+
"Sample Street",
|
|
213
|
+
"Placeholder Avenue",
|
|
214
|
+
"Synthetic Way",
|
|
215
|
+
"Example Boulevard",
|
|
216
|
+
"Testing Terrace",
|
|
217
|
+
"Mock Road",
|
|
218
|
+
"Prototype Court"
|
|
219
|
+
]);
|
|
220
|
+
var SYNTHETIC_CITY_NAMES = Object.freeze([
|
|
221
|
+
"Faketon",
|
|
222
|
+
"Synthville",
|
|
223
|
+
"Exampleburg",
|
|
224
|
+
"Testford",
|
|
225
|
+
"Mockhaven",
|
|
226
|
+
"Fixtureton"
|
|
227
|
+
]);
|
|
228
|
+
|
|
229
|
+
// src/safe/providers.ts
|
|
230
|
+
function ssn(rng, block = "never-issued") {
|
|
231
|
+
if (block === "advertising") {
|
|
232
|
+
return `987-65-432${String(rng.int(0, 9))}`;
|
|
233
|
+
}
|
|
234
|
+
const area = rng.int(900, 999);
|
|
235
|
+
const group = rng.digits(2);
|
|
236
|
+
const serial = rng.digits(4);
|
|
237
|
+
return `${String(area)}-${group}-${serial}`;
|
|
238
|
+
}
|
|
239
|
+
function phone(rng) {
|
|
240
|
+
const area = `${String(rng.int(2, 9))}${rng.digits(2)}`;
|
|
241
|
+
const line = `01${rng.digits(2)}`;
|
|
242
|
+
return `(${area}) 555-${line}`;
|
|
243
|
+
}
|
|
244
|
+
function name(rng) {
|
|
245
|
+
return { given: rng.pick(SYNTHETIC_GIVEN_NAMES), family: rng.pick(SYNTHETIC_FAMILY_NAMES) };
|
|
246
|
+
}
|
|
247
|
+
function email(rng, person) {
|
|
248
|
+
const domain = rng.pick(RESERVED_EMAIL_DOMAINS);
|
|
249
|
+
const slug = person ? `${person.given}.${person.family}`.toLowerCase() : `synth${rng.digits(6)}`;
|
|
250
|
+
return `${slug}@${domain}`;
|
|
251
|
+
}
|
|
252
|
+
function ipv4(rng) {
|
|
253
|
+
return `${rng.pick(TEST_NET_V4_PREFIXES)}.${String(rng.int(1, 254))}`;
|
|
254
|
+
}
|
|
255
|
+
function ipv6(rng) {
|
|
256
|
+
const tail = rng.nextUint32().toString(16).padStart(4, "0").slice(-4);
|
|
257
|
+
return `${DOC_V6_PREFIX}::${tail}`;
|
|
258
|
+
}
|
|
259
|
+
function uuid(rng) {
|
|
260
|
+
const bytes = new Uint8Array(16);
|
|
261
|
+
for (let i = 0; i < 16; i += 1) bytes[i] = rng.int(0, 255);
|
|
262
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
263
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
264
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
|
|
265
|
+
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
|
|
266
|
+
}
|
|
267
|
+
function npi(rng) {
|
|
268
|
+
const base9 = rng.digits(9);
|
|
269
|
+
const wrongCheck = (npiCheckDigit(base9) + 1) % 10;
|
|
270
|
+
return `${base9}${String(wrongCheck)}`;
|
|
271
|
+
}
|
|
272
|
+
function dea(rng, person) {
|
|
273
|
+
const type = rng.pick(DEA_REGISTRANT_TYPES);
|
|
274
|
+
const initialSource = person?.family ?? rng.pick(SYNTHETIC_FAMILY_NAMES);
|
|
275
|
+
const initial = initialSource.slice(0, 1).toUpperCase();
|
|
276
|
+
const base6 = rng.digits(6);
|
|
277
|
+
const wrongCheck = (deaCheckDigit(base6) + 1) % 10;
|
|
278
|
+
return `${type}${initial}${base6}${String(wrongCheck)}`;
|
|
279
|
+
}
|
|
280
|
+
function identifier(rng, typeCode = "MR") {
|
|
281
|
+
return {
|
|
282
|
+
value: rng.digits(8),
|
|
283
|
+
typeCode,
|
|
284
|
+
assigningAuthority: SYNTHETIC_ASSIGNING_AUTHORITY.namespaceId,
|
|
285
|
+
assigningAuthorityOid: SYNTHETIC_ASSIGNING_AUTHORITY.universalId
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function address(rng) {
|
|
289
|
+
const number = rng.int(1, 9999);
|
|
290
|
+
return {
|
|
291
|
+
street: `${String(number)} ${rng.pick(SYNTHETIC_STREET_NAMES)}`,
|
|
292
|
+
city: rng.pick(SYNTHETIC_CITY_NAMES),
|
|
293
|
+
state: rng.pick(US_STATES),
|
|
294
|
+
zip: "00000"
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function dateYmd(rng, minYear = 1930, maxYear = 2010) {
|
|
298
|
+
const year = rng.int(minYear, maxYear);
|
|
299
|
+
const month = rng.int(1, 12);
|
|
300
|
+
const daysInMonth = new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
301
|
+
const day = rng.int(1, daysInMonth);
|
|
302
|
+
return `${String(year).padStart(4, "0")}${String(month).padStart(2, "0")}${String(day).padStart(2, "0")}`;
|
|
303
|
+
}
|
|
304
|
+
var US_STATES = Object.freeze([
|
|
305
|
+
"AL",
|
|
306
|
+
"AK",
|
|
307
|
+
"AZ",
|
|
308
|
+
"AR",
|
|
309
|
+
"CA",
|
|
310
|
+
"CO",
|
|
311
|
+
"CT",
|
|
312
|
+
"DE",
|
|
313
|
+
"FL",
|
|
314
|
+
"GA",
|
|
315
|
+
"HI",
|
|
316
|
+
"ID",
|
|
317
|
+
"IL",
|
|
318
|
+
"IN",
|
|
319
|
+
"IA",
|
|
320
|
+
"KS",
|
|
321
|
+
"KY",
|
|
322
|
+
"LA",
|
|
323
|
+
"ME",
|
|
324
|
+
"MD",
|
|
325
|
+
"MA",
|
|
326
|
+
"MI",
|
|
327
|
+
"MN",
|
|
328
|
+
"MS",
|
|
329
|
+
"MO",
|
|
330
|
+
"MT",
|
|
331
|
+
"NE",
|
|
332
|
+
"NV",
|
|
333
|
+
"NH",
|
|
334
|
+
"NJ",
|
|
335
|
+
"NM",
|
|
336
|
+
"NY",
|
|
337
|
+
"NC",
|
|
338
|
+
"ND",
|
|
339
|
+
"OH",
|
|
340
|
+
"OK",
|
|
341
|
+
"OR",
|
|
342
|
+
"PA",
|
|
343
|
+
"RI",
|
|
344
|
+
"SC",
|
|
345
|
+
"SD",
|
|
346
|
+
"TN",
|
|
347
|
+
"TX",
|
|
348
|
+
"UT",
|
|
349
|
+
"VT",
|
|
350
|
+
"VA",
|
|
351
|
+
"WA",
|
|
352
|
+
"WV",
|
|
353
|
+
"WI",
|
|
354
|
+
"WY"
|
|
355
|
+
]);
|
|
356
|
+
|
|
357
|
+
// src/safe/index.ts
|
|
358
|
+
var safe = Object.freeze({
|
|
359
|
+
ssn,
|
|
360
|
+
phone,
|
|
361
|
+
name,
|
|
362
|
+
email,
|
|
363
|
+
ipv4,
|
|
364
|
+
ipv6,
|
|
365
|
+
uuid,
|
|
366
|
+
identifier,
|
|
367
|
+
address,
|
|
368
|
+
dateYmd,
|
|
369
|
+
npi,
|
|
370
|
+
dea
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// src/x12/identity.ts
|
|
374
|
+
var SYNTHETIC_ORG_NAMES = Object.freeze([
|
|
375
|
+
"SYNTH BILLING GROUP",
|
|
376
|
+
"FIXTURE CLINIC INC",
|
|
377
|
+
"PLACEHOLDER MEDICAL CTR",
|
|
378
|
+
"SAMPLE HEALTH PARTNERS",
|
|
379
|
+
"MOCK CARE ASSOCIATES",
|
|
380
|
+
"PROTOTYPE PHYSICIANS LLC"
|
|
381
|
+
]);
|
|
382
|
+
var SYNTHETIC_PAYER_NAMES = Object.freeze([
|
|
383
|
+
"SYNTHCARE HEALTH PLAN",
|
|
384
|
+
"FIXTURE MUTUAL INSURANCE",
|
|
385
|
+
"PLACEHOLDER BENEFIT ADMIN",
|
|
386
|
+
"SAMPLE STATE MEDICAID",
|
|
387
|
+
"MOCK NATIONAL INSURER"
|
|
388
|
+
]);
|
|
389
|
+
function x12Person(rng) {
|
|
390
|
+
const person = safe.name(rng);
|
|
391
|
+
const memberId = `MBR${safe.identifier(rng, "MB").value}`;
|
|
392
|
+
const dob = safe.dateYmd(rng, 1935, 2010);
|
|
393
|
+
const sex = rng.pick(["M", "F"]);
|
|
394
|
+
const address2 = safe.address(rng);
|
|
395
|
+
return { person, memberId, dob, sex, address: address2 };
|
|
396
|
+
}
|
|
397
|
+
function x12Organization(rng) {
|
|
398
|
+
const name2 = rng.pick(SYNTHETIC_ORG_NAMES);
|
|
399
|
+
const npiValue = safe.npi(rng);
|
|
400
|
+
const taxIdSsn = safe.ssn(rng).replace(/\D/g, "");
|
|
401
|
+
const address2 = safe.address(rng);
|
|
402
|
+
return { name: name2, npi: npiValue, taxIdSsn, address: address2 };
|
|
403
|
+
}
|
|
404
|
+
function x12ProviderPerson(rng) {
|
|
405
|
+
const person = safe.name(rng);
|
|
406
|
+
const npiValue = safe.npi(rng);
|
|
407
|
+
return { person, npi: npiValue };
|
|
408
|
+
}
|
|
409
|
+
function x12Payer(rng) {
|
|
410
|
+
const name2 = rng.pick(SYNTHETIC_PAYER_NAMES);
|
|
411
|
+
const payerId = `SYN${rng.digits(5)}`;
|
|
412
|
+
return { name: name2, payerId };
|
|
413
|
+
}
|
|
414
|
+
function x12TradingPartners(rng) {
|
|
415
|
+
return { senderId: `SYNSUB${rng.digits(3)}`, receiverId: `SYNRCV${rng.digits(3)}` };
|
|
416
|
+
}
|
|
417
|
+
function x12EnvelopeTiming(rng) {
|
|
418
|
+
const serviceDate = safe.dateYmd(rng, 2024, 2026);
|
|
419
|
+
const yy = serviceDate.slice(2, 4);
|
|
420
|
+
const mmdd = serviceDate.slice(4, 8);
|
|
421
|
+
const hh = String(rng.int(0, 23)).padStart(2, "0");
|
|
422
|
+
const mi = String(rng.int(0, 59)).padStart(2, "0");
|
|
423
|
+
return {
|
|
424
|
+
interchangeDate: `${yy}${mmdd}`,
|
|
425
|
+
interchangeTime: `${hh}${mi}`,
|
|
426
|
+
interchangeControlNumber: rng.digits(9),
|
|
427
|
+
groupControlNumber: String(rng.int(1, 99999)),
|
|
428
|
+
transactionSetControlNumber: rng.digits(4),
|
|
429
|
+
serviceDate
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/x12/example-codes.ts
|
|
434
|
+
var PROFESSIONAL_PROCEDURES = Object.freeze([
|
|
435
|
+
{ code: "99213", label: "office/outpatient visit, established patient" },
|
|
436
|
+
{ code: "99214", label: "office/outpatient visit, established patient, moderate" },
|
|
437
|
+
{ code: "99203", label: "office/outpatient visit, new patient" },
|
|
438
|
+
{ code: "85025", label: "complete blood count with differential" },
|
|
439
|
+
{ code: "80053", label: "comprehensive metabolic panel" },
|
|
440
|
+
{ code: "93000", label: "electrocardiogram, routine" }
|
|
441
|
+
]);
|
|
442
|
+
var PROCEDURE_MODIFIERS = Object.freeze(["25", "59", "76", "GT"]);
|
|
443
|
+
var PLACES_OF_SERVICE = Object.freeze(["11", "22", "21", "12", "49"]);
|
|
444
|
+
var DIAGNOSES = Object.freeze([
|
|
445
|
+
{ code: "J20.9", label: "acute bronchitis, unspecified" },
|
|
446
|
+
{ code: "E11.9", label: "type 2 diabetes mellitus without complications" },
|
|
447
|
+
{ code: "I10", label: "essential (primary) hypertension" },
|
|
448
|
+
{ code: "M54.5", label: "low back pain" },
|
|
449
|
+
{ code: "R07.9", label: "chest pain, unspecified" },
|
|
450
|
+
{ code: "Z00.00", label: "general adult medical exam without abnormal findings" }
|
|
451
|
+
]);
|
|
452
|
+
var REVENUE_CODES = Object.freeze([
|
|
453
|
+
{ code: "0120", label: "room & board, semi-private" },
|
|
454
|
+
{ code: "0300", label: "laboratory, general" },
|
|
455
|
+
{ code: "0450", label: "emergency room, general" },
|
|
456
|
+
{ code: "0636", label: "drugs requiring detailed coding" }
|
|
457
|
+
]);
|
|
458
|
+
var INSTITUTIONAL_PROCEDURES = Object.freeze([
|
|
459
|
+
{ code: "99221", label: "initial hospital care, per day" },
|
|
460
|
+
{ code: "99231", label: "subsequent hospital care, per day" }
|
|
461
|
+
]);
|
|
462
|
+
var DENTAL_PROCEDURES = Object.freeze([
|
|
463
|
+
{ code: "D2391", label: "resin-based composite, one surface, posterior" },
|
|
464
|
+
{ code: "D1110", label: "prophylaxis, adult" },
|
|
465
|
+
{ code: "D0120", label: "periodic oral evaluation" }
|
|
466
|
+
]);
|
|
467
|
+
var TOOTH_CODES = Object.freeze(["14", "3", "19", "30"]);
|
|
468
|
+
var TOOTH_SURFACES = Object.freeze(["M", "O", "D", "B", "L"]);
|
|
469
|
+
var CARC_CODES = Object.freeze(["1", "2", "3", "45", "96", "197"]);
|
|
470
|
+
var SERVICE_TYPE_CODES = Object.freeze(["30", "1", "35", "88", "98"]);
|
|
471
|
+
|
|
472
|
+
// src/x12/claim-837.ts
|
|
473
|
+
function serviceDtp(serviceDate) {
|
|
474
|
+
return { qualifier: "472", formatQualifier: "D8", value: serviceDate };
|
|
475
|
+
}
|
|
476
|
+
function envelopeOf(partners, timing) {
|
|
477
|
+
return {
|
|
478
|
+
senderId: partners.senderId,
|
|
479
|
+
receiverId: partners.receiverId,
|
|
480
|
+
interchangeDate: timing.interchangeDate,
|
|
481
|
+
interchangeTime: timing.interchangeTime,
|
|
482
|
+
interchangeControlNumber: timing.interchangeControlNumber,
|
|
483
|
+
groupControlNumber: timing.groupControlNumber,
|
|
484
|
+
transactionSetControlNumber: timing.transactionSetControlNumber,
|
|
485
|
+
usageIndicator: "T"
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
function professionalLine(rng, serviceDate) {
|
|
489
|
+
const charge = dec(`${String(rng.int(75, 400))}.00`);
|
|
490
|
+
const line = {
|
|
491
|
+
variant: "P",
|
|
492
|
+
procedureQualifier: "HC",
|
|
493
|
+
procedureCode: rng.pick(PROFESSIONAL_PROCEDURES).code,
|
|
494
|
+
...rng.bool(0.4) ? { modifiers: [rng.pick(PROCEDURE_MODIFIERS)] } : {},
|
|
495
|
+
charge,
|
|
496
|
+
unitOfMeasure: "UN",
|
|
497
|
+
units: dec("1"),
|
|
498
|
+
placeOfServiceCode: rng.pick(PLACES_OF_SERVICE),
|
|
499
|
+
diagnosisPointers: ["1"],
|
|
500
|
+
dates: [serviceDtp(serviceDate)]
|
|
501
|
+
};
|
|
502
|
+
return { line, charge };
|
|
503
|
+
}
|
|
504
|
+
function institutionalLine(rng, serviceDate) {
|
|
505
|
+
const charge = dec(`${String(rng.int(500, 5e3))}.00`);
|
|
506
|
+
const line = {
|
|
507
|
+
variant: "I",
|
|
508
|
+
revenueCode: rng.pick(REVENUE_CODES).code,
|
|
509
|
+
procedureQualifier: "HC",
|
|
510
|
+
procedureCode: rng.pick(INSTITUTIONAL_PROCEDURES).code,
|
|
511
|
+
charge,
|
|
512
|
+
unitOfMeasure: "UN",
|
|
513
|
+
units: dec("1"),
|
|
514
|
+
dates: [serviceDtp(serviceDate)]
|
|
515
|
+
};
|
|
516
|
+
return { line, charge };
|
|
517
|
+
}
|
|
518
|
+
function dentalLine(rng, serviceDate) {
|
|
519
|
+
const charge = dec(`${String(rng.int(80, 900))}.00`);
|
|
520
|
+
const line = {
|
|
521
|
+
variant: "D",
|
|
522
|
+
procedureQualifier: "AD",
|
|
523
|
+
procedureCode: rng.pick(DENTAL_PROCEDURES).code,
|
|
524
|
+
charge,
|
|
525
|
+
units: dec("1"),
|
|
526
|
+
placeOfServiceCode: "11",
|
|
527
|
+
toothInformation: [
|
|
528
|
+
{ qualifier: "JP", toothCode: rng.pick(TOOTH_CODES), surfaces: [rng.pick(TOOTH_SURFACES)] }
|
|
529
|
+
],
|
|
530
|
+
dates: [serviceDtp(serviceDate)]
|
|
531
|
+
};
|
|
532
|
+
return { line, charge };
|
|
533
|
+
}
|
|
534
|
+
function claimOf(rng, variant, serviceDate) {
|
|
535
|
+
const lineCount = rng.int(1, 2);
|
|
536
|
+
const built = Array.from({ length: lineCount }, () => {
|
|
537
|
+
if (variant === "P") return professionalLine(rng, serviceDate);
|
|
538
|
+
if (variant === "I") return institutionalLine(rng, serviceDate);
|
|
539
|
+
return dentalLine(rng, serviceDate);
|
|
540
|
+
});
|
|
541
|
+
const total = built.reduce((acc, b) => acc.add(b.charge), dec("0"));
|
|
542
|
+
const diagnosis = rng.pick(DIAGNOSES).code;
|
|
543
|
+
const secondary = rng.pick(DIAGNOSES).code;
|
|
544
|
+
return {
|
|
545
|
+
claimId: `PTACCT${rng.digits(6)}`,
|
|
546
|
+
totalCharge: total,
|
|
547
|
+
placeOfServiceCode: variant === "P" ? rng.pick(PLACES_OF_SERVICE) : "11",
|
|
548
|
+
facilityCodeQualifier: "B",
|
|
549
|
+
claimFrequencyCode: "1",
|
|
550
|
+
providerSignatureOnFile: "Y",
|
|
551
|
+
providerAcceptAssignment: "A",
|
|
552
|
+
benefitsAssignment: "Y",
|
|
553
|
+
releaseOfInformationCode: "Y",
|
|
554
|
+
diagnoses: [
|
|
555
|
+
{ qualifier: "ABK", code: diagnosis },
|
|
556
|
+
{ qualifier: "ABF", code: secondary }
|
|
557
|
+
],
|
|
558
|
+
dates: [{ qualifier: "431", formatQualifier: "D8", value: serviceDate }],
|
|
559
|
+
serviceLines: built.map((b) => b.line)
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
function specOf(rng, variant) {
|
|
563
|
+
const partners = x12TradingPartners(rng);
|
|
564
|
+
const timing = x12EnvelopeTiming(rng);
|
|
565
|
+
const envelope = envelopeOf(partners, timing);
|
|
566
|
+
const org = x12Organization(rng);
|
|
567
|
+
const subscriberPerson = x12Person(rng);
|
|
568
|
+
const rendering = x12ProviderPerson(rng);
|
|
569
|
+
const payer = x12Payer(rng);
|
|
570
|
+
const claim = claimOf(rng, variant, timing.serviceDate);
|
|
571
|
+
const subscriber = {
|
|
572
|
+
info: {
|
|
573
|
+
payerResponsibilityCode: "P",
|
|
574
|
+
individualRelationshipCode: "18",
|
|
575
|
+
// self
|
|
576
|
+
groupNumber: `GRP${rng.digits(5)}`,
|
|
577
|
+
claimFilingIndicator: "MB"
|
|
578
|
+
},
|
|
579
|
+
subscriber: {
|
|
580
|
+
entityIdentifierCode: "IL",
|
|
581
|
+
entityTypeQualifier: "1",
|
|
582
|
+
name: subscriberPerson.person.family,
|
|
583
|
+
firstName: subscriberPerson.person.given,
|
|
584
|
+
idQualifier: "MI",
|
|
585
|
+
idCode: subscriberPerson.memberId,
|
|
586
|
+
address: {
|
|
587
|
+
lines: [subscriberPerson.address.street],
|
|
588
|
+
city: subscriberPerson.address.city,
|
|
589
|
+
state: subscriberPerson.address.state,
|
|
590
|
+
postalCode: subscriberPerson.address.zip
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
payer: {
|
|
594
|
+
entityIdentifierCode: "PR",
|
|
595
|
+
entityTypeQualifier: "2",
|
|
596
|
+
name: payer.name,
|
|
597
|
+
idQualifier: "PI",
|
|
598
|
+
idCode: payer.payerId
|
|
599
|
+
},
|
|
600
|
+
claims: [
|
|
601
|
+
{
|
|
602
|
+
...claim,
|
|
603
|
+
// Rendering provider (Loop 2310B, NM1 fields round-trip) — a person with an invalid-Luhn NPI.
|
|
604
|
+
providers: [
|
|
605
|
+
{
|
|
606
|
+
entityIdentifierCode: "82",
|
|
607
|
+
entityTypeQualifier: "1",
|
|
608
|
+
name: rendering.person.family,
|
|
609
|
+
firstName: rendering.person.given,
|
|
610
|
+
idQualifier: "XX",
|
|
611
|
+
idCode: rendering.npi
|
|
612
|
+
}
|
|
613
|
+
]
|
|
614
|
+
}
|
|
615
|
+
]
|
|
616
|
+
};
|
|
617
|
+
const billingProvider = {
|
|
618
|
+
provider: {
|
|
619
|
+
entityIdentifierCode: "85",
|
|
620
|
+
entityTypeQualifier: "2",
|
|
621
|
+
name: org.name,
|
|
622
|
+
idQualifier: "XX",
|
|
623
|
+
idCode: org.npi,
|
|
624
|
+
address: {
|
|
625
|
+
lines: [org.address.street],
|
|
626
|
+
city: org.address.city,
|
|
627
|
+
state: org.address.state,
|
|
628
|
+
postalCode: org.address.zip
|
|
629
|
+
},
|
|
630
|
+
// Provider tax id as a never-issued (900-range) SSN at REF*SY — provably synthetic (roadmap §4.1).
|
|
631
|
+
references: [{ qualifier: "SY", value: org.taxIdSsn }]
|
|
632
|
+
},
|
|
633
|
+
subscribers: [subscriber]
|
|
634
|
+
};
|
|
635
|
+
return {
|
|
636
|
+
envelope,
|
|
637
|
+
submitter: {
|
|
638
|
+
entityIdentifierCode: "41",
|
|
639
|
+
entityTypeQualifier: "2",
|
|
640
|
+
name: org.name,
|
|
641
|
+
idQualifier: "46",
|
|
642
|
+
idCode: envelope.senderId
|
|
643
|
+
},
|
|
644
|
+
receiver: {
|
|
645
|
+
entityIdentifierCode: "40",
|
|
646
|
+
entityTypeQualifier: "2",
|
|
647
|
+
name: payer.name,
|
|
648
|
+
idQualifier: "46",
|
|
649
|
+
idCode: envelope.receiverId
|
|
650
|
+
},
|
|
651
|
+
billingProviders: [billingProvider]
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
function generate837(variant, options) {
|
|
655
|
+
const rng = createRng(options.seed);
|
|
656
|
+
const spec = specOf(rng, variant);
|
|
657
|
+
if (variant === "P") return x12.build837P(spec);
|
|
658
|
+
if (variant === "I") return x12.build837I(spec);
|
|
659
|
+
return x12.build837D(spec);
|
|
660
|
+
}
|
|
661
|
+
function generate837P(options) {
|
|
662
|
+
return generate837("P", options);
|
|
663
|
+
}
|
|
664
|
+
function generate837I(options) {
|
|
665
|
+
return generate837("I", options);
|
|
666
|
+
}
|
|
667
|
+
function generate837D(options) {
|
|
668
|
+
return generate837("D", options);
|
|
669
|
+
}
|
|
670
|
+
function generate835(options) {
|
|
671
|
+
const rng = createRng(options.seed);
|
|
672
|
+
const partners = x12TradingPartners(rng);
|
|
673
|
+
const timing = x12EnvelopeTiming(rng);
|
|
674
|
+
const patient = x12Person(rng);
|
|
675
|
+
const org = x12Organization(rng);
|
|
676
|
+
const payer = x12Payer(rng);
|
|
677
|
+
const chargeN = rng.int(200, 2e3);
|
|
678
|
+
const patientRespN = rng.int(10, Math.min(chargeN - 1, 150));
|
|
679
|
+
const paymentN = chargeN - patientRespN;
|
|
680
|
+
const casReason = rng.pick(["1", "2", "3"]);
|
|
681
|
+
const line = {
|
|
682
|
+
productServiceIdQualifier: "HC",
|
|
683
|
+
productServiceId: rng.pick(PROFESSIONAL_PROCEDURES).code,
|
|
684
|
+
...rng.bool(0.4) ? { modifiers: [rng.pick(PROCEDURE_MODIFIERS)] } : {},
|
|
685
|
+
chargeAmount: dec(money(chargeN)),
|
|
686
|
+
paymentAmount: dec(money(paymentN)),
|
|
687
|
+
serviceDateStart: timing.serviceDate,
|
|
688
|
+
serviceDateEnd: timing.serviceDate,
|
|
689
|
+
adjustments: [{ groupCode: "PR", reasonCode: casReason, amount: dec(money(patientRespN)) }],
|
|
690
|
+
amounts: [{ qualifier: "B6", amount: dec(money(paymentN)) }]
|
|
691
|
+
};
|
|
692
|
+
const claim = {
|
|
693
|
+
patientControlNumber: `PTACCT${rng.digits(6)}`,
|
|
694
|
+
claimStatusCode: "1",
|
|
695
|
+
// processed as primary
|
|
696
|
+
totalChargeAmount: dec(money(chargeN)),
|
|
697
|
+
totalPaymentAmount: dec(money(paymentN)),
|
|
698
|
+
patientResponsibilityAmount: dec(money(patientRespN)),
|
|
699
|
+
claimFilingIndicatorCode: "MB",
|
|
700
|
+
payerClaimControlNumber: `ICN${rng.digits(9)}`,
|
|
701
|
+
facilityTypeCode: "11",
|
|
702
|
+
claimFrequencyCode: "1",
|
|
703
|
+
patient: {
|
|
704
|
+
entityIdentifierCode: "QC",
|
|
705
|
+
lastName: patient.person.family,
|
|
706
|
+
firstName: patient.person.given,
|
|
707
|
+
idQualifier: "MI",
|
|
708
|
+
idCode: patient.memberId
|
|
709
|
+
},
|
|
710
|
+
serviceProvider: {
|
|
711
|
+
entityIdentifierCode: "82",
|
|
712
|
+
name: org.name,
|
|
713
|
+
idQualifier: "XX",
|
|
714
|
+
idCode: org.npi
|
|
715
|
+
},
|
|
716
|
+
servicePeriodStart: timing.serviceDate,
|
|
717
|
+
servicePeriodEnd: timing.serviceDate,
|
|
718
|
+
serviceLines: [line]
|
|
719
|
+
};
|
|
720
|
+
const spec = {
|
|
721
|
+
envelope: {
|
|
722
|
+
senderId: partners.senderId,
|
|
723
|
+
receiverId: partners.receiverId,
|
|
724
|
+
interchangeDate: timing.interchangeDate,
|
|
725
|
+
interchangeTime: timing.interchangeTime,
|
|
726
|
+
interchangeControlNumber: timing.interchangeControlNumber,
|
|
727
|
+
groupControlNumber: timing.groupControlNumber,
|
|
728
|
+
transactionSetControlNumber: timing.transactionSetControlNumber,
|
|
729
|
+
usageIndicator: "T"
|
|
730
|
+
},
|
|
731
|
+
payment: {
|
|
732
|
+
transactionHandlingCode: "I",
|
|
733
|
+
totalActualPayment: dec(money(paymentN)),
|
|
734
|
+
creditDebitFlag: "C",
|
|
735
|
+
method: "ACH",
|
|
736
|
+
paymentDate: timing.serviceDate
|
|
737
|
+
},
|
|
738
|
+
traces: [
|
|
739
|
+
{
|
|
740
|
+
traceTypeCode: "1",
|
|
741
|
+
referenceId: rng.digits(7),
|
|
742
|
+
originatingCompanyId: `1${rng.digits(9)}`
|
|
743
|
+
}
|
|
744
|
+
],
|
|
745
|
+
payer: {
|
|
746
|
+
entityIdentifierCode: "PR",
|
|
747
|
+
name: payer.name,
|
|
748
|
+
address: {
|
|
749
|
+
lines: [org.address.street],
|
|
750
|
+
city: org.address.city,
|
|
751
|
+
state: org.address.state,
|
|
752
|
+
postalCode: org.address.zip
|
|
753
|
+
},
|
|
754
|
+
additionalIdentifiers: [{ qualifier: "2U", value: payer.payerId }]
|
|
755
|
+
},
|
|
756
|
+
payee: {
|
|
757
|
+
entityIdentifierCode: "PE",
|
|
758
|
+
name: org.name,
|
|
759
|
+
idQualifier: "XX",
|
|
760
|
+
idCode: org.npi,
|
|
761
|
+
address: {
|
|
762
|
+
lines: [org.address.street],
|
|
763
|
+
city: org.address.city,
|
|
764
|
+
state: org.address.state,
|
|
765
|
+
postalCode: org.address.zip
|
|
766
|
+
}
|
|
767
|
+
},
|
|
768
|
+
claims: [claim]
|
|
769
|
+
};
|
|
770
|
+
return x12.build835(spec);
|
|
771
|
+
}
|
|
772
|
+
function generate271(options) {
|
|
773
|
+
const rng = createRng(options.seed);
|
|
774
|
+
const partners = x12TradingPartners(rng);
|
|
775
|
+
const timing = x12EnvelopeTiming(rng);
|
|
776
|
+
const subscriber = x12Person(rng);
|
|
777
|
+
const providerOrg = x12Organization(rng);
|
|
778
|
+
const payer = x12Payer(rng);
|
|
779
|
+
const serviceTypes = [
|
|
780
|
+
{ code: rng.pick(SERVICE_TYPE_CODES) },
|
|
781
|
+
{ code: rng.pick(SERVICE_TYPE_CODES) }
|
|
782
|
+
];
|
|
783
|
+
const spec = {
|
|
784
|
+
envelope: {
|
|
785
|
+
senderId: partners.senderId,
|
|
786
|
+
receiverId: partners.receiverId,
|
|
787
|
+
interchangeDate: timing.interchangeDate,
|
|
788
|
+
interchangeTime: timing.interchangeTime,
|
|
789
|
+
interchangeControlNumber: timing.interchangeControlNumber,
|
|
790
|
+
groupControlNumber: timing.groupControlNumber,
|
|
791
|
+
transactionSetControlNumber: timing.transactionSetControlNumber,
|
|
792
|
+
usageIndicator: "T"
|
|
793
|
+
},
|
|
794
|
+
informationSources: [
|
|
795
|
+
{
|
|
796
|
+
entity: {
|
|
797
|
+
entityIdentifierCode: "PR",
|
|
798
|
+
entityTypeQualifier: "2",
|
|
799
|
+
name: payer.name,
|
|
800
|
+
idQualifier: "PI",
|
|
801
|
+
idCode: payer.payerId
|
|
802
|
+
},
|
|
803
|
+
receivers: [
|
|
804
|
+
{
|
|
805
|
+
entity: {
|
|
806
|
+
entityIdentifierCode: "1P",
|
|
807
|
+
entityTypeQualifier: "2",
|
|
808
|
+
name: providerOrg.name,
|
|
809
|
+
idQualifier: "XX",
|
|
810
|
+
idCode: providerOrg.npi
|
|
811
|
+
},
|
|
812
|
+
subscribers: [
|
|
813
|
+
{
|
|
814
|
+
traces: [{ traceTypeCode: "2", referenceId: `ELIG${rng.digits(10)}` }],
|
|
815
|
+
name: {
|
|
816
|
+
entityIdentifierCode: "IL",
|
|
817
|
+
entityTypeQualifier: "1",
|
|
818
|
+
lastName: subscriber.person.family,
|
|
819
|
+
firstName: subscriber.person.given,
|
|
820
|
+
idQualifier: "MI",
|
|
821
|
+
idCode: subscriber.memberId,
|
|
822
|
+
address: {
|
|
823
|
+
lines: [subscriber.address.street],
|
|
824
|
+
city: subscriber.address.city,
|
|
825
|
+
state: subscriber.address.state,
|
|
826
|
+
postalCode: subscriber.address.zip
|
|
827
|
+
},
|
|
828
|
+
dateOfBirth: subscriber.dob,
|
|
829
|
+
genderCode: subscriber.sex
|
|
830
|
+
},
|
|
831
|
+
references: [{ qualifier: "6P", value: `GRP${rng.digits(5)}` }],
|
|
832
|
+
dates: [{ qualifier: "307", formatQualifier: "D8", value: timing.serviceDate }],
|
|
833
|
+
benefits: [
|
|
834
|
+
{
|
|
835
|
+
eligibilityCode: "1",
|
|
836
|
+
// active coverage
|
|
837
|
+
coverageLevelCode: "IND",
|
|
838
|
+
serviceTypeCodes: serviceTypes,
|
|
839
|
+
inPlanNetwork: "Y",
|
|
840
|
+
monetaryAmount: dec(money(rng.int(500, 5e3))),
|
|
841
|
+
percent: dec(String(rng.pick([80, 90, 100])))
|
|
842
|
+
}
|
|
843
|
+
]
|
|
844
|
+
}
|
|
845
|
+
]
|
|
846
|
+
}
|
|
847
|
+
]
|
|
848
|
+
}
|
|
849
|
+
]
|
|
850
|
+
};
|
|
851
|
+
return x12.build271(spec);
|
|
852
|
+
}
|
|
853
|
+
function roundTrip(interchange) {
|
|
854
|
+
const content = x12.serializeX12(interchange);
|
|
855
|
+
const reparsed = x12.parseX12(content);
|
|
856
|
+
const warnings = reparsed.warnings.map((w) => String(w.code));
|
|
857
|
+
const byteStable = x12.serializeX12(reparsed) === content;
|
|
858
|
+
return {
|
|
859
|
+
content,
|
|
860
|
+
warnings,
|
|
861
|
+
byteStable,
|
|
862
|
+
specClean: warnings.length === 0 && byteStable
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// src/x12/index.ts
|
|
867
|
+
var DEFAULT_MIX = Object.freeze(["837P", "837I", "837D", "835", "271"]);
|
|
868
|
+
function generateKind(kind, seed) {
|
|
869
|
+
if (kind === "835") return roundTrip(generate835({ seed }));
|
|
870
|
+
if (kind === "271") return roundTrip(generate271({ seed }));
|
|
871
|
+
const variant = kind === "837I" ? "I" : kind === "837D" ? "D" : "P";
|
|
872
|
+
return roundTrip(generate837(variant, { seed }));
|
|
873
|
+
}
|
|
874
|
+
function x12Corpus(options) {
|
|
875
|
+
const { seed, mix = DEFAULT_MIX } = options;
|
|
876
|
+
const count = options.count ?? mix.length;
|
|
877
|
+
const seedStream = createRng(seed);
|
|
878
|
+
const artifacts = Array.from({ length: count }, (_unused, i) => {
|
|
879
|
+
const kind = mix[i % mix.length] ?? "837P";
|
|
880
|
+
const txSeed = seedStream.nextUint32();
|
|
881
|
+
const rt = generateKind(kind, txSeed);
|
|
882
|
+
return {
|
|
883
|
+
format: "x12",
|
|
884
|
+
kind,
|
|
885
|
+
content: rt.content,
|
|
886
|
+
warnings: rt.warnings
|
|
887
|
+
};
|
|
888
|
+
});
|
|
889
|
+
return makeCorpus(seed, artifacts);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
exports.CARC_CODES = CARC_CODES;
|
|
893
|
+
exports.DENTAL_PROCEDURES = DENTAL_PROCEDURES;
|
|
894
|
+
exports.DIAGNOSES = DIAGNOSES;
|
|
895
|
+
exports.INSTITUTIONAL_PROCEDURES = INSTITUTIONAL_PROCEDURES;
|
|
896
|
+
exports.PLACES_OF_SERVICE = PLACES_OF_SERVICE;
|
|
897
|
+
exports.PROCEDURE_MODIFIERS = PROCEDURE_MODIFIERS;
|
|
898
|
+
exports.PROFESSIONAL_PROCEDURES = PROFESSIONAL_PROCEDURES;
|
|
899
|
+
exports.REVENUE_CODES = REVENUE_CODES;
|
|
900
|
+
exports.SERVICE_TYPE_CODES = SERVICE_TYPE_CODES;
|
|
901
|
+
exports.TOOTH_CODES = TOOTH_CODES;
|
|
902
|
+
exports.TOOTH_SURFACES = TOOTH_SURFACES;
|
|
903
|
+
exports.dec = dec;
|
|
904
|
+
exports.generate271 = generate271;
|
|
905
|
+
exports.generate835 = generate835;
|
|
906
|
+
exports.generate837 = generate837;
|
|
907
|
+
exports.generate837D = generate837D;
|
|
908
|
+
exports.generate837I = generate837I;
|
|
909
|
+
exports.generate837P = generate837P;
|
|
910
|
+
exports.money = money;
|
|
911
|
+
exports.roundTrip = roundTrip;
|
|
912
|
+
exports.x12Corpus = x12Corpus;
|
|
913
|
+
exports.x12EnvelopeTiming = x12EnvelopeTiming;
|
|
914
|
+
exports.x12Organization = x12Organization;
|
|
915
|
+
exports.x12Payer = x12Payer;
|
|
916
|
+
exports.x12Person = x12Person;
|
|
917
|
+
exports.x12ProviderPerson = x12ProviderPerson;
|
|
918
|
+
exports.x12TradingPartners = x12TradingPartners;
|
|
919
|
+
//# sourceMappingURL=index.cjs.map
|
|
920
|
+
//# sourceMappingURL=index.cjs.map
|