@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.d.cts
CHANGED
|
@@ -397,6 +397,12 @@ interface FhirCorpusOptions {
|
|
|
397
397
|
readonly count?: number;
|
|
398
398
|
/** The resource kinds to cycle through. Defaults to the full US Core clinical spine + a Bundle. */
|
|
399
399
|
readonly mix?: readonly FhirResourceKind[];
|
|
400
|
+
/**
|
|
401
|
+
* Whether each artifact is read back through its parser and the parser's findings recorded as its
|
|
402
|
+
* `warnings`. Defaults to `true`. `false` skips the read, a large share of a corpus's time; every
|
|
403
|
+
* artifact's `warnings` is then empty without having been checked.
|
|
404
|
+
*/
|
|
405
|
+
readonly verify?: boolean;
|
|
400
406
|
}
|
|
401
407
|
/**
|
|
402
408
|
* Build a reproducible {@link Corpus} of spec-clean FHIR resources across the supported kinds. Each
|
package/dist/fhir/index.d.ts
CHANGED
|
@@ -397,6 +397,12 @@ interface FhirCorpusOptions {
|
|
|
397
397
|
readonly count?: number;
|
|
398
398
|
/** The resource kinds to cycle through. Defaults to the full US Core clinical spine + a Bundle. */
|
|
399
399
|
readonly mix?: readonly FhirResourceKind[];
|
|
400
|
+
/**
|
|
401
|
+
* Whether each artifact is read back through its parser and the parser's findings recorded as its
|
|
402
|
+
* `warnings`. Defaults to `true`. `false` skips the read, a large share of a corpus's time; every
|
|
403
|
+
* artifact's `warnings` is then empty without having been checked.
|
|
404
|
+
*/
|
|
405
|
+
readonly verify?: boolean;
|
|
400
406
|
}
|
|
401
407
|
/**
|
|
402
408
|
* Build a reproducible {@link Corpus} of spec-clean FHIR resources across the supported kinds. Each
|
package/dist/fhir/index.mjs
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
2
3
|
|
|
3
|
-
|
|
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
|
+
});
|
|
4
10
|
|
|
5
11
|
// src/rng/splitmix32.ts
|
|
6
12
|
function splitmix32(seed) {
|
|
@@ -32,11 +38,42 @@ function sfc32Next(s) {
|
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
// src/codes.ts
|
|
35
|
-
var SYNTH_FATAL_CODES = {
|
|
41
|
+
var SYNTH_FATAL_CODES = Object.freeze({
|
|
42
|
+
/**
|
|
43
|
+
* A format was requested that this build cannot generate through a real parser builder/serializer.
|
|
44
|
+
* Fatal, never a hand-written byte fallback.
|
|
45
|
+
*
|
|
46
|
+
* **No code path in this build raises it.** All six formats generate, so it is reserved for a
|
|
47
|
+
* future format that does not, and is kept because removing a published code is a breaking change.
|
|
48
|
+
* An unsupported *kind* within a format that does generate is `SYNTH_UNSUPPORTED_KIND`.
|
|
49
|
+
*/
|
|
50
|
+
SYNTH_UNSUPPORTED_FORMAT: "SYNTH_UNSUPPORTED_FORMAT",
|
|
51
|
+
/**
|
|
52
|
+
* A vendor quirk was requested that the target format's profile system does not support. Fatal,
|
|
53
|
+
* never a silent no-op and never a fabricated quirk.
|
|
54
|
+
*/
|
|
55
|
+
SYNTH_UNSUPPORTED_QUIRK: "SYNTH_UNSUPPORTED_QUIRK",
|
|
56
|
+
/**
|
|
57
|
+
* A quirk transform found no structural anchor to mutate, so the fixture would not carry the
|
|
58
|
+
* deviation it is labelled with. Fatal: a golden file that lies about its parser verdict is worse
|
|
59
|
+
* than no golden file.
|
|
60
|
+
*/
|
|
61
|
+
SYNTH_QUIRK_ANCHOR_ABSENT: "SYNTH_QUIRK_ANCHOR_ABSENT",
|
|
62
|
+
/**
|
|
63
|
+
* A bare parse of a freshly-generated quirk artifact did not produce exactly the declared intended
|
|
64
|
+
* warning code(s). Fatal, never emit a mislabeled fixture.
|
|
65
|
+
*/
|
|
66
|
+
SYNTH_INTENDED_WARNING_MISMATCH: "SYNTH_INTENDED_WARNING_MISMATCH",
|
|
67
|
+
/** A concept's code-system URI has no OID mapping in the C-CDA example-code table. Fatal. */
|
|
68
|
+
SYNTH_UNMAPPED_CODE_SYSTEM: "SYNTH_UNMAPPED_CODE_SYSTEM",
|
|
69
|
+
/** A money value could not be read as an X12 decimal. Fatal: a generator never rounds to a float. */
|
|
70
|
+
SYNTH_INVALID_DECIMAL: "SYNTH_INVALID_DECIMAL",
|
|
36
71
|
/** An integer range was requested with its maximum below its minimum. Fatal. */
|
|
37
72
|
SYNTH_INVALID_RANGE: "SYNTH_INVALID_RANGE",
|
|
38
73
|
/** A value was drawn from an empty pool. Fatal, never a fabricated substitute. */
|
|
39
74
|
SYNTH_EMPTY_POOL: "SYNTH_EMPTY_POOL",
|
|
75
|
+
/** A `defineSynthProfile` spec was not usable (a missing or blank `name`). Fatal. */
|
|
76
|
+
SYNTH_INVALID_PROFILE: "SYNTH_INVALID_PROFILE",
|
|
40
77
|
/**
|
|
41
78
|
* A caller-supplied selector (a message kind, a document type, a corpus mix entry, a claim
|
|
42
79
|
* variant, a Bundle type, a resource profile) is not in the closed set that governs it. Fatal:
|
|
@@ -53,7 +90,7 @@ var SYNTH_FATAL_CODES = {
|
|
|
53
90
|
* mislabelled artifact is worse than no artifact.
|
|
54
91
|
*/
|
|
55
92
|
SYNTH_PROFILE_NOT_GENERATED: "SYNTH_PROFILE_NOT_GENERATED"
|
|
56
|
-
};
|
|
93
|
+
});
|
|
57
94
|
var SYNTH_FATAL_MESSAGES = Object.freeze({
|
|
58
95
|
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.",
|
|
59
96
|
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).",
|
|
@@ -520,42 +557,64 @@ var SYSTEM = Object.freeze({
|
|
|
520
557
|
/** US Core `us-core-provenance-participant-type`, `Provenance.agent.type` (`transmitter`). */
|
|
521
558
|
US_CORE_PROVENANCE_PARTICIPANT_TYPE: "http://hl7.org/fhir/us/core/CodeSystem/us-core-provenance-participant-type"
|
|
522
559
|
});
|
|
560
|
+
function defaultHost() {
|
|
561
|
+
if (typeof import.meta.resolve !== "function") return { require: __require, resolve: void 0 };
|
|
562
|
+
return { require: createRequire(import.meta.url), resolve: (s) => import.meta.resolve(s) };
|
|
563
|
+
}
|
|
564
|
+
function isRequireEsmRefusal(error) {
|
|
565
|
+
return error?.code === "ERR_REQUIRE_ESM";
|
|
566
|
+
}
|
|
567
|
+
function loadPeer(specifier, host) {
|
|
568
|
+
if (host.resolve === void 0) return host.require(specifier);
|
|
569
|
+
const entry = fileURLToPath(host.resolve(specifier));
|
|
570
|
+
try {
|
|
571
|
+
return host.require(entry);
|
|
572
|
+
} catch (error) {
|
|
573
|
+
if (!isRequireEsmRefusal(error)) throw error;
|
|
574
|
+
return host.require(specifier);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
function lazyPeer(specifier, host) {
|
|
578
|
+
let loaded;
|
|
579
|
+
return () => loaded ??= loadPeer(specifier, defaultHost());
|
|
580
|
+
}
|
|
581
|
+
var fhirPeer = lazyPeer("@cosyte/fhir");
|
|
523
582
|
|
|
524
583
|
// src/fhir/builder.ts
|
|
525
584
|
function prop(name2, value) {
|
|
526
585
|
return { name: name2, value };
|
|
527
586
|
}
|
|
528
587
|
function str(value) {
|
|
529
|
-
return primitive(value);
|
|
588
|
+
return fhirPeer().primitive(value);
|
|
530
589
|
}
|
|
531
590
|
function dec(raw) {
|
|
532
|
-
return primitive(decimal(raw));
|
|
591
|
+
return fhirPeer().primitive(fhirPeer().decimal(raw));
|
|
533
592
|
}
|
|
534
593
|
function bool(value) {
|
|
535
|
-
return primitive(value);
|
|
594
|
+
return fhirPeer().primitive(value);
|
|
536
595
|
}
|
|
537
596
|
function coding(concept) {
|
|
538
|
-
return complex([
|
|
597
|
+
return fhirPeer().complex([
|
|
539
598
|
prop("system", str(concept.system)),
|
|
540
599
|
prop("code", str(concept.code)),
|
|
541
600
|
prop("display", str(concept.display))
|
|
542
601
|
]);
|
|
543
602
|
}
|
|
544
603
|
function codeableConcept(concept) {
|
|
545
|
-
return complex([prop("coding", list([coding(concept)]))]);
|
|
604
|
+
return fhirPeer().complex([prop("coding", fhirPeer().list([coding(concept)]))]);
|
|
546
605
|
}
|
|
547
606
|
function reference(ref) {
|
|
548
|
-
return complex([prop("reference", str(ref))]);
|
|
607
|
+
return fhirPeer().complex([prop("reference", str(ref))]);
|
|
549
608
|
}
|
|
550
609
|
function narrative(text) {
|
|
551
610
|
const escaped = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
552
|
-
return complex([
|
|
611
|
+
return fhirPeer().complex([
|
|
553
612
|
prop("status", str("generated")),
|
|
554
613
|
prop("div", str(`<div xmlns="http://www.w3.org/1999/xhtml"><p>${escaped}</p></div>`))
|
|
555
614
|
]);
|
|
556
615
|
}
|
|
557
616
|
function meta(profiles) {
|
|
558
|
-
return complex([prop("profile", list(profiles.map((p) => str(p))))]);
|
|
617
|
+
return fhirPeer().complex([prop("profile", fhirPeer().list(profiles.map((p) => str(p))))]);
|
|
559
618
|
}
|
|
560
619
|
function toFhirDate(ymd) {
|
|
561
620
|
return `${ymd.slice(0, 4)}-${ymd.slice(4, 6)}-${ymd.slice(6, 8)}`;
|
|
@@ -572,13 +631,13 @@ function fhirPatientIdentity(rng) {
|
|
|
572
631
|
return { id, person, mrn, birthDate, gender, address: address2, phone: phone2, email: email2 };
|
|
573
632
|
}
|
|
574
633
|
function mrnIdentifier(mrn) {
|
|
575
|
-
return complex([
|
|
634
|
+
return fhirPeer().complex([
|
|
576
635
|
prop(
|
|
577
636
|
"type",
|
|
578
|
-
complex([
|
|
637
|
+
fhirPeer().complex([
|
|
579
638
|
prop(
|
|
580
639
|
"coding",
|
|
581
|
-
list([
|
|
640
|
+
fhirPeer().list([
|
|
582
641
|
coding({
|
|
583
642
|
system: SYSTEM.IDENTIFIER_TYPE,
|
|
584
643
|
code: "MR",
|
|
@@ -874,13 +933,16 @@ function resolveMix(allowed, requested, fallback) {
|
|
|
874
933
|
// src/fhir/patient.ts
|
|
875
934
|
var PATIENT_PROFILES = Object.freeze(["base", "us-core"]);
|
|
876
935
|
function ombExtension(url, category) {
|
|
877
|
-
return complex([
|
|
936
|
+
return fhirPeer().complex([
|
|
878
937
|
prop("url", str(url)),
|
|
879
938
|
prop(
|
|
880
939
|
"extension",
|
|
881
|
-
list([
|
|
882
|
-
complex([
|
|
883
|
-
|
|
940
|
+
fhirPeer().list([
|
|
941
|
+
fhirPeer().complex([
|
|
942
|
+
prop("url", str("ombCategory")),
|
|
943
|
+
prop("valueCoding", coding(category))
|
|
944
|
+
]),
|
|
945
|
+
fhirPeer().complex([prop("url", str("text")), prop("valueString", str(category.display))])
|
|
884
946
|
])
|
|
885
947
|
)
|
|
886
948
|
]);
|
|
@@ -911,24 +973,27 @@ function generatePatient(options = {}) {
|
|
|
911
973
|
props.push(
|
|
912
974
|
prop(
|
|
913
975
|
"extension",
|
|
914
|
-
list([
|
|
976
|
+
fhirPeer().list([
|
|
915
977
|
ombExtension(US_CORE_RACE_EXTENSION, race),
|
|
916
978
|
ombExtension(US_CORE_ETHNICITY_EXTENSION, ethnicity),
|
|
917
|
-
complex([
|
|
979
|
+
fhirPeer().complex([
|
|
980
|
+
prop("url", str(US_CORE_BIRTHSEX_EXTENSION)),
|
|
981
|
+
prop("valueCode", str(birthsex))
|
|
982
|
+
])
|
|
918
983
|
])
|
|
919
984
|
)
|
|
920
985
|
);
|
|
921
986
|
}
|
|
922
|
-
props.push(prop("identifier", list([mrnIdentifier(id.mrn)])));
|
|
987
|
+
props.push(prop("identifier", fhirPeer().list([mrnIdentifier(id.mrn)])));
|
|
923
988
|
props.push(prop("active", bool(true)));
|
|
924
989
|
props.push(
|
|
925
990
|
prop(
|
|
926
991
|
"name",
|
|
927
|
-
list([
|
|
928
|
-
complex([
|
|
992
|
+
fhirPeer().list([
|
|
993
|
+
fhirPeer().complex([
|
|
929
994
|
prop("use", str("official")),
|
|
930
995
|
prop("family", str(id.person.family)),
|
|
931
|
-
prop("given", list([str(id.person.given)]))
|
|
996
|
+
prop("given", fhirPeer().list([str(id.person.given)]))
|
|
932
997
|
])
|
|
933
998
|
])
|
|
934
999
|
)
|
|
@@ -936,13 +1001,13 @@ function generatePatient(options = {}) {
|
|
|
936
1001
|
props.push(
|
|
937
1002
|
prop(
|
|
938
1003
|
"telecom",
|
|
939
|
-
list([
|
|
940
|
-
complex([
|
|
1004
|
+
fhirPeer().list([
|
|
1005
|
+
fhirPeer().complex([
|
|
941
1006
|
prop("system", str("phone")),
|
|
942
1007
|
prop("value", str(id.phone)),
|
|
943
1008
|
prop("use", str("home"))
|
|
944
1009
|
]),
|
|
945
|
-
complex([prop("system", str("email")), prop("value", str(id.email))])
|
|
1010
|
+
fhirPeer().complex([prop("system", str("email")), prop("value", str(id.email))])
|
|
946
1011
|
])
|
|
947
1012
|
)
|
|
948
1013
|
);
|
|
@@ -951,10 +1016,10 @@ function generatePatient(options = {}) {
|
|
|
951
1016
|
props.push(
|
|
952
1017
|
prop(
|
|
953
1018
|
"address",
|
|
954
|
-
list([
|
|
955
|
-
complex([
|
|
1019
|
+
fhirPeer().list([
|
|
1020
|
+
fhirPeer().complex([
|
|
956
1021
|
prop("use", str("home")),
|
|
957
|
-
prop("line", list([str(id.address.street)])),
|
|
1022
|
+
prop("line", fhirPeer().list([str(id.address.street)])),
|
|
958
1023
|
prop("city", str(id.address.city)),
|
|
959
1024
|
prop("state", str(id.address.state)),
|
|
960
1025
|
prop("postalCode", str(id.address.zip))
|
|
@@ -962,8 +1027,10 @@ function generatePatient(options = {}) {
|
|
|
962
1027
|
])
|
|
963
1028
|
)
|
|
964
1029
|
);
|
|
965
|
-
return complex(props);
|
|
1030
|
+
return fhirPeer().complex(props);
|
|
966
1031
|
}
|
|
1032
|
+
|
|
1033
|
+
// src/fhir/condition.ts
|
|
967
1034
|
function generateCondition(options = {}) {
|
|
968
1035
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
969
1036
|
const rng = createRng(seed);
|
|
@@ -993,7 +1060,7 @@ function generateCondition(options = {}) {
|
|
|
993
1060
|
props.push(
|
|
994
1061
|
prop(
|
|
995
1062
|
"category",
|
|
996
|
-
list([
|
|
1063
|
+
fhirPeer().list([
|
|
997
1064
|
codeableConcept({
|
|
998
1065
|
system: SYSTEM.CONDITION_CATEGORY,
|
|
999
1066
|
code: "problem-list-item",
|
|
@@ -1004,15 +1071,17 @@ function generateCondition(options = {}) {
|
|
|
1004
1071
|
);
|
|
1005
1072
|
props.push(prop("code", codeableConcept(code)));
|
|
1006
1073
|
props.push(prop("subject", reference(subject)));
|
|
1007
|
-
return complex(props);
|
|
1074
|
+
return fhirPeer().complex(props);
|
|
1008
1075
|
}
|
|
1076
|
+
|
|
1077
|
+
// src/fhir/observation.ts
|
|
1009
1078
|
function drawValue(rng, concept) {
|
|
1010
1079
|
const span = concept.high - concept.low;
|
|
1011
1080
|
const raw = concept.low + rng.float() * span;
|
|
1012
1081
|
return raw.toFixed(concept.decimals);
|
|
1013
1082
|
}
|
|
1014
1083
|
function valueQuantity(rng, concept) {
|
|
1015
|
-
return complex([
|
|
1084
|
+
return fhirPeer().complex([
|
|
1016
1085
|
prop("value", dec(drawValue(rng, concept))),
|
|
1017
1086
|
prop("unit", str(concept.unit)),
|
|
1018
1087
|
prop("system", str(SYSTEM.UCUM)),
|
|
@@ -1034,7 +1103,7 @@ function buildObservation(seed, subject, usCore, profileUrl, category, pool, eff
|
|
|
1034
1103
|
props.push(
|
|
1035
1104
|
prop(
|
|
1036
1105
|
"category",
|
|
1037
|
-
list([
|
|
1106
|
+
fhirPeer().list([
|
|
1038
1107
|
codeableConcept({
|
|
1039
1108
|
system: SYSTEM.OBSERVATION_CATEGORY,
|
|
1040
1109
|
code: category.code,
|
|
@@ -1050,7 +1119,7 @@ function buildObservation(seed, subject, usCore, profileUrl, category, pool, eff
|
|
|
1050
1119
|
const d = String(rng.int(1, 28)).padStart(2, "0");
|
|
1051
1120
|
if (effective) props.push(prop("effectiveDateTime", str(`${String(y)}-${m}-${d}`)));
|
|
1052
1121
|
props.push(prop("valueQuantity", valueQuantity(rng, concept)));
|
|
1053
|
-
return complex(props);
|
|
1122
|
+
return fhirPeer().complex(props);
|
|
1054
1123
|
}
|
|
1055
1124
|
function generateObservationLab(options = {}) {
|
|
1056
1125
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
@@ -1076,6 +1145,8 @@ function generateVitalSign(options = {}) {
|
|
|
1076
1145
|
true
|
|
1077
1146
|
);
|
|
1078
1147
|
}
|
|
1148
|
+
|
|
1149
|
+
// src/fhir/medication-request.ts
|
|
1079
1150
|
function generateMedicationRequest(options = {}) {
|
|
1080
1151
|
const {
|
|
1081
1152
|
seed = 0,
|
|
@@ -1100,8 +1171,10 @@ function generateMedicationRequest(options = {}) {
|
|
|
1100
1171
|
props.push(prop("subject", reference(subject)));
|
|
1101
1172
|
props.push(prop("authoredOn", str(`${String(y)}-${m}-${d}`)));
|
|
1102
1173
|
props.push(prop("requester", reference(requester)));
|
|
1103
|
-
return complex(props);
|
|
1174
|
+
return fhirPeer().complex(props);
|
|
1104
1175
|
}
|
|
1176
|
+
|
|
1177
|
+
// src/fhir/encounter.ts
|
|
1105
1178
|
function generateEncounter(options = {}) {
|
|
1106
1179
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
1107
1180
|
const rng = createRng(seed);
|
|
@@ -1118,8 +1191,8 @@ function generateEncounter(options = {}) {
|
|
|
1118
1191
|
props.push(
|
|
1119
1192
|
prop(
|
|
1120
1193
|
"identifier",
|
|
1121
|
-
list([
|
|
1122
|
-
complex([
|
|
1194
|
+
fhirPeer().list([
|
|
1195
|
+
fhirPeer().complex([
|
|
1123
1196
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1124
1197
|
prop("value", str(id.value))
|
|
1125
1198
|
])
|
|
@@ -1128,11 +1201,13 @@ function generateEncounter(options = {}) {
|
|
|
1128
1201
|
);
|
|
1129
1202
|
props.push(prop("status", str("finished")));
|
|
1130
1203
|
props.push(prop("class", coding(cls)));
|
|
1131
|
-
props.push(prop("type", list([codeableConcept(type)])));
|
|
1204
|
+
props.push(prop("type", fhirPeer().list([codeableConcept(type)])));
|
|
1132
1205
|
props.push(prop("subject", reference(subject)));
|
|
1133
|
-
props.push(prop("period", complex([prop("start", str(`${start}T09:00:00Z`))])));
|
|
1134
|
-
return complex(props);
|
|
1206
|
+
props.push(prop("period", fhirPeer().complex([prop("start", str(`${start}T09:00:00Z`))])));
|
|
1207
|
+
return fhirPeer().complex(props);
|
|
1135
1208
|
}
|
|
1209
|
+
|
|
1210
|
+
// src/fhir/immunization.ts
|
|
1136
1211
|
function generateImmunization(options = {}) {
|
|
1137
1212
|
const { seed = 0, patient = "Patient/syn-patient-1", usCore = true } = options;
|
|
1138
1213
|
const rng = createRng(seed);
|
|
@@ -1149,8 +1224,10 @@ function generateImmunization(options = {}) {
|
|
|
1149
1224
|
props.push(prop("patient", reference(patient)));
|
|
1150
1225
|
props.push(prop("occurrenceDateTime", str(occurrence)));
|
|
1151
1226
|
props.push(prop("primarySource", bool(true)));
|
|
1152
|
-
return complex(props);
|
|
1227
|
+
return fhirPeer().complex(props);
|
|
1153
1228
|
}
|
|
1229
|
+
|
|
1230
|
+
// src/fhir/allergy-intolerance.ts
|
|
1154
1231
|
function generateAllergyIntolerance(options = {}) {
|
|
1155
1232
|
const { seed = 0, patient = "Patient/syn-patient-1", usCore = true } = options;
|
|
1156
1233
|
const rng = createRng(seed);
|
|
@@ -1183,11 +1260,17 @@ function generateAllergyIntolerance(options = {}) {
|
|
|
1183
1260
|
props.push(
|
|
1184
1261
|
prop(
|
|
1185
1262
|
"reaction",
|
|
1186
|
-
|
|
1263
|
+
fhirPeer().list([
|
|
1264
|
+
fhirPeer().complex([
|
|
1265
|
+
prop("manifestation", fhirPeer().list([codeableConcept(manifestation)]))
|
|
1266
|
+
])
|
|
1267
|
+
])
|
|
1187
1268
|
)
|
|
1188
1269
|
);
|
|
1189
|
-
return complex(props);
|
|
1270
|
+
return fhirPeer().complex(props);
|
|
1190
1271
|
}
|
|
1272
|
+
|
|
1273
|
+
// src/fhir/procedure.ts
|
|
1191
1274
|
function generateProcedure(options = {}) {
|
|
1192
1275
|
const { seed = 0, subject = "Patient/syn-patient-1", usCore = true } = options;
|
|
1193
1276
|
const rng = createRng(seed);
|
|
@@ -1203,8 +1286,10 @@ function generateProcedure(options = {}) {
|
|
|
1203
1286
|
props.push(prop("code", codeableConcept(code)));
|
|
1204
1287
|
props.push(prop("subject", reference(subject)));
|
|
1205
1288
|
props.push(prop("performedDateTime", str(`${performed}T10:00:00Z`)));
|
|
1206
|
-
return complex(props);
|
|
1289
|
+
return fhirPeer().complex(props);
|
|
1207
1290
|
}
|
|
1291
|
+
|
|
1292
|
+
// src/fhir/provenance.ts
|
|
1208
1293
|
function generateProvenance(options = {}) {
|
|
1209
1294
|
const { seed = 0, target = "Patient/syn-patient-1", usCore = true } = options;
|
|
1210
1295
|
const rng = createRng(seed);
|
|
@@ -1217,19 +1302,19 @@ function generateProvenance(options = {}) {
|
|
|
1217
1302
|
];
|
|
1218
1303
|
if (usCore) props.push(prop("meta", meta([US_CORE_PROFILE.PROVENANCE])));
|
|
1219
1304
|
props.push(prop("text", narrative("Synthetic provenance for a generated fixture.")));
|
|
1220
|
-
props.push(prop("target", list([reference(target)])));
|
|
1305
|
+
props.push(prop("target", fhirPeer().list([reference(target)])));
|
|
1221
1306
|
props.push(prop("recorded", str(`${recorded}T10:00:00Z`)));
|
|
1222
1307
|
props.push(
|
|
1223
1308
|
prop(
|
|
1224
1309
|
"agent",
|
|
1225
|
-
list([
|
|
1226
|
-
complex([
|
|
1310
|
+
fhirPeer().list([
|
|
1311
|
+
fhirPeer().complex([
|
|
1227
1312
|
prop(
|
|
1228
1313
|
"type",
|
|
1229
|
-
complex([
|
|
1314
|
+
fhirPeer().complex([
|
|
1230
1315
|
prop(
|
|
1231
1316
|
"coding",
|
|
1232
|
-
list([
|
|
1317
|
+
fhirPeer().list([
|
|
1233
1318
|
coding({
|
|
1234
1319
|
system: SYSTEM.PROVENANCE_PARTICIPANT_TYPE,
|
|
1235
1320
|
code: "author",
|
|
@@ -1250,8 +1335,10 @@ function generateProvenance(options = {}) {
|
|
|
1250
1335
|
])
|
|
1251
1336
|
)
|
|
1252
1337
|
);
|
|
1253
|
-
return complex(props);
|
|
1338
|
+
return fhirPeer().complex(props);
|
|
1254
1339
|
}
|
|
1340
|
+
|
|
1341
|
+
// src/fhir/diagnostic-report.ts
|
|
1255
1342
|
function generateDiagnosticReport(options = {}) {
|
|
1256
1343
|
const { seed = 0, subject = "Patient/syn-patient-1", results = [], usCore = true } = options;
|
|
1257
1344
|
const rng = createRng(seed);
|
|
@@ -1267,7 +1354,7 @@ function generateDiagnosticReport(options = {}) {
|
|
|
1267
1354
|
props.push(
|
|
1268
1355
|
prop(
|
|
1269
1356
|
"category",
|
|
1270
|
-
list([
|
|
1357
|
+
fhirPeer().list([
|
|
1271
1358
|
codeableConcept({
|
|
1272
1359
|
system: SYSTEM.DIAGNOSTIC_SERVICE_SECTION,
|
|
1273
1360
|
code: "LAB",
|
|
@@ -1281,12 +1368,13 @@ function generateDiagnosticReport(options = {}) {
|
|
|
1281
1368
|
props.push(prop("effectiveDateTime", str(`${day}T08:30:00Z`)));
|
|
1282
1369
|
props.push(prop("issued", str(`${day}T09:00:00.000Z`)));
|
|
1283
1370
|
if (results.length > 0) {
|
|
1284
|
-
props.push(prop("result", list(results.map((r) => reference(r)))));
|
|
1371
|
+
props.push(prop("result", fhirPeer().list(results.map((r) => reference(r)))));
|
|
1285
1372
|
}
|
|
1286
|
-
return complex(props);
|
|
1373
|
+
return fhirPeer().complex(props);
|
|
1287
1374
|
}
|
|
1288
1375
|
|
|
1289
1376
|
// src/corpus.ts
|
|
1377
|
+
var UNCHECKED = Object.freeze([]);
|
|
1290
1378
|
function makeCorpus(seed, artifacts, quirks = []) {
|
|
1291
1379
|
const counts = {};
|
|
1292
1380
|
const formats = /* @__PURE__ */ new Set();
|
|
@@ -1306,11 +1394,13 @@ function makeCorpus(seed, artifacts, quirks = []) {
|
|
|
1306
1394
|
artifacts: Object.freeze(frozenArtifacts)
|
|
1307
1395
|
});
|
|
1308
1396
|
}
|
|
1397
|
+
|
|
1398
|
+
// src/fhir/composition.ts
|
|
1309
1399
|
function section(sec) {
|
|
1310
|
-
return complex([
|
|
1400
|
+
return fhirPeer().complex([
|
|
1311
1401
|
prop("title", str(sec.title)),
|
|
1312
1402
|
prop("code", codeableConcept({ system: SYSTEM.LOINC, code: sec.code, display: sec.title })),
|
|
1313
|
-
prop("entry", list(sec.entries.map((e) => reference(e))))
|
|
1403
|
+
prop("entry", fhirPeer().list(sec.entries.map((e) => reference(e))))
|
|
1314
1404
|
]);
|
|
1315
1405
|
}
|
|
1316
1406
|
function buildComposition(rng, input) {
|
|
@@ -1329,18 +1419,20 @@ function buildComposition(rng, input) {
|
|
|
1329
1419
|
),
|
|
1330
1420
|
prop("subject", reference(input.subject)),
|
|
1331
1421
|
prop("date", str(`${input.date}T09:00:00Z`)),
|
|
1332
|
-
prop("author", list([reference(input.organization)])),
|
|
1422
|
+
prop("author", fhirPeer().list([reference(input.organization)])),
|
|
1333
1423
|
prop("title", str("Synthetic Continuity of Care Document")),
|
|
1334
1424
|
prop("custodian", reference(input.organization)),
|
|
1335
|
-
prop("section", list(input.sections.map((s) => section(s))))
|
|
1425
|
+
prop("section", fhirPeer().list(input.sections.map((s) => section(s))))
|
|
1336
1426
|
];
|
|
1337
|
-
return complex(props);
|
|
1427
|
+
return fhirPeer().complex(props);
|
|
1338
1428
|
}
|
|
1429
|
+
|
|
1430
|
+
// src/fhir/round-trip.ts
|
|
1339
1431
|
function roundTrip(resource, options = {}) {
|
|
1340
|
-
const content = serializeResource(resource);
|
|
1341
|
-
const { resource: reparsed } = parseResource(content);
|
|
1342
|
-
const byteStable = serializeResource(reparsed) === content;
|
|
1343
|
-
const result = validateResource(
|
|
1432
|
+
const content = fhirPeer().serializeResource(resource);
|
|
1433
|
+
const { resource: reparsed } = fhirPeer().parseResource(content);
|
|
1434
|
+
const byteStable = fhirPeer().serializeResource(reparsed) === content;
|
|
1435
|
+
const result = fhirPeer().validateResource(
|
|
1344
1436
|
reparsed,
|
|
1345
1437
|
options.profiles !== void 0 ? { mode: "strict", profiles: options.profiles } : { mode: "strict" }
|
|
1346
1438
|
);
|
|
@@ -1349,6 +1441,13 @@ function roundTrip(resource, options = {}) {
|
|
|
1349
1441
|
const valid = result.valid;
|
|
1350
1442
|
return { content, errors, warnings, byteStable, valid, specClean: valid && byteStable };
|
|
1351
1443
|
}
|
|
1444
|
+
function fhirCorpusArtifact(resource, verify) {
|
|
1445
|
+
const content = fhirPeer().serializeResource(resource);
|
|
1446
|
+
if (!verify) return { content, warnings: UNCHECKED };
|
|
1447
|
+
const { resource: reparsed } = fhirPeer().parseResource(content);
|
|
1448
|
+
const warnings = fhirPeer().validateResource(reparsed, { mode: "strict" }).issues.filter((i) => i.severity === "error" || i.severity === "fatal").map((i) => i.code);
|
|
1449
|
+
return { content, warnings };
|
|
1450
|
+
}
|
|
1352
1451
|
|
|
1353
1452
|
// src/fhir/bundle.ts
|
|
1354
1453
|
var BUNDLE_TYPES = Object.freeze([
|
|
@@ -1362,14 +1461,14 @@ function resourceTypeOf(resource) {
|
|
|
1362
1461
|
}
|
|
1363
1462
|
function buildOrganization(rng) {
|
|
1364
1463
|
const id = safe.identifier(rng, "AN");
|
|
1365
|
-
return complex([
|
|
1464
|
+
return fhirPeer().complex([
|
|
1366
1465
|
prop("resourceType", str("Organization")),
|
|
1367
1466
|
prop("id", str(`syn-org-${rng.digits(8)}`)),
|
|
1368
1467
|
prop("text", narrative("Synthetic health organization.")),
|
|
1369
1468
|
prop(
|
|
1370
1469
|
"identifier",
|
|
1371
|
-
list([
|
|
1372
|
-
complex([
|
|
1470
|
+
fhirPeer().list([
|
|
1471
|
+
fhirPeer().complex([
|
|
1373
1472
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1374
1473
|
prop("value", str(id.value))
|
|
1375
1474
|
])
|
|
@@ -1482,11 +1581,14 @@ function generateBundle(options = {}) {
|
|
|
1482
1581
|
entryProps.push(
|
|
1483
1582
|
prop(
|
|
1484
1583
|
"request",
|
|
1485
|
-
complex([
|
|
1584
|
+
fhirPeer().complex([
|
|
1585
|
+
prop("method", str("POST")),
|
|
1586
|
+
prop("url", str(resourceTypeOf(member.resource)))
|
|
1587
|
+
])
|
|
1486
1588
|
)
|
|
1487
1589
|
);
|
|
1488
1590
|
}
|
|
1489
|
-
return complex(entryProps);
|
|
1591
|
+
return fhirPeer().complex(entryProps);
|
|
1490
1592
|
});
|
|
1491
1593
|
const props = [
|
|
1492
1594
|
prop("resourceType", str("Bundle")),
|
|
@@ -1497,7 +1599,7 @@ function generateBundle(options = {}) {
|
|
|
1497
1599
|
props.push(
|
|
1498
1600
|
prop(
|
|
1499
1601
|
"identifier",
|
|
1500
|
-
complex([
|
|
1602
|
+
fhirPeer().complex([
|
|
1501
1603
|
prop("system", str(`urn:oid:${id.assigningAuthorityOid}`)),
|
|
1502
1604
|
prop("value", str(`urn:uuid:${safe.uuid(rng)}`))
|
|
1503
1605
|
])
|
|
@@ -1506,8 +1608,8 @@ function generateBundle(options = {}) {
|
|
|
1506
1608
|
}
|
|
1507
1609
|
props.push(prop("type", str(type)));
|
|
1508
1610
|
if (type === "document") props.push(prop("timestamp", str(`${spine.date}T09:00:00.000Z`)));
|
|
1509
|
-
props.push(prop("entry", list(entries)));
|
|
1510
|
-
return complex(props);
|
|
1611
|
+
props.push(prop("entry", fhirPeer().list(entries)));
|
|
1612
|
+
return fhirPeer().complex(props);
|
|
1511
1613
|
}
|
|
1512
1614
|
var ALL_KINDS = Object.freeze([
|
|
1513
1615
|
"Patient",
|
|
@@ -1568,13 +1670,13 @@ function generateKind(kind, seed) {
|
|
|
1568
1670
|
}
|
|
1569
1671
|
}
|
|
1570
1672
|
function fhirCorpus(options) {
|
|
1571
|
-
const { seed, count = 1 } = options;
|
|
1673
|
+
const { seed, count = 1, verify = true } = options;
|
|
1572
1674
|
const kinds = resolveMix(ALL_KINDS, options.mix, DEFAULT_MIX);
|
|
1573
1675
|
const seedStream = createRng(seed);
|
|
1574
1676
|
const artifacts = Array.from({ length: count }, (_unused, i) => {
|
|
1575
1677
|
const kind = kinds[i % kinds.length] ?? "USCorePatient";
|
|
1576
|
-
const rt =
|
|
1577
|
-
return { format: "fhir", kind, content: rt.content, warnings: rt.
|
|
1678
|
+
const rt = fhirCorpusArtifact(generateKind(kind, seedStream.nextUint32()), verify);
|
|
1679
|
+
return { format: "fhir", kind, content: rt.content, warnings: rt.warnings };
|
|
1578
1680
|
});
|
|
1579
1681
|
return makeCorpus(seed, artifacts);
|
|
1580
1682
|
}
|