@cosyte/synth 0.0.3 → 0.0.4
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 +297 -0
- package/README.md +6 -2
- package/dist/astm/index.cjs +83 -42
- package/dist/astm/index.cjs.map +1 -1
- package/dist/astm/index.d.cts +1 -1
- package/dist/astm/index.d.ts +1 -1
- package/dist/astm/index.mjs +83 -42
- package/dist/astm/index.mjs.map +1 -1
- package/dist/ccda/index.cjs +89 -44
- package/dist/ccda/index.cjs.map +1 -1
- package/dist/ccda/index.d.cts +5 -3
- package/dist/ccda/index.d.ts +5 -3
- package/dist/ccda/index.mjs +89 -44
- package/dist/ccda/index.mjs.map +1 -1
- package/dist/deid/index.cjs +92 -13
- package/dist/deid/index.cjs.map +1 -1
- package/dist/deid/index.d.cts +1 -1
- package/dist/deid/index.d.ts +1 -1
- package/dist/deid/index.mjs +93 -14
- package/dist/deid/index.mjs.map +1 -1
- package/dist/fhir/index.cjs +78 -5
- package/dist/fhir/index.cjs.map +1 -1
- package/dist/fhir/index.mjs +78 -5
- package/dist/fhir/index.mjs.map +1 -1
- package/dist/hl7/index.cjs +89 -41
- package/dist/hl7/index.cjs.map +1 -1
- package/dist/hl7/index.d.cts +1 -1
- package/dist/hl7/index.d.ts +1 -1
- package/dist/hl7/index.mjs +89 -41
- package/dist/hl7/index.mjs.map +1 -1
- package/dist/index.cjs +91 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +126 -8
- package/dist/index.d.ts +126 -8
- package/dist/index.mjs +89 -41
- package/dist/index.mjs.map +1 -1
- package/dist/ncpdp/index.cjs +56 -4
- package/dist/ncpdp/index.cjs.map +1 -1
- package/dist/ncpdp/index.mjs +56 -4
- package/dist/ncpdp/index.mjs.map +1 -1
- package/dist/{quirk-JLyO1Ncj.d.ts → quirk-C9t9CkPS.d.ts} +17 -6
- package/dist/{quirk-DmkgoZdh.d.cts → quirk-DYMDojVw.d.cts} +17 -6
- package/dist/x12/index.cjs +82 -13
- package/dist/x12/index.cjs.map +1 -1
- package/dist/x12/index.d.cts +2 -1
- package/dist/x12/index.d.ts +2 -1
- package/dist/x12/index.mjs +83 -14
- package/dist/x12/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/deid/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import { Hl7MessageKind } from '../hl7/index.cjs';
|
|
|
2
2
|
import { DeidPolicy, GenericLocus } from '@cosyte/deid';
|
|
3
3
|
import '@cosyte/hl7';
|
|
4
4
|
import '../providers-OLz3zAc-.cjs';
|
|
5
|
-
import '../quirk-
|
|
5
|
+
import '../quirk-DYMDojVw.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* The format-agnostic core of the **`@cosyte/deid` pairing loop** — a **closed-loop
|
package/dist/deid/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Hl7MessageKind } from '../hl7/index.js';
|
|
|
2
2
|
import { DeidPolicy, GenericLocus } from '@cosyte/deid';
|
|
3
3
|
import '@cosyte/hl7';
|
|
4
4
|
import '../providers-OLz3zAc-.js';
|
|
5
|
-
import '../quirk-
|
|
5
|
+
import '../quirk-C9t9CkPS.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* The format-agnostic core of the **`@cosyte/deid` pairing loop** — a **closed-loop
|
package/dist/deid/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { extractX12Loci, deidentifyX12 } from '@cosyte/deid/x12';
|
|
|
4
4
|
import { extractTelecomLoci, deidentifyTelecom } from '@cosyte/deid/ncpdp';
|
|
5
5
|
import { deidentifyCcda } from '@cosyte/deid/ccda';
|
|
6
6
|
import { serializeResource, complex, list, primitive, decimal } from '@cosyte/fhir';
|
|
7
|
-
import { serializeX12, parseX12, build835, build271, X12Decimal,
|
|
7
|
+
import { serializeX12, parseX12, build835, build271, X12Decimal, build837D, build837I, build837P } from '@cosyte/x12';
|
|
8
8
|
import { serializeCcda, buildCcda, NCI_ROUTE, SNOMED_CT, CVX, RXNORM, LOINC } from '@cosyte/ccda';
|
|
9
9
|
import { parseTelecom, serializeTelecom, buildTelecomRequest } from '@cosyte/ncpdp/telecom';
|
|
10
10
|
import { buildMessage } from '@cosyte/hl7';
|
|
@@ -41,6 +41,49 @@ function sfc32Next(s) {
|
|
|
41
41
|
return t >>> 0;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// src/codes.ts
|
|
45
|
+
var SYNTH_FATAL_CODES = {
|
|
46
|
+
/** A concept's code-system URI has no OID mapping in the C-CDA example-code table. Fatal. */
|
|
47
|
+
SYNTH_UNMAPPED_CODE_SYSTEM: "SYNTH_UNMAPPED_CODE_SYSTEM",
|
|
48
|
+
/** A money value could not be read as an X12 decimal. Fatal — a generator never rounds to a float. */
|
|
49
|
+
SYNTH_INVALID_DECIMAL: "SYNTH_INVALID_DECIMAL",
|
|
50
|
+
/** An integer range was requested with its maximum below its minimum. Fatal. */
|
|
51
|
+
SYNTH_INVALID_RANGE: "SYNTH_INVALID_RANGE",
|
|
52
|
+
/** A value was drawn from an empty pool. Fatal — never a fabricated substitute. */
|
|
53
|
+
SYNTH_EMPTY_POOL: "SYNTH_EMPTY_POOL",
|
|
54
|
+
/**
|
|
55
|
+
* A caller-supplied selector (a message kind, a document type, a corpus mix entry, a claim
|
|
56
|
+
* variant, a Bundle type, a resource profile) is not in the closed set that governs it. Fatal —
|
|
57
|
+
* see `resolveKind`: a selector union is erased at run time, and a selector that falls through
|
|
58
|
+
* either mislabels the fixture or hands the value to a peer builder that quotes it back.
|
|
59
|
+
*/
|
|
60
|
+
SYNTH_UNSUPPORTED_KIND: "SYNTH_UNSUPPORTED_KIND"
|
|
61
|
+
};
|
|
62
|
+
var SYNTH_FATAL_MESSAGES = Object.freeze({
|
|
63
|
+
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.",
|
|
64
|
+
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).",
|
|
65
|
+
SYNTH_QUIRK_ANCHOR_ABSENT: "The quirk transform found no structural anchor to mutate, so the fixture would not carry the deviation it is labelled with. Refusing to emit a mislabeled fixture.",
|
|
66
|
+
SYNTH_INTENDED_WARNING_MISMATCH: "A bare parse of the generated quirk artifact did not produce exactly the declared intended warning code(s). Refusing to emit a mislabeled fixture.",
|
|
67
|
+
SYNTH_UNMAPPED_CODE_SYSTEM: "The concept's code-system URI has no OID mapping in the C-CDA example-code table.",
|
|
68
|
+
SYNTH_INVALID_DECIMAL: "The value could not be read as an X12 decimal.",
|
|
69
|
+
SYNTH_INVALID_RANGE: "An integer range was requested with its maximum below its minimum.",
|
|
70
|
+
SYNTH_EMPTY_POOL: "A value was drawn from an empty pool.",
|
|
71
|
+
SYNTH_INVALID_PROFILE: "defineSynthProfile requires a non-empty string name.",
|
|
72
|
+
SYNTH_UNSUPPORTED_KIND: "The requested kind, document type, corpus mix entry, variant or profile is not one this generator supports. The supported set is the exported union for that option."
|
|
73
|
+
});
|
|
74
|
+
var SynthError = class extends Error {
|
|
75
|
+
/** The stable fatal code. */
|
|
76
|
+
code;
|
|
77
|
+
/**
|
|
78
|
+
* @param code - The stable {@link SynthFatalCode}. The message comes from the frozen registry.
|
|
79
|
+
*/
|
|
80
|
+
constructor(code) {
|
|
81
|
+
super(SYNTH_FATAL_MESSAGES[code]);
|
|
82
|
+
this.name = "SynthError";
|
|
83
|
+
this.code = code;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
44
87
|
// src/rng/rng.ts
|
|
45
88
|
var Sfc32Rng = class {
|
|
46
89
|
seed;
|
|
@@ -58,7 +101,7 @@ var Sfc32Rng = class {
|
|
|
58
101
|
return this.nextUint32() / 4294967296;
|
|
59
102
|
}
|
|
60
103
|
int(min, max) {
|
|
61
|
-
if (max < min) throw new
|
|
104
|
+
if (max < min) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_RANGE);
|
|
62
105
|
const span = max - min + 1;
|
|
63
106
|
return min + Math.floor(this.float() * span);
|
|
64
107
|
}
|
|
@@ -66,7 +109,7 @@ var Sfc32Rng = class {
|
|
|
66
109
|
return this.float() < p;
|
|
67
110
|
}
|
|
68
111
|
pick(items) {
|
|
69
|
-
if (items.length === 0) throw new
|
|
112
|
+
if (items.length === 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_EMPTY_POOL);
|
|
70
113
|
return items[this.int(0, items.length - 1)];
|
|
71
114
|
}
|
|
72
115
|
digits(n) {
|
|
@@ -436,10 +479,18 @@ function pidSegment(id) {
|
|
|
436
479
|
];
|
|
437
480
|
}
|
|
438
481
|
|
|
482
|
+
// src/select.ts
|
|
483
|
+
function resolveKind(allowed, requested) {
|
|
484
|
+
const match = allowed.find((value) => value === requested);
|
|
485
|
+
if (match === void 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_UNSUPPORTED_KIND);
|
|
486
|
+
return match;
|
|
487
|
+
}
|
|
488
|
+
|
|
439
489
|
// src/hl7/adt.ts
|
|
490
|
+
var ADT_TRIGGERS = Object.freeze(["A01", "A04", "A08"]);
|
|
440
491
|
function generateAdt(options = {}) {
|
|
441
492
|
const seed = options.seed ?? 0;
|
|
442
|
-
const trigger = options.trigger ?? "A01";
|
|
493
|
+
const trigger = resolveKind(ADT_TRIGGERS, options.trigger ?? "A01");
|
|
443
494
|
const rng = createRng(seed);
|
|
444
495
|
const { message, timestamp } = mshScaffold(rng, `ADT^${trigger}`);
|
|
445
496
|
message.addSegment("EVN", [trigger, timestamp]);
|
|
@@ -710,8 +761,19 @@ function generateVxu(options = {}) {
|
|
|
710
761
|
]);
|
|
711
762
|
return message;
|
|
712
763
|
}
|
|
764
|
+
|
|
765
|
+
// src/hl7/index.ts
|
|
766
|
+
var ALL_KINDS = Object.freeze([
|
|
767
|
+
"ADT^A01",
|
|
768
|
+
"ADT^A04",
|
|
769
|
+
"ADT^A08",
|
|
770
|
+
"ORU^R01",
|
|
771
|
+
"ORM^O01",
|
|
772
|
+
"SIU^S12",
|
|
773
|
+
"VXU^V04"
|
|
774
|
+
]);
|
|
713
775
|
function generateHl7(kind, seed) {
|
|
714
|
-
switch (kind) {
|
|
776
|
+
switch (resolveKind(ALL_KINDS, kind)) {
|
|
715
777
|
case "ADT^A01":
|
|
716
778
|
return generateAdt({ seed, trigger: "A01" });
|
|
717
779
|
case "ADT^A04":
|
|
@@ -1130,6 +1192,7 @@ var EXAMPLE_ENCOUNTER_CLASSES = Object.freeze([
|
|
|
1130
1192
|
]);
|
|
1131
1193
|
|
|
1132
1194
|
// src/fhir/patient.ts
|
|
1195
|
+
var PATIENT_PROFILES = Object.freeze(["base", "us-core"]);
|
|
1133
1196
|
function ombExtension(url, category) {
|
|
1134
1197
|
return complex([
|
|
1135
1198
|
prop("url", str(url)),
|
|
@@ -1143,7 +1206,8 @@ function ombExtension(url, category) {
|
|
|
1143
1206
|
]);
|
|
1144
1207
|
}
|
|
1145
1208
|
function generatePatient(options = {}) {
|
|
1146
|
-
const { seed = 0
|
|
1209
|
+
const { seed = 0 } = options;
|
|
1210
|
+
const profile = resolveKind(PATIENT_PROFILES, options.profile ?? "base");
|
|
1147
1211
|
const rng = createRng(seed);
|
|
1148
1212
|
const id = fhirPatientIdentity(rng);
|
|
1149
1213
|
const usCore = profile === "us-core";
|
|
@@ -1526,6 +1590,11 @@ function buildComposition(rng, input) {
|
|
|
1526
1590
|
}
|
|
1527
1591
|
|
|
1528
1592
|
// src/fhir/bundle.ts
|
|
1593
|
+
var BUNDLE_TYPES = Object.freeze([
|
|
1594
|
+
"collection",
|
|
1595
|
+
"transaction",
|
|
1596
|
+
"document"
|
|
1597
|
+
]);
|
|
1529
1598
|
function resourceTypeOf(resource) {
|
|
1530
1599
|
const rt = resource.properties.find((p) => p.name === "resourceType");
|
|
1531
1600
|
return rt !== void 0 && rt.value.kind === "primitive" ? String(rt.value.value) : "Resource";
|
|
@@ -1627,7 +1696,8 @@ function documentSections(urls) {
|
|
|
1627
1696
|
];
|
|
1628
1697
|
}
|
|
1629
1698
|
function generateBundle(options = {}) {
|
|
1630
|
-
const { seed = 0
|
|
1699
|
+
const { seed = 0 } = options;
|
|
1700
|
+
const type = resolveKind(BUNDLE_TYPES, options.type ?? "collection");
|
|
1631
1701
|
const rng = createRng(seed);
|
|
1632
1702
|
const spine = buildSpine(rng);
|
|
1633
1703
|
const members = type === "document" ? [
|
|
@@ -1680,7 +1750,7 @@ function generateBundle(options = {}) {
|
|
|
1680
1750
|
}
|
|
1681
1751
|
function dec2(value) {
|
|
1682
1752
|
const d = X12Decimal.fromString(value);
|
|
1683
|
-
if (d === void 0) throw new
|
|
1753
|
+
if (d === void 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_DECIMAL);
|
|
1684
1754
|
return d;
|
|
1685
1755
|
}
|
|
1686
1756
|
function money(n) {
|
|
@@ -1786,6 +1856,7 @@ var TOOTH_SURFACES = Object.freeze(["M", "O", "D", "B", "L"]);
|
|
|
1786
1856
|
var SERVICE_TYPE_CODES = Object.freeze(["30", "1", "35", "88", "98"]);
|
|
1787
1857
|
|
|
1788
1858
|
// src/x12/claim-837.ts
|
|
1859
|
+
var CLAIM_837_VARIANTS = Object.freeze(["P", "I", "D"]);
|
|
1789
1860
|
function serviceDtp(serviceDate2) {
|
|
1790
1861
|
return { qualifier: "472", formatQualifier: "D8", value: serviceDate2 };
|
|
1791
1862
|
}
|
|
@@ -1968,11 +2039,17 @@ function specOf(rng, variant) {
|
|
|
1968
2039
|
};
|
|
1969
2040
|
}
|
|
1970
2041
|
function generate837(variant, options) {
|
|
2042
|
+
const resolved = resolveKind(CLAIM_837_VARIANTS, variant);
|
|
1971
2043
|
const rng = createRng(options.seed);
|
|
1972
|
-
const spec = specOf(rng,
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
2044
|
+
const spec = specOf(rng, resolved);
|
|
2045
|
+
switch (resolved) {
|
|
2046
|
+
case "P":
|
|
2047
|
+
return build837P(spec);
|
|
2048
|
+
case "I":
|
|
2049
|
+
return build837I(spec);
|
|
2050
|
+
case "D":
|
|
2051
|
+
return build837D(spec);
|
|
2052
|
+
}
|
|
1976
2053
|
}
|
|
1977
2054
|
function generate837P(options) {
|
|
1978
2055
|
return generate837("P", options);
|
|
@@ -2337,7 +2414,7 @@ var URI_TO_OID = Object.freeze({
|
|
|
2337
2414
|
function toBuildCode(concept) {
|
|
2338
2415
|
const codeSystem = URI_TO_OID[concept.system];
|
|
2339
2416
|
if (codeSystem === void 0) {
|
|
2340
|
-
throw new
|
|
2417
|
+
throw new SynthError(SYNTH_FATAL_CODES.SYNTH_UNMAPPED_CODE_SYSTEM);
|
|
2341
2418
|
}
|
|
2342
2419
|
return { code: concept.code, codeSystem, displayName: concept.display };
|
|
2343
2420
|
}
|
|
@@ -2395,6 +2472,7 @@ function ccdaPatientIdentity(rng) {
|
|
|
2395
2472
|
}
|
|
2396
2473
|
|
|
2397
2474
|
// src/ccda/ccd.ts
|
|
2475
|
+
var CCDA_DOCUMENT_TYPES = Object.freeze(["ccd", "referralNote"]);
|
|
2398
2476
|
function pickN(rng, pool, n) {
|
|
2399
2477
|
const take = Math.min(n, pool.length);
|
|
2400
2478
|
const indices = pool.map((_v, i) => i);
|
|
@@ -2477,7 +2555,8 @@ function buildInit(rng, documentType) {
|
|
|
2477
2555
|
return base;
|
|
2478
2556
|
}
|
|
2479
2557
|
function generateCcda(options = {}) {
|
|
2480
|
-
const { seed = 0
|
|
2558
|
+
const { seed = 0 } = options;
|
|
2559
|
+
const documentType = resolveKind(CCDA_DOCUMENT_TYPES, options.documentType ?? "ccd");
|
|
2481
2560
|
const rng = createRng(seed);
|
|
2482
2561
|
return buildCcda(buildInit(rng, documentType));
|
|
2483
2562
|
}
|