@cosyte/synth 0.1.4 → 0.1.6
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 +24 -0
- package/README.md +14 -10
- package/dist/astm/index.cjs +164 -102
- 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 +163 -102
- package/dist/astm/index.mjs.map +1 -1
- package/dist/ccda/index.cjs +100 -28
- 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 +87 -16
- package/dist/ccda/index.mjs.map +1 -1
- package/dist/deid/index.cjs +305 -165
- package/dist/deid/index.cjs.map +1 -1
- package/dist/deid/index.mjs +292 -153
- package/dist/deid/index.mjs.map +1 -1
- package/dist/fhir/index.cjs +179 -76
- 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 +178 -76
- package/dist/fhir/index.mjs.map +1 -1
- package/dist/hl7/index.cjs +86 -12
- 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 +85 -12
- package/dist/hl7/index.mjs.map +1 -1
- package/dist/index.cjs +3 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.mjs +3 -5
- package/dist/index.mjs.map +1 -1
- package/dist/ncpdp/index.cjs +131 -36
- 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 +130 -36
- package/dist/ncpdp/index.mjs.map +1 -1
- package/dist/x12/index.cjs +147 -50
- package/dist/x12/index.cjs.map +1 -1
- package/dist/x12/index.d.cts +6 -0
- package/dist/x12/index.d.ts +6 -0
- package/dist/x12/index.mjs +146 -50
- package/dist/x12/index.mjs.map +1 -1
- package/package.json +20 -15
package/dist/fhir/index.cjs
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var module$1 = require('module');
|
|
4
|
+
var url = require('url');
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
6
13
|
|
|
7
14
|
// src/rng/splitmix32.ts
|
|
8
15
|
function splitmix32(seed) {
|
|
@@ -34,11 +41,42 @@ function sfc32Next(s) {
|
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
// src/codes.ts
|
|
37
|
-
var SYNTH_FATAL_CODES = {
|
|
44
|
+
var SYNTH_FATAL_CODES = Object.freeze({
|
|
45
|
+
/**
|
|
46
|
+
* A format was requested that this build cannot generate through a real parser builder/serializer.
|
|
47
|
+
* Fatal, never a hand-written byte fallback.
|
|
48
|
+
*
|
|
49
|
+
* **No code path in this build raises it.** All six formats generate, so it is reserved for a
|
|
50
|
+
* future format that does not, and is kept because removing a published code is a breaking change.
|
|
51
|
+
* An unsupported *kind* within a format that does generate is `SYNTH_UNSUPPORTED_KIND`.
|
|
52
|
+
*/
|
|
53
|
+
SYNTH_UNSUPPORTED_FORMAT: "SYNTH_UNSUPPORTED_FORMAT",
|
|
54
|
+
/**
|
|
55
|
+
* A vendor quirk was requested that the target format's profile system does not support. Fatal,
|
|
56
|
+
* never a silent no-op and never a fabricated quirk.
|
|
57
|
+
*/
|
|
58
|
+
SYNTH_UNSUPPORTED_QUIRK: "SYNTH_UNSUPPORTED_QUIRK",
|
|
59
|
+
/**
|
|
60
|
+
* A quirk transform found no structural anchor to mutate, so the fixture would not carry the
|
|
61
|
+
* deviation it is labelled with. Fatal: a golden file that lies about its parser verdict is worse
|
|
62
|
+
* than no golden file.
|
|
63
|
+
*/
|
|
64
|
+
SYNTH_QUIRK_ANCHOR_ABSENT: "SYNTH_QUIRK_ANCHOR_ABSENT",
|
|
65
|
+
/**
|
|
66
|
+
* A bare parse of a freshly-generated quirk artifact did not produce exactly the declared intended
|
|
67
|
+
* warning code(s). Fatal, never emit a mislabeled fixture.
|
|
68
|
+
*/
|
|
69
|
+
SYNTH_INTENDED_WARNING_MISMATCH: "SYNTH_INTENDED_WARNING_MISMATCH",
|
|
70
|
+
/** A concept's code-system URI has no OID mapping in the C-CDA example-code table. Fatal. */
|
|
71
|
+
SYNTH_UNMAPPED_CODE_SYSTEM: "SYNTH_UNMAPPED_CODE_SYSTEM",
|
|
72
|
+
/** A money value could not be read as an X12 decimal. Fatal: a generator never rounds to a float. */
|
|
73
|
+
SYNTH_INVALID_DECIMAL: "SYNTH_INVALID_DECIMAL",
|
|
38
74
|
/** An integer range was requested with its maximum below its minimum. Fatal. */
|
|
39
75
|
SYNTH_INVALID_RANGE: "SYNTH_INVALID_RANGE",
|
|
40
76
|
/** A value was drawn from an empty pool. Fatal, never a fabricated substitute. */
|
|
41
77
|
SYNTH_EMPTY_POOL: "SYNTH_EMPTY_POOL",
|
|
78
|
+
/** A `defineSynthProfile` spec was not usable (a missing or blank `name`). Fatal. */
|
|
79
|
+
SYNTH_INVALID_PROFILE: "SYNTH_INVALID_PROFILE",
|
|
42
80
|
/**
|
|
43
81
|
* A caller-supplied selector (a message kind, a document type, a corpus mix entry, a claim
|
|
44
82
|
* variant, a Bundle type, a resource profile) is not in the closed set that governs it. Fatal:
|
|
@@ -55,7 +93,7 @@ var SYNTH_FATAL_CODES = {
|
|
|
55
93
|
* mislabelled artifact is worse than no artifact.
|
|
56
94
|
*/
|
|
57
95
|
SYNTH_PROFILE_NOT_GENERATED: "SYNTH_PROFILE_NOT_GENERATED"
|
|
58
|
-
};
|
|
96
|
+
});
|
|
59
97
|
var SYNTH_FATAL_MESSAGES = Object.freeze({
|
|
60
98
|
SYNTH_UNSUPPORTED_FORMAT: "The requested format is not generable by this build. A generator has no byte fallback: it builds through a parser's own serializer or it refuses.",
|
|
61
99
|
SYNTH_UNSUPPORTED_QUIRK: "The requested vendor quirk is not in the target format's quirk registry. Compare the request against that format's exported registry (HL7_QUIRKS, CCDA_QUIRKS, ASTM_QUIRKS).",
|
|
@@ -522,42 +560,64 @@ var SYSTEM = Object.freeze({
|
|
|
522
560
|
/** US Core `us-core-provenance-participant-type`, `Provenance.agent.type` (`transmitter`). */
|
|
523
561
|
US_CORE_PROVENANCE_PARTICIPANT_TYPE: "http://hl7.org/fhir/us/core/CodeSystem/us-core-provenance-participant-type"
|
|
524
562
|
});
|
|
563
|
+
function defaultHost() {
|
|
564
|
+
if (typeof undefined !== "function") return { require: __require, resolve: void 0 };
|
|
565
|
+
return { require: module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))), resolve: (s) => undefined(s) };
|
|
566
|
+
}
|
|
567
|
+
function isRequireEsmRefusal(error) {
|
|
568
|
+
return error?.code === "ERR_REQUIRE_ESM";
|
|
569
|
+
}
|
|
570
|
+
function loadPeer(specifier, host) {
|
|
571
|
+
if (host.resolve === void 0) return host.require(specifier);
|
|
572
|
+
const entry = url.fileURLToPath(host.resolve(specifier));
|
|
573
|
+
try {
|
|
574
|
+
return host.require(entry);
|
|
575
|
+
} catch (error) {
|
|
576
|
+
if (!isRequireEsmRefusal(error)) throw error;
|
|
577
|
+
return host.require(specifier);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
function lazyPeer(specifier, host) {
|
|
581
|
+
let loaded;
|
|
582
|
+
return () => loaded ??= loadPeer(specifier, defaultHost());
|
|
583
|
+
}
|
|
584
|
+
var fhirPeer = lazyPeer("@cosyte/fhir");
|
|
525
585
|
|
|
526
586
|
// src/fhir/builder.ts
|
|
527
587
|
function prop(name2, value) {
|
|
528
588
|
return { name: name2, value };
|
|
529
589
|
}
|
|
530
590
|
function str(value) {
|
|
531
|
-
return
|
|
591
|
+
return fhirPeer().primitive(value);
|
|
532
592
|
}
|
|
533
593
|
function dec(raw) {
|
|
534
|
-
return
|
|
594
|
+
return fhirPeer().primitive(fhirPeer().decimal(raw));
|
|
535
595
|
}
|
|
536
596
|
function bool(value) {
|
|
537
|
-
return
|
|
597
|
+
return fhirPeer().primitive(value);
|
|
538
598
|
}
|
|
539
599
|
function coding(concept) {
|
|
540
|
-
return
|
|
600
|
+
return fhirPeer().complex([
|
|
541
601
|
prop("system", str(concept.system)),
|
|
542
602
|
prop("code", str(concept.code)),
|
|
543
603
|
prop("display", str(concept.display))
|
|
544
604
|
]);
|
|
545
605
|
}
|
|
546
606
|
function codeableConcept(concept) {
|
|
547
|
-
return
|
|
607
|
+
return fhirPeer().complex([prop("coding", fhirPeer().list([coding(concept)]))]);
|
|
548
608
|
}
|
|
549
609
|
function reference(ref) {
|
|
550
|
-
return
|
|
610
|
+
return fhirPeer().complex([prop("reference", str(ref))]);
|
|
551
611
|
}
|
|
552
612
|
function narrative(text) {
|
|
553
613
|
const escaped = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
554
|
-
return
|
|
614
|
+
return fhirPeer().complex([
|
|
555
615
|
prop("status", str("generated")),
|
|
556
616
|
prop("div", str(`<div xmlns="http://www.w3.org/1999/xhtml"><p>${escaped}</p></div>`))
|
|
557
617
|
]);
|
|
558
618
|
}
|
|
559
619
|
function meta(profiles) {
|
|
560
|
-
return
|
|
620
|
+
return fhirPeer().complex([prop("profile", fhirPeer().list(profiles.map((p) => str(p))))]);
|
|
561
621
|
}
|
|
562
622
|
function toFhirDate(ymd) {
|
|
563
623
|
return `${ymd.slice(0, 4)}-${ymd.slice(4, 6)}-${ymd.slice(6, 8)}`;
|
|
@@ -574,13 +634,13 @@ function fhirPatientIdentity(rng) {
|
|
|
574
634
|
return { id, person, mrn, birthDate, gender, address: address2, phone: phone2, email: email2 };
|
|
575
635
|
}
|
|
576
636
|
function mrnIdentifier(mrn) {
|
|
577
|
-
return
|
|
637
|
+
return fhirPeer().complex([
|
|
578
638
|
prop(
|
|
579
639
|
"type",
|
|
580
|
-
|
|
640
|
+
fhirPeer().complex([
|
|
581
641
|
prop(
|
|
582
642
|
"coding",
|
|
583
|
-
|
|
643
|
+
fhirPeer().list([
|
|
584
644
|
coding({
|
|
585
645
|
system: SYSTEM.IDENTIFIER_TYPE,
|
|
586
646
|
code: "MR",
|
|
@@ -876,13 +936,16 @@ function resolveMix(allowed, requested, fallback) {
|
|
|
876
936
|
// src/fhir/patient.ts
|
|
877
937
|
var PATIENT_PROFILES = Object.freeze(["base", "us-core"]);
|
|
878
938
|
function ombExtension(url, category) {
|
|
879
|
-
return
|
|
939
|
+
return fhirPeer().complex([
|
|
880
940
|
prop("url", str(url)),
|
|
881
941
|
prop(
|
|
882
942
|
"extension",
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
943
|
+
fhirPeer().list([
|
|
944
|
+
fhirPeer().complex([
|
|
945
|
+
prop("url", str("ombCategory")),
|
|
946
|
+
prop("valueCoding", coding(category))
|
|
947
|
+
]),
|
|
948
|
+
fhirPeer().complex([prop("url", str("text")), prop("valueString", str(category.display))])
|
|
886
949
|
])
|
|
887
950
|
)
|
|
888
951
|
]);
|
|
@@ -913,24 +976,27 @@ function generatePatient(options = {}) {
|
|
|
913
976
|
props.push(
|
|
914
977
|
prop(
|
|
915
978
|
"extension",
|
|
916
|
-
|
|
979
|
+
fhirPeer().list([
|
|
917
980
|
ombExtension(US_CORE_RACE_EXTENSION, race),
|
|
918
981
|
ombExtension(US_CORE_ETHNICITY_EXTENSION, ethnicity),
|
|
919
|
-
|
|
982
|
+
fhirPeer().complex([
|
|
983
|
+
prop("url", str(US_CORE_BIRTHSEX_EXTENSION)),
|
|
984
|
+
prop("valueCode", str(birthsex))
|
|
985
|
+
])
|
|
920
986
|
])
|
|
921
987
|
)
|
|
922
988
|
);
|
|
923
989
|
}
|
|
924
|
-
props.push(prop("identifier",
|
|
990
|
+
props.push(prop("identifier", fhirPeer().list([mrnIdentifier(id.mrn)])));
|
|
925
991
|
props.push(prop("active", bool(true)));
|
|
926
992
|
props.push(
|
|
927
993
|
prop(
|
|
928
994
|
"name",
|
|
929
|
-
|
|
930
|
-
|
|
995
|
+
fhirPeer().list([
|
|
996
|
+
fhirPeer().complex([
|
|
931
997
|
prop("use", str("official")),
|
|
932
998
|
prop("family", str(id.person.family)),
|
|
933
|
-
prop("given",
|
|
999
|
+
prop("given", fhirPeer().list([str(id.person.given)]))
|
|
934
1000
|
])
|
|
935
1001
|
])
|
|
936
1002
|
)
|
|
@@ -938,13 +1004,13 @@ function generatePatient(options = {}) {
|
|
|
938
1004
|
props.push(
|
|
939
1005
|
prop(
|
|
940
1006
|
"telecom",
|
|
941
|
-
|
|
942
|
-
|
|
1007
|
+
fhirPeer().list([
|
|
1008
|
+
fhirPeer().complex([
|
|
943
1009
|
prop("system", str("phone")),
|
|
944
1010
|
prop("value", str(id.phone)),
|
|
945
1011
|
prop("use", str("home"))
|
|
946
1012
|
]),
|
|
947
|
-
|
|
1013
|
+
fhirPeer().complex([prop("system", str("email")), prop("value", str(id.email))])
|
|
948
1014
|
])
|
|
949
1015
|
)
|
|
950
1016
|
);
|
|
@@ -953,10 +1019,10 @@ function generatePatient(options = {}) {
|
|
|
953
1019
|
props.push(
|
|
954
1020
|
prop(
|
|
955
1021
|
"address",
|
|
956
|
-
|
|
957
|
-
|
|
1022
|
+
fhirPeer().list([
|
|
1023
|
+
fhirPeer().complex([
|
|
958
1024
|
prop("use", str("home")),
|
|
959
|
-
prop("line",
|
|
1025
|
+
prop("line", fhirPeer().list([str(id.address.street)])),
|
|
960
1026
|
prop("city", str(id.address.city)),
|
|
961
1027
|
prop("state", str(id.address.state)),
|
|
962
1028
|
prop("postalCode", str(id.address.zip))
|
|
@@ -964,8 +1030,10 @@ function generatePatient(options = {}) {
|
|
|
964
1030
|
])
|
|
965
1031
|
)
|
|
966
1032
|
);
|
|
967
|
-
return
|
|
1033
|
+
return fhirPeer().complex(props);
|
|
968
1034
|
}
|
|
1035
|
+
|
|
1036
|
+
// src/fhir/condition.ts
|
|
969
1037
|
function generateCondition(options = {}) {
|
|
970
1038
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
971
1039
|
const rng = createRng(seed);
|
|
@@ -995,7 +1063,7 @@ function generateCondition(options = {}) {
|
|
|
995
1063
|
props.push(
|
|
996
1064
|
prop(
|
|
997
1065
|
"category",
|
|
998
|
-
|
|
1066
|
+
fhirPeer().list([
|
|
999
1067
|
codeableConcept({
|
|
1000
1068
|
system: SYSTEM.CONDITION_CATEGORY,
|
|
1001
1069
|
code: "problem-list-item",
|
|
@@ -1006,15 +1074,17 @@ function generateCondition(options = {}) {
|
|
|
1006
1074
|
);
|
|
1007
1075
|
props.push(prop("code", codeableConcept(code)));
|
|
1008
1076
|
props.push(prop("subject", reference(subject)));
|
|
1009
|
-
return
|
|
1077
|
+
return fhirPeer().complex(props);
|
|
1010
1078
|
}
|
|
1079
|
+
|
|
1080
|
+
// src/fhir/observation.ts
|
|
1011
1081
|
function drawValue(rng, concept) {
|
|
1012
1082
|
const span = concept.high - concept.low;
|
|
1013
1083
|
const raw = concept.low + rng.float() * span;
|
|
1014
1084
|
return raw.toFixed(concept.decimals);
|
|
1015
1085
|
}
|
|
1016
1086
|
function valueQuantity(rng, concept) {
|
|
1017
|
-
return
|
|
1087
|
+
return fhirPeer().complex([
|
|
1018
1088
|
prop("value", dec(drawValue(rng, concept))),
|
|
1019
1089
|
prop("unit", str(concept.unit)),
|
|
1020
1090
|
prop("system", str(SYSTEM.UCUM)),
|
|
@@ -1036,7 +1106,7 @@ function buildObservation(seed, subject, usCore, profileUrl, category, pool, eff
|
|
|
1036
1106
|
props.push(
|
|
1037
1107
|
prop(
|
|
1038
1108
|
"category",
|
|
1039
|
-
|
|
1109
|
+
fhirPeer().list([
|
|
1040
1110
|
codeableConcept({
|
|
1041
1111
|
system: SYSTEM.OBSERVATION_CATEGORY,
|
|
1042
1112
|
code: category.code,
|
|
@@ -1052,7 +1122,7 @@ function buildObservation(seed, subject, usCore, profileUrl, category, pool, eff
|
|
|
1052
1122
|
const d = String(rng.int(1, 28)).padStart(2, "0");
|
|
1053
1123
|
if (effective) props.push(prop("effectiveDateTime", str(`${String(y)}-${m}-${d}`)));
|
|
1054
1124
|
props.push(prop("valueQuantity", valueQuantity(rng, concept)));
|
|
1055
|
-
return
|
|
1125
|
+
return fhirPeer().complex(props);
|
|
1056
1126
|
}
|
|
1057
1127
|
function generateObservationLab(options = {}) {
|
|
1058
1128
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
@@ -1078,6 +1148,8 @@ function generateVitalSign(options = {}) {
|
|
|
1078
1148
|
true
|
|
1079
1149
|
);
|
|
1080
1150
|
}
|
|
1151
|
+
|
|
1152
|
+
// src/fhir/medication-request.ts
|
|
1081
1153
|
function generateMedicationRequest(options = {}) {
|
|
1082
1154
|
const {
|
|
1083
1155
|
seed = 0,
|
|
@@ -1102,8 +1174,10 @@ function generateMedicationRequest(options = {}) {
|
|
|
1102
1174
|
props.push(prop("subject", reference(subject)));
|
|
1103
1175
|
props.push(prop("authoredOn", str(`${String(y)}-${m}-${d}`)));
|
|
1104
1176
|
props.push(prop("requester", reference(requester)));
|
|
1105
|
-
return
|
|
1177
|
+
return fhirPeer().complex(props);
|
|
1106
1178
|
}
|
|
1179
|
+
|
|
1180
|
+
// src/fhir/encounter.ts
|
|
1107
1181
|
function generateEncounter(options = {}) {
|
|
1108
1182
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
1109
1183
|
const rng = createRng(seed);
|
|
@@ -1120,8 +1194,8 @@ function generateEncounter(options = {}) {
|
|
|
1120
1194
|
props.push(
|
|
1121
1195
|
prop(
|
|
1122
1196
|
"identifier",
|
|
1123
|
-
|
|
1124
|
-
|
|
1197
|
+
fhirPeer().list([
|
|
1198
|
+
fhirPeer().complex([
|
|
1125
1199
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1126
1200
|
prop("value", str(id.value))
|
|
1127
1201
|
])
|
|
@@ -1130,11 +1204,13 @@ function generateEncounter(options = {}) {
|
|
|
1130
1204
|
);
|
|
1131
1205
|
props.push(prop("status", str("finished")));
|
|
1132
1206
|
props.push(prop("class", coding(cls)));
|
|
1133
|
-
props.push(prop("type",
|
|
1207
|
+
props.push(prop("type", fhirPeer().list([codeableConcept(type)])));
|
|
1134
1208
|
props.push(prop("subject", reference(subject)));
|
|
1135
|
-
props.push(prop("period",
|
|
1136
|
-
return
|
|
1209
|
+
props.push(prop("period", fhirPeer().complex([prop("start", str(`${start}T09:00:00Z`))])));
|
|
1210
|
+
return fhirPeer().complex(props);
|
|
1137
1211
|
}
|
|
1212
|
+
|
|
1213
|
+
// src/fhir/immunization.ts
|
|
1138
1214
|
function generateImmunization(options = {}) {
|
|
1139
1215
|
const { seed = 0, patient = "Patient/syn-patient-1", usCore = true } = options;
|
|
1140
1216
|
const rng = createRng(seed);
|
|
@@ -1151,8 +1227,10 @@ function generateImmunization(options = {}) {
|
|
|
1151
1227
|
props.push(prop("patient", reference(patient)));
|
|
1152
1228
|
props.push(prop("occurrenceDateTime", str(occurrence)));
|
|
1153
1229
|
props.push(prop("primarySource", bool(true)));
|
|
1154
|
-
return
|
|
1230
|
+
return fhirPeer().complex(props);
|
|
1155
1231
|
}
|
|
1232
|
+
|
|
1233
|
+
// src/fhir/allergy-intolerance.ts
|
|
1156
1234
|
function generateAllergyIntolerance(options = {}) {
|
|
1157
1235
|
const { seed = 0, patient = "Patient/syn-patient-1", usCore = true } = options;
|
|
1158
1236
|
const rng = createRng(seed);
|
|
@@ -1185,11 +1263,17 @@ function generateAllergyIntolerance(options = {}) {
|
|
|
1185
1263
|
props.push(
|
|
1186
1264
|
prop(
|
|
1187
1265
|
"reaction",
|
|
1188
|
-
|
|
1266
|
+
fhirPeer().list([
|
|
1267
|
+
fhirPeer().complex([
|
|
1268
|
+
prop("manifestation", fhirPeer().list([codeableConcept(manifestation)]))
|
|
1269
|
+
])
|
|
1270
|
+
])
|
|
1189
1271
|
)
|
|
1190
1272
|
);
|
|
1191
|
-
return
|
|
1273
|
+
return fhirPeer().complex(props);
|
|
1192
1274
|
}
|
|
1275
|
+
|
|
1276
|
+
// src/fhir/procedure.ts
|
|
1193
1277
|
function generateProcedure(options = {}) {
|
|
1194
1278
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
1195
1279
|
const rng = createRng(seed);
|
|
@@ -1205,8 +1289,10 @@ function generateProcedure(options = {}) {
|
|
|
1205
1289
|
props.push(prop("code", codeableConcept(code)));
|
|
1206
1290
|
props.push(prop("subject", reference(subject)));
|
|
1207
1291
|
props.push(prop("performedDateTime", str(`${performed}T10:00:00Z`)));
|
|
1208
|
-
return
|
|
1292
|
+
return fhirPeer().complex(props);
|
|
1209
1293
|
}
|
|
1294
|
+
|
|
1295
|
+
// src/fhir/provenance.ts
|
|
1210
1296
|
function generateProvenance(options = {}) {
|
|
1211
1297
|
const { seed = 0, target = "Patient/syn-patient-1", usCore = true } = options;
|
|
1212
1298
|
const rng = createRng(seed);
|
|
@@ -1219,19 +1305,19 @@ function generateProvenance(options = {}) {
|
|
|
1219
1305
|
];
|
|
1220
1306
|
if (usCore) props.push(prop("meta", meta([US_CORE_PROFILE.PROVENANCE])));
|
|
1221
1307
|
props.push(prop("text", narrative("Synthetic provenance for a generated fixture.")));
|
|
1222
|
-
props.push(prop("target",
|
|
1308
|
+
props.push(prop("target", fhirPeer().list([reference(target)])));
|
|
1223
1309
|
props.push(prop("recorded", str(`${recorded}T10:00:00Z`)));
|
|
1224
1310
|
props.push(
|
|
1225
1311
|
prop(
|
|
1226
1312
|
"agent",
|
|
1227
|
-
|
|
1228
|
-
|
|
1313
|
+
fhirPeer().list([
|
|
1314
|
+
fhirPeer().complex([
|
|
1229
1315
|
prop(
|
|
1230
1316
|
"type",
|
|
1231
|
-
|
|
1317
|
+
fhirPeer().complex([
|
|
1232
1318
|
prop(
|
|
1233
1319
|
"coding",
|
|
1234
|
-
|
|
1320
|
+
fhirPeer().list([
|
|
1235
1321
|
coding({
|
|
1236
1322
|
system: SYSTEM.PROVENANCE_PARTICIPANT_TYPE,
|
|
1237
1323
|
code: "author",
|
|
@@ -1252,8 +1338,10 @@ function generateProvenance(options = {}) {
|
|
|
1252
1338
|
])
|
|
1253
1339
|
)
|
|
1254
1340
|
);
|
|
1255
|
-
return
|
|
1341
|
+
return fhirPeer().complex(props);
|
|
1256
1342
|
}
|
|
1343
|
+
|
|
1344
|
+
// src/fhir/diagnostic-report.ts
|
|
1257
1345
|
function generateDiagnosticReport(options = {}) {
|
|
1258
1346
|
const { seed = 0, subject = "Patient/syn-patient-1", results = [], usCore = true } = options;
|
|
1259
1347
|
const rng = createRng(seed);
|
|
@@ -1269,7 +1357,7 @@ function generateDiagnosticReport(options = {}) {
|
|
|
1269
1357
|
props.push(
|
|
1270
1358
|
prop(
|
|
1271
1359
|
"category",
|
|
1272
|
-
|
|
1360
|
+
fhirPeer().list([
|
|
1273
1361
|
codeableConcept({
|
|
1274
1362
|
system: SYSTEM.DIAGNOSTIC_SERVICE_SECTION,
|
|
1275
1363
|
code: "LAB",
|
|
@@ -1283,12 +1371,13 @@ function generateDiagnosticReport(options = {}) {
|
|
|
1283
1371
|
props.push(prop("effectiveDateTime", str(`${day}T08:30:00Z`)));
|
|
1284
1372
|
props.push(prop("issued", str(`${day}T09:00:00.000Z`)));
|
|
1285
1373
|
if (results.length > 0) {
|
|
1286
|
-
props.push(prop("result",
|
|
1374
|
+
props.push(prop("result", fhirPeer().list(results.map((r) => reference(r)))));
|
|
1287
1375
|
}
|
|
1288
|
-
return
|
|
1376
|
+
return fhirPeer().complex(props);
|
|
1289
1377
|
}
|
|
1290
1378
|
|
|
1291
1379
|
// src/corpus.ts
|
|
1380
|
+
var UNCHECKED = Object.freeze([]);
|
|
1292
1381
|
function makeCorpus(seed, artifacts, quirks = []) {
|
|
1293
1382
|
const counts = {};
|
|
1294
1383
|
const formats = /* @__PURE__ */ new Set();
|
|
@@ -1308,11 +1397,13 @@ function makeCorpus(seed, artifacts, quirks = []) {
|
|
|
1308
1397
|
artifacts: Object.freeze(frozenArtifacts)
|
|
1309
1398
|
});
|
|
1310
1399
|
}
|
|
1400
|
+
|
|
1401
|
+
// src/fhir/composition.ts
|
|
1311
1402
|
function section(sec) {
|
|
1312
|
-
return
|
|
1403
|
+
return fhirPeer().complex([
|
|
1313
1404
|
prop("title", str(sec.title)),
|
|
1314
1405
|
prop("code", codeableConcept({ system: SYSTEM.LOINC, code: sec.code, display: sec.title })),
|
|
1315
|
-
prop("entry",
|
|
1406
|
+
prop("entry", fhirPeer().list(sec.entries.map((e) => reference(e))))
|
|
1316
1407
|
]);
|
|
1317
1408
|
}
|
|
1318
1409
|
function buildComposition(rng, input) {
|
|
@@ -1331,18 +1422,20 @@ function buildComposition(rng, input) {
|
|
|
1331
1422
|
),
|
|
1332
1423
|
prop("subject", reference(input.subject)),
|
|
1333
1424
|
prop("date", str(`${input.date}T09:00:00Z`)),
|
|
1334
|
-
prop("author",
|
|
1425
|
+
prop("author", fhirPeer().list([reference(input.organization)])),
|
|
1335
1426
|
prop("title", str("Synthetic Continuity of Care Document")),
|
|
1336
1427
|
prop("custodian", reference(input.organization)),
|
|
1337
|
-
prop("section",
|
|
1428
|
+
prop("section", fhirPeer().list(input.sections.map((s) => section(s))))
|
|
1338
1429
|
];
|
|
1339
|
-
return
|
|
1430
|
+
return fhirPeer().complex(props);
|
|
1340
1431
|
}
|
|
1432
|
+
|
|
1433
|
+
// src/fhir/round-trip.ts
|
|
1341
1434
|
function roundTrip(resource, options = {}) {
|
|
1342
|
-
const content =
|
|
1343
|
-
const { resource: reparsed } =
|
|
1344
|
-
const byteStable =
|
|
1345
|
-
const result =
|
|
1435
|
+
const content = fhirPeer().serializeResource(resource);
|
|
1436
|
+
const { resource: reparsed } = fhirPeer().parseResource(content);
|
|
1437
|
+
const byteStable = fhirPeer().serializeResource(reparsed) === content;
|
|
1438
|
+
const result = fhirPeer().validateResource(
|
|
1346
1439
|
reparsed,
|
|
1347
1440
|
options.profiles !== void 0 ? { mode: "strict", profiles: options.profiles } : { mode: "strict" }
|
|
1348
1441
|
);
|
|
@@ -1351,6 +1444,13 @@ function roundTrip(resource, options = {}) {
|
|
|
1351
1444
|
const valid = result.valid;
|
|
1352
1445
|
return { content, errors, warnings, byteStable, valid, specClean: valid && byteStable };
|
|
1353
1446
|
}
|
|
1447
|
+
function fhirCorpusArtifact(resource, verify) {
|
|
1448
|
+
const content = fhirPeer().serializeResource(resource);
|
|
1449
|
+
if (!verify) return { content, warnings: UNCHECKED };
|
|
1450
|
+
const { resource: reparsed } = fhirPeer().parseResource(content);
|
|
1451
|
+
const warnings = fhirPeer().validateResource(reparsed, { mode: "strict" }).issues.filter((i) => i.severity === "error" || i.severity === "fatal").map((i) => i.code);
|
|
1452
|
+
return { content, warnings };
|
|
1453
|
+
}
|
|
1354
1454
|
|
|
1355
1455
|
// src/fhir/bundle.ts
|
|
1356
1456
|
var BUNDLE_TYPES = Object.freeze([
|
|
@@ -1364,14 +1464,14 @@ function resourceTypeOf(resource) {
|
|
|
1364
1464
|
}
|
|
1365
1465
|
function buildOrganization(rng) {
|
|
1366
1466
|
const id = safe.identifier(rng, "AN");
|
|
1367
|
-
return
|
|
1467
|
+
return fhirPeer().complex([
|
|
1368
1468
|
prop("resourceType", str("Organization")),
|
|
1369
1469
|
prop("id", str(`syn-org-${rng.digits(8)}`)),
|
|
1370
1470
|
prop("text", narrative("Synthetic health organization.")),
|
|
1371
1471
|
prop(
|
|
1372
1472
|
"identifier",
|
|
1373
|
-
|
|
1374
|
-
|
|
1473
|
+
fhirPeer().list([
|
|
1474
|
+
fhirPeer().complex([
|
|
1375
1475
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1376
1476
|
prop("value", str(id.value))
|
|
1377
1477
|
])
|
|
@@ -1484,11 +1584,14 @@ function generateBundle(options = {}) {
|
|
|
1484
1584
|
entryProps.push(
|
|
1485
1585
|
prop(
|
|
1486
1586
|
"request",
|
|
1487
|
-
|
|
1587
|
+
fhirPeer().complex([
|
|
1588
|
+
prop("method", str("POST")),
|
|
1589
|
+
prop("url", str(resourceTypeOf(member.resource)))
|
|
1590
|
+
])
|
|
1488
1591
|
)
|
|
1489
1592
|
);
|
|
1490
1593
|
}
|
|
1491
|
-
return
|
|
1594
|
+
return fhirPeer().complex(entryProps);
|
|
1492
1595
|
});
|
|
1493
1596
|
const props = [
|
|
1494
1597
|
prop("resourceType", str("Bundle")),
|
|
@@ -1499,7 +1602,7 @@ function generateBundle(options = {}) {
|
|
|
1499
1602
|
props.push(
|
|
1500
1603
|
prop(
|
|
1501
1604
|
"identifier",
|
|
1502
|
-
|
|
1605
|
+
fhirPeer().complex([
|
|
1503
1606
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1504
1607
|
prop("value", str(`urn:uuid:${safe.uuid(rng)}`))
|
|
1505
1608
|
])
|
|
@@ -1508,8 +1611,8 @@ function generateBundle(options = {}) {
|
|
|
1508
1611
|
}
|
|
1509
1612
|
props.push(prop("type", str(type)));
|
|
1510
1613
|
if (type === "document") props.push(prop("timestamp", str(`${spine.date}T09:00:00.000Z`)));
|
|
1511
|
-
props.push(prop("entry",
|
|
1512
|
-
return
|
|
1614
|
+
props.push(prop("entry", fhirPeer().list(entries)));
|
|
1615
|
+
return fhirPeer().complex(props);
|
|
1513
1616
|
}
|
|
1514
1617
|
var ALL_KINDS = Object.freeze([
|
|
1515
1618
|
"Patient",
|
|
@@ -1570,13 +1673,13 @@ function generateKind(kind, seed) {
|
|
|
1570
1673
|
}
|
|
1571
1674
|
}
|
|
1572
1675
|
function fhirCorpus(options) {
|
|
1573
|
-
const { seed, count = 1 } = options;
|
|
1676
|
+
const { seed, count = 1, verify = true } = options;
|
|
1574
1677
|
const kinds = resolveMix(ALL_KINDS, options.mix, DEFAULT_MIX);
|
|
1575
1678
|
const seedStream = createRng(seed);
|
|
1576
1679
|
const artifacts = Array.from({ length: count }, (_unused, i) => {
|
|
1577
1680
|
const kind = kinds[i % kinds.length] ?? "USCorePatient";
|
|
1578
|
-
const rt =
|
|
1579
|
-
return { format: "fhir", kind, content: rt.content, warnings: rt.
|
|
1681
|
+
const rt = fhirCorpusArtifact(generateKind(kind, seedStream.nextUint32()), verify);
|
|
1682
|
+
return { format: "fhir", kind, content: rt.content, warnings: rt.warnings };
|
|
1580
1683
|
});
|
|
1581
1684
|
return makeCorpus(seed, artifacts);
|
|
1582
1685
|
}
|