@cosyte/synth 0.0.2 → 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 +321 -0
- package/README.md +13 -4
- 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.cjs
CHANGED
|
@@ -43,6 +43,49 @@ function sfc32Next(s) {
|
|
|
43
43
|
return t >>> 0;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// src/codes.ts
|
|
47
|
+
var SYNTH_FATAL_CODES = {
|
|
48
|
+
/** A concept's code-system URI has no OID mapping in the C-CDA example-code table. Fatal. */
|
|
49
|
+
SYNTH_UNMAPPED_CODE_SYSTEM: "SYNTH_UNMAPPED_CODE_SYSTEM",
|
|
50
|
+
/** A money value could not be read as an X12 decimal. Fatal — a generator never rounds to a float. */
|
|
51
|
+
SYNTH_INVALID_DECIMAL: "SYNTH_INVALID_DECIMAL",
|
|
52
|
+
/** An integer range was requested with its maximum below its minimum. Fatal. */
|
|
53
|
+
SYNTH_INVALID_RANGE: "SYNTH_INVALID_RANGE",
|
|
54
|
+
/** A value was drawn from an empty pool. Fatal — never a fabricated substitute. */
|
|
55
|
+
SYNTH_EMPTY_POOL: "SYNTH_EMPTY_POOL",
|
|
56
|
+
/**
|
|
57
|
+
* A caller-supplied selector (a message kind, a document type, a corpus mix entry, a claim
|
|
58
|
+
* variant, a Bundle type, a resource profile) is not in the closed set that governs it. Fatal —
|
|
59
|
+
* see `resolveKind`: a selector union is erased at run time, and a selector that falls through
|
|
60
|
+
* either mislabels the fixture or hands the value to a peer builder that quotes it back.
|
|
61
|
+
*/
|
|
62
|
+
SYNTH_UNSUPPORTED_KIND: "SYNTH_UNSUPPORTED_KIND"
|
|
63
|
+
};
|
|
64
|
+
var SYNTH_FATAL_MESSAGES = Object.freeze({
|
|
65
|
+
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.",
|
|
66
|
+
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).",
|
|
67
|
+
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.",
|
|
68
|
+
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.",
|
|
69
|
+
SYNTH_UNMAPPED_CODE_SYSTEM: "The concept's code-system URI has no OID mapping in the C-CDA example-code table.",
|
|
70
|
+
SYNTH_INVALID_DECIMAL: "The value could not be read as an X12 decimal.",
|
|
71
|
+
SYNTH_INVALID_RANGE: "An integer range was requested with its maximum below its minimum.",
|
|
72
|
+
SYNTH_EMPTY_POOL: "A value was drawn from an empty pool.",
|
|
73
|
+
SYNTH_INVALID_PROFILE: "defineSynthProfile requires a non-empty string name.",
|
|
74
|
+
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."
|
|
75
|
+
});
|
|
76
|
+
var SynthError = class extends Error {
|
|
77
|
+
/** The stable fatal code. */
|
|
78
|
+
code;
|
|
79
|
+
/**
|
|
80
|
+
* @param code - The stable {@link SynthFatalCode}. The message comes from the frozen registry.
|
|
81
|
+
*/
|
|
82
|
+
constructor(code) {
|
|
83
|
+
super(SYNTH_FATAL_MESSAGES[code]);
|
|
84
|
+
this.name = "SynthError";
|
|
85
|
+
this.code = code;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
46
89
|
// src/rng/rng.ts
|
|
47
90
|
var Sfc32Rng = class {
|
|
48
91
|
seed;
|
|
@@ -60,7 +103,7 @@ var Sfc32Rng = class {
|
|
|
60
103
|
return this.nextUint32() / 4294967296;
|
|
61
104
|
}
|
|
62
105
|
int(min, max) {
|
|
63
|
-
if (max < min) throw new
|
|
106
|
+
if (max < min) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_RANGE);
|
|
64
107
|
const span = max - min + 1;
|
|
65
108
|
return min + Math.floor(this.float() * span);
|
|
66
109
|
}
|
|
@@ -68,7 +111,7 @@ var Sfc32Rng = class {
|
|
|
68
111
|
return this.float() < p;
|
|
69
112
|
}
|
|
70
113
|
pick(items) {
|
|
71
|
-
if (items.length === 0) throw new
|
|
114
|
+
if (items.length === 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_EMPTY_POOL);
|
|
72
115
|
return items[this.int(0, items.length - 1)];
|
|
73
116
|
}
|
|
74
117
|
digits(n) {
|
|
@@ -438,10 +481,18 @@ function pidSegment(id) {
|
|
|
438
481
|
];
|
|
439
482
|
}
|
|
440
483
|
|
|
484
|
+
// src/select.ts
|
|
485
|
+
function resolveKind(allowed, requested) {
|
|
486
|
+
const match = allowed.find((value) => value === requested);
|
|
487
|
+
if (match === void 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_UNSUPPORTED_KIND);
|
|
488
|
+
return match;
|
|
489
|
+
}
|
|
490
|
+
|
|
441
491
|
// src/hl7/adt.ts
|
|
492
|
+
var ADT_TRIGGERS = Object.freeze(["A01", "A04", "A08"]);
|
|
442
493
|
function generateAdt(options = {}) {
|
|
443
494
|
const seed = options.seed ?? 0;
|
|
444
|
-
const trigger = options.trigger ?? "A01";
|
|
495
|
+
const trigger = resolveKind(ADT_TRIGGERS, options.trigger ?? "A01");
|
|
445
496
|
const rng = createRng(seed);
|
|
446
497
|
const { message, timestamp } = mshScaffold(rng, `ADT^${trigger}`);
|
|
447
498
|
message.addSegment("EVN", [trigger, timestamp]);
|
|
@@ -712,8 +763,19 @@ function generateVxu(options = {}) {
|
|
|
712
763
|
]);
|
|
713
764
|
return message;
|
|
714
765
|
}
|
|
766
|
+
|
|
767
|
+
// src/hl7/index.ts
|
|
768
|
+
var ALL_KINDS = Object.freeze([
|
|
769
|
+
"ADT^A01",
|
|
770
|
+
"ADT^A04",
|
|
771
|
+
"ADT^A08",
|
|
772
|
+
"ORU^R01",
|
|
773
|
+
"ORM^O01",
|
|
774
|
+
"SIU^S12",
|
|
775
|
+
"VXU^V04"
|
|
776
|
+
]);
|
|
715
777
|
function generateHl7(kind, seed) {
|
|
716
|
-
switch (kind) {
|
|
778
|
+
switch (resolveKind(ALL_KINDS, kind)) {
|
|
717
779
|
case "ADT^A01":
|
|
718
780
|
return generateAdt({ seed, trigger: "A01" });
|
|
719
781
|
case "ADT^A04":
|
|
@@ -1132,6 +1194,7 @@ var EXAMPLE_ENCOUNTER_CLASSES = Object.freeze([
|
|
|
1132
1194
|
]);
|
|
1133
1195
|
|
|
1134
1196
|
// src/fhir/patient.ts
|
|
1197
|
+
var PATIENT_PROFILES = Object.freeze(["base", "us-core"]);
|
|
1135
1198
|
function ombExtension(url, category) {
|
|
1136
1199
|
return fhir.complex([
|
|
1137
1200
|
prop("url", str(url)),
|
|
@@ -1145,7 +1208,8 @@ function ombExtension(url, category) {
|
|
|
1145
1208
|
]);
|
|
1146
1209
|
}
|
|
1147
1210
|
function generatePatient(options = {}) {
|
|
1148
|
-
const { seed = 0
|
|
1211
|
+
const { seed = 0 } = options;
|
|
1212
|
+
const profile = resolveKind(PATIENT_PROFILES, options.profile ?? "base");
|
|
1149
1213
|
const rng = createRng(seed);
|
|
1150
1214
|
const id = fhirPatientIdentity(rng);
|
|
1151
1215
|
const usCore = profile === "us-core";
|
|
@@ -1528,6 +1592,11 @@ function buildComposition(rng, input) {
|
|
|
1528
1592
|
}
|
|
1529
1593
|
|
|
1530
1594
|
// src/fhir/bundle.ts
|
|
1595
|
+
var BUNDLE_TYPES = Object.freeze([
|
|
1596
|
+
"collection",
|
|
1597
|
+
"transaction",
|
|
1598
|
+
"document"
|
|
1599
|
+
]);
|
|
1531
1600
|
function resourceTypeOf(resource) {
|
|
1532
1601
|
const rt = resource.properties.find((p) => p.name === "resourceType");
|
|
1533
1602
|
return rt !== void 0 && rt.value.kind === "primitive" ? String(rt.value.value) : "Resource";
|
|
@@ -1629,7 +1698,8 @@ function documentSections(urls) {
|
|
|
1629
1698
|
];
|
|
1630
1699
|
}
|
|
1631
1700
|
function generateBundle(options = {}) {
|
|
1632
|
-
const { seed = 0
|
|
1701
|
+
const { seed = 0 } = options;
|
|
1702
|
+
const type = resolveKind(BUNDLE_TYPES, options.type ?? "collection");
|
|
1633
1703
|
const rng = createRng(seed);
|
|
1634
1704
|
const spine = buildSpine(rng);
|
|
1635
1705
|
const members = type === "document" ? [
|
|
@@ -1682,7 +1752,7 @@ function generateBundle(options = {}) {
|
|
|
1682
1752
|
}
|
|
1683
1753
|
function dec2(value) {
|
|
1684
1754
|
const d = x12.X12Decimal.fromString(value);
|
|
1685
|
-
if (d === void 0) throw new
|
|
1755
|
+
if (d === void 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_DECIMAL);
|
|
1686
1756
|
return d;
|
|
1687
1757
|
}
|
|
1688
1758
|
function money(n) {
|
|
@@ -1788,6 +1858,7 @@ var TOOTH_SURFACES = Object.freeze(["M", "O", "D", "B", "L"]);
|
|
|
1788
1858
|
var SERVICE_TYPE_CODES = Object.freeze(["30", "1", "35", "88", "98"]);
|
|
1789
1859
|
|
|
1790
1860
|
// src/x12/claim-837.ts
|
|
1861
|
+
var CLAIM_837_VARIANTS = Object.freeze(["P", "I", "D"]);
|
|
1791
1862
|
function serviceDtp(serviceDate2) {
|
|
1792
1863
|
return { qualifier: "472", formatQualifier: "D8", value: serviceDate2 };
|
|
1793
1864
|
}
|
|
@@ -1970,11 +2041,17 @@ function specOf(rng, variant) {
|
|
|
1970
2041
|
};
|
|
1971
2042
|
}
|
|
1972
2043
|
function generate837(variant, options) {
|
|
2044
|
+
const resolved = resolveKind(CLAIM_837_VARIANTS, variant);
|
|
1973
2045
|
const rng = createRng(options.seed);
|
|
1974
|
-
const spec = specOf(rng,
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
2046
|
+
const spec = specOf(rng, resolved);
|
|
2047
|
+
switch (resolved) {
|
|
2048
|
+
case "P":
|
|
2049
|
+
return x12.build837P(spec);
|
|
2050
|
+
case "I":
|
|
2051
|
+
return x12.build837I(spec);
|
|
2052
|
+
case "D":
|
|
2053
|
+
return x12.build837D(spec);
|
|
2054
|
+
}
|
|
1978
2055
|
}
|
|
1979
2056
|
function generate837P(options) {
|
|
1980
2057
|
return generate837("P", options);
|
|
@@ -2339,7 +2416,7 @@ var URI_TO_OID = Object.freeze({
|
|
|
2339
2416
|
function toBuildCode(concept) {
|
|
2340
2417
|
const codeSystem = URI_TO_OID[concept.system];
|
|
2341
2418
|
if (codeSystem === void 0) {
|
|
2342
|
-
throw new
|
|
2419
|
+
throw new SynthError(SYNTH_FATAL_CODES.SYNTH_UNMAPPED_CODE_SYSTEM);
|
|
2343
2420
|
}
|
|
2344
2421
|
return { code: concept.code, codeSystem, displayName: concept.display };
|
|
2345
2422
|
}
|
|
@@ -2397,6 +2474,7 @@ function ccdaPatientIdentity(rng) {
|
|
|
2397
2474
|
}
|
|
2398
2475
|
|
|
2399
2476
|
// src/ccda/ccd.ts
|
|
2477
|
+
var CCDA_DOCUMENT_TYPES = Object.freeze(["ccd", "referralNote"]);
|
|
2400
2478
|
function pickN(rng, pool, n) {
|
|
2401
2479
|
const take = Math.min(n, pool.length);
|
|
2402
2480
|
const indices = pool.map((_v, i) => i);
|
|
@@ -2479,7 +2557,8 @@ function buildInit(rng, documentType) {
|
|
|
2479
2557
|
return base;
|
|
2480
2558
|
}
|
|
2481
2559
|
function generateCcda(options = {}) {
|
|
2482
|
-
const { seed = 0
|
|
2560
|
+
const { seed = 0 } = options;
|
|
2561
|
+
const documentType = resolveKind(CCDA_DOCUMENT_TYPES, options.documentType ?? "ccd");
|
|
2483
2562
|
const rng = createRng(seed);
|
|
2484
2563
|
return ccda.buildCcda(buildInit(rng, documentType));
|
|
2485
2564
|
}
|