@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/hl7/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Hl7Message, RawField } from '@cosyte/hl7';
|
|
2
2
|
import { S as SyntheticName, a as SyntheticIdentifier, b as SyntheticAddress, R as Rng, C as Corpus } from '../providers-OLz3zAc-.cjs';
|
|
3
|
-
import { Q as QuirkDescriptor, S as SynthProfile, a as QuirkArtifact, b as QuirkRoundTripResult } from '../quirk-
|
|
3
|
+
import { Q as QuirkDescriptor, S as SynthProfile, a as QuirkArtifact, b as QuirkRoundTripResult } from '../quirk-DYMDojVw.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Spec-clean HL7 v2 `ADT` generation, built **through `@cosyte/hl7`'s `buildMessage`** so MSH
|
package/dist/hl7/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Hl7Message, RawField } from '@cosyte/hl7';
|
|
2
2
|
import { S as SyntheticName, a as SyntheticIdentifier, b as SyntheticAddress, R as Rng, C as Corpus } from '../providers-OLz3zAc-.js';
|
|
3
|
-
import { Q as QuirkDescriptor, S as SynthProfile, a as QuirkArtifact, b as QuirkRoundTripResult } from '../quirk-
|
|
3
|
+
import { Q as QuirkDescriptor, S as SynthProfile, a as QuirkArtifact, b as QuirkRoundTripResult } from '../quirk-C9t9CkPS.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Spec-clean HL7 v2 `ADT` generation, built **through `@cosyte/hl7`'s `buildMessage`** so MSH
|
package/dist/hl7/index.mjs
CHANGED
|
@@ -29,6 +29,57 @@ function sfc32Next(s) {
|
|
|
29
29
|
return t >>> 0;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// src/codes.ts
|
|
33
|
+
var SYNTH_FATAL_CODES = {
|
|
34
|
+
/**
|
|
35
|
+
* A vendor quirk was requested that the target format's profile system does not support. Fatal —
|
|
36
|
+
* never a silent no-op and never a fabricated quirk.
|
|
37
|
+
*/
|
|
38
|
+
SYNTH_UNSUPPORTED_QUIRK: "SYNTH_UNSUPPORTED_QUIRK",
|
|
39
|
+
/**
|
|
40
|
+
* A bare parse of a freshly-generated quirk artifact did not produce exactly the declared intended
|
|
41
|
+
* warning code(s). Fatal — never emit a mislabeled fixture.
|
|
42
|
+
*/
|
|
43
|
+
SYNTH_INTENDED_WARNING_MISMATCH: "SYNTH_INTENDED_WARNING_MISMATCH",
|
|
44
|
+
/** An integer range was requested with its maximum below its minimum. Fatal. */
|
|
45
|
+
SYNTH_INVALID_RANGE: "SYNTH_INVALID_RANGE",
|
|
46
|
+
/** A value was drawn from an empty pool. Fatal — never a fabricated substitute. */
|
|
47
|
+
SYNTH_EMPTY_POOL: "SYNTH_EMPTY_POOL",
|
|
48
|
+
/** A `defineSynthProfile` spec was not usable (a missing or blank `name`). Fatal. */
|
|
49
|
+
SYNTH_INVALID_PROFILE: "SYNTH_INVALID_PROFILE",
|
|
50
|
+
/**
|
|
51
|
+
* A caller-supplied selector (a message kind, a document type, a corpus mix entry, a claim
|
|
52
|
+
* variant, a Bundle type, a resource profile) is not in the closed set that governs it. Fatal —
|
|
53
|
+
* see `resolveKind`: a selector union is erased at run time, and a selector that falls through
|
|
54
|
+
* either mislabels the fixture or hands the value to a peer builder that quotes it back.
|
|
55
|
+
*/
|
|
56
|
+
SYNTH_UNSUPPORTED_KIND: "SYNTH_UNSUPPORTED_KIND"
|
|
57
|
+
};
|
|
58
|
+
var SYNTH_FATAL_MESSAGES = Object.freeze({
|
|
59
|
+
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.",
|
|
60
|
+
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).",
|
|
61
|
+
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.",
|
|
62
|
+
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.",
|
|
63
|
+
SYNTH_UNMAPPED_CODE_SYSTEM: "The concept's code-system URI has no OID mapping in the C-CDA example-code table.",
|
|
64
|
+
SYNTH_INVALID_DECIMAL: "The value could not be read as an X12 decimal.",
|
|
65
|
+
SYNTH_INVALID_RANGE: "An integer range was requested with its maximum below its minimum.",
|
|
66
|
+
SYNTH_EMPTY_POOL: "A value was drawn from an empty pool.",
|
|
67
|
+
SYNTH_INVALID_PROFILE: "defineSynthProfile requires a non-empty string name.",
|
|
68
|
+
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."
|
|
69
|
+
});
|
|
70
|
+
var SynthError = class extends Error {
|
|
71
|
+
/** The stable fatal code. */
|
|
72
|
+
code;
|
|
73
|
+
/**
|
|
74
|
+
* @param code - The stable {@link SynthFatalCode}. The message comes from the frozen registry.
|
|
75
|
+
*/
|
|
76
|
+
constructor(code) {
|
|
77
|
+
super(SYNTH_FATAL_MESSAGES[code]);
|
|
78
|
+
this.name = "SynthError";
|
|
79
|
+
this.code = code;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
32
83
|
// src/rng/rng.ts
|
|
33
84
|
var Sfc32Rng = class {
|
|
34
85
|
seed;
|
|
@@ -46,7 +97,7 @@ var Sfc32Rng = class {
|
|
|
46
97
|
return this.nextUint32() / 4294967296;
|
|
47
98
|
}
|
|
48
99
|
int(min, max) {
|
|
49
|
-
if (max < min) throw new
|
|
100
|
+
if (max < min) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_RANGE);
|
|
50
101
|
const span = max - min + 1;
|
|
51
102
|
return min + Math.floor(this.float() * span);
|
|
52
103
|
}
|
|
@@ -54,7 +105,7 @@ var Sfc32Rng = class {
|
|
|
54
105
|
return this.float() < p;
|
|
55
106
|
}
|
|
56
107
|
pick(items) {
|
|
57
|
-
if (items.length === 0) throw new
|
|
108
|
+
if (items.length === 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_EMPTY_POOL);
|
|
58
109
|
return items[this.int(0, items.length - 1)];
|
|
59
110
|
}
|
|
60
111
|
digits(n) {
|
|
@@ -445,10 +496,22 @@ function pidSegment(id) {
|
|
|
445
496
|
];
|
|
446
497
|
}
|
|
447
498
|
|
|
499
|
+
// src/select.ts
|
|
500
|
+
function resolveKind(allowed, requested) {
|
|
501
|
+
const match = allowed.find((value) => value === requested);
|
|
502
|
+
if (match === void 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_UNSUPPORTED_KIND);
|
|
503
|
+
return match;
|
|
504
|
+
}
|
|
505
|
+
function resolveMix(allowed, requested, fallback) {
|
|
506
|
+
if (requested === void 0) return fallback;
|
|
507
|
+
return requested.map((entry) => resolveKind(allowed, entry));
|
|
508
|
+
}
|
|
509
|
+
|
|
448
510
|
// src/hl7/adt.ts
|
|
511
|
+
var ADT_TRIGGERS = Object.freeze(["A01", "A04", "A08"]);
|
|
449
512
|
function generateAdt(options = {}) {
|
|
450
513
|
const seed = options.seed ?? 0;
|
|
451
|
-
const trigger = options.trigger ?? "A01";
|
|
514
|
+
const trigger = resolveKind(ADT_TRIGGERS, options.trigger ?? "A01");
|
|
452
515
|
const rng = createRng(seed);
|
|
453
516
|
const { message, timestamp } = mshScaffold(rng, `ADT^${trigger}`);
|
|
454
517
|
message.addSegment("EVN", [trigger, timestamp]);
|
|
@@ -735,7 +798,7 @@ function roundTrip(message) {
|
|
|
735
798
|
// src/profile.ts
|
|
736
799
|
function defineSynthProfile(spec) {
|
|
737
800
|
if (typeof spec.name !== "string" || spec.name.trim().length === 0) {
|
|
738
|
-
throw new
|
|
801
|
+
throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_PROFILE);
|
|
739
802
|
}
|
|
740
803
|
return Object.freeze({
|
|
741
804
|
name: spec.name,
|
|
@@ -745,28 +808,6 @@ function defineSynthProfile(spec) {
|
|
|
745
808
|
});
|
|
746
809
|
}
|
|
747
810
|
|
|
748
|
-
// src/codes.ts
|
|
749
|
-
var SYNTH_FATAL_CODES = {
|
|
750
|
-
/**
|
|
751
|
-
* A vendor quirk was requested that the target format's profile system does not support. Fatal —
|
|
752
|
-
* never a silent no-op and never a fabricated quirk.
|
|
753
|
-
*/
|
|
754
|
-
SYNTH_UNSUPPORTED_QUIRK: "SYNTH_UNSUPPORTED_QUIRK"
|
|
755
|
-
};
|
|
756
|
-
var SynthError = class extends Error {
|
|
757
|
-
/** The stable fatal code. */
|
|
758
|
-
code;
|
|
759
|
-
/**
|
|
760
|
-
* @param code - The stable {@link SynthFatalCode}.
|
|
761
|
-
* @param message - A human-readable detail (never contains PHI — there is none).
|
|
762
|
-
*/
|
|
763
|
-
constructor(code, message) {
|
|
764
|
-
super(message);
|
|
765
|
-
this.name = "SynthError";
|
|
766
|
-
this.code = code;
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
|
|
770
811
|
// src/quirk.ts
|
|
771
812
|
var PROFILE_QUIRK_APPLIED = "PROFILE_QUIRK_APPLIED";
|
|
772
813
|
function sameCodeSet(a, b) {
|
|
@@ -783,12 +824,8 @@ function sameCodeSet(a, b) {
|
|
|
783
824
|
}
|
|
784
825
|
function resolveQuirk(registry, format, name2) {
|
|
785
826
|
const descriptor = registry[name2];
|
|
786
|
-
if (descriptor === void 0) {
|
|
787
|
-
|
|
788
|
-
throw new SynthError(
|
|
789
|
-
SYNTH_FATAL_CODES.SYNTH_UNSUPPORTED_QUIRK,
|
|
790
|
-
`${format}: unsupported quirk "${name2}". The ${format} profile system supports: ${supported}.`
|
|
791
|
-
);
|
|
827
|
+
if (descriptor === void 0 || descriptor.format !== format) {
|
|
828
|
+
throw new SynthError(SYNTH_FATAL_CODES.SYNTH_UNSUPPORTED_QUIRK);
|
|
792
829
|
}
|
|
793
830
|
return descriptor;
|
|
794
831
|
}
|
|
@@ -803,11 +840,9 @@ function profileTolerated(disposition, intendedWarnings, warningsUnderProfile) {
|
|
|
803
840
|
return false;
|
|
804
841
|
}
|
|
805
842
|
}
|
|
806
|
-
function assertIntendedWarnings(
|
|
843
|
+
function assertIntendedWarnings(intendedWarnings, bareWarnings) {
|
|
807
844
|
if (!sameCodeSet(bareWarnings, intendedWarnings)) {
|
|
808
|
-
throw new
|
|
809
|
-
`quirk "${quirk}": the intended-warning contract does not hold \u2014 expected exactly [${intendedWarnings.join(", ")}] but a bare parse produced [${bareWarnings.join(", ")}]. Refusing to emit a mislabeled fixture.`
|
|
810
|
-
);
|
|
845
|
+
throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INTENDED_WARNING_MISMATCH);
|
|
811
846
|
}
|
|
812
847
|
}
|
|
813
848
|
function validateProfileQuirks(profile, registry, format) {
|
|
@@ -848,6 +883,15 @@ function applyQuirk(quirk, wire) {
|
|
|
848
883
|
return [...segments, "NTE|1||\\Zff\\"].join("\r");
|
|
849
884
|
}
|
|
850
885
|
}
|
|
886
|
+
var ALL_QUIRK_KINDS = Object.freeze([
|
|
887
|
+
"ADT^A01",
|
|
888
|
+
"ADT^A04",
|
|
889
|
+
"ADT^A08",
|
|
890
|
+
"ORU^R01",
|
|
891
|
+
"ORM^O01",
|
|
892
|
+
"SIU^S12",
|
|
893
|
+
"VXU^V04"
|
|
894
|
+
]);
|
|
851
895
|
function baseMessage(kind, seed) {
|
|
852
896
|
switch (kind) {
|
|
853
897
|
case "ADT^A01":
|
|
@@ -868,11 +912,10 @@ function baseMessage(kind, seed) {
|
|
|
868
912
|
}
|
|
869
913
|
function generateHl7Quirk(options) {
|
|
870
914
|
const seed = options.seed ?? 0;
|
|
871
|
-
const kind = options.kind ?? "ORU^R01";
|
|
915
|
+
const kind = resolveKind(ALL_QUIRK_KINDS, options.kind ?? "ORU^R01");
|
|
872
916
|
const descriptor = resolveQuirk(HL7_QUIRKS, "hl7v2", options.quirk);
|
|
873
917
|
const content = applyQuirk(options.quirk, baseMessage(kind, seed).toString());
|
|
874
918
|
assertIntendedWarnings(
|
|
875
|
-
descriptor.name,
|
|
876
919
|
descriptor.intendedWarnings,
|
|
877
920
|
parseHL7(content).warnings.map((w) => String(w.code))
|
|
878
921
|
);
|
|
@@ -918,6 +961,7 @@ var ALL_HL7_QUIRKS = Object.freeze(
|
|
|
918
961
|
function hl7QuirkCorpus(options) {
|
|
919
962
|
const quirks = options.profile ? validateProfileQuirks(options.profile, HL7_QUIRKS, "hl7v2") : options.quirks ?? ALL_HL7_QUIRKS;
|
|
920
963
|
const names = quirks.length > 0 ? quirks : ALL_HL7_QUIRKS;
|
|
964
|
+
for (const name2 of names) resolveQuirk(HL7_QUIRKS, "hl7v2", name2);
|
|
921
965
|
const kind = options.kind ?? "ORU^R01";
|
|
922
966
|
const count = options.count ?? names.length;
|
|
923
967
|
const seedStream = createRng(options.seed);
|
|
@@ -940,7 +984,7 @@ var hl7QuirkProfile = defineSynthProfile({
|
|
|
940
984
|
});
|
|
941
985
|
|
|
942
986
|
// src/hl7/index.ts
|
|
943
|
-
var
|
|
987
|
+
var ALL_KINDS = Object.freeze([
|
|
944
988
|
"ADT^A01",
|
|
945
989
|
"ADT^A04",
|
|
946
990
|
"ADT^A08",
|
|
@@ -949,8 +993,10 @@ var DEFAULT_MIX = Object.freeze([
|
|
|
949
993
|
"SIU^S12",
|
|
950
994
|
"VXU^V04"
|
|
951
995
|
]);
|
|
996
|
+
var DEFAULT_MIX = ALL_KINDS;
|
|
997
|
+
var ADT_TRIGGERS2 = Object.freeze(["A01", "A04", "A08"]);
|
|
952
998
|
function generateHl7(kind, seed) {
|
|
953
|
-
switch (kind) {
|
|
999
|
+
switch (resolveKind(ALL_KINDS, kind)) {
|
|
954
1000
|
case "ADT^A01":
|
|
955
1001
|
return generateAdt({ seed, trigger: "A01" });
|
|
956
1002
|
case "ADT^A04":
|
|
@@ -969,7 +1015,9 @@ function generateHl7(kind, seed) {
|
|
|
969
1015
|
}
|
|
970
1016
|
function hl7Corpus(options) {
|
|
971
1017
|
const { seed, count = 1 } = options;
|
|
972
|
-
const kinds = options.triggers !== void 0 ? options.triggers.map(
|
|
1018
|
+
const kinds = options.triggers !== void 0 ? options.triggers.map(
|
|
1019
|
+
(t) => `ADT^${resolveKind(ADT_TRIGGERS2, t)}`
|
|
1020
|
+
) : resolveMix(ALL_KINDS, options.mix, DEFAULT_MIX);
|
|
973
1021
|
const seedStream = createRng(seed);
|
|
974
1022
|
const artifacts = Array.from({ length: count }, (_unused, i) => {
|
|
975
1023
|
const kind = kinds[i % kinds.length] ?? "ADT^A01";
|