@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
@@ -1,6 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var ccda = require('@cosyte/ccda');
3
+ var module$1 = require('module');
4
+ var url = require('url');
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
+ });
4
13
 
5
14
  // src/rng/splitmix32.ts
6
15
  function splitmix32(seed) {
@@ -32,7 +41,16 @@ function sfc32Next(s) {
32
41
  }
33
42
 
34
43
  // src/codes.ts
35
- 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",
36
54
  /**
37
55
  * A vendor quirk was requested that the target format's profile system does not support. Fatal,
38
56
  * never a silent no-op and never a fabricated quirk.
@@ -51,6 +69,8 @@ var SYNTH_FATAL_CODES = {
51
69
  SYNTH_INTENDED_WARNING_MISMATCH: "SYNTH_INTENDED_WARNING_MISMATCH",
52
70
  /** A concept's code-system URI has no OID mapping in the C-CDA example-code table. Fatal. */
53
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",
54
74
  /** An integer range was requested with its maximum below its minimum. Fatal. */
55
75
  SYNTH_INVALID_RANGE: "SYNTH_INVALID_RANGE",
56
76
  /** A value was drawn from an empty pool. Fatal, never a fabricated substitute. */
@@ -63,7 +83,17 @@ var SYNTH_FATAL_CODES = {
63
83
  * see `resolveKind`: a selector union is erased at run time, and a selector that falls through
64
84
  * either mislabels the fixture or hands the value to a peer builder that quotes it back.
65
85
  */
66
- SYNTH_UNSUPPORTED_KIND: "SYNTH_UNSUPPORTED_KIND"};
86
+ SYNTH_UNSUPPORTED_KIND: "SYNTH_UNSUPPORTED_KIND",
87
+ /**
88
+ * A requested profile IS published by the adopted implementation guide, and this build does not
89
+ * generate it. Deliberately distinct from `SYNTH_UNSUPPORTED_KIND`, which says the name is not in
90
+ * the adopted set at all: "the guide does not publish this" and "we do not generate this yet" are
91
+ * different answers, and a caller building to a regulatory profile set has to be able to tell them
92
+ * apart without matching message text. Fatal, and raised **before** anything is generated: a
93
+ * mislabelled artifact is worse than no artifact.
94
+ */
95
+ SYNTH_PROFILE_NOT_GENERATED: "SYNTH_PROFILE_NOT_GENERATED"
96
+ });
67
97
  var SYNTH_FATAL_MESSAGES = Object.freeze({
68
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.",
69
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).",
@@ -129,6 +159,7 @@ function createRng(seed) {
129
159
  }
130
160
 
131
161
  // src/corpus.ts
162
+ var UNCHECKED = Object.freeze([]);
132
163
  function makeCorpus(seed, artifacts, quirks = []) {
133
164
  const counts = {};
134
165
  const formats = /* @__PURE__ */ new Set();
@@ -739,11 +770,21 @@ Object.freeze([
739
770
  ]);
740
771
 
741
772
  // src/ccda/example-codes.ts
773
+ var LOINC_OID = "2.16.840.1.113883.6.1";
774
+ var SNOMED_CT_OID = "2.16.840.1.113883.6.96";
775
+ var RXNORM_OID = "2.16.840.1.113883.6.88";
776
+ var CVX_OID = "2.16.840.1.113883.12.292";
777
+ var NCI_ROUTE_OID = "2.16.840.1.113883.3.26.1.1";
778
+ var LOINC = LOINC_OID;
779
+ var SNOMED_CT = SNOMED_CT_OID;
780
+ var RXNORM = RXNORM_OID;
781
+ var CVX = CVX_OID;
782
+ var NCI_ROUTE = NCI_ROUTE_OID;
742
783
  var URI_TO_OID = Object.freeze({
743
- "http://loinc.org": ccda.LOINC,
744
- "http://snomed.info/sct": ccda.SNOMED_CT,
745
- "http://www.nlm.nih.gov/research/umls/rxnorm": ccda.RXNORM,
746
- "http://hl7.org/fhir/sid/cvx": ccda.CVX
784
+ "http://loinc.org": LOINC,
785
+ "http://snomed.info/sct": SNOMED_CT,
786
+ "http://www.nlm.nih.gov/research/umls/rxnorm": RXNORM,
787
+ "http://hl7.org/fhir/sid/cvx": CVX
747
788
  });
748
789
  function toBuildCode(concept) {
749
790
  const codeSystem = URI_TO_OID[concept.system];
@@ -767,24 +808,24 @@ var VITAL_SIGNS = EXAMPLE_VITAL_SIGNS;
767
808
  var VACCINES = EXAMPLE_VACCINES;
768
809
  var PROCEDURES = EXAMPLE_PROCEDURES;
769
810
  var SMOKING_STATUSES = Object.freeze([
770
- Object.freeze({ code: "266919005", codeSystem: ccda.SNOMED_CT, displayName: "Never smoker" }),
771
- Object.freeze({ code: "8517006", codeSystem: ccda.SNOMED_CT, displayName: "Former smoker" }),
811
+ Object.freeze({ code: "266919005", codeSystem: SNOMED_CT, displayName: "Never smoker" }),
812
+ Object.freeze({ code: "8517006", codeSystem: SNOMED_CT, displayName: "Former smoker" }),
772
813
  Object.freeze({
773
814
  code: "449868002",
774
- codeSystem: ccda.SNOMED_CT,
815
+ codeSystem: SNOMED_CT,
775
816
  displayName: "Current every day smoker"
776
817
  }),
777
818
  Object.freeze({
778
819
  code: "428041000124106",
779
- codeSystem: ccda.SNOMED_CT,
820
+ codeSystem: SNOMED_CT,
780
821
  displayName: "Current some day smoker"
781
822
  })
782
823
  ]);
783
824
  var ROUTES = Object.freeze([
784
- Object.freeze({ code: "C38288", codeSystem: ccda.NCI_ROUTE, displayName: "Oral" }),
785
- Object.freeze({ code: "C28161", codeSystem: ccda.NCI_ROUTE, displayName: "Intramuscular" }),
786
- Object.freeze({ code: "C38276", codeSystem: ccda.NCI_ROUTE, displayName: "Intravenous" }),
787
- Object.freeze({ code: "C38299", codeSystem: ccda.NCI_ROUTE, displayName: "Subcutaneous" })
825
+ Object.freeze({ code: "C38288", codeSystem: NCI_ROUTE, displayName: "Oral" }),
826
+ Object.freeze({ code: "C28161", codeSystem: NCI_ROUTE, displayName: "Intramuscular" }),
827
+ Object.freeze({ code: "C38276", codeSystem: NCI_ROUTE, displayName: "Intravenous" }),
828
+ Object.freeze({ code: "C38299", codeSystem: NCI_ROUTE, displayName: "Subcutaneous" })
788
829
  ]);
789
830
 
790
831
  // src/ccda/identity.ts
@@ -815,6 +856,28 @@ function resolveMix(allowed, requested, fallback) {
815
856
  if (requested === void 0) return fallback;
816
857
  return requested.map((entry) => resolveKind(allowed, entry));
817
858
  }
859
+ function defaultHost() {
860
+ if (typeof undefined !== "function") return { require: __require, resolve: void 0 };
861
+ 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) };
862
+ }
863
+ function isRequireEsmRefusal(error) {
864
+ return error?.code === "ERR_REQUIRE_ESM";
865
+ }
866
+ function loadPeer(specifier, host) {
867
+ if (host.resolve === void 0) return host.require(specifier);
868
+ const entry = url.fileURLToPath(host.resolve(specifier));
869
+ try {
870
+ return host.require(entry);
871
+ } catch (error) {
872
+ if (!isRequireEsmRefusal(error)) throw error;
873
+ return host.require(specifier);
874
+ }
875
+ }
876
+ function lazyPeer(specifier, host) {
877
+ let loaded;
878
+ return () => loaded ??= loadPeer(specifier, defaultHost());
879
+ }
880
+ var ccdaPeer = lazyPeer("@cosyte/ccda");
818
881
 
819
882
  // src/ccda/ccd.ts
820
883
  var CCDA_DOCUMENT_TYPES = Object.freeze(["ccd", "referralNote"]);
@@ -903,7 +966,7 @@ function generateCcda(options = {}) {
903
966
  const { seed = 0 } = options;
904
967
  const documentType = resolveKind(CCDA_DOCUMENT_TYPES, options.documentType ?? "ccd");
905
968
  const rng = createRng(seed);
906
- return ccda.buildCcda(buildInit(rng, documentType));
969
+ return ccdaPeer().buildCcda(buildInit(rng, documentType));
907
970
  }
908
971
  function generateCcd(options = {}) {
909
972
  return generateCcda({ ...options, documentType: "ccd" });
@@ -911,11 +974,13 @@ function generateCcd(options = {}) {
911
974
  function generateReferralNote(options = {}) {
912
975
  return generateCcda({ ...options, documentType: "referralNote" });
913
976
  }
977
+
978
+ // src/ccda/round-trip.ts
914
979
  function roundTrip(doc) {
915
- const content = ccda.serializeCcda(doc);
916
- const reparsed = ccda.parseCcda(content);
980
+ const content = ccdaPeer().serializeCcda(doc);
981
+ const reparsed = ccdaPeer().parseCcda(content);
917
982
  const warnings = reparsed.warnings.map((w) => String(w.code));
918
- const byteStable = ccda.serializeCcda(reparsed) === content;
983
+ const byteStable = ccdaPeer().serializeCcda(reparsed) === content;
919
984
  return {
920
985
  content,
921
986
  warnings,
@@ -923,6 +988,14 @@ function roundTrip(doc) {
923
988
  specClean: warnings.length === 0 && byteStable
924
989
  };
925
990
  }
991
+ function ccdaCorpusArtifact(doc, verify) {
992
+ const content = ccdaPeer().serializeCcda(doc);
993
+ if (!verify) return { content, warnings: UNCHECKED };
994
+ return {
995
+ content,
996
+ warnings: ccdaPeer().parseCcda(content).warnings.map((w) => String(w.code))
997
+ };
998
+ }
926
999
 
927
1000
  // src/profile.ts
928
1001
  function defineSynthProfile(spec) {
@@ -1007,7 +1080,7 @@ var CCDA_QUIRKS = Object.freeze({
1007
1080
  })
1008
1081
  });
1009
1082
  function toleratingProfile(quirk) {
1010
- return quirk === "template-extension-absent" ? ccda.ccdaProfiles.legacyR11 : ccda.ccdaProfiles.smartScorecard;
1083
+ return quirk === "template-extension-absent" ? ccdaPeer().ccdaProfiles.legacyR11 : ccdaPeer().ccdaProfiles.smartScorecard;
1011
1084
  }
1012
1085
  var DOC_TEMPLATE_ROOTS = [
1013
1086
  "2.16.840.1.113883.10.20.22.1.1",
@@ -1047,11 +1120,11 @@ function generateCcdaQuirk(options) {
1047
1120
  const seed = options.seed ?? 0;
1048
1121
  const documentType = options.documentType ?? "ccd";
1049
1122
  const descriptor = resolveQuirk(CCDA_QUIRKS, "ccda", options.quirk);
1050
- const clean = ccda.serializeCcda(generateCcda({ seed, documentType }));
1123
+ const clean = ccdaPeer().serializeCcda(generateCcda({ seed, documentType }));
1051
1124
  const content = injectCcdaQuirk(options.quirk, clean);
1052
1125
  assertIntendedWarnings(
1053
1126
  descriptor.intendedWarnings,
1054
- ccda.parseCcda(content).warnings.map((w) => String(w.code))
1127
+ ccdaPeer().parseCcda(content).warnings.map((w) => String(w.code))
1055
1128
  );
1056
1129
  return Object.freeze({
1057
1130
  format: "ccda",
@@ -1064,17 +1137,16 @@ function generateCcdaQuirk(options) {
1064
1137
  function ccdaQuirkRoundTrip(artifact) {
1065
1138
  const quirk = artifact.quirk;
1066
1139
  const descriptor = resolveQuirk(CCDA_QUIRKS, "ccda", quirk);
1067
- const bare = ccda.parseCcda(artifact.content).warnings.map((w) => String(w.code));
1140
+ const bare = ccdaPeer().parseCcda(artifact.content).warnings.map((w) => String(w.code));
1068
1141
  const profile = toleratingProfile(quirk);
1069
- const profiledWarnings = ccda.parseCcda(artifact.content, { profile }).warnings.map(
1070
- (w) => String(w.code)
1071
- );
1142
+ const profiledWarnings = ccdaPeer().parseCcda(artifact.content, { profile }).warnings.map((w) => String(w.code));
1072
1143
  return {
1073
1144
  content: artifact.content,
1074
1145
  warnings: bare,
1075
1146
  intendedWarnings: artifact.intendedWarnings,
1076
1147
  intendedWarningHeld: sameCodeSet(bare, artifact.intendedWarnings),
1077
1148
  withProfile: {
1149
+ /* v8 ignore next -- the `?? profile.name` is unreachable: every descriptor in the frozen CCDA_QUIRKS names its toleratingProfile */
1078
1150
  profileName: descriptor.toleratingProfile ?? profile.name,
1079
1151
  disposition: descriptor.disposition,
1080
1152
  warnings: profiledWarnings,
@@ -1118,13 +1190,13 @@ var ccdaQuirkProfile = defineSynthProfile({
1118
1190
  var ALL_KINDS = Object.freeze(["ccd", "referralNote"]);
1119
1191
  var DEFAULT_MIX = ALL_KINDS;
1120
1192
  function ccdaCorpus(options) {
1121
- const { seed, count = 1 } = options;
1193
+ const { seed, count = 1, verify = true } = options;
1122
1194
  const mix = resolveMix(ALL_KINDS, options.mix, DEFAULT_MIX);
1123
1195
  const seedStream = createRng(seed);
1124
1196
  const artifacts = Array.from({ length: count }, (_unused, i) => {
1125
1197
  const documentType = mix[i % mix.length] ?? "ccd";
1126
1198
  const docSeed = seedStream.nextUint32();
1127
- const rt = roundTrip(generateCcda({ seed: docSeed, documentType }));
1199
+ const rt = ccdaCorpusArtifact(generateCcda({ seed: docSeed, documentType }), verify);
1128
1200
  return {
1129
1201
  format: "ccda",
1130
1202
  kind: documentType,