@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,1012 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var hl7 = require('@cosyte/hl7');
|
|
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
|
+
|
|
93
|
+
// src/hl7/field.ts
|
|
94
|
+
function componentsField(components) {
|
|
95
|
+
return {
|
|
96
|
+
repetitions: [{ components: components.map((c) => ({ subcomponents: [c] })) }],
|
|
97
|
+
isNull: false
|
|
98
|
+
};
|
|
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/hl7/common.ts
|
|
374
|
+
function seededTimestamp(rng) {
|
|
375
|
+
const date = safe.dateYmd(rng, 2020, 2025);
|
|
376
|
+
const hh = String(rng.int(0, 23)).padStart(2, "0");
|
|
377
|
+
const mm = String(rng.int(0, 59)).padStart(2, "0");
|
|
378
|
+
const ss = String(rng.int(0, 59)).padStart(2, "0");
|
|
379
|
+
return `${date}${hh}${mm}${ss}`;
|
|
380
|
+
}
|
|
381
|
+
function mshScaffold(rng, type) {
|
|
382
|
+
const timestamp = seededTimestamp(rng);
|
|
383
|
+
const controlId = `SYNTH${rng.digits(10)}`;
|
|
384
|
+
const message = hl7.buildMessage({
|
|
385
|
+
type,
|
|
386
|
+
sendingApp: "COSYTE-SYNTH",
|
|
387
|
+
sendingFacility: "SYNTH-FAC",
|
|
388
|
+
receivingApp: "RECEIVER",
|
|
389
|
+
receivingFacility: "RECV-FAC",
|
|
390
|
+
controlId,
|
|
391
|
+
timestamp,
|
|
392
|
+
version: "2.5",
|
|
393
|
+
processingId: "P"
|
|
394
|
+
});
|
|
395
|
+
return { message, timestamp, controlId };
|
|
396
|
+
}
|
|
397
|
+
function patientIdentity(rng) {
|
|
398
|
+
const person = safe.name(rng);
|
|
399
|
+
const mrn = safe.identifier(rng, "MR");
|
|
400
|
+
const dob = safe.dateYmd(rng, 1930, 2010);
|
|
401
|
+
const sex = rng.pick(["M", "F"]);
|
|
402
|
+
const address2 = safe.address(rng);
|
|
403
|
+
const phone2 = safe.phone(rng);
|
|
404
|
+
const ssnDigits = safe.ssn(rng).replace(/-/g, "");
|
|
405
|
+
return { person, mrn, dob, sex, address: address2, phone: phone2, ssnDigits };
|
|
406
|
+
}
|
|
407
|
+
function pidSegment(id) {
|
|
408
|
+
return [
|
|
409
|
+
"1",
|
|
410
|
+
// PID-1 set id
|
|
411
|
+
"",
|
|
412
|
+
// PID-2 (legacy, absent)
|
|
413
|
+
componentsField([id.mrn.value, "", "", id.mrn.assigningAuthority, id.mrn.typeCode]),
|
|
414
|
+
// PID-3 CX
|
|
415
|
+
"",
|
|
416
|
+
// PID-4
|
|
417
|
+
componentsField([id.person.family, id.person.given]),
|
|
418
|
+
// PID-5 XPN
|
|
419
|
+
"",
|
|
420
|
+
// PID-6
|
|
421
|
+
id.dob,
|
|
422
|
+
// PID-7 DOB
|
|
423
|
+
id.sex,
|
|
424
|
+
// PID-8 sex
|
|
425
|
+
"",
|
|
426
|
+
// PID-9
|
|
427
|
+
"",
|
|
428
|
+
// PID-10
|
|
429
|
+
componentsField([id.address.street, "", id.address.city, id.address.state, id.address.zip]),
|
|
430
|
+
// PID-11 XAD
|
|
431
|
+
"",
|
|
432
|
+
// PID-12
|
|
433
|
+
id.phone,
|
|
434
|
+
// PID-13 phone
|
|
435
|
+
"",
|
|
436
|
+
// PID-14
|
|
437
|
+
"",
|
|
438
|
+
// PID-15
|
|
439
|
+
"",
|
|
440
|
+
// PID-16
|
|
441
|
+
"",
|
|
442
|
+
// PID-17
|
|
443
|
+
"",
|
|
444
|
+
// PID-18
|
|
445
|
+
id.ssnDigits
|
|
446
|
+
// PID-19 SSN (digits)
|
|
447
|
+
];
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// src/hl7/adt.ts
|
|
451
|
+
function generateAdt(options = {}) {
|
|
452
|
+
const seed = options.seed ?? 0;
|
|
453
|
+
const trigger = options.trigger ?? "A01";
|
|
454
|
+
const rng = createRng(seed);
|
|
455
|
+
const { message, timestamp } = mshScaffold(rng, `ADT^${trigger}`);
|
|
456
|
+
message.addSegment("EVN", [trigger, timestamp]);
|
|
457
|
+
message.addSegment("PID", pidSegment(patientIdentity(rng)));
|
|
458
|
+
const patientClass = rng.pick(["I", "O", "E"]);
|
|
459
|
+
message.addSegment("PV1", [
|
|
460
|
+
"1",
|
|
461
|
+
// PV1-1 set id
|
|
462
|
+
patientClass,
|
|
463
|
+
// PV1-2 patient class
|
|
464
|
+
componentsField(["SYNTHWARD", String(rng.int(1, 999)).padStart(3, "0"), "01"])
|
|
465
|
+
// PV1-3 PL
|
|
466
|
+
]);
|
|
467
|
+
return message;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// src/hl7/example-codes.ts
|
|
471
|
+
var EXAMPLE_LAB_OBSERVATIONS = Object.freeze([
|
|
472
|
+
Object.freeze({ code: "4548-4", text: "Hemoglobin A1c", system: "LN", units: "%" }),
|
|
473
|
+
Object.freeze({ code: "718-7", text: "Hemoglobin", system: "LN", units: "g/dL" }),
|
|
474
|
+
Object.freeze({ code: "2345-7", text: "Glucose", system: "LN", units: "mg/dL" }),
|
|
475
|
+
Object.freeze({ code: "2951-2", text: "Sodium", system: "LN", units: "mmol/L" }),
|
|
476
|
+
Object.freeze({ code: "2823-3", text: "Potassium", system: "LN", units: "mmol/L" }),
|
|
477
|
+
Object.freeze({ code: "789-8", text: "Erythrocytes", system: "LN", units: "10*6/uL" })
|
|
478
|
+
]);
|
|
479
|
+
var EXAMPLE_ORDER_SERVICES = Object.freeze([
|
|
480
|
+
Object.freeze({ code: "24323-8", text: "Comprehensive metabolic panel", system: "LN" }),
|
|
481
|
+
Object.freeze({ code: "58410-2", text: "CBC panel", system: "LN" }),
|
|
482
|
+
Object.freeze({ code: "24356-8", text: "Urinalysis panel", system: "LN" }),
|
|
483
|
+
Object.freeze({ code: "24331-1", text: "Lipid panel", system: "LN" })
|
|
484
|
+
]);
|
|
485
|
+
var EXAMPLE_VACCINES = Object.freeze([
|
|
486
|
+
Object.freeze({ code: "08", text: "Hep B, adolescent or pediatric", system: "CVX" }),
|
|
487
|
+
Object.freeze({ code: "20", text: "DTaP", system: "CVX" }),
|
|
488
|
+
Object.freeze({ code: "03", text: "MMR", system: "CVX" }),
|
|
489
|
+
Object.freeze({ code: "10", text: "IPV", system: "CVX" }),
|
|
490
|
+
Object.freeze({ code: "141", text: "Influenza, seasonal, injectable", system: "CVX" }),
|
|
491
|
+
Object.freeze({ code: "21", text: "Varicella", system: "CVX" })
|
|
492
|
+
]);
|
|
493
|
+
|
|
494
|
+
// src/hl7/oru.ts
|
|
495
|
+
function obxSegment(rng, setId) {
|
|
496
|
+
const obs = rng.pick(EXAMPLE_LAB_OBSERVATIONS);
|
|
497
|
+
const value = `${String(rng.int(1, 300))}.${String(rng.int(0, 9))}`;
|
|
498
|
+
const observedAt = seededTimestamp(rng);
|
|
499
|
+
return [
|
|
500
|
+
String(setId),
|
|
501
|
+
// OBX-1 set id
|
|
502
|
+
"NM",
|
|
503
|
+
// OBX-2 value type (numeric)
|
|
504
|
+
componentsField([obs.code, obs.text, obs.system]),
|
|
505
|
+
// OBX-3 observation identifier (CE)
|
|
506
|
+
"",
|
|
507
|
+
// OBX-4 observation sub-id
|
|
508
|
+
value,
|
|
509
|
+
// OBX-5 observation value
|
|
510
|
+
obs.units ?? "",
|
|
511
|
+
// OBX-6 units
|
|
512
|
+
"",
|
|
513
|
+
// OBX-7 reference range
|
|
514
|
+
"N",
|
|
515
|
+
// OBX-8 abnormal flags (normal)
|
|
516
|
+
"",
|
|
517
|
+
// OBX-9
|
|
518
|
+
"",
|
|
519
|
+
// OBX-10
|
|
520
|
+
"F",
|
|
521
|
+
// OBX-11 observation result status (final)
|
|
522
|
+
"",
|
|
523
|
+
// OBX-12
|
|
524
|
+
"",
|
|
525
|
+
// OBX-13
|
|
526
|
+
observedAt
|
|
527
|
+
// OBX-14 date/time of the observation
|
|
528
|
+
];
|
|
529
|
+
}
|
|
530
|
+
function generateOru(options = {}) {
|
|
531
|
+
const seed = options.seed ?? 0;
|
|
532
|
+
const rng = createRng(seed);
|
|
533
|
+
const { message } = mshScaffold(rng, "ORU^R01");
|
|
534
|
+
message.addSegment("PID", pidSegment(patientIdentity(rng)));
|
|
535
|
+
const service = rng.pick(EXAMPLE_ORDER_SERVICES);
|
|
536
|
+
const placer = rng.digits(8);
|
|
537
|
+
const filler = rng.digits(8);
|
|
538
|
+
message.addSegment("OBR", [
|
|
539
|
+
"1",
|
|
540
|
+
// OBR-1 set id
|
|
541
|
+
placer,
|
|
542
|
+
// OBR-2 placer order number
|
|
543
|
+
filler,
|
|
544
|
+
// OBR-3 filler order number
|
|
545
|
+
componentsField([service.code, service.text, service.system]),
|
|
546
|
+
// OBR-4 universal service id (CE)
|
|
547
|
+
"",
|
|
548
|
+
// OBR-5
|
|
549
|
+
"",
|
|
550
|
+
// OBR-6
|
|
551
|
+
seededTimestamp(rng)
|
|
552
|
+
// OBR-7 observation date/time
|
|
553
|
+
]);
|
|
554
|
+
const obxCount = rng.int(1, 3);
|
|
555
|
+
for (let i = 1; i <= obxCount; i += 1) {
|
|
556
|
+
message.addSegment("OBX", obxSegment(rng, i));
|
|
557
|
+
}
|
|
558
|
+
return message;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// src/hl7/orm.ts
|
|
562
|
+
function generateOrm(options = {}) {
|
|
563
|
+
const seed = options.seed ?? 0;
|
|
564
|
+
const rng = createRng(seed);
|
|
565
|
+
const { message } = mshScaffold(rng, "ORM^O01");
|
|
566
|
+
message.addSegment("PID", pidSegment(patientIdentity(rng)));
|
|
567
|
+
const service = rng.pick(EXAMPLE_ORDER_SERVICES);
|
|
568
|
+
const placer = rng.digits(8);
|
|
569
|
+
const filler = rng.digits(8);
|
|
570
|
+
const orderedAt = seededTimestamp(rng);
|
|
571
|
+
message.addSegment("ORC", [
|
|
572
|
+
"NW",
|
|
573
|
+
// ORC-1 order control (new order)
|
|
574
|
+
placer,
|
|
575
|
+
// ORC-2 placer order number
|
|
576
|
+
filler,
|
|
577
|
+
// ORC-3 filler order number
|
|
578
|
+
"",
|
|
579
|
+
// ORC-4 placer group number
|
|
580
|
+
"",
|
|
581
|
+
// ORC-5 order status
|
|
582
|
+
"",
|
|
583
|
+
// ORC-6
|
|
584
|
+
"",
|
|
585
|
+
// ORC-7 quantity/timing
|
|
586
|
+
"",
|
|
587
|
+
// ORC-8
|
|
588
|
+
orderedAt
|
|
589
|
+
// ORC-9 date/time of transaction
|
|
590
|
+
]);
|
|
591
|
+
message.addSegment("OBR", [
|
|
592
|
+
"1",
|
|
593
|
+
// OBR-1 set id
|
|
594
|
+
placer,
|
|
595
|
+
// OBR-2 placer order number (matches ORC)
|
|
596
|
+
filler,
|
|
597
|
+
// OBR-3 filler order number (matches ORC)
|
|
598
|
+
componentsField([service.code, service.text, service.system])
|
|
599
|
+
// OBR-4 universal service id (CE)
|
|
600
|
+
]);
|
|
601
|
+
return message;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/hl7/siu.ts
|
|
605
|
+
function generateSiu(options = {}) {
|
|
606
|
+
const seed = options.seed ?? 0;
|
|
607
|
+
const rng = createRng(seed);
|
|
608
|
+
const { message } = mshScaffold(rng, "SIU^S12");
|
|
609
|
+
const placerAppt = rng.digits(8);
|
|
610
|
+
const fillerAppt = rng.digits(8);
|
|
611
|
+
const startAt = seededTimestamp(rng);
|
|
612
|
+
const durationMinutes = String(rng.int(15, 90));
|
|
613
|
+
message.addSegment("SCH", [
|
|
614
|
+
placerAppt,
|
|
615
|
+
// SCH-1 placer appointment id
|
|
616
|
+
fillerAppt,
|
|
617
|
+
// SCH-2 filler appointment id
|
|
618
|
+
"",
|
|
619
|
+
// SCH-3 occurrence number
|
|
620
|
+
"",
|
|
621
|
+
// SCH-4 placer group number
|
|
622
|
+
"",
|
|
623
|
+
// SCH-5 schedule id
|
|
624
|
+
"",
|
|
625
|
+
// SCH-6 event reason
|
|
626
|
+
componentsField(["ROUTINE", "Routine appointment", "L"]),
|
|
627
|
+
// SCH-7 appointment reason (CE)
|
|
628
|
+
"",
|
|
629
|
+
// SCH-8 appointment type
|
|
630
|
+
durationMinutes,
|
|
631
|
+
// SCH-9 appointment duration
|
|
632
|
+
componentsField(["min", "minutes", "UCUM"]),
|
|
633
|
+
// SCH-10 appointment duration units (CE)
|
|
634
|
+
componentsField(["1", "", startAt, "", "", "", durationMinutes])
|
|
635
|
+
// SCH-11 appointment timing quantity (TQ)
|
|
636
|
+
]);
|
|
637
|
+
message.addSegment("PID", pidSegment(patientIdentity(rng)));
|
|
638
|
+
message.addSegment("RGS", [
|
|
639
|
+
"1",
|
|
640
|
+
// RGS-1 set id
|
|
641
|
+
"A"
|
|
642
|
+
// RGS-2 segment action code (add)
|
|
643
|
+
]);
|
|
644
|
+
message.addSegment("AIL", [
|
|
645
|
+
"1",
|
|
646
|
+
// AIL-1 set id
|
|
647
|
+
"A",
|
|
648
|
+
// AIL-2 segment action code
|
|
649
|
+
componentsField(["SYNTHCLINIC", "Synthetic Clinic", "COSYTE-SYNTH"])
|
|
650
|
+
// AIL-3 location resource id
|
|
651
|
+
]);
|
|
652
|
+
return message;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// src/hl7/vxu.ts
|
|
656
|
+
function generateVxu(options = {}) {
|
|
657
|
+
const seed = options.seed ?? 0;
|
|
658
|
+
const rng = createRng(seed);
|
|
659
|
+
const { message } = mshScaffold(rng, "VXU^V04");
|
|
660
|
+
message.addSegment("PID", pidSegment(patientIdentity(rng)));
|
|
661
|
+
const placer = rng.digits(8);
|
|
662
|
+
const filler = rng.digits(8);
|
|
663
|
+
message.addSegment("ORC", [
|
|
664
|
+
"RE",
|
|
665
|
+
// ORC-1 order control (observation to follow / record)
|
|
666
|
+
placer,
|
|
667
|
+
// ORC-2 placer order number
|
|
668
|
+
filler
|
|
669
|
+
// ORC-3 filler order number
|
|
670
|
+
]);
|
|
671
|
+
const vaccine = rng.pick(EXAMPLE_VACCINES);
|
|
672
|
+
const administeredAt = seededTimestamp(rng);
|
|
673
|
+
const doseAmount = String(rng.int(1, 5) / 10);
|
|
674
|
+
message.addSegment("RXA", [
|
|
675
|
+
"0",
|
|
676
|
+
// RXA-1 give sub-id counter
|
|
677
|
+
"1",
|
|
678
|
+
// RXA-2 administration sub-id counter
|
|
679
|
+
administeredAt,
|
|
680
|
+
// RXA-3 date/time start of administration
|
|
681
|
+
administeredAt,
|
|
682
|
+
// RXA-4 date/time end of administration
|
|
683
|
+
componentsField([vaccine.code, vaccine.text, vaccine.system]),
|
|
684
|
+
// RXA-5 administered code (CE)
|
|
685
|
+
doseAmount,
|
|
686
|
+
// RXA-6 administered amount
|
|
687
|
+
componentsField(["mL", "milliliters", "UCUM"]),
|
|
688
|
+
// RXA-7 administered units (CE)
|
|
689
|
+
"",
|
|
690
|
+
// RXA-8
|
|
691
|
+
"",
|
|
692
|
+
// RXA-9 administration notes
|
|
693
|
+
"",
|
|
694
|
+
// RXA-10
|
|
695
|
+
"",
|
|
696
|
+
// RXA-11
|
|
697
|
+
"",
|
|
698
|
+
// RXA-12
|
|
699
|
+
"",
|
|
700
|
+
// RXA-13
|
|
701
|
+
"",
|
|
702
|
+
// RXA-14
|
|
703
|
+
"",
|
|
704
|
+
// RXA-15 substance lot number
|
|
705
|
+
"",
|
|
706
|
+
// RXA-16
|
|
707
|
+
"",
|
|
708
|
+
// RXA-17
|
|
709
|
+
"",
|
|
710
|
+
// RXA-18
|
|
711
|
+
"",
|
|
712
|
+
// RXA-19
|
|
713
|
+
"CP"
|
|
714
|
+
// RXA-20 completion status (complete)
|
|
715
|
+
]);
|
|
716
|
+
message.addSegment("RXR", [
|
|
717
|
+
componentsField(["IM", "Intramuscular", "HL70162"]),
|
|
718
|
+
// RXR-1 route (CE)
|
|
719
|
+
componentsField(["LD", "Left Deltoid", "HL70163"])
|
|
720
|
+
// RXR-2 administration site (CE)
|
|
721
|
+
]);
|
|
722
|
+
return message;
|
|
723
|
+
}
|
|
724
|
+
function roundTrip(message) {
|
|
725
|
+
const content = message.toString();
|
|
726
|
+
const reparsed = hl7.parseHL7(content);
|
|
727
|
+
const warnings = reparsed.warnings.map((w) => String(w.code));
|
|
728
|
+
const byteStable = reparsed.toString() === content;
|
|
729
|
+
return {
|
|
730
|
+
content,
|
|
731
|
+
warnings,
|
|
732
|
+
byteStable,
|
|
733
|
+
specClean: warnings.length === 0 && byteStable
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// src/profile.ts
|
|
738
|
+
function defineSynthProfile(spec) {
|
|
739
|
+
if (typeof spec.name !== "string" || spec.name.trim().length === 0) {
|
|
740
|
+
throw new TypeError("defineSynthProfile: `name` is required and must be a non-empty string.");
|
|
741
|
+
}
|
|
742
|
+
return Object.freeze({
|
|
743
|
+
name: spec.name,
|
|
744
|
+
...spec.givenNames ? { givenNames: Object.freeze([...spec.givenNames]) } : {},
|
|
745
|
+
...spec.familyNames ? { familyNames: Object.freeze([...spec.familyNames]) } : {},
|
|
746
|
+
quirks: Object.freeze([...spec.quirks ?? []])
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// src/codes.ts
|
|
751
|
+
var SYNTH_FATAL_CODES = {
|
|
752
|
+
/**
|
|
753
|
+
* A vendor quirk was requested that the target format's profile system does not support. Fatal —
|
|
754
|
+
* never a silent no-op and never a fabricated quirk.
|
|
755
|
+
*/
|
|
756
|
+
SYNTH_UNSUPPORTED_QUIRK: "SYNTH_UNSUPPORTED_QUIRK"
|
|
757
|
+
};
|
|
758
|
+
var SynthError = class extends Error {
|
|
759
|
+
/** The stable fatal code. */
|
|
760
|
+
code;
|
|
761
|
+
/**
|
|
762
|
+
* @param code - The stable {@link SynthFatalCode}.
|
|
763
|
+
* @param message - A human-readable detail (never contains PHI — there is none).
|
|
764
|
+
*/
|
|
765
|
+
constructor(code, message) {
|
|
766
|
+
super(message);
|
|
767
|
+
this.name = "SynthError";
|
|
768
|
+
this.code = code;
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
|
|
772
|
+
// src/quirk.ts
|
|
773
|
+
var PROFILE_QUIRK_APPLIED = "PROFILE_QUIRK_APPLIED";
|
|
774
|
+
function sameCodeSet(a, b) {
|
|
775
|
+
if (a.length !== b.length) return false;
|
|
776
|
+
const counts = /* @__PURE__ */ new Map();
|
|
777
|
+
for (const c of a) counts.set(c, (counts.get(c) ?? 0) + 1);
|
|
778
|
+
for (const c of b) {
|
|
779
|
+
const n = counts.get(c);
|
|
780
|
+
if (n === void 0) return false;
|
|
781
|
+
if (n === 1) counts.delete(c);
|
|
782
|
+
else counts.set(c, n - 1);
|
|
783
|
+
}
|
|
784
|
+
return counts.size === 0;
|
|
785
|
+
}
|
|
786
|
+
function resolveQuirk(registry, format, name2) {
|
|
787
|
+
const descriptor = registry[name2];
|
|
788
|
+
if (descriptor === void 0) {
|
|
789
|
+
const supported = Object.keys(registry).sort().join(", ");
|
|
790
|
+
throw new SynthError(
|
|
791
|
+
SYNTH_FATAL_CODES.SYNTH_UNSUPPORTED_QUIRK,
|
|
792
|
+
`${format}: unsupported quirk "${name2}". The ${format} profile system supports: ${supported}.`
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
return descriptor;
|
|
796
|
+
}
|
|
797
|
+
function profileTolerated(disposition, intendedWarnings, warningsUnderProfile) {
|
|
798
|
+
const stillHasIntended = intendedWarnings.some((c) => warningsUnderProfile.includes(c));
|
|
799
|
+
switch (disposition) {
|
|
800
|
+
case "suppressed":
|
|
801
|
+
return !stillHasIntended;
|
|
802
|
+
case "rebadged":
|
|
803
|
+
return !stillHasIntended && warningsUnderProfile.includes(PROFILE_QUIRK_APPLIED);
|
|
804
|
+
case "bare":
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
function assertIntendedWarnings(quirk, intendedWarnings, bareWarnings) {
|
|
809
|
+
if (!sameCodeSet(bareWarnings, intendedWarnings)) {
|
|
810
|
+
throw new Error(
|
|
811
|
+
`quirk "${quirk}": the intended-warning contract does not hold \u2014 expected exactly [${intendedWarnings.join(", ")}] but a bare parse produced [${bareWarnings.join(", ")}]. Refusing to emit a mislabeled fixture.`
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
function validateProfileQuirks(profile, registry, format) {
|
|
816
|
+
for (const name2 of profile.quirks) resolveQuirk(registry, format, name2);
|
|
817
|
+
return profile.quirks;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// src/hl7/quirk.ts
|
|
821
|
+
var HL7_QUIRKS = Object.freeze({
|
|
822
|
+
"unknown-zsegment": Object.freeze({
|
|
823
|
+
name: "unknown-zsegment",
|
|
824
|
+
format: "hl7v2",
|
|
825
|
+
intendedWarnings: Object.freeze(["UNKNOWN_SEGMENT"]),
|
|
826
|
+
grounding: "HL7 v2.x \xA72.5 site-defined Z-segments; grounded on @cosyte/hl7's public imaging/PACS profiles (Visage 7 / Philips Vue PACS / VA Radiology interface specs) which declare the ZDS segment.",
|
|
827
|
+
toleratingProfile: "visage",
|
|
828
|
+
disposition: "suppressed"
|
|
829
|
+
}),
|
|
830
|
+
"unknown-escape": Object.freeze({
|
|
831
|
+
name: "unknown-escape",
|
|
832
|
+
format: "hl7v2",
|
|
833
|
+
intendedWarnings: Object.freeze(["UNKNOWN_ESCAPE_SEQUENCE"]),
|
|
834
|
+
grounding: "HL7 v2.x \xA72.7 escaping \u2014 a locally-defined \\Z..\\ escape is preserved verbatim and flagged. HL7 v2 has no profile re-badge, so no built-in profile downgrades it.",
|
|
835
|
+
disposition: "bare"
|
|
836
|
+
})
|
|
837
|
+
});
|
|
838
|
+
function toleratingProfile(quirk) {
|
|
839
|
+
return quirk === "unknown-zsegment" ? hl7.profiles.visage : void 0;
|
|
840
|
+
}
|
|
841
|
+
function segmentsOf(wire) {
|
|
842
|
+
return wire.split(/\r\n|\r|\n/).filter((s) => s.length > 0);
|
|
843
|
+
}
|
|
844
|
+
function applyQuirk(quirk, wire) {
|
|
845
|
+
const segments = segmentsOf(wire);
|
|
846
|
+
switch (quirk) {
|
|
847
|
+
case "unknown-zsegment":
|
|
848
|
+
return [...segments, "ZDS|1|SYNTHETIC-Z-SEGMENT^COSYTE-SYNTH"].join("\r");
|
|
849
|
+
case "unknown-escape":
|
|
850
|
+
return [...segments, "NTE|1||\\Zff\\"].join("\r");
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
function baseMessage(kind, seed) {
|
|
854
|
+
switch (kind) {
|
|
855
|
+
case "ADT^A01":
|
|
856
|
+
return generateAdt({ seed, trigger: "A01" });
|
|
857
|
+
case "ADT^A04":
|
|
858
|
+
return generateAdt({ seed, trigger: "A04" });
|
|
859
|
+
case "ADT^A08":
|
|
860
|
+
return generateAdt({ seed, trigger: "A08" });
|
|
861
|
+
case "ORU^R01":
|
|
862
|
+
return generateOru({ seed });
|
|
863
|
+
case "ORM^O01":
|
|
864
|
+
return generateOrm({ seed });
|
|
865
|
+
case "SIU^S12":
|
|
866
|
+
return generateSiu({ seed });
|
|
867
|
+
case "VXU^V04":
|
|
868
|
+
return generateVxu({ seed });
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
function generateHl7Quirk(options) {
|
|
872
|
+
const seed = options.seed ?? 0;
|
|
873
|
+
const kind = options.kind ?? "ORU^R01";
|
|
874
|
+
const descriptor = resolveQuirk(HL7_QUIRKS, "hl7v2", options.quirk);
|
|
875
|
+
const content = applyQuirk(options.quirk, baseMessage(kind, seed).toString());
|
|
876
|
+
assertIntendedWarnings(
|
|
877
|
+
descriptor.name,
|
|
878
|
+
descriptor.intendedWarnings,
|
|
879
|
+
hl7.parseHL7(content).warnings.map((w) => String(w.code))
|
|
880
|
+
);
|
|
881
|
+
return Object.freeze({
|
|
882
|
+
format: "hl7v2",
|
|
883
|
+
quirk: descriptor.name,
|
|
884
|
+
kind,
|
|
885
|
+
content,
|
|
886
|
+
intendedWarnings: descriptor.intendedWarnings
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
function hl7QuirkRoundTrip(artifact) {
|
|
890
|
+
const quirk = artifact.quirk;
|
|
891
|
+
const descriptor = resolveQuirk(HL7_QUIRKS, "hl7v2", quirk);
|
|
892
|
+
const bare = hl7.parseHL7(artifact.content).warnings.map((w) => String(w.code));
|
|
893
|
+
const profile = toleratingProfile(quirk);
|
|
894
|
+
const withProfile = profile !== void 0 && descriptor.toleratingProfile !== void 0 ? {
|
|
895
|
+
profileName: descriptor.toleratingProfile,
|
|
896
|
+
disposition: descriptor.disposition,
|
|
897
|
+
warnings: hl7.parseHL7(artifact.content, profile).warnings.map((w) => String(w.code)),
|
|
898
|
+
tolerated: false
|
|
899
|
+
} : void 0;
|
|
900
|
+
return {
|
|
901
|
+
content: artifact.content,
|
|
902
|
+
warnings: bare,
|
|
903
|
+
intendedWarnings: artifact.intendedWarnings,
|
|
904
|
+
intendedWarningHeld: sameCodeSet(bare, artifact.intendedWarnings),
|
|
905
|
+
...withProfile ? {
|
|
906
|
+
withProfile: {
|
|
907
|
+
...withProfile,
|
|
908
|
+
tolerated: profileTolerated(
|
|
909
|
+
descriptor.disposition,
|
|
910
|
+
artifact.intendedWarnings,
|
|
911
|
+
withProfile.warnings
|
|
912
|
+
)
|
|
913
|
+
}
|
|
914
|
+
} : {}
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
var ALL_HL7_QUIRKS = Object.freeze(
|
|
918
|
+
Object.keys(HL7_QUIRKS)
|
|
919
|
+
);
|
|
920
|
+
function hl7QuirkCorpus(options) {
|
|
921
|
+
const quirks = options.profile ? validateProfileQuirks(options.profile, HL7_QUIRKS, "hl7v2") : options.quirks ?? ALL_HL7_QUIRKS;
|
|
922
|
+
const names = quirks.length > 0 ? quirks : ALL_HL7_QUIRKS;
|
|
923
|
+
const kind = options.kind ?? "ORU^R01";
|
|
924
|
+
const count = options.count ?? names.length;
|
|
925
|
+
const seedStream = createRng(options.seed);
|
|
926
|
+
const artifacts = Array.from({ length: count }, (_unused, i) => {
|
|
927
|
+
const quirk = names[i % names.length];
|
|
928
|
+
const artifactSeed = seedStream.nextUint32();
|
|
929
|
+
const artifact = generateHl7Quirk({ seed: artifactSeed, quirk, kind });
|
|
930
|
+
return {
|
|
931
|
+
format: "hl7v2",
|
|
932
|
+
kind: `${kind}~${quirk}`,
|
|
933
|
+
content: artifact.content,
|
|
934
|
+
warnings: artifact.intendedWarnings
|
|
935
|
+
};
|
|
936
|
+
});
|
|
937
|
+
return makeCorpus(options.seed, artifacts, [...new Set(names)]);
|
|
938
|
+
}
|
|
939
|
+
var hl7QuirkProfile = defineSynthProfile({
|
|
940
|
+
name: "cosyte-hl7-quirks",
|
|
941
|
+
quirks: [...ALL_HL7_QUIRKS]
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
// src/hl7/index.ts
|
|
945
|
+
var DEFAULT_MIX = Object.freeze([
|
|
946
|
+
"ADT^A01",
|
|
947
|
+
"ADT^A04",
|
|
948
|
+
"ADT^A08",
|
|
949
|
+
"ORU^R01",
|
|
950
|
+
"ORM^O01",
|
|
951
|
+
"SIU^S12",
|
|
952
|
+
"VXU^V04"
|
|
953
|
+
]);
|
|
954
|
+
function generateHl7(kind, seed) {
|
|
955
|
+
switch (kind) {
|
|
956
|
+
case "ADT^A01":
|
|
957
|
+
return generateAdt({ seed, trigger: "A01" });
|
|
958
|
+
case "ADT^A04":
|
|
959
|
+
return generateAdt({ seed, trigger: "A04" });
|
|
960
|
+
case "ADT^A08":
|
|
961
|
+
return generateAdt({ seed, trigger: "A08" });
|
|
962
|
+
case "ORU^R01":
|
|
963
|
+
return generateOru({ seed });
|
|
964
|
+
case "ORM^O01":
|
|
965
|
+
return generateOrm({ seed });
|
|
966
|
+
case "SIU^S12":
|
|
967
|
+
return generateSiu({ seed });
|
|
968
|
+
case "VXU^V04":
|
|
969
|
+
return generateVxu({ seed });
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
function hl7Corpus(options) {
|
|
973
|
+
const { seed, count = 1 } = options;
|
|
974
|
+
const kinds = options.triggers !== void 0 ? options.triggers.map((t) => `ADT^${t}`) : options.mix ?? DEFAULT_MIX;
|
|
975
|
+
const seedStream = createRng(seed);
|
|
976
|
+
const artifacts = Array.from({ length: count }, (_unused, i) => {
|
|
977
|
+
const kind = kinds[i % kinds.length] ?? "ADT^A01";
|
|
978
|
+
const messageSeed = seedStream.nextUint32();
|
|
979
|
+
const rt = roundTrip(generateHl7(kind, messageSeed));
|
|
980
|
+
return {
|
|
981
|
+
format: "hl7v2",
|
|
982
|
+
kind,
|
|
983
|
+
content: rt.content,
|
|
984
|
+
warnings: rt.warnings
|
|
985
|
+
};
|
|
986
|
+
});
|
|
987
|
+
return makeCorpus(seed, artifacts);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
exports.EXAMPLE_LAB_OBSERVATIONS = EXAMPLE_LAB_OBSERVATIONS;
|
|
991
|
+
exports.EXAMPLE_ORDER_SERVICES = EXAMPLE_ORDER_SERVICES;
|
|
992
|
+
exports.EXAMPLE_VACCINES = EXAMPLE_VACCINES;
|
|
993
|
+
exports.HL7_QUIRKS = HL7_QUIRKS;
|
|
994
|
+
exports.componentsField = componentsField;
|
|
995
|
+
exports.generateAdt = generateAdt;
|
|
996
|
+
exports.generateHl7 = generateHl7;
|
|
997
|
+
exports.generateHl7Quirk = generateHl7Quirk;
|
|
998
|
+
exports.generateOrm = generateOrm;
|
|
999
|
+
exports.generateOru = generateOru;
|
|
1000
|
+
exports.generateSiu = generateSiu;
|
|
1001
|
+
exports.generateVxu = generateVxu;
|
|
1002
|
+
exports.hl7Corpus = hl7Corpus;
|
|
1003
|
+
exports.hl7QuirkCorpus = hl7QuirkCorpus;
|
|
1004
|
+
exports.hl7QuirkProfile = hl7QuirkProfile;
|
|
1005
|
+
exports.hl7QuirkRoundTrip = hl7QuirkRoundTrip;
|
|
1006
|
+
exports.mshScaffold = mshScaffold;
|
|
1007
|
+
exports.patientIdentity = patientIdentity;
|
|
1008
|
+
exports.pidSegment = pidSegment;
|
|
1009
|
+
exports.roundTrip = roundTrip;
|
|
1010
|
+
exports.seededTimestamp = seededTimestamp;
|
|
1011
|
+
//# sourceMappingURL=index.cjs.map
|
|
1012
|
+
//# sourceMappingURL=index.cjs.map
|