@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,847 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var astm = require('@cosyte/astm');
|
|
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/safe/reserved.ts
|
|
94
|
+
var SYNTHETIC_ASSIGNING_AUTHORITY = Object.freeze({
|
|
95
|
+
/** The human-readable assigning-authority namespace id (HL7 HD.1). */
|
|
96
|
+
namespaceId: "COSYTE-SYNTH",
|
|
97
|
+
/** The universal id — an OID under HL7's example arc `2.16.840.1.113883.19` (HD.2). */
|
|
98
|
+
universalId: "2.16.840.1.113883.19.999",
|
|
99
|
+
/** The universal id type (HD.3). */
|
|
100
|
+
universalIdType: "ISO"
|
|
101
|
+
});
|
|
102
|
+
var RESERVED_EMAIL_DOMAINS = Object.freeze([
|
|
103
|
+
"example.com",
|
|
104
|
+
"example.org",
|
|
105
|
+
"example.net"
|
|
106
|
+
]);
|
|
107
|
+
var TEST_NET_V4_PREFIXES = Object.freeze([
|
|
108
|
+
"192.0.2",
|
|
109
|
+
// TEST-NET-1
|
|
110
|
+
"198.51.100",
|
|
111
|
+
// TEST-NET-2
|
|
112
|
+
"203.0.113"
|
|
113
|
+
// TEST-NET-3
|
|
114
|
+
]);
|
|
115
|
+
var DOC_V6_PREFIX = "2001:db8";
|
|
116
|
+
var NPI_LUHN_PREFIX = "80840";
|
|
117
|
+
function luhnMod10(digits) {
|
|
118
|
+
let sum = 0;
|
|
119
|
+
let double = false;
|
|
120
|
+
for (let i = digits.length - 1; i >= 0; i -= 1) {
|
|
121
|
+
let d = digits.charCodeAt(i) - 48;
|
|
122
|
+
if (d < 0 || d > 9) continue;
|
|
123
|
+
if (double) {
|
|
124
|
+
d *= 2;
|
|
125
|
+
if (d > 9) d -= 9;
|
|
126
|
+
}
|
|
127
|
+
sum += d;
|
|
128
|
+
double = !double;
|
|
129
|
+
}
|
|
130
|
+
return sum % 10;
|
|
131
|
+
}
|
|
132
|
+
function npiCheckDigit(base9) {
|
|
133
|
+
const partial = luhnMod10(`${NPI_LUHN_PREFIX}${base9}0`);
|
|
134
|
+
return (10 - partial) % 10;
|
|
135
|
+
}
|
|
136
|
+
var DEA_REGISTRANT_TYPES = Object.freeze([
|
|
137
|
+
"A",
|
|
138
|
+
"B",
|
|
139
|
+
"F",
|
|
140
|
+
"G",
|
|
141
|
+
"M",
|
|
142
|
+
"P",
|
|
143
|
+
"R",
|
|
144
|
+
"X"
|
|
145
|
+
]);
|
|
146
|
+
function deaCheckDigit(base6) {
|
|
147
|
+
let odd = 0;
|
|
148
|
+
let even = 0;
|
|
149
|
+
for (let i = 0; i < 6; i += 1) {
|
|
150
|
+
const digit = base6.charCodeAt(i) - 48;
|
|
151
|
+
if (i % 2 === 0) odd += digit;
|
|
152
|
+
else even += digit;
|
|
153
|
+
}
|
|
154
|
+
return (odd + 2 * even) % 10;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/safe/names-pool.ts
|
|
158
|
+
var SYNTHETIC_GIVEN_NAMES = Object.freeze([
|
|
159
|
+
"Testina",
|
|
160
|
+
"Fixtura",
|
|
161
|
+
"Synthos",
|
|
162
|
+
"Placeholda",
|
|
163
|
+
"Sampleton",
|
|
164
|
+
"Prototius",
|
|
165
|
+
"Stubbina",
|
|
166
|
+
"Exampla",
|
|
167
|
+
"Quilliam",
|
|
168
|
+
"Fabrica",
|
|
169
|
+
"Simula",
|
|
170
|
+
"Testry",
|
|
171
|
+
"Seedwin",
|
|
172
|
+
"Corpora",
|
|
173
|
+
"Reprodo",
|
|
174
|
+
"Mocktavia",
|
|
175
|
+
"Dummett",
|
|
176
|
+
"Voidwin",
|
|
177
|
+
"Deteria",
|
|
178
|
+
"Randomir"
|
|
179
|
+
]);
|
|
180
|
+
var SYNTHETIC_FAMILY_NAMES = Object.freeze([
|
|
181
|
+
"Testerson",
|
|
182
|
+
"Fauxman",
|
|
183
|
+
"Placeholt",
|
|
184
|
+
"Mockridge",
|
|
185
|
+
"Fixtingham",
|
|
186
|
+
"Synthwell",
|
|
187
|
+
"Dummerton",
|
|
188
|
+
"Examplewood",
|
|
189
|
+
"Fabricant",
|
|
190
|
+
"Simulacre",
|
|
191
|
+
"Nonesuch",
|
|
192
|
+
"Seedman",
|
|
193
|
+
"Corpusworth",
|
|
194
|
+
"Reprodus",
|
|
195
|
+
"Voidmark",
|
|
196
|
+
"Deterwood",
|
|
197
|
+
"Randomson",
|
|
198
|
+
"Quillfeather",
|
|
199
|
+
"Notreal",
|
|
200
|
+
"Genfield"
|
|
201
|
+
]);
|
|
202
|
+
var SYNTHETIC_STREET_NAMES = Object.freeze([
|
|
203
|
+
"Fixture Lane",
|
|
204
|
+
"Sample Street",
|
|
205
|
+
"Placeholder Avenue",
|
|
206
|
+
"Synthetic Way",
|
|
207
|
+
"Example Boulevard",
|
|
208
|
+
"Testing Terrace",
|
|
209
|
+
"Mock Road",
|
|
210
|
+
"Prototype Court"
|
|
211
|
+
]);
|
|
212
|
+
var SYNTHETIC_CITY_NAMES = Object.freeze([
|
|
213
|
+
"Faketon",
|
|
214
|
+
"Synthville",
|
|
215
|
+
"Exampleburg",
|
|
216
|
+
"Testford",
|
|
217
|
+
"Mockhaven",
|
|
218
|
+
"Fixtureton"
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
// src/safe/providers.ts
|
|
222
|
+
function ssn(rng, block = "never-issued") {
|
|
223
|
+
if (block === "advertising") {
|
|
224
|
+
return `987-65-432${String(rng.int(0, 9))}`;
|
|
225
|
+
}
|
|
226
|
+
const area = rng.int(900, 999);
|
|
227
|
+
const group = rng.digits(2);
|
|
228
|
+
const serial = rng.digits(4);
|
|
229
|
+
return `${String(area)}-${group}-${serial}`;
|
|
230
|
+
}
|
|
231
|
+
function phone(rng) {
|
|
232
|
+
const area = `${String(rng.int(2, 9))}${rng.digits(2)}`;
|
|
233
|
+
const line = `01${rng.digits(2)}`;
|
|
234
|
+
return `(${area}) 555-${line}`;
|
|
235
|
+
}
|
|
236
|
+
function name(rng) {
|
|
237
|
+
return { given: rng.pick(SYNTHETIC_GIVEN_NAMES), family: rng.pick(SYNTHETIC_FAMILY_NAMES) };
|
|
238
|
+
}
|
|
239
|
+
function email(rng, person) {
|
|
240
|
+
const domain = rng.pick(RESERVED_EMAIL_DOMAINS);
|
|
241
|
+
const slug = person ? `${person.given}.${person.family}`.toLowerCase() : `synth${rng.digits(6)}`;
|
|
242
|
+
return `${slug}@${domain}`;
|
|
243
|
+
}
|
|
244
|
+
function ipv4(rng) {
|
|
245
|
+
return `${rng.pick(TEST_NET_V4_PREFIXES)}.${String(rng.int(1, 254))}`;
|
|
246
|
+
}
|
|
247
|
+
function ipv6(rng) {
|
|
248
|
+
const tail = rng.nextUint32().toString(16).padStart(4, "0").slice(-4);
|
|
249
|
+
return `${DOC_V6_PREFIX}::${tail}`;
|
|
250
|
+
}
|
|
251
|
+
function uuid(rng) {
|
|
252
|
+
const bytes = new Uint8Array(16);
|
|
253
|
+
for (let i = 0; i < 16; i += 1) bytes[i] = rng.int(0, 255);
|
|
254
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
255
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
256
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
|
|
257
|
+
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("")}`;
|
|
258
|
+
}
|
|
259
|
+
function npi(rng) {
|
|
260
|
+
const base9 = rng.digits(9);
|
|
261
|
+
const wrongCheck = (npiCheckDigit(base9) + 1) % 10;
|
|
262
|
+
return `${base9}${String(wrongCheck)}`;
|
|
263
|
+
}
|
|
264
|
+
function dea(rng, person) {
|
|
265
|
+
const type = rng.pick(DEA_REGISTRANT_TYPES);
|
|
266
|
+
const initialSource = person?.family ?? rng.pick(SYNTHETIC_FAMILY_NAMES);
|
|
267
|
+
const initial = initialSource.slice(0, 1).toUpperCase();
|
|
268
|
+
const base6 = rng.digits(6);
|
|
269
|
+
const wrongCheck = (deaCheckDigit(base6) + 1) % 10;
|
|
270
|
+
return `${type}${initial}${base6}${String(wrongCheck)}`;
|
|
271
|
+
}
|
|
272
|
+
function identifier(rng, typeCode = "MR") {
|
|
273
|
+
return {
|
|
274
|
+
value: rng.digits(8),
|
|
275
|
+
typeCode,
|
|
276
|
+
assigningAuthority: SYNTHETIC_ASSIGNING_AUTHORITY.namespaceId,
|
|
277
|
+
assigningAuthorityOid: SYNTHETIC_ASSIGNING_AUTHORITY.universalId
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function address(rng) {
|
|
281
|
+
const number = rng.int(1, 9999);
|
|
282
|
+
return {
|
|
283
|
+
street: `${String(number)} ${rng.pick(SYNTHETIC_STREET_NAMES)}`,
|
|
284
|
+
city: rng.pick(SYNTHETIC_CITY_NAMES),
|
|
285
|
+
state: rng.pick(US_STATES),
|
|
286
|
+
zip: "00000"
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function dateYmd(rng, minYear = 1930, maxYear = 2010) {
|
|
290
|
+
const year = rng.int(minYear, maxYear);
|
|
291
|
+
const month = rng.int(1, 12);
|
|
292
|
+
const daysInMonth = new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
293
|
+
const day = rng.int(1, daysInMonth);
|
|
294
|
+
return `${String(year).padStart(4, "0")}${String(month).padStart(2, "0")}${String(day).padStart(2, "0")}`;
|
|
295
|
+
}
|
|
296
|
+
var US_STATES = Object.freeze([
|
|
297
|
+
"AL",
|
|
298
|
+
"AK",
|
|
299
|
+
"AZ",
|
|
300
|
+
"AR",
|
|
301
|
+
"CA",
|
|
302
|
+
"CO",
|
|
303
|
+
"CT",
|
|
304
|
+
"DE",
|
|
305
|
+
"FL",
|
|
306
|
+
"GA",
|
|
307
|
+
"HI",
|
|
308
|
+
"ID",
|
|
309
|
+
"IL",
|
|
310
|
+
"IN",
|
|
311
|
+
"IA",
|
|
312
|
+
"KS",
|
|
313
|
+
"KY",
|
|
314
|
+
"LA",
|
|
315
|
+
"ME",
|
|
316
|
+
"MD",
|
|
317
|
+
"MA",
|
|
318
|
+
"MI",
|
|
319
|
+
"MN",
|
|
320
|
+
"MS",
|
|
321
|
+
"MO",
|
|
322
|
+
"MT",
|
|
323
|
+
"NE",
|
|
324
|
+
"NV",
|
|
325
|
+
"NH",
|
|
326
|
+
"NJ",
|
|
327
|
+
"NM",
|
|
328
|
+
"NY",
|
|
329
|
+
"NC",
|
|
330
|
+
"ND",
|
|
331
|
+
"OH",
|
|
332
|
+
"OK",
|
|
333
|
+
"OR",
|
|
334
|
+
"PA",
|
|
335
|
+
"RI",
|
|
336
|
+
"SC",
|
|
337
|
+
"SD",
|
|
338
|
+
"TN",
|
|
339
|
+
"TX",
|
|
340
|
+
"UT",
|
|
341
|
+
"VT",
|
|
342
|
+
"VA",
|
|
343
|
+
"WA",
|
|
344
|
+
"WV",
|
|
345
|
+
"WI",
|
|
346
|
+
"WY"
|
|
347
|
+
]);
|
|
348
|
+
|
|
349
|
+
// src/safe/index.ts
|
|
350
|
+
var safe = Object.freeze({
|
|
351
|
+
ssn,
|
|
352
|
+
phone,
|
|
353
|
+
name,
|
|
354
|
+
email,
|
|
355
|
+
ipv4,
|
|
356
|
+
ipv6,
|
|
357
|
+
uuid,
|
|
358
|
+
identifier,
|
|
359
|
+
address,
|
|
360
|
+
dateYmd,
|
|
361
|
+
npi,
|
|
362
|
+
dea
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// src/astm/identity.ts
|
|
366
|
+
var SYNTHETIC_MIDDLE_INITIALS = Object.freeze([
|
|
367
|
+
"A",
|
|
368
|
+
"B",
|
|
369
|
+
"C",
|
|
370
|
+
"J",
|
|
371
|
+
"M",
|
|
372
|
+
"R",
|
|
373
|
+
"T"
|
|
374
|
+
]);
|
|
375
|
+
var SYNTHETIC_SENDERS = Object.freeze([
|
|
376
|
+
"SYNTH-LIS",
|
|
377
|
+
"FIXTURE-HOST",
|
|
378
|
+
"PLACEHOLDER-LAB"
|
|
379
|
+
]);
|
|
380
|
+
var SYNTHETIC_ANALYZERS = Object.freeze([
|
|
381
|
+
"SYNTH-ANALYZER^ModelS^1",
|
|
382
|
+
"MOCK-CHEM^ModelC^2",
|
|
383
|
+
"FIXTURE-HEMA^ModelH^1"
|
|
384
|
+
]);
|
|
385
|
+
function astmPatient(rng) {
|
|
386
|
+
const person = safe.name(rng);
|
|
387
|
+
const middle = rng.pick(SYNTHETIC_MIDDLE_INITIALS);
|
|
388
|
+
const birthDate = safe.dateYmd(rng, 1935, 2010);
|
|
389
|
+
const sex = rng.pick(["M", "F"]);
|
|
390
|
+
const practiceAssignedId = `PRA${safe.identifier(rng, "MR").value}`;
|
|
391
|
+
const laboratoryAssignedId = `LAB${safe.identifier(rng, "MR").value}`;
|
|
392
|
+
return { person, middle, birthDate, sex, practiceAssignedId, laboratoryAssignedId };
|
|
393
|
+
}
|
|
394
|
+
function astmOrder(rng) {
|
|
395
|
+
const specimenId = `ACC${rng.digits(8)}`;
|
|
396
|
+
const priority = rng.pick(["R", "S"]);
|
|
397
|
+
return { specimenId, priority };
|
|
398
|
+
}
|
|
399
|
+
function astmHeaderIdentity(rng) {
|
|
400
|
+
const sender = rng.pick(SYNTHETIC_SENDERS);
|
|
401
|
+
const analyzer = rng.pick(SYNTHETIC_ANALYZERS);
|
|
402
|
+
return { sender, analyzer };
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// src/astm/example-codes.ts
|
|
406
|
+
var EXAMPLE_ASTM_TESTS = Object.freeze([
|
|
407
|
+
{
|
|
408
|
+
localCode: "GLU",
|
|
409
|
+
loinc: "2345-7",
|
|
410
|
+
name: "Glucose",
|
|
411
|
+
units: "mg/dL",
|
|
412
|
+
referenceRange: "70-110",
|
|
413
|
+
valueLow: 55,
|
|
414
|
+
valueHigh: 260,
|
|
415
|
+
decimals: 0
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
localCode: "K",
|
|
419
|
+
loinc: "2823-3",
|
|
420
|
+
name: "Potassium",
|
|
421
|
+
units: "mmol/L",
|
|
422
|
+
referenceRange: "3.5-5.1",
|
|
423
|
+
valueLow: 28,
|
|
424
|
+
valueHigh: 62,
|
|
425
|
+
decimals: 1
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
localCode: "NA",
|
|
429
|
+
loinc: "2951-2",
|
|
430
|
+
name: "Sodium",
|
|
431
|
+
units: "mmol/L",
|
|
432
|
+
referenceRange: "136-145",
|
|
433
|
+
valueLow: 125,
|
|
434
|
+
valueHigh: 155,
|
|
435
|
+
decimals: 0
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
localCode: "CREA",
|
|
439
|
+
loinc: "2160-0",
|
|
440
|
+
name: "Creatinine",
|
|
441
|
+
units: "mg/dL",
|
|
442
|
+
referenceRange: "0.6-1.3",
|
|
443
|
+
valueLow: 4,
|
|
444
|
+
valueHigh: 32,
|
|
445
|
+
decimals: 1
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
localCode: "HGB",
|
|
449
|
+
loinc: "718-7",
|
|
450
|
+
name: "Hemoglobin",
|
|
451
|
+
units: "g/dL",
|
|
452
|
+
referenceRange: "12.0-17.5",
|
|
453
|
+
valueLow: 80,
|
|
454
|
+
valueHigh: 190,
|
|
455
|
+
decimals: 1
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
localCode: "WBC",
|
|
459
|
+
loinc: "6690-2",
|
|
460
|
+
name: "Leukocytes",
|
|
461
|
+
units: "10*3/uL",
|
|
462
|
+
referenceRange: "4.5-11.0",
|
|
463
|
+
valueLow: 30,
|
|
464
|
+
valueHigh: 150,
|
|
465
|
+
decimals: 1
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
localCode: "TSH",
|
|
469
|
+
loinc: "3016-3",
|
|
470
|
+
name: "Thyrotropin",
|
|
471
|
+
units: "mIU/L",
|
|
472
|
+
referenceRange: "0.40-4.50",
|
|
473
|
+
valueLow: 2,
|
|
474
|
+
valueHigh: 90,
|
|
475
|
+
decimals: 2
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
localCode: "ALT",
|
|
479
|
+
loinc: "1742-6",
|
|
480
|
+
name: "Alanine aminotransferase",
|
|
481
|
+
units: "U/L",
|
|
482
|
+
referenceRange: "7-56",
|
|
483
|
+
valueLow: 5,
|
|
484
|
+
valueHigh: 120,
|
|
485
|
+
decimals: 0
|
|
486
|
+
}
|
|
487
|
+
]);
|
|
488
|
+
var ASTM_ABNORMAL_FLAGS = Object.freeze(["N", "L", "H", "A"]);
|
|
489
|
+
var ASTM_RESULT_STATUSES = Object.freeze(["F", "P", "C"]);
|
|
490
|
+
var ASTM_COMMENT_TEXT = Object.freeze([
|
|
491
|
+
"Synthetic fixture comment - not a clinical observation.",
|
|
492
|
+
"Sample generated by @cosyte/synth.",
|
|
493
|
+
"Placeholder result comment for conformance testing."
|
|
494
|
+
]);
|
|
495
|
+
|
|
496
|
+
// src/astm/message.ts
|
|
497
|
+
function resultValue(rng, low, high, decimals) {
|
|
498
|
+
const raw = rng.int(low, high);
|
|
499
|
+
if (decimals === 0) return String(raw);
|
|
500
|
+
const scale = 10 ** decimals;
|
|
501
|
+
return (raw / scale).toFixed(decimals);
|
|
502
|
+
}
|
|
503
|
+
function buildResultInput(options) {
|
|
504
|
+
const rng = createRng(options.seed);
|
|
505
|
+
const head = astmHeaderIdentity(rng);
|
|
506
|
+
const patient = astmPatient(rng);
|
|
507
|
+
const order = astmOrder(rng);
|
|
508
|
+
const resultCount = options.resultCount ?? rng.int(1, 4);
|
|
509
|
+
const records = [
|
|
510
|
+
{
|
|
511
|
+
type: "P",
|
|
512
|
+
practiceAssignedId: patient.practiceAssignedId,
|
|
513
|
+
laboratoryAssignedId: patient.laboratoryAssignedId,
|
|
514
|
+
name: { last: patient.person.family, first: patient.person.given, middle: patient.middle },
|
|
515
|
+
birthDate: patient.birthDate,
|
|
516
|
+
sex: patient.sex
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
type: "O",
|
|
520
|
+
specimenId: order.specimenId,
|
|
521
|
+
universalTestId: ["", "", "", "ALL"],
|
|
522
|
+
priority: order.priority,
|
|
523
|
+
actionCode: "N",
|
|
524
|
+
reportType: "F"
|
|
525
|
+
}
|
|
526
|
+
];
|
|
527
|
+
for (let i = 0; i < resultCount; i += 1) {
|
|
528
|
+
const test = rng.pick(EXAMPLE_ASTM_TESTS);
|
|
529
|
+
records.push({
|
|
530
|
+
type: "R",
|
|
531
|
+
universalTestId: ["", "", "", test.localCode, test.name, test.loinc],
|
|
532
|
+
value: resultValue(rng, test.valueLow, test.valueHigh, test.decimals),
|
|
533
|
+
units: test.units,
|
|
534
|
+
referenceRange: test.referenceRange,
|
|
535
|
+
abnormalFlags: rng.pick(ASTM_ABNORMAL_FLAGS),
|
|
536
|
+
resultStatus: "F"
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
if (options.comment ?? true) {
|
|
540
|
+
records.push({ type: "C", source: "L", text: rng.pick(ASTM_COMMENT_TEXT), commentType: "G" });
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
header: { fields: [head.sender, head.analyzer] },
|
|
544
|
+
records,
|
|
545
|
+
terminationCode: "N"
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function generateAstmResult(options) {
|
|
549
|
+
return astm.buildAstmMessage(buildResultInput(options));
|
|
550
|
+
}
|
|
551
|
+
function generateAstmOrder(options) {
|
|
552
|
+
return generateAstmResult({ ...options, resultCount: 0, comment: false });
|
|
553
|
+
}
|
|
554
|
+
function generateAstmResultFramed(options) {
|
|
555
|
+
const raw = generateAstmResult(options);
|
|
556
|
+
const recordLines = raw.split("\r").filter((line) => line.length > 0).map((line) => `${line}\r`);
|
|
557
|
+
return astm.composeAstmFrames(recordLines);
|
|
558
|
+
}
|
|
559
|
+
function astmRoundTrip(raw) {
|
|
560
|
+
const message = astm.parseAstmRecords(raw);
|
|
561
|
+
const warnings = message.warnings.map((w) => String(w.code));
|
|
562
|
+
const byteStable = astm.serializeAstmRecords(message) === raw;
|
|
563
|
+
return { content: raw, warnings, byteStable, specClean: warnings.length === 0 && byteStable };
|
|
564
|
+
}
|
|
565
|
+
function astmFramedRoundTrip(bytes) {
|
|
566
|
+
const { message, frameWarnings } = astm.parseFramedAstm(bytes);
|
|
567
|
+
const warnings = [
|
|
568
|
+
...frameWarnings.map((w) => String(w.code)),
|
|
569
|
+
...message.warnings.map((w) => String(w.code))
|
|
570
|
+
];
|
|
571
|
+
const reframed = astm.serializeFramedAstm(message);
|
|
572
|
+
const byteStable = bytesEqual(reframed, bytes);
|
|
573
|
+
const content = latin1(bytes);
|
|
574
|
+
return { content, warnings, byteStable, specClean: warnings.length === 0 && byteStable };
|
|
575
|
+
}
|
|
576
|
+
function bytesEqual(a, b) {
|
|
577
|
+
if (a.length !== b.length) return false;
|
|
578
|
+
for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
function latin1(bytes) {
|
|
582
|
+
let out = "";
|
|
583
|
+
for (const b of bytes) out += String.fromCharCode(b);
|
|
584
|
+
return out;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// src/profile.ts
|
|
588
|
+
function defineSynthProfile(spec) {
|
|
589
|
+
if (typeof spec.name !== "string" || spec.name.trim().length === 0) {
|
|
590
|
+
throw new TypeError("defineSynthProfile: `name` is required and must be a non-empty string.");
|
|
591
|
+
}
|
|
592
|
+
return Object.freeze({
|
|
593
|
+
name: spec.name,
|
|
594
|
+
...spec.givenNames ? { givenNames: Object.freeze([...spec.givenNames]) } : {},
|
|
595
|
+
...spec.familyNames ? { familyNames: Object.freeze([...spec.familyNames]) } : {},
|
|
596
|
+
quirks: Object.freeze([...spec.quirks ?? []])
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// src/codes.ts
|
|
601
|
+
var SYNTH_FATAL_CODES = {
|
|
602
|
+
/**
|
|
603
|
+
* A vendor quirk was requested that the target format's profile system does not support. Fatal —
|
|
604
|
+
* never a silent no-op and never a fabricated quirk.
|
|
605
|
+
*/
|
|
606
|
+
SYNTH_UNSUPPORTED_QUIRK: "SYNTH_UNSUPPORTED_QUIRK"
|
|
607
|
+
};
|
|
608
|
+
var SynthError = class extends Error {
|
|
609
|
+
/** The stable fatal code. */
|
|
610
|
+
code;
|
|
611
|
+
/**
|
|
612
|
+
* @param code - The stable {@link SynthFatalCode}.
|
|
613
|
+
* @param message - A human-readable detail (never contains PHI — there is none).
|
|
614
|
+
*/
|
|
615
|
+
constructor(code, message) {
|
|
616
|
+
super(message);
|
|
617
|
+
this.name = "SynthError";
|
|
618
|
+
this.code = code;
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
// src/quirk.ts
|
|
623
|
+
var PROFILE_QUIRK_APPLIED = "PROFILE_QUIRK_APPLIED";
|
|
624
|
+
function sameCodeSet(a, b) {
|
|
625
|
+
if (a.length !== b.length) return false;
|
|
626
|
+
const counts = /* @__PURE__ */ new Map();
|
|
627
|
+
for (const c of a) counts.set(c, (counts.get(c) ?? 0) + 1);
|
|
628
|
+
for (const c of b) {
|
|
629
|
+
const n = counts.get(c);
|
|
630
|
+
if (n === void 0) return false;
|
|
631
|
+
if (n === 1) counts.delete(c);
|
|
632
|
+
else counts.set(c, n - 1);
|
|
633
|
+
}
|
|
634
|
+
return counts.size === 0;
|
|
635
|
+
}
|
|
636
|
+
function resolveQuirk(registry, format, name2) {
|
|
637
|
+
const descriptor = registry[name2];
|
|
638
|
+
if (descriptor === void 0) {
|
|
639
|
+
const supported = Object.keys(registry).sort().join(", ");
|
|
640
|
+
throw new SynthError(
|
|
641
|
+
SYNTH_FATAL_CODES.SYNTH_UNSUPPORTED_QUIRK,
|
|
642
|
+
`${format}: unsupported quirk "${name2}". The ${format} profile system supports: ${supported}.`
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
return descriptor;
|
|
646
|
+
}
|
|
647
|
+
function profileTolerated(disposition, intendedWarnings, warningsUnderProfile) {
|
|
648
|
+
const stillHasIntended = intendedWarnings.some((c) => warningsUnderProfile.includes(c));
|
|
649
|
+
switch (disposition) {
|
|
650
|
+
case "suppressed":
|
|
651
|
+
return !stillHasIntended;
|
|
652
|
+
case "rebadged":
|
|
653
|
+
return !stillHasIntended && warningsUnderProfile.includes(PROFILE_QUIRK_APPLIED);
|
|
654
|
+
case "bare":
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
function assertIntendedWarnings(quirk, intendedWarnings, bareWarnings) {
|
|
659
|
+
if (!sameCodeSet(bareWarnings, intendedWarnings)) {
|
|
660
|
+
throw new Error(
|
|
661
|
+
`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.`
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
function validateProfileQuirks(profile, registry, format) {
|
|
666
|
+
for (const name2 of profile.quirks) resolveQuirk(registry, format, name2);
|
|
667
|
+
return profile.quirks;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/astm/quirk.ts
|
|
671
|
+
var ASTM_QUIRKS = Object.freeze({
|
|
672
|
+
"unknown-escape": Object.freeze({
|
|
673
|
+
name: "unknown-escape",
|
|
674
|
+
format: "astm",
|
|
675
|
+
intendedWarnings: Object.freeze(["ASTM_UNKNOWN_ESCAPE_SEQUENCE"]),
|
|
676
|
+
grounding: "ASTM E1394 escape delimiter (&); a non-standard &Z& body is preserved verbatim and flagged. Re-badged by @cosyte/astm's public `referenceCorpus` profile (kxepal/python-astm + senaite OSS).",
|
|
677
|
+
toleratingProfile: "referenceCorpus",
|
|
678
|
+
disposition: "rebadged"
|
|
679
|
+
}),
|
|
680
|
+
"unknown-record-type": Object.freeze({
|
|
681
|
+
name: "unknown-record-type",
|
|
682
|
+
format: "astm",
|
|
683
|
+
intendedWarnings: Object.freeze(["ASTM_RECORD_UNKNOWN_TYPE"]),
|
|
684
|
+
grounding: "ASTM E1394 permits manufacturer/site-defined record types; a Z record is surfaced as unsupported. A tolerable code (in the parser's defineAstmProfile allow-list) \u2014 a consumer authors a profile to re-badge it; no built-in public profile does.",
|
|
685
|
+
disposition: "bare"
|
|
686
|
+
})
|
|
687
|
+
});
|
|
688
|
+
function toleratingProfile(quirk) {
|
|
689
|
+
return quirk === "unknown-escape" ? astm.astmProfiles.referenceCorpus : void 0;
|
|
690
|
+
}
|
|
691
|
+
var CR = "\r";
|
|
692
|
+
function applyQuirk(quirk, records) {
|
|
693
|
+
const lines = records.split(CR);
|
|
694
|
+
switch (quirk) {
|
|
695
|
+
case "unknown-escape": {
|
|
696
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
697
|
+
const line = lines[i];
|
|
698
|
+
if (line !== void 0 && line.startsWith("R|")) {
|
|
699
|
+
const fields = line.split("|");
|
|
700
|
+
const units = fields[4];
|
|
701
|
+
if (units !== void 0 && units.length > 0) {
|
|
702
|
+
fields[4] = `&Z&${units}`;
|
|
703
|
+
lines[i] = fields.join("|");
|
|
704
|
+
return lines.join(CR);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
return records;
|
|
709
|
+
}
|
|
710
|
+
case "unknown-record-type": {
|
|
711
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
712
|
+
const line = lines[i];
|
|
713
|
+
if (line !== void 0 && line.startsWith("C|")) {
|
|
714
|
+
lines[i] = `Z${line.slice(1)}`;
|
|
715
|
+
return lines.join(CR);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return records;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function generateAstmQuirk(options) {
|
|
723
|
+
const seed = options.seed ?? 0;
|
|
724
|
+
const kind = "Result";
|
|
725
|
+
const descriptor = resolveQuirk(ASTM_QUIRKS, "astm", options.quirk);
|
|
726
|
+
const clean = generateAstmResult({ seed });
|
|
727
|
+
const content = applyQuirk(options.quirk, clean);
|
|
728
|
+
if (content === clean) {
|
|
729
|
+
throw new Error(
|
|
730
|
+
`generateAstmQuirk: quirk "${options.quirk}" found no structural anchor in a ${kind} report at seed ${seed} \u2014 refusing to emit a fixture that does not carry the intended deviation.`
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
assertIntendedWarnings(
|
|
734
|
+
descriptor.name,
|
|
735
|
+
descriptor.intendedWarnings,
|
|
736
|
+
astm.parseAstmRecords(content).warnings.map((w) => String(w.code))
|
|
737
|
+
);
|
|
738
|
+
return Object.freeze({
|
|
739
|
+
format: "astm",
|
|
740
|
+
quirk: descriptor.name,
|
|
741
|
+
kind,
|
|
742
|
+
content,
|
|
743
|
+
intendedWarnings: descriptor.intendedWarnings
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
function astmQuirkRoundTrip(artifact) {
|
|
747
|
+
const quirk = artifact.quirk;
|
|
748
|
+
const descriptor = resolveQuirk(ASTM_QUIRKS, "astm", quirk);
|
|
749
|
+
const bare = astm.parseAstmRecords(artifact.content).warnings.map((w) => String(w.code));
|
|
750
|
+
const profile = toleratingProfile(quirk);
|
|
751
|
+
const withProfile = profile !== void 0 && descriptor.toleratingProfile !== void 0 ? (() => {
|
|
752
|
+
const warnings = astm.parseAstmRecords(artifact.content, { profile }).warnings.map(
|
|
753
|
+
(w) => String(w.code)
|
|
754
|
+
);
|
|
755
|
+
return {
|
|
756
|
+
profileName: descriptor.toleratingProfile,
|
|
757
|
+
disposition: descriptor.disposition,
|
|
758
|
+
warnings,
|
|
759
|
+
tolerated: profileTolerated(
|
|
760
|
+
descriptor.disposition,
|
|
761
|
+
artifact.intendedWarnings,
|
|
762
|
+
warnings
|
|
763
|
+
)
|
|
764
|
+
};
|
|
765
|
+
})() : void 0;
|
|
766
|
+
return {
|
|
767
|
+
content: artifact.content,
|
|
768
|
+
warnings: bare,
|
|
769
|
+
intendedWarnings: artifact.intendedWarnings,
|
|
770
|
+
intendedWarningHeld: sameCodeSet(bare, artifact.intendedWarnings),
|
|
771
|
+
...withProfile ? { withProfile } : {}
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
var ALL_ASTM_QUIRKS = Object.freeze(
|
|
775
|
+
Object.keys(ASTM_QUIRKS)
|
|
776
|
+
);
|
|
777
|
+
function astmQuirkCorpus(options) {
|
|
778
|
+
const quirks = options.profile ? validateProfileQuirks(options.profile, ASTM_QUIRKS, "astm") : options.quirks ?? ALL_ASTM_QUIRKS;
|
|
779
|
+
const names = quirks.length > 0 ? quirks : ALL_ASTM_QUIRKS;
|
|
780
|
+
const count = options.count ?? names.length;
|
|
781
|
+
const seedStream = createRng(options.seed);
|
|
782
|
+
const artifacts = Array.from({ length: count }, (_unused, i) => {
|
|
783
|
+
const quirk = names[i % names.length];
|
|
784
|
+
const artifactSeed = seedStream.nextUint32();
|
|
785
|
+
const artifact = generateAstmQuirk({ seed: artifactSeed, quirk });
|
|
786
|
+
return {
|
|
787
|
+
format: "astm",
|
|
788
|
+
kind: `Result~${quirk}`,
|
|
789
|
+
content: artifact.content,
|
|
790
|
+
warnings: artifact.intendedWarnings
|
|
791
|
+
};
|
|
792
|
+
});
|
|
793
|
+
return makeCorpus(options.seed, artifacts, [...new Set(names)]);
|
|
794
|
+
}
|
|
795
|
+
var astmQuirkProfile = defineSynthProfile({
|
|
796
|
+
name: "cosyte-astm-quirks",
|
|
797
|
+
quirks: [...ALL_ASTM_QUIRKS]
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
// src/astm/index.ts
|
|
801
|
+
var DEFAULT_MIX = Object.freeze(["Result", "Order"]);
|
|
802
|
+
function generateKind(kind, seed) {
|
|
803
|
+
switch (kind) {
|
|
804
|
+
case "Result":
|
|
805
|
+
return astmRoundTrip(generateAstmResult({ seed }));
|
|
806
|
+
case "Order":
|
|
807
|
+
return astmRoundTrip(generateAstmOrder({ seed }));
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
function astmCorpus(options) {
|
|
811
|
+
const { seed, mix = DEFAULT_MIX } = options;
|
|
812
|
+
const count = options.count ?? mix.length;
|
|
813
|
+
const seedStream = createRng(seed);
|
|
814
|
+
const artifacts = Array.from({ length: count }, (_unused, i) => {
|
|
815
|
+
const kind = mix[i % mix.length] ?? "Result";
|
|
816
|
+
const msgSeed = seedStream.nextUint32();
|
|
817
|
+
const rt = generateKind(kind, msgSeed);
|
|
818
|
+
return {
|
|
819
|
+
format: "astm",
|
|
820
|
+
kind,
|
|
821
|
+
content: rt.content,
|
|
822
|
+
warnings: rt.warnings
|
|
823
|
+
};
|
|
824
|
+
});
|
|
825
|
+
return makeCorpus(seed, artifacts);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
exports.ASTM_ABNORMAL_FLAGS = ASTM_ABNORMAL_FLAGS;
|
|
829
|
+
exports.ASTM_COMMENT_TEXT = ASTM_COMMENT_TEXT;
|
|
830
|
+
exports.ASTM_QUIRKS = ASTM_QUIRKS;
|
|
831
|
+
exports.ASTM_RESULT_STATUSES = ASTM_RESULT_STATUSES;
|
|
832
|
+
exports.EXAMPLE_ASTM_TESTS = EXAMPLE_ASTM_TESTS;
|
|
833
|
+
exports.astmCorpus = astmCorpus;
|
|
834
|
+
exports.astmFramedRoundTrip = astmFramedRoundTrip;
|
|
835
|
+
exports.astmHeaderIdentity = astmHeaderIdentity;
|
|
836
|
+
exports.astmOrder = astmOrder;
|
|
837
|
+
exports.astmPatient = astmPatient;
|
|
838
|
+
exports.astmQuirkCorpus = astmQuirkCorpus;
|
|
839
|
+
exports.astmQuirkProfile = astmQuirkProfile;
|
|
840
|
+
exports.astmQuirkRoundTrip = astmQuirkRoundTrip;
|
|
841
|
+
exports.astmRoundTrip = astmRoundTrip;
|
|
842
|
+
exports.generateAstmOrder = generateAstmOrder;
|
|
843
|
+
exports.generateAstmQuirk = generateAstmQuirk;
|
|
844
|
+
exports.generateAstmResult = generateAstmResult;
|
|
845
|
+
exports.generateAstmResultFramed = generateAstmResultFramed;
|
|
846
|
+
//# sourceMappingURL=index.cjs.map
|
|
847
|
+
//# sourceMappingURL=index.cjs.map
|