@cosyte/synth 0.1.5 → 0.1.7
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 +30 -0
- package/dist/astm/index.cjs +57 -19
- package/dist/astm/index.cjs.map +1 -1
- package/dist/astm/index.d.cts +7 -0
- package/dist/astm/index.d.ts +7 -0
- package/dist/astm/index.mjs +56 -19
- package/dist/astm/index.mjs.map +1 -1
- package/dist/ccda/index.cjs +76 -26
- package/dist/ccda/index.cjs.map +1 -1
- package/dist/ccda/index.d.cts +6 -0
- package/dist/ccda/index.d.ts +6 -0
- package/dist/ccda/index.mjs +63 -14
- package/dist/ccda/index.mjs.map +1 -1
- package/dist/deid/index.cjs +216 -125
- package/dist/deid/index.cjs.map +1 -1
- package/dist/deid/index.mjs +203 -113
- package/dist/deid/index.mjs.map +1 -1
- package/dist/fhir/index.cjs +146 -74
- package/dist/fhir/index.cjs.map +1 -1
- package/dist/fhir/index.d.cts +6 -0
- package/dist/fhir/index.d.ts +6 -0
- package/dist/fhir/index.mjs +145 -74
- package/dist/fhir/index.mjs.map +1 -1
- package/dist/hl7/index.cjs +53 -9
- package/dist/hl7/index.cjs.map +1 -1
- package/dist/hl7/index.d.cts +6 -0
- package/dist/hl7/index.d.ts +6 -0
- package/dist/hl7/index.mjs +52 -9
- package/dist/hl7/index.mjs.map +1 -1
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -3
- package/dist/index.mjs.map +1 -1
- package/dist/ncpdp/index.cjs +76 -23
- package/dist/ncpdp/index.cjs.map +1 -1
- package/dist/ncpdp/index.d.cts +7 -0
- package/dist/ncpdp/index.d.ts +7 -0
- package/dist/ncpdp/index.mjs +75 -23
- package/dist/ncpdp/index.mjs.map +1 -1
- package/dist/x12/index.cjs +72 -23
- package/dist/x12/index.cjs.map +1 -1
- package/dist/x12/index.d.cts +8 -1
- package/dist/x12/index.d.ts +8 -1
- package/dist/x12/index.mjs +71 -23
- package/dist/x12/index.mjs.map +1 -1
- package/package.json +20 -15
package/dist/deid/index.mjs
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { extractX12Loci, deidentifyX12 } from '@cosyte/deid/x12';
|
|
4
|
-
import { extractTelecomLoci, deidentifyTelecom } from '@cosyte/deid/ncpdp';
|
|
5
|
-
import { deidentifyCcda } from '@cosyte/deid/ccda';
|
|
6
|
-
import { serializeResource, complex, list, primitive, decimal } from '@cosyte/fhir';
|
|
7
|
-
import { serializeX12, parseX12, build835, build271, X12Decimal, build837D, build837I, build837P } from '@cosyte/x12';
|
|
8
|
-
import { serializeCcda, buildCcda, NCI_ROUTE, SNOMED_CT, CVX, RXNORM, LOINC } from '@cosyte/ccda';
|
|
9
|
-
import { parseTelecom, serializeTelecom, buildTelecomRequest } from '@cosyte/ncpdp/telecom';
|
|
10
|
-
import { buildMessage } from '@cosyte/hl7';
|
|
11
|
-
import { defineDeidPolicy, SAFE_HARBOR_CATEGORIES } from '@cosyte/deid';
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
12
3
|
|
|
13
|
-
|
|
4
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
5
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
6
|
+
}) : x)(function(x) {
|
|
7
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
8
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
|
+
});
|
|
14
10
|
|
|
15
11
|
// src/rng/splitmix32.ts
|
|
16
12
|
function splitmix32(seed) {
|
|
@@ -450,6 +446,40 @@ var safe = Object.freeze({
|
|
|
450
446
|
npi,
|
|
451
447
|
dea
|
|
452
448
|
});
|
|
449
|
+
function defaultHost() {
|
|
450
|
+
if (typeof import.meta.resolve !== "function") return { require: __require, resolve: void 0 };
|
|
451
|
+
return { require: createRequire(import.meta.url), resolve: (s) => import.meta.resolve(s) };
|
|
452
|
+
}
|
|
453
|
+
function isRequireEsmRefusal(error) {
|
|
454
|
+
return error?.code === "ERR_REQUIRE_ESM";
|
|
455
|
+
}
|
|
456
|
+
function loadPeer(specifier, host) {
|
|
457
|
+
if (host.resolve === void 0) return host.require(specifier);
|
|
458
|
+
const entry = fileURLToPath(host.resolve(specifier));
|
|
459
|
+
try {
|
|
460
|
+
return host.require(entry);
|
|
461
|
+
} catch (error) {
|
|
462
|
+
if (!isRequireEsmRefusal(error)) throw error;
|
|
463
|
+
return host.require(specifier);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function lazyPeer(specifier, host) {
|
|
467
|
+
let loaded;
|
|
468
|
+
return () => loaded ??= loadPeer(specifier, defaultHost());
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// src/peers.ts
|
|
472
|
+
var hl7Peer = lazyPeer("@cosyte/hl7");
|
|
473
|
+
var fhirPeer = lazyPeer("@cosyte/fhir");
|
|
474
|
+
var ccdaPeer = lazyPeer("@cosyte/ccda");
|
|
475
|
+
var x12Peer = lazyPeer("@cosyte/x12");
|
|
476
|
+
var ncpdpTelecomPeer = lazyPeer("@cosyte/ncpdp/telecom");
|
|
477
|
+
var deidPeer = lazyPeer("@cosyte/deid");
|
|
478
|
+
var deidHl7Peer = lazyPeer("@cosyte/deid/hl7");
|
|
479
|
+
var deidFhirPeer = lazyPeer("@cosyte/deid/fhir");
|
|
480
|
+
var deidX12Peer = lazyPeer("@cosyte/deid/x12");
|
|
481
|
+
var deidNcpdpPeer = lazyPeer("@cosyte/deid/ncpdp");
|
|
482
|
+
var deidCcdaPeer = lazyPeer("@cosyte/deid/ccda");
|
|
453
483
|
|
|
454
484
|
// src/hl7/common.ts
|
|
455
485
|
function seededTimestamp(rng) {
|
|
@@ -462,7 +492,7 @@ function seededTimestamp(rng) {
|
|
|
462
492
|
function mshScaffold(rng, type) {
|
|
463
493
|
const timestamp = seededTimestamp(rng);
|
|
464
494
|
const controlId = `SYNTH${rng.digits(10)}`;
|
|
465
|
-
const message = buildMessage({
|
|
495
|
+
const message = hl7Peer().buildMessage({
|
|
466
496
|
type,
|
|
467
497
|
sendingApp: "COSYTE-SYNTH",
|
|
468
498
|
sendingFacility: "SYNTH-FAC",
|
|
@@ -913,36 +943,36 @@ function prop(name2, value) {
|
|
|
913
943
|
return { name: name2, value };
|
|
914
944
|
}
|
|
915
945
|
function str(value) {
|
|
916
|
-
return primitive(value);
|
|
946
|
+
return fhirPeer().primitive(value);
|
|
917
947
|
}
|
|
918
948
|
function dec(raw) {
|
|
919
|
-
return primitive(decimal(raw));
|
|
949
|
+
return fhirPeer().primitive(fhirPeer().decimal(raw));
|
|
920
950
|
}
|
|
921
951
|
function bool(value) {
|
|
922
|
-
return primitive(value);
|
|
952
|
+
return fhirPeer().primitive(value);
|
|
923
953
|
}
|
|
924
954
|
function coding(concept) {
|
|
925
|
-
return complex([
|
|
955
|
+
return fhirPeer().complex([
|
|
926
956
|
prop("system", str(concept.system)),
|
|
927
957
|
prop("code", str(concept.code)),
|
|
928
958
|
prop("display", str(concept.display))
|
|
929
959
|
]);
|
|
930
960
|
}
|
|
931
961
|
function codeableConcept(concept) {
|
|
932
|
-
return complex([prop("coding", list([coding(concept)]))]);
|
|
962
|
+
return fhirPeer().complex([prop("coding", fhirPeer().list([coding(concept)]))]);
|
|
933
963
|
}
|
|
934
964
|
function reference(ref) {
|
|
935
|
-
return complex([prop("reference", str(ref))]);
|
|
965
|
+
return fhirPeer().complex([prop("reference", str(ref))]);
|
|
936
966
|
}
|
|
937
967
|
function narrative(text) {
|
|
938
968
|
const escaped = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
939
|
-
return complex([
|
|
969
|
+
return fhirPeer().complex([
|
|
940
970
|
prop("status", str("generated")),
|
|
941
971
|
prop("div", str(`<div xmlns="http://www.w3.org/1999/xhtml"><p>${escaped}</p></div>`))
|
|
942
972
|
]);
|
|
943
973
|
}
|
|
944
974
|
function meta(profiles) {
|
|
945
|
-
return complex([prop("profile", list(profiles.map((p) => str(p))))]);
|
|
975
|
+
return fhirPeer().complex([prop("profile", fhirPeer().list(profiles.map((p) => str(p))))]);
|
|
946
976
|
}
|
|
947
977
|
function toFhirDate(ymd) {
|
|
948
978
|
return `${ymd.slice(0, 4)}-${ymd.slice(4, 6)}-${ymd.slice(6, 8)}`;
|
|
@@ -959,13 +989,13 @@ function fhirPatientIdentity(rng) {
|
|
|
959
989
|
return { id, person, mrn, birthDate, gender, address: address2, phone: phone2, email: email2 };
|
|
960
990
|
}
|
|
961
991
|
function mrnIdentifier(mrn) {
|
|
962
|
-
return complex([
|
|
992
|
+
return fhirPeer().complex([
|
|
963
993
|
prop(
|
|
964
994
|
"type",
|
|
965
|
-
complex([
|
|
995
|
+
fhirPeer().complex([
|
|
966
996
|
prop(
|
|
967
997
|
"coding",
|
|
968
|
-
list([
|
|
998
|
+
fhirPeer().list([
|
|
969
999
|
coding({
|
|
970
1000
|
system: SYSTEM.IDENTIFIER_TYPE,
|
|
971
1001
|
code: "MR",
|
|
@@ -1250,13 +1280,16 @@ var EXAMPLE_ENCOUNTER_CLASSES = Object.freeze([
|
|
|
1250
1280
|
// src/fhir/patient.ts
|
|
1251
1281
|
var PATIENT_PROFILES = Object.freeze(["base", "us-core"]);
|
|
1252
1282
|
function ombExtension(url, category) {
|
|
1253
|
-
return complex([
|
|
1283
|
+
return fhirPeer().complex([
|
|
1254
1284
|
prop("url", str(url)),
|
|
1255
1285
|
prop(
|
|
1256
1286
|
"extension",
|
|
1257
|
-
list([
|
|
1258
|
-
complex([
|
|
1259
|
-
|
|
1287
|
+
fhirPeer().list([
|
|
1288
|
+
fhirPeer().complex([
|
|
1289
|
+
prop("url", str("ombCategory")),
|
|
1290
|
+
prop("valueCoding", coding(category))
|
|
1291
|
+
]),
|
|
1292
|
+
fhirPeer().complex([prop("url", str("text")), prop("valueString", str(category.display))])
|
|
1260
1293
|
])
|
|
1261
1294
|
)
|
|
1262
1295
|
]);
|
|
@@ -1287,24 +1320,27 @@ function generatePatient(options = {}) {
|
|
|
1287
1320
|
props.push(
|
|
1288
1321
|
prop(
|
|
1289
1322
|
"extension",
|
|
1290
|
-
list([
|
|
1323
|
+
fhirPeer().list([
|
|
1291
1324
|
ombExtension(US_CORE_RACE_EXTENSION, race),
|
|
1292
1325
|
ombExtension(US_CORE_ETHNICITY_EXTENSION, ethnicity),
|
|
1293
|
-
complex([
|
|
1326
|
+
fhirPeer().complex([
|
|
1327
|
+
prop("url", str(US_CORE_BIRTHSEX_EXTENSION)),
|
|
1328
|
+
prop("valueCode", str(birthsex))
|
|
1329
|
+
])
|
|
1294
1330
|
])
|
|
1295
1331
|
)
|
|
1296
1332
|
);
|
|
1297
1333
|
}
|
|
1298
|
-
props.push(prop("identifier", list([mrnIdentifier(id.mrn)])));
|
|
1334
|
+
props.push(prop("identifier", fhirPeer().list([mrnIdentifier(id.mrn)])));
|
|
1299
1335
|
props.push(prop("active", bool(true)));
|
|
1300
1336
|
props.push(
|
|
1301
1337
|
prop(
|
|
1302
1338
|
"name",
|
|
1303
|
-
list([
|
|
1304
|
-
complex([
|
|
1339
|
+
fhirPeer().list([
|
|
1340
|
+
fhirPeer().complex([
|
|
1305
1341
|
prop("use", str("official")),
|
|
1306
1342
|
prop("family", str(id.person.family)),
|
|
1307
|
-
prop("given", list([str(id.person.given)]))
|
|
1343
|
+
prop("given", fhirPeer().list([str(id.person.given)]))
|
|
1308
1344
|
])
|
|
1309
1345
|
])
|
|
1310
1346
|
)
|
|
@@ -1312,13 +1348,13 @@ function generatePatient(options = {}) {
|
|
|
1312
1348
|
props.push(
|
|
1313
1349
|
prop(
|
|
1314
1350
|
"telecom",
|
|
1315
|
-
list([
|
|
1316
|
-
complex([
|
|
1351
|
+
fhirPeer().list([
|
|
1352
|
+
fhirPeer().complex([
|
|
1317
1353
|
prop("system", str("phone")),
|
|
1318
1354
|
prop("value", str(id.phone)),
|
|
1319
1355
|
prop("use", str("home"))
|
|
1320
1356
|
]),
|
|
1321
|
-
complex([prop("system", str("email")), prop("value", str(id.email))])
|
|
1357
|
+
fhirPeer().complex([prop("system", str("email")), prop("value", str(id.email))])
|
|
1322
1358
|
])
|
|
1323
1359
|
)
|
|
1324
1360
|
);
|
|
@@ -1327,10 +1363,10 @@ function generatePatient(options = {}) {
|
|
|
1327
1363
|
props.push(
|
|
1328
1364
|
prop(
|
|
1329
1365
|
"address",
|
|
1330
|
-
list([
|
|
1331
|
-
complex([
|
|
1366
|
+
fhirPeer().list([
|
|
1367
|
+
fhirPeer().complex([
|
|
1332
1368
|
prop("use", str("home")),
|
|
1333
|
-
prop("line", list([str(id.address.street)])),
|
|
1369
|
+
prop("line", fhirPeer().list([str(id.address.street)])),
|
|
1334
1370
|
prop("city", str(id.address.city)),
|
|
1335
1371
|
prop("state", str(id.address.state)),
|
|
1336
1372
|
prop("postalCode", str(id.address.zip))
|
|
@@ -1338,8 +1374,10 @@ function generatePatient(options = {}) {
|
|
|
1338
1374
|
])
|
|
1339
1375
|
)
|
|
1340
1376
|
);
|
|
1341
|
-
return complex(props);
|
|
1377
|
+
return fhirPeer().complex(props);
|
|
1342
1378
|
}
|
|
1379
|
+
|
|
1380
|
+
// src/fhir/condition.ts
|
|
1343
1381
|
function generateCondition(options = {}) {
|
|
1344
1382
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
1345
1383
|
const rng = createRng(seed);
|
|
@@ -1369,7 +1407,7 @@ function generateCondition(options = {}) {
|
|
|
1369
1407
|
props.push(
|
|
1370
1408
|
prop(
|
|
1371
1409
|
"category",
|
|
1372
|
-
list([
|
|
1410
|
+
fhirPeer().list([
|
|
1373
1411
|
codeableConcept({
|
|
1374
1412
|
system: SYSTEM.CONDITION_CATEGORY,
|
|
1375
1413
|
code: "problem-list-item",
|
|
@@ -1380,15 +1418,17 @@ function generateCondition(options = {}) {
|
|
|
1380
1418
|
);
|
|
1381
1419
|
props.push(prop("code", codeableConcept(code)));
|
|
1382
1420
|
props.push(prop("subject", reference(subject)));
|
|
1383
|
-
return complex(props);
|
|
1421
|
+
return fhirPeer().complex(props);
|
|
1384
1422
|
}
|
|
1423
|
+
|
|
1424
|
+
// src/fhir/observation.ts
|
|
1385
1425
|
function drawValue(rng, concept) {
|
|
1386
1426
|
const span = concept.high - concept.low;
|
|
1387
1427
|
const raw = concept.low + rng.float() * span;
|
|
1388
1428
|
return raw.toFixed(concept.decimals);
|
|
1389
1429
|
}
|
|
1390
1430
|
function valueQuantity(rng, concept) {
|
|
1391
|
-
return complex([
|
|
1431
|
+
return fhirPeer().complex([
|
|
1392
1432
|
prop("value", dec(drawValue(rng, concept))),
|
|
1393
1433
|
prop("unit", str(concept.unit)),
|
|
1394
1434
|
prop("system", str(SYSTEM.UCUM)),
|
|
@@ -1410,7 +1450,7 @@ function buildObservation(seed, subject, usCore, profileUrl, category, pool, eff
|
|
|
1410
1450
|
props.push(
|
|
1411
1451
|
prop(
|
|
1412
1452
|
"category",
|
|
1413
|
-
list([
|
|
1453
|
+
fhirPeer().list([
|
|
1414
1454
|
codeableConcept({
|
|
1415
1455
|
system: SYSTEM.OBSERVATION_CATEGORY,
|
|
1416
1456
|
code: category.code,
|
|
@@ -1426,7 +1466,7 @@ function buildObservation(seed, subject, usCore, profileUrl, category, pool, eff
|
|
|
1426
1466
|
const d = String(rng.int(1, 28)).padStart(2, "0");
|
|
1427
1467
|
if (effective) props.push(prop("effectiveDateTime", str(`${String(y)}-${m}-${d}`)));
|
|
1428
1468
|
props.push(prop("valueQuantity", valueQuantity(rng, concept)));
|
|
1429
|
-
return complex(props);
|
|
1469
|
+
return fhirPeer().complex(props);
|
|
1430
1470
|
}
|
|
1431
1471
|
function generateObservationLab(options = {}) {
|
|
1432
1472
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
@@ -1452,6 +1492,8 @@ function generateVitalSign(options = {}) {
|
|
|
1452
1492
|
true
|
|
1453
1493
|
);
|
|
1454
1494
|
}
|
|
1495
|
+
|
|
1496
|
+
// src/fhir/medication-request.ts
|
|
1455
1497
|
function generateMedicationRequest(options = {}) {
|
|
1456
1498
|
const {
|
|
1457
1499
|
seed = 0,
|
|
@@ -1476,8 +1518,10 @@ function generateMedicationRequest(options = {}) {
|
|
|
1476
1518
|
props.push(prop("subject", reference(subject)));
|
|
1477
1519
|
props.push(prop("authoredOn", str(`${String(y)}-${m}-${d}`)));
|
|
1478
1520
|
props.push(prop("requester", reference(requester)));
|
|
1479
|
-
return complex(props);
|
|
1521
|
+
return fhirPeer().complex(props);
|
|
1480
1522
|
}
|
|
1523
|
+
|
|
1524
|
+
// src/fhir/encounter.ts
|
|
1481
1525
|
function generateEncounter(options = {}) {
|
|
1482
1526
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
1483
1527
|
const rng = createRng(seed);
|
|
@@ -1494,8 +1538,8 @@ function generateEncounter(options = {}) {
|
|
|
1494
1538
|
props.push(
|
|
1495
1539
|
prop(
|
|
1496
1540
|
"identifier",
|
|
1497
|
-
list([
|
|
1498
|
-
complex([
|
|
1541
|
+
fhirPeer().list([
|
|
1542
|
+
fhirPeer().complex([
|
|
1499
1543
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1500
1544
|
prop("value", str(id.value))
|
|
1501
1545
|
])
|
|
@@ -1504,11 +1548,13 @@ function generateEncounter(options = {}) {
|
|
|
1504
1548
|
);
|
|
1505
1549
|
props.push(prop("status", str("finished")));
|
|
1506
1550
|
props.push(prop("class", coding(cls)));
|
|
1507
|
-
props.push(prop("type", list([codeableConcept(type)])));
|
|
1551
|
+
props.push(prop("type", fhirPeer().list([codeableConcept(type)])));
|
|
1508
1552
|
props.push(prop("subject", reference(subject)));
|
|
1509
|
-
props.push(prop("period", complex([prop("start", str(`${start}T09:00:00Z`))])));
|
|
1510
|
-
return complex(props);
|
|
1553
|
+
props.push(prop("period", fhirPeer().complex([prop("start", str(`${start}T09:00:00Z`))])));
|
|
1554
|
+
return fhirPeer().complex(props);
|
|
1511
1555
|
}
|
|
1556
|
+
|
|
1557
|
+
// src/fhir/immunization.ts
|
|
1512
1558
|
function generateImmunization(options = {}) {
|
|
1513
1559
|
const { seed = 0, patient = "Patient/syn-patient-1", usCore = true } = options;
|
|
1514
1560
|
const rng = createRng(seed);
|
|
@@ -1525,8 +1571,10 @@ function generateImmunization(options = {}) {
|
|
|
1525
1571
|
props.push(prop("patient", reference(patient)));
|
|
1526
1572
|
props.push(prop("occurrenceDateTime", str(occurrence)));
|
|
1527
1573
|
props.push(prop("primarySource", bool(true)));
|
|
1528
|
-
return complex(props);
|
|
1574
|
+
return fhirPeer().complex(props);
|
|
1529
1575
|
}
|
|
1576
|
+
|
|
1577
|
+
// src/fhir/allergy-intolerance.ts
|
|
1530
1578
|
function generateAllergyIntolerance(options = {}) {
|
|
1531
1579
|
const { seed = 0, patient = "Patient/syn-patient-1", usCore = true } = options;
|
|
1532
1580
|
const rng = createRng(seed);
|
|
@@ -1559,11 +1607,17 @@ function generateAllergyIntolerance(options = {}) {
|
|
|
1559
1607
|
props.push(
|
|
1560
1608
|
prop(
|
|
1561
1609
|
"reaction",
|
|
1562
|
-
|
|
1610
|
+
fhirPeer().list([
|
|
1611
|
+
fhirPeer().complex([
|
|
1612
|
+
prop("manifestation", fhirPeer().list([codeableConcept(manifestation)]))
|
|
1613
|
+
])
|
|
1614
|
+
])
|
|
1563
1615
|
)
|
|
1564
1616
|
);
|
|
1565
|
-
return complex(props);
|
|
1617
|
+
return fhirPeer().complex(props);
|
|
1566
1618
|
}
|
|
1619
|
+
|
|
1620
|
+
// src/fhir/procedure.ts
|
|
1567
1621
|
function generateProcedure(options = {}) {
|
|
1568
1622
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
1569
1623
|
const rng = createRng(seed);
|
|
@@ -1579,8 +1633,10 @@ function generateProcedure(options = {}) {
|
|
|
1579
1633
|
props.push(prop("code", codeableConcept(code)));
|
|
1580
1634
|
props.push(prop("subject", reference(subject)));
|
|
1581
1635
|
props.push(prop("performedDateTime", str(`${performed}T10:00:00Z`)));
|
|
1582
|
-
return complex(props);
|
|
1636
|
+
return fhirPeer().complex(props);
|
|
1583
1637
|
}
|
|
1638
|
+
|
|
1639
|
+
// src/fhir/diagnostic-report.ts
|
|
1584
1640
|
function generateDiagnosticReport(options = {}) {
|
|
1585
1641
|
const { seed = 0, subject = "Patient/syn-patient-1", results = [], usCore = true } = options;
|
|
1586
1642
|
const rng = createRng(seed);
|
|
@@ -1596,7 +1652,7 @@ function generateDiagnosticReport(options = {}) {
|
|
|
1596
1652
|
props.push(
|
|
1597
1653
|
prop(
|
|
1598
1654
|
"category",
|
|
1599
|
-
list([
|
|
1655
|
+
fhirPeer().list([
|
|
1600
1656
|
codeableConcept({
|
|
1601
1657
|
system: SYSTEM.DIAGNOSTIC_SERVICE_SECTION,
|
|
1602
1658
|
code: "LAB",
|
|
@@ -1610,15 +1666,17 @@ function generateDiagnosticReport(options = {}) {
|
|
|
1610
1666
|
props.push(prop("effectiveDateTime", str(`${day}T08:30:00Z`)));
|
|
1611
1667
|
props.push(prop("issued", str(`${day}T09:00:00.000Z`)));
|
|
1612
1668
|
if (results.length > 0) {
|
|
1613
|
-
props.push(prop("result", list(results.map((r) => reference(r)))));
|
|
1669
|
+
props.push(prop("result", fhirPeer().list(results.map((r) => reference(r)))));
|
|
1614
1670
|
}
|
|
1615
|
-
return complex(props);
|
|
1671
|
+
return fhirPeer().complex(props);
|
|
1616
1672
|
}
|
|
1673
|
+
|
|
1674
|
+
// src/fhir/composition.ts
|
|
1617
1675
|
function section(sec) {
|
|
1618
|
-
return complex([
|
|
1676
|
+
return fhirPeer().complex([
|
|
1619
1677
|
prop("title", str(sec.title)),
|
|
1620
1678
|
prop("code", codeableConcept({ system: SYSTEM.LOINC, code: sec.code, display: sec.title })),
|
|
1621
|
-
prop("entry", list(sec.entries.map((e) => reference(e))))
|
|
1679
|
+
prop("entry", fhirPeer().list(sec.entries.map((e) => reference(e))))
|
|
1622
1680
|
]);
|
|
1623
1681
|
}
|
|
1624
1682
|
function buildComposition(rng, input) {
|
|
@@ -1637,12 +1695,12 @@ function buildComposition(rng, input) {
|
|
|
1637
1695
|
),
|
|
1638
1696
|
prop("subject", reference(input.subject)),
|
|
1639
1697
|
prop("date", str(`${input.date}T09:00:00Z`)),
|
|
1640
|
-
prop("author", list([reference(input.organization)])),
|
|
1698
|
+
prop("author", fhirPeer().list([reference(input.organization)])),
|
|
1641
1699
|
prop("title", str("Synthetic Continuity of Care Document")),
|
|
1642
1700
|
prop("custodian", reference(input.organization)),
|
|
1643
|
-
prop("section", list(input.sections.map((s) => section(s))))
|
|
1701
|
+
prop("section", fhirPeer().list(input.sections.map((s) => section(s))))
|
|
1644
1702
|
];
|
|
1645
|
-
return complex(props);
|
|
1703
|
+
return fhirPeer().complex(props);
|
|
1646
1704
|
}
|
|
1647
1705
|
|
|
1648
1706
|
// src/fhir/bundle.ts
|
|
@@ -1657,14 +1715,14 @@ function resourceTypeOf(resource) {
|
|
|
1657
1715
|
}
|
|
1658
1716
|
function buildOrganization(rng) {
|
|
1659
1717
|
const id = safe.identifier(rng, "AN");
|
|
1660
|
-
return complex([
|
|
1718
|
+
return fhirPeer().complex([
|
|
1661
1719
|
prop("resourceType", str("Organization")),
|
|
1662
1720
|
prop("id", str(`syn-org-${rng.digits(8)}`)),
|
|
1663
1721
|
prop("text", narrative("Synthetic health organization.")),
|
|
1664
1722
|
prop(
|
|
1665
1723
|
"identifier",
|
|
1666
|
-
list([
|
|
1667
|
-
complex([
|
|
1724
|
+
fhirPeer().list([
|
|
1725
|
+
fhirPeer().complex([
|
|
1668
1726
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1669
1727
|
prop("value", str(id.value))
|
|
1670
1728
|
])
|
|
@@ -1777,11 +1835,14 @@ function generateBundle(options = {}) {
|
|
|
1777
1835
|
entryProps.push(
|
|
1778
1836
|
prop(
|
|
1779
1837
|
"request",
|
|
1780
|
-
complex([
|
|
1838
|
+
fhirPeer().complex([
|
|
1839
|
+
prop("method", str("POST")),
|
|
1840
|
+
prop("url", str(resourceTypeOf(member.resource)))
|
|
1841
|
+
])
|
|
1781
1842
|
)
|
|
1782
1843
|
);
|
|
1783
1844
|
}
|
|
1784
|
-
return complex(entryProps);
|
|
1845
|
+
return fhirPeer().complex(entryProps);
|
|
1785
1846
|
});
|
|
1786
1847
|
const props = [
|
|
1787
1848
|
prop("resourceType", str("Bundle")),
|
|
@@ -1792,7 +1853,7 @@ function generateBundle(options = {}) {
|
|
|
1792
1853
|
props.push(
|
|
1793
1854
|
prop(
|
|
1794
1855
|
"identifier",
|
|
1795
|
-
complex([
|
|
1856
|
+
fhirPeer().complex([
|
|
1796
1857
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1797
1858
|
prop("value", str(`urn:uuid:${safe.uuid(rng)}`))
|
|
1798
1859
|
])
|
|
@@ -1801,11 +1862,13 @@ function generateBundle(options = {}) {
|
|
|
1801
1862
|
}
|
|
1802
1863
|
props.push(prop("type", str(type)));
|
|
1803
1864
|
if (type === "document") props.push(prop("timestamp", str(`${spine.date}T09:00:00.000Z`)));
|
|
1804
|
-
props.push(prop("entry", list(entries)));
|
|
1805
|
-
return complex(props);
|
|
1865
|
+
props.push(prop("entry", fhirPeer().list(entries)));
|
|
1866
|
+
return fhirPeer().complex(props);
|
|
1806
1867
|
}
|
|
1868
|
+
|
|
1869
|
+
// src/x12/money.ts
|
|
1807
1870
|
function dec2(value) {
|
|
1808
|
-
const d = X12Decimal.fromString(value);
|
|
1871
|
+
const d = x12Peer().X12Decimal.fromString(value);
|
|
1809
1872
|
if (d === void 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_DECIMAL);
|
|
1810
1873
|
return d;
|
|
1811
1874
|
}
|
|
@@ -1888,12 +1951,12 @@ var PROCEDURE_MODIFIERS = Object.freeze(["25", "59", "76", "GT"]);
|
|
|
1888
1951
|
var PLACES_OF_SERVICE = Object.freeze(["11", "22", "21", "12", "49"]);
|
|
1889
1952
|
var DIAGNOSES = Object.freeze(
|
|
1890
1953
|
[
|
|
1891
|
-
{ code: "
|
|
1892
|
-
{ code: "
|
|
1954
|
+
{ code: "J209", label: "acute bronchitis, unspecified" },
|
|
1955
|
+
{ code: "E119", label: "type 2 diabetes mellitus without complications" },
|
|
1893
1956
|
{ code: "I10", label: "essential (primary) hypertension" },
|
|
1894
|
-
{ code: "
|
|
1895
|
-
{ code: "
|
|
1896
|
-
{ code: "
|
|
1957
|
+
{ code: "M545", label: "low back pain" },
|
|
1958
|
+
{ code: "R079", label: "chest pain, unspecified" },
|
|
1959
|
+
{ code: "Z0000", label: "general adult medical exam without abnormal findings" }
|
|
1897
1960
|
].map((entry) => Object.freeze(entry))
|
|
1898
1961
|
);
|
|
1899
1962
|
var REVENUE_CODES = Object.freeze(
|
|
@@ -2110,11 +2173,11 @@ function generate837(variant, options) {
|
|
|
2110
2173
|
const spec = specOf(rng, resolved);
|
|
2111
2174
|
switch (resolved) {
|
|
2112
2175
|
case "P":
|
|
2113
|
-
return build837P(spec);
|
|
2176
|
+
return x12Peer().build837P(spec);
|
|
2114
2177
|
case "I":
|
|
2115
|
-
return build837I(spec);
|
|
2178
|
+
return x12Peer().build837I(spec);
|
|
2116
2179
|
case "D":
|
|
2117
|
-
return build837D(spec);
|
|
2180
|
+
return x12Peer().build837D(spec);
|
|
2118
2181
|
}
|
|
2119
2182
|
}
|
|
2120
2183
|
function generate837P(options) {
|
|
@@ -2126,6 +2189,8 @@ function generate837I(options) {
|
|
|
2126
2189
|
function generate837D(options) {
|
|
2127
2190
|
return generate837("D", options);
|
|
2128
2191
|
}
|
|
2192
|
+
|
|
2193
|
+
// src/x12/remit-835.ts
|
|
2129
2194
|
function generate835(options) {
|
|
2130
2195
|
const rng = createRng(options.seed);
|
|
2131
2196
|
const partners = x12TradingPartners(rng);
|
|
@@ -2226,8 +2291,10 @@ function generate835(options) {
|
|
|
2226
2291
|
},
|
|
2227
2292
|
claims: [claim]
|
|
2228
2293
|
};
|
|
2229
|
-
return build835(spec);
|
|
2294
|
+
return x12Peer().build835(spec);
|
|
2230
2295
|
}
|
|
2296
|
+
|
|
2297
|
+
// src/x12/eligibility-271.ts
|
|
2231
2298
|
function generate271(options) {
|
|
2232
2299
|
const rng = createRng(options.seed);
|
|
2233
2300
|
const partners = x12TradingPartners(rng);
|
|
@@ -2297,7 +2364,8 @@ function generate271(options) {
|
|
|
2297
2364
|
serviceTypeCodes: serviceTypes,
|
|
2298
2365
|
inPlanNetwork: "Y",
|
|
2299
2366
|
monetaryAmount: dec2(money(rng.int(500, 5e3))),
|
|
2300
|
-
percent: dec2(
|
|
2367
|
+
percent: dec2(rng.pick([".8", ".9", "1"]))
|
|
2368
|
+
// EB-08 is a decimal fraction
|
|
2301
2369
|
}
|
|
2302
2370
|
]
|
|
2303
2371
|
}
|
|
@@ -2307,7 +2375,7 @@ function generate271(options) {
|
|
|
2307
2375
|
}
|
|
2308
2376
|
]
|
|
2309
2377
|
};
|
|
2310
|
-
return build271(spec);
|
|
2378
|
+
return x12Peer().build271(spec);
|
|
2311
2379
|
}
|
|
2312
2380
|
|
|
2313
2381
|
// src/ncpdp/identity.ts
|
|
@@ -2363,6 +2431,8 @@ var EXAMPLE_DRUGS = Object.freeze(
|
|
|
2363
2431
|
].map((entry) => Object.freeze(entry))
|
|
2364
2432
|
);
|
|
2365
2433
|
var DAW_CODES = Object.freeze(["0", "1", "2"]);
|
|
2434
|
+
|
|
2435
|
+
// src/ncpdp/telecom.ts
|
|
2366
2436
|
var SYNTHETIC_BIN = "999999";
|
|
2367
2437
|
function digitsOnly(value) {
|
|
2368
2438
|
return value.replace(/\D/g, "");
|
|
@@ -2446,7 +2516,8 @@ function claimSegment(rng, minimal) {
|
|
|
2446
2516
|
field("E1", "03"),
|
|
2447
2517
|
// 03 = NDC
|
|
2448
2518
|
field("D7", drug.ndc),
|
|
2449
|
-
field("E7", String(rng.int(30, 90))),
|
|
2519
|
+
field("E7", String(rng.int(30, 90) * 1e3)),
|
|
2520
|
+
// 442-E7 carries three implied decimals
|
|
2450
2521
|
field("D5", String(rng.pick([30, 60, 90]))),
|
|
2451
2522
|
field("D8", rng.pick(DAW_CODES))
|
|
2452
2523
|
]
|
|
@@ -2462,7 +2533,9 @@ function generateTelecom(code, options) {
|
|
|
2462
2533
|
prescriberSegment(rng),
|
|
2463
2534
|
claimSegment(rng, false)
|
|
2464
2535
|
];
|
|
2465
|
-
return serializeTelecom(
|
|
2536
|
+
return ncpdpTelecomPeer().serializeTelecom(
|
|
2537
|
+
ncpdpTelecomPeer().buildTelecomRequest({ header: head, segments })
|
|
2538
|
+
);
|
|
2466
2539
|
}
|
|
2467
2540
|
function generateB1(options) {
|
|
2468
2541
|
return generateTelecom("B1", options);
|
|
@@ -2473,6 +2546,18 @@ function generateB2(options) {
|
|
|
2473
2546
|
function generateB3(options) {
|
|
2474
2547
|
return generateTelecom("B3", options);
|
|
2475
2548
|
}
|
|
2549
|
+
|
|
2550
|
+
// src/ccda/example-codes.ts
|
|
2551
|
+
var LOINC_OID = "2.16.840.1.113883.6.1";
|
|
2552
|
+
var SNOMED_CT_OID = "2.16.840.1.113883.6.96";
|
|
2553
|
+
var RXNORM_OID = "2.16.840.1.113883.6.88";
|
|
2554
|
+
var CVX_OID = "2.16.840.1.113883.12.292";
|
|
2555
|
+
var NCI_ROUTE_OID = "2.16.840.1.113883.3.26.1.1";
|
|
2556
|
+
var LOINC = LOINC_OID;
|
|
2557
|
+
var SNOMED_CT = SNOMED_CT_OID;
|
|
2558
|
+
var RXNORM = RXNORM_OID;
|
|
2559
|
+
var CVX = CVX_OID;
|
|
2560
|
+
var NCI_ROUTE = NCI_ROUTE_OID;
|
|
2476
2561
|
var URI_TO_OID = Object.freeze({
|
|
2477
2562
|
"http://loinc.org": LOINC,
|
|
2478
2563
|
"http://snomed.info/sct": SNOMED_CT,
|
|
@@ -2626,16 +2711,18 @@ function generateCcda(options = {}) {
|
|
|
2626
2711
|
const { seed = 0 } = options;
|
|
2627
2712
|
const documentType = resolveKind(CCDA_DOCUMENT_TYPES, options.documentType ?? "ccd");
|
|
2628
2713
|
const rng = createRng(seed);
|
|
2629
|
-
return buildCcda(buildInit(rng, documentType));
|
|
2714
|
+
return ccdaPeer().buildCcda(buildInit(rng, documentType));
|
|
2630
2715
|
}
|
|
2716
|
+
|
|
2717
|
+
// src/deid/loop.ts
|
|
2631
2718
|
var DEID_LOOP_POLICY_NAME = "synth-deid-loop-removal";
|
|
2632
2719
|
function deidLoopPolicy() {
|
|
2633
|
-
return defineDeidPolicy({
|
|
2720
|
+
return deidPeer().defineDeidPolicy({
|
|
2634
2721
|
name: DEID_LOOP_POLICY_NAME,
|
|
2635
2722
|
transforms: {
|
|
2636
|
-
[SAFE_HARBOR_CATEGORIES.MRN]: "redact",
|
|
2637
|
-
[SAFE_HARBOR_CATEGORIES.HEALTH_PLAN_BENEFICIARY]: "redact",
|
|
2638
|
-
[SAFE_HARBOR_CATEGORIES.ACCOUNT]: "redact"
|
|
2723
|
+
[deidPeer().SAFE_HARBOR_CATEGORIES.MRN]: "redact",
|
|
2724
|
+
[deidPeer().SAFE_HARBOR_CATEGORIES.HEALTH_PLAN_BENEFICIARY]: "redact",
|
|
2725
|
+
[deidPeer().SAFE_HARBOR_CATEGORIES.ACCOUNT]: "redact"
|
|
2639
2726
|
}
|
|
2640
2727
|
});
|
|
2641
2728
|
}
|
|
@@ -2772,7 +2859,8 @@ var DEID_LOOP_SKIPPED = Object.freeze([
|
|
|
2772
2859
|
reason: "@cosyte/synth does not generate DICOM, so there is nothing to pair."
|
|
2773
2860
|
})
|
|
2774
2861
|
]);
|
|
2775
|
-
var
|
|
2862
|
+
var policy;
|
|
2863
|
+
var loopPolicy = () => policy ??= deidLoopPolicy();
|
|
2776
2864
|
function residue(loci) {
|
|
2777
2865
|
return loci.map((l) => l.value).join("\n");
|
|
2778
2866
|
}
|
|
@@ -2797,8 +2885,8 @@ function hl7DeidLoop(options = {}) {
|
|
|
2797
2885
|
const kind = options.kind ?? "ORU^R01";
|
|
2798
2886
|
const message = generateHl7(kind, seed);
|
|
2799
2887
|
const original = message.toString();
|
|
2800
|
-
const planted = identifierSentinels(extractHl7Loci(message).loci, original);
|
|
2801
|
-
const deidDoc = deidentifyHl7(message, { policy:
|
|
2888
|
+
const planted = identifierSentinels(deidHl7Peer().extractHl7Loci(message).loci, original);
|
|
2889
|
+
const deidDoc = deidHl7Peer().deidentifyHl7(message, { policy: loopPolicy() }).document;
|
|
2802
2890
|
const deidentified = deidDoc.toString();
|
|
2803
2891
|
return assembleVerdict({
|
|
2804
2892
|
format: "hl7",
|
|
@@ -2807,17 +2895,17 @@ function hl7DeidLoop(options = {}) {
|
|
|
2807
2895
|
planted,
|
|
2808
2896
|
original,
|
|
2809
2897
|
deidentified,
|
|
2810
|
-
phiResidue: residue(extractHl7Loci(deidDoc).loci),
|
|
2898
|
+
phiResidue: residue(deidHl7Peer().extractHl7Loci(deidDoc).loci),
|
|
2811
2899
|
clinicalCodes: HL7_CLINICAL
|
|
2812
2900
|
});
|
|
2813
2901
|
}
|
|
2814
2902
|
function fhirDeidLoop(options = {}) {
|
|
2815
2903
|
const seed = options.seed ?? 0;
|
|
2816
2904
|
const bundle = generateBundle({ seed });
|
|
2817
|
-
const original = serializeResource(bundle);
|
|
2818
|
-
const planted = identifierSentinels(extractFhirLoci(bundle).loci, original);
|
|
2819
|
-
const deidDoc = deidentifyFhir(bundle, { policy:
|
|
2820
|
-
const deidentified = serializeResource(deidDoc);
|
|
2905
|
+
const original = fhirPeer().serializeResource(bundle);
|
|
2906
|
+
const planted = identifierSentinels(deidFhirPeer().extractFhirLoci(bundle).loci, original);
|
|
2907
|
+
const deidDoc = deidFhirPeer().deidentifyFhir(bundle, { policy: loopPolicy() }).document;
|
|
2908
|
+
const deidentified = fhirPeer().serializeResource(deidDoc);
|
|
2821
2909
|
return assembleVerdict({
|
|
2822
2910
|
format: "fhir",
|
|
2823
2911
|
artifact: "Bundle",
|
|
@@ -2825,7 +2913,7 @@ function fhirDeidLoop(options = {}) {
|
|
|
2825
2913
|
planted,
|
|
2826
2914
|
original,
|
|
2827
2915
|
deidentified,
|
|
2828
|
-
phiResidue: residue(extractFhirLoci(deidDoc).loci),
|
|
2916
|
+
phiResidue: residue(deidFhirPeer().extractFhirLoci(deidDoc).loci),
|
|
2829
2917
|
clinicalCodes: FHIR_CLINICAL
|
|
2830
2918
|
});
|
|
2831
2919
|
}
|
|
@@ -2847,9 +2935,9 @@ function x12DeidLoop(options = {}) {
|
|
|
2847
2935
|
const seed = options.seed ?? 0;
|
|
2848
2936
|
const variant = options.variant ?? "837P";
|
|
2849
2937
|
const interchange = generateX12(variant, seed);
|
|
2850
|
-
const original = serializeX12(interchange);
|
|
2851
|
-
const planted = identifierSentinels(extractX12Loci(interchange).loci, original);
|
|
2852
|
-
const deidentified = deidentifyX12(interchange, { policy:
|
|
2938
|
+
const original = x12Peer().serializeX12(interchange);
|
|
2939
|
+
const planted = identifierSentinels(deidX12Peer().extractX12Loci(interchange).loci, original);
|
|
2940
|
+
const deidentified = deidX12Peer().deidentifyX12(interchange, { policy: loopPolicy() }).x12;
|
|
2853
2941
|
return assembleVerdict({
|
|
2854
2942
|
format: "x12",
|
|
2855
2943
|
artifact: variant,
|
|
@@ -2857,7 +2945,7 @@ function x12DeidLoop(options = {}) {
|
|
|
2857
2945
|
planted,
|
|
2858
2946
|
original,
|
|
2859
2947
|
deidentified,
|
|
2860
|
-
phiResidue: residue(extractX12Loci(parseX12(deidentified)).loci),
|
|
2948
|
+
phiResidue: residue(deidX12Peer().extractX12Loci(x12Peer().parseX12(deidentified)).loci),
|
|
2861
2949
|
clinicalCodes: X12_CLINICAL
|
|
2862
2950
|
});
|
|
2863
2951
|
}
|
|
@@ -2875,9 +2963,9 @@ function ncpdpTelecomDeidLoop(options = {}) {
|
|
|
2875
2963
|
const seed = options.seed ?? 0;
|
|
2876
2964
|
const transaction = options.transaction ?? "B1";
|
|
2877
2965
|
const original = generateTelecomWire(transaction, seed);
|
|
2878
|
-
const tx = parseTelecom(original);
|
|
2879
|
-
const planted = identifierSentinels(extractTelecomLoci(tx).loci, original);
|
|
2880
|
-
const deidentified = deidentifyTelecom(tx, { policy:
|
|
2966
|
+
const tx = ncpdpTelecomPeer().parseTelecom(original);
|
|
2967
|
+
const planted = identifierSentinels(deidNcpdpPeer().extractTelecomLoci(tx).loci, original);
|
|
2968
|
+
const deidentified = deidNcpdpPeer().deidentifyTelecom(tx, { policy: loopPolicy() }).telecom;
|
|
2881
2969
|
return assembleVerdict({
|
|
2882
2970
|
format: "ncpdp-telecom",
|
|
2883
2971
|
artifact: transaction,
|
|
@@ -2885,7 +2973,9 @@ function ncpdpTelecomDeidLoop(options = {}) {
|
|
|
2885
2973
|
planted,
|
|
2886
2974
|
original,
|
|
2887
2975
|
deidentified,
|
|
2888
|
-
phiResidue: residue(
|
|
2976
|
+
phiResidue: residue(
|
|
2977
|
+
deidNcpdpPeer().extractTelecomLoci(ncpdpTelecomPeer().parseTelecom(deidentified)).loci
|
|
2978
|
+
),
|
|
2889
2979
|
clinicalCodes: NCPDP_CLINICAL
|
|
2890
2980
|
});
|
|
2891
2981
|
}
|
|
@@ -2893,9 +2983,9 @@ function ccdaDeidLoop(options = {}) {
|
|
|
2893
2983
|
const seed = options.seed ?? 0;
|
|
2894
2984
|
const documentType = options.documentType ?? "ccd";
|
|
2895
2985
|
const doc = generateCcda({ seed, documentType: documentType === "ccd" ? "ccd" : "referralNote" });
|
|
2896
|
-
const original = serializeCcda(doc);
|
|
2986
|
+
const original = ccdaPeer().serializeCcda(doc);
|
|
2897
2987
|
const planted = recordTargetSentinels(original);
|
|
2898
|
-
const deidentified = deidentifyCcda(doc, { policy:
|
|
2988
|
+
const deidentified = deidCcdaPeer().deidentifyCcda(doc, { policy: loopPolicy() }).document.toString();
|
|
2899
2989
|
return assembleVerdict({
|
|
2900
2990
|
format: "ccda",
|
|
2901
2991
|
artifact: documentType === "ccd" ? "CCD" : "ReferralNote",
|
|
@@ -2910,9 +3000,9 @@ function ccdaDeidLoop(options = {}) {
|
|
|
2910
3000
|
function summarizeDeidCoverage(results) {
|
|
2911
3001
|
const byFormatMap = /* @__PURE__ */ new Map();
|
|
2912
3002
|
for (const r of results) {
|
|
2913
|
-
const
|
|
2914
|
-
|
|
2915
|
-
byFormatMap.set(r.format,
|
|
3003
|
+
const list = byFormatMap.get(r.format) ?? [];
|
|
3004
|
+
list.push(r);
|
|
3005
|
+
byFormatMap.set(r.format, list);
|
|
2916
3006
|
}
|
|
2917
3007
|
const byFormat = [];
|
|
2918
3008
|
for (const [format, runs] of byFormatMap) {
|