@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.
Files changed (49) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +14 -10
  3. package/dist/astm/index.cjs +164 -102
  4. package/dist/astm/index.cjs.map +1 -1
  5. package/dist/astm/index.d.cts +7 -0
  6. package/dist/astm/index.d.ts +7 -0
  7. package/dist/astm/index.mjs +163 -102
  8. package/dist/astm/index.mjs.map +1 -1
  9. package/dist/ccda/index.cjs +100 -28
  10. package/dist/ccda/index.cjs.map +1 -1
  11. package/dist/ccda/index.d.cts +6 -0
  12. package/dist/ccda/index.d.ts +6 -0
  13. package/dist/ccda/index.mjs +87 -16
  14. package/dist/ccda/index.mjs.map +1 -1
  15. package/dist/deid/index.cjs +305 -165
  16. package/dist/deid/index.cjs.map +1 -1
  17. package/dist/deid/index.mjs +292 -153
  18. package/dist/deid/index.mjs.map +1 -1
  19. package/dist/fhir/index.cjs +179 -76
  20. package/dist/fhir/index.cjs.map +1 -1
  21. package/dist/fhir/index.d.cts +6 -0
  22. package/dist/fhir/index.d.ts +6 -0
  23. package/dist/fhir/index.mjs +178 -76
  24. package/dist/fhir/index.mjs.map +1 -1
  25. package/dist/hl7/index.cjs +86 -12
  26. package/dist/hl7/index.cjs.map +1 -1
  27. package/dist/hl7/index.d.cts +6 -0
  28. package/dist/hl7/index.d.ts +6 -0
  29. package/dist/hl7/index.mjs +85 -12
  30. package/dist/hl7/index.mjs.map +1 -1
  31. package/dist/index.cjs +3 -5
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +8 -4
  34. package/dist/index.d.ts +8 -4
  35. package/dist/index.mjs +3 -5
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/ncpdp/index.cjs +131 -36
  38. package/dist/ncpdp/index.cjs.map +1 -1
  39. package/dist/ncpdp/index.d.cts +7 -0
  40. package/dist/ncpdp/index.d.ts +7 -0
  41. package/dist/ncpdp/index.mjs +130 -36
  42. package/dist/ncpdp/index.mjs.map +1 -1
  43. package/dist/x12/index.cjs +147 -50
  44. package/dist/x12/index.cjs.map +1 -1
  45. package/dist/x12/index.d.cts +6 -0
  46. package/dist/x12/index.d.ts +6 -0
  47. package/dist/x12/index.mjs +146 -50
  48. package/dist/x12/index.mjs.map +1 -1
  49. package/package.json +20 -15
@@ -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
@@ -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
@@ -1,6 +1,12 @@
1
- import { list, complex, primitive, decimal, serializeResource, parseResource, validateResource } from '@cosyte/fhir';
1
+ import { createRequire } from 'module';
2
+ import { fileURLToPath } from 'url';
2
3
 
3
- // src/fhir/patient.ts
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
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([prop("url", str("ombCategory")), prop("valueCoding", coding(category))]),
883
- complex([prop("url", str("text")), prop("valueString", str(category.display))])
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([prop("url", str(US_CORE_BIRTHSEX_EXTENSION)), prop("valueCode", str(birthsex))])
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
- list([complex([prop("manifestation", list([codeableConcept(manifestation)]))])])
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([prop("method", str("POST")), prop("url", str(resourceTypeOf(member.resource)))])
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 = roundTrip(generateKind(kind, seedStream.nextUint32()));
1577
- return { format: "fhir", kind, content: rt.content, warnings: rt.errors };
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
  }