@cosyte/synth 0.1.5 → 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 (46) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/astm/index.cjs +55 -18
  3. package/dist/astm/index.cjs.map +1 -1
  4. package/dist/astm/index.d.cts +7 -0
  5. package/dist/astm/index.d.ts +7 -0
  6. package/dist/astm/index.mjs +54 -18
  7. package/dist/astm/index.mjs.map +1 -1
  8. package/dist/ccda/index.cjs +76 -26
  9. package/dist/ccda/index.cjs.map +1 -1
  10. package/dist/ccda/index.d.cts +6 -0
  11. package/dist/ccda/index.d.ts +6 -0
  12. package/dist/ccda/index.mjs +63 -14
  13. package/dist/ccda/index.mjs.map +1 -1
  14. package/dist/deid/index.cjs +207 -118
  15. package/dist/deid/index.cjs.map +1 -1
  16. package/dist/deid/index.mjs +194 -106
  17. package/dist/deid/index.mjs.map +1 -1
  18. package/dist/fhir/index.cjs +146 -74
  19. package/dist/fhir/index.cjs.map +1 -1
  20. package/dist/fhir/index.d.cts +6 -0
  21. package/dist/fhir/index.d.ts +6 -0
  22. package/dist/fhir/index.mjs +145 -74
  23. package/dist/fhir/index.mjs.map +1 -1
  24. package/dist/hl7/index.cjs +53 -9
  25. package/dist/hl7/index.cjs.map +1 -1
  26. package/dist/hl7/index.d.cts +6 -0
  27. package/dist/hl7/index.d.ts +6 -0
  28. package/dist/hl7/index.mjs +52 -9
  29. package/dist/hl7/index.mjs.map +1 -1
  30. package/dist/index.cjs +1 -3
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.mjs +1 -3
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/ncpdp/index.cjs +74 -22
  35. package/dist/ncpdp/index.cjs.map +1 -1
  36. package/dist/ncpdp/index.d.cts +7 -0
  37. package/dist/ncpdp/index.d.ts +7 -0
  38. package/dist/ncpdp/index.mjs +73 -22
  39. package/dist/ncpdp/index.mjs.map +1 -1
  40. package/dist/x12/index.cjs +65 -17
  41. package/dist/x12/index.cjs.map +1 -1
  42. package/dist/x12/index.d.cts +6 -0
  43. package/dist/x12/index.d.ts +6 -0
  44. package/dist/x12/index.mjs +64 -17
  45. package/dist/x12/index.mjs.map +1 -1
  46. package/package.json +20 -15
@@ -158,6 +158,7 @@ declare function generateB3(options: GenerateTelecomOptions): string;
158
158
  *
159
159
  * @module
160
160
  */
161
+
161
162
  /** The verdict of one round-trip through `@cosyte/ncpdp`. */
162
163
  interface RoundTripResult {
163
164
  /** The serialized NCPDP wire text (the serializer's own conservative emit). */
@@ -412,6 +413,12 @@ interface NcpdpCorpusOptions {
412
413
  readonly count?: number;
413
414
  /** The transaction kinds to cycle through. Defaults to one of each. */
414
415
  readonly mix?: readonly NcpdpCorpusKind[];
416
+ /**
417
+ * Whether each artifact is read back through its parser and the parser's findings recorded as its
418
+ * `warnings`. Defaults to `true`. `false` skips the read, a large share of a corpus's time; every
419
+ * artifact's `warnings` is then empty without having been checked.
420
+ */
421
+ readonly verify?: boolean;
415
422
  }
416
423
  /**
417
424
  * Build a reproducible {@link Corpus} of spec-clean NCPDP transactions. Each transaction is generated
@@ -158,6 +158,7 @@ declare function generateB3(options: GenerateTelecomOptions): string;
158
158
  *
159
159
  * @module
160
160
  */
161
+
161
162
  /** The verdict of one round-trip through `@cosyte/ncpdp`. */
162
163
  interface RoundTripResult {
163
164
  /** The serialized NCPDP wire text (the serializer's own conservative emit). */
@@ -412,6 +413,12 @@ interface NcpdpCorpusOptions {
412
413
  readonly count?: number;
413
414
  /** The transaction kinds to cycle through. Defaults to one of each. */
414
415
  readonly mix?: readonly NcpdpCorpusKind[];
416
+ /**
417
+ * Whether each artifact is read back through its parser and the parser's findings recorded as its
418
+ * `warnings`. Defaults to `true`. `false` skips the read, a large share of a corpus's time; every
419
+ * artifact's `warnings` is then empty without having been checked.
420
+ */
421
+ readonly verify?: boolean;
415
422
  }
416
423
  /**
417
424
  * Build a reproducible {@link Corpus} of spec-clean NCPDP transactions. Each transaction is generated
@@ -1,6 +1,12 @@
1
- import { buildNewRx, serializeScript, ScriptMessage, parseScript } from '@cosyte/ncpdp/script';
2
- import { decimalValue, codedValue } from '@cosyte/ncpdp/common';
3
- import { serializeTelecom, buildTelecomRequest, parseTelecom } from '@cosyte/ncpdp/telecom';
1
+ import { createRequire } from 'module';
2
+ import { fileURLToPath } from 'url';
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) {
@@ -150,6 +156,7 @@ function createRng(seed) {
150
156
  }
151
157
 
152
158
  // src/corpus.ts
159
+ var UNCHECKED = Object.freeze([]);
153
160
  function makeCorpus(seed, artifacts, quirks = []) {
154
161
  const counts = {};
155
162
  const formats = /* @__PURE__ */ new Set();
@@ -528,6 +535,30 @@ var EXAMPLE_SIG_TEXT = Object.freeze([
528
535
  "Inhale 2 puffs by mouth every 4 to 6 hours as needed"
529
536
  ]);
530
537
  var DAW_CODES = Object.freeze(["0", "1", "2"]);
538
+ function defaultHost() {
539
+ if (typeof import.meta.resolve !== "function") return { require: __require, resolve: void 0 };
540
+ return { require: createRequire(import.meta.url), resolve: (s) => import.meta.resolve(s) };
541
+ }
542
+ function isRequireEsmRefusal(error) {
543
+ return error?.code === "ERR_REQUIRE_ESM";
544
+ }
545
+ function loadPeer(specifier, host) {
546
+ if (host.resolve === void 0) return host.require(specifier);
547
+ const entry = fileURLToPath(host.resolve(specifier));
548
+ try {
549
+ return host.require(entry);
550
+ } catch (error) {
551
+ if (!isRequireEsmRefusal(error)) throw error;
552
+ return host.require(specifier);
553
+ }
554
+ }
555
+ function lazyPeer(specifier, host) {
556
+ let loaded;
557
+ return () => loaded ??= loadPeer(specifier, defaultHost());
558
+ }
559
+ var ncpdpScriptPeer = lazyPeer("@cosyte/ncpdp/script");
560
+ var ncpdpTelecomPeer = lazyPeer("@cosyte/ncpdp/telecom");
561
+ var ncpdpCommonPeer = lazyPeer("@cosyte/ncpdp/common");
531
562
 
532
563
  // src/ncpdp/script.ts
533
564
  var SCRIPT_VERSION = "2017071";
@@ -558,13 +589,13 @@ function medicationModel(rng, routing) {
558
589
  const written = `${routing.date.slice(0, 4)}-${routing.date.slice(4, 6)}-${routing.date.slice(6, 8)}`;
559
590
  return {
560
591
  description: drug.description,
561
- coded: { productCode: codedValue(drug.ndc, "ND") },
592
+ coded: { productCode: ncpdpCommonPeer().codedValue(drug.ndc, "ND") },
562
593
  quantity: {
563
- value: decimalValue(String(rng.int(30, 90))),
594
+ value: ncpdpCommonPeer().decimalValue(String(rng.int(30, 90))),
564
595
  unitOfMeasure: drug.form,
565
596
  codeListQualifier: "38"
566
597
  },
567
- daysSupply: decimalValue(String(rng.pick([30, 60, 90]))),
598
+ daysSupply: ncpdpCommonPeer().decimalValue(String(rng.pick([30, 60, 90]))),
568
599
  numberOfRefills: String(rng.int(0, 5)),
569
600
  substitutions: rng.pick(["0", "1"]),
570
601
  writtenDate: written,
@@ -588,14 +619,14 @@ function generateNewRx(options) {
588
619
  const pharmacy = pharmacyModel(rng);
589
620
  const prescriber = prescriberModel(rng);
590
621
  const medication = medicationModel(rng, routing);
591
- const message = buildNewRx({
622
+ const message = ncpdpScriptPeer().buildNewRx({
592
623
  header: headerModel(routing),
593
624
  patient,
594
625
  pharmacy,
595
626
  prescriber,
596
627
  medication
597
628
  });
598
- return serializeScript(message);
629
+ return ncpdpScriptPeer().serializeScript(message);
599
630
  }
600
631
  function lifecycleFields(rng) {
601
632
  const routing = ncpdpScriptRouting(rng);
@@ -612,14 +643,20 @@ function generateRxRenewalRequest(options) {
612
643
  const rng = createRng(options.seed);
613
644
  const { header: header2, ...fields } = lifecycleFields(rng);
614
645
  const body = { kind: "RxRenewalRequest", ...fields };
615
- return serializeScript(new ScriptMessage({ header: header2, body, warnings: [] }));
646
+ return ncpdpScriptPeer().serializeScript(
647
+ new (ncpdpScriptPeer()).ScriptMessage({ header: header2, body, warnings: [] })
648
+ );
616
649
  }
617
650
  function generateRxChangeRequest(options) {
618
651
  const rng = createRng(options.seed);
619
652
  const { header: header2, ...fields } = lifecycleFields(rng);
620
653
  const body = { kind: "RxChangeRequest", ...fields };
621
- return serializeScript(new ScriptMessage({ header: header2, body, warnings: [] }));
654
+ return ncpdpScriptPeer().serializeScript(
655
+ new (ncpdpScriptPeer()).ScriptMessage({ header: header2, body, warnings: [] })
656
+ );
622
657
  }
658
+
659
+ // src/ncpdp/telecom.ts
623
660
  var SYNTHETIC_BIN = "999999";
624
661
  function digitsOnly(value) {
625
662
  return value.replace(/\D/g, "");
@@ -719,7 +756,9 @@ function generateTelecom(code, options) {
719
756
  prescriberSegment(rng),
720
757
  claimSegment(rng, false)
721
758
  ];
722
- return serializeTelecom(buildTelecomRequest({ header: head, segments }));
759
+ return ncpdpTelecomPeer().serializeTelecom(
760
+ ncpdpTelecomPeer().buildTelecomRequest({ header: head, segments })
761
+ );
723
762
  }
724
763
  function generateB1(options) {
725
764
  return generateTelecom("B1", options);
@@ -730,18 +769,30 @@ function generateB2(options) {
730
769
  function generateB3(options) {
731
770
  return generateTelecom("B3", options);
732
771
  }
772
+
773
+ // src/ncpdp/round-trip.ts
733
774
  function scriptRoundTrip(xml) {
734
- const message = parseScript(xml);
775
+ const message = ncpdpScriptPeer().parseScript(xml);
735
776
  const warnings = message.warnings.map((w) => String(w.code));
736
- const byteStable = serializeScript(message) === xml;
777
+ const byteStable = ncpdpScriptPeer().serializeScript(message) === xml;
737
778
  return { content: xml, warnings, byteStable, specClean: warnings.length === 0 && byteStable };
738
779
  }
739
780
  function telecomRoundTrip(wire) {
740
- const transaction = parseTelecom(wire);
781
+ const transaction = ncpdpTelecomPeer().parseTelecom(wire);
741
782
  const warnings = transaction.warnings.map((w) => String(w.code));
742
- const byteStable = serializeTelecom(transaction) === wire;
783
+ const byteStable = ncpdpTelecomPeer().serializeTelecom(transaction) === wire;
743
784
  return { content: wire, warnings, byteStable, specClean: warnings.length === 0 && byteStable };
744
785
  }
786
+ function scriptCorpusArtifact(xml, verify) {
787
+ if (!verify) return { content: xml, warnings: UNCHECKED };
788
+ const warnings = ncpdpScriptPeer().parseScript(xml).warnings.map((w) => String(w.code));
789
+ return { content: xml, warnings };
790
+ }
791
+ function telecomCorpusArtifact(wire, verify) {
792
+ if (!verify) return { content: wire, warnings: UNCHECKED };
793
+ const warnings = ncpdpTelecomPeer().parseTelecom(wire).warnings.map((w) => String(w.code));
794
+ return { content: wire, warnings };
795
+ }
745
796
 
746
797
  // src/select.ts
747
798
  function resolveKind(allowed, requested) {
@@ -764,29 +815,29 @@ var ALL_KINDS = Object.freeze([
764
815
  "B3"
765
816
  ]);
766
817
  var DEFAULT_MIX = ALL_KINDS;
767
- function generateKind(kind, seed) {
818
+ function generateKind(kind, seed, verify) {
768
819
  switch (kind) {
769
820
  case "NewRx":
770
- return scriptRoundTrip(generateNewRx({ seed }));
821
+ return scriptCorpusArtifact(generateNewRx({ seed }), verify);
771
822
  case "RxRenewalRequest":
772
- return scriptRoundTrip(generateRxRenewalRequest({ seed }));
823
+ return scriptCorpusArtifact(generateRxRenewalRequest({ seed }), verify);
773
824
  case "RxChangeRequest":
774
- return scriptRoundTrip(generateRxChangeRequest({ seed }));
825
+ return scriptCorpusArtifact(generateRxChangeRequest({ seed }), verify);
775
826
  case "B1":
776
827
  case "B2":
777
828
  case "B3":
778
- return telecomRoundTrip(generateTelecom(kind, { seed }));
829
+ return telecomCorpusArtifact(generateTelecom(kind, { seed }), verify);
779
830
  }
780
831
  }
781
832
  function ncpdpCorpus(options) {
782
- const { seed } = options;
833
+ const { seed, verify = true } = options;
783
834
  const mix = resolveMix(ALL_KINDS, options.mix, DEFAULT_MIX);
784
835
  const count = options.count ?? mix.length;
785
836
  const seedStream = createRng(seed);
786
837
  const artifacts = Array.from({ length: count }, (_unused, i) => {
787
838
  const kind = mix[i % mix.length] ?? "NewRx";
788
839
  const txSeed = seedStream.nextUint32();
789
- const rt = generateKind(kind, txSeed);
840
+ const rt = generateKind(kind, txSeed, verify);
790
841
  return {
791
842
  format: "ncpdp",
792
843
  kind,