@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/x12/index.d.cts
CHANGED
|
@@ -200,7 +200,8 @@ declare function roundTrip(interchange: X12Interchange): RoundTripResult;
|
|
|
200
200
|
*
|
|
201
201
|
* @param value - A decimal string, e.g. `"150.00"`.
|
|
202
202
|
* @returns The parsed {@link "@cosyte/x12".X12Decimal}.
|
|
203
|
-
* @throws
|
|
203
|
+
* @throws SynthError `SYNTH_INVALID_DECIMAL` if `value` is not a valid X12 decimal. The refusal does
|
|
204
|
+
* not quote `value`: it is caller-supplied and a diagnostic is not a place to put caller input.
|
|
204
205
|
* @example
|
|
205
206
|
* ```ts
|
|
206
207
|
* import { dec } from "@cosyte/synth/x12";
|
package/dist/x12/index.d.ts
CHANGED
|
@@ -200,7 +200,8 @@ declare function roundTrip(interchange: X12Interchange): RoundTripResult;
|
|
|
200
200
|
*
|
|
201
201
|
* @param value - A decimal string, e.g. `"150.00"`.
|
|
202
202
|
* @returns The parsed {@link "@cosyte/x12".X12Decimal}.
|
|
203
|
-
* @throws
|
|
203
|
+
* @throws SynthError `SYNTH_INVALID_DECIMAL` if `value` is not a valid X12 decimal. The refusal does
|
|
204
|
+
* not quote `value`: it is caller-supplied and a diagnostic is not a place to put caller input.
|
|
204
205
|
* @example
|
|
205
206
|
* ```ts
|
|
206
207
|
* import { dec } from "@cosyte/synth/x12";
|
package/dist/x12/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { X12Decimal,
|
|
1
|
+
import { X12Decimal, build837D, build837I, build837P, build835, build271, serializeX12, parseX12 } from '@cosyte/x12';
|
|
2
2
|
|
|
3
3
|
// src/rng/splitmix32.ts
|
|
4
4
|
function splitmix32(seed) {
|
|
@@ -29,6 +29,47 @@ function sfc32Next(s) {
|
|
|
29
29
|
return t >>> 0;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// src/codes.ts
|
|
33
|
+
var SYNTH_FATAL_CODES = {
|
|
34
|
+
/** A money value could not be read as an X12 decimal. Fatal — a generator never rounds to a float. */
|
|
35
|
+
SYNTH_INVALID_DECIMAL: "SYNTH_INVALID_DECIMAL",
|
|
36
|
+
/** An integer range was requested with its maximum below its minimum. Fatal. */
|
|
37
|
+
SYNTH_INVALID_RANGE: "SYNTH_INVALID_RANGE",
|
|
38
|
+
/** A value was drawn from an empty pool. Fatal — never a fabricated substitute. */
|
|
39
|
+
SYNTH_EMPTY_POOL: "SYNTH_EMPTY_POOL",
|
|
40
|
+
/**
|
|
41
|
+
* A caller-supplied selector (a message kind, a document type, a corpus mix entry, a claim
|
|
42
|
+
* variant, a Bundle type, a resource profile) is not in the closed set that governs it. Fatal —
|
|
43
|
+
* see `resolveKind`: a selector union is erased at run time, and a selector that falls through
|
|
44
|
+
* either mislabels the fixture or hands the value to a peer builder that quotes it back.
|
|
45
|
+
*/
|
|
46
|
+
SYNTH_UNSUPPORTED_KIND: "SYNTH_UNSUPPORTED_KIND"
|
|
47
|
+
};
|
|
48
|
+
var SYNTH_FATAL_MESSAGES = Object.freeze({
|
|
49
|
+
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.",
|
|
50
|
+
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).",
|
|
51
|
+
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.",
|
|
52
|
+
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.",
|
|
53
|
+
SYNTH_UNMAPPED_CODE_SYSTEM: "The concept's code-system URI has no OID mapping in the C-CDA example-code table.",
|
|
54
|
+
SYNTH_INVALID_DECIMAL: "The value could not be read as an X12 decimal.",
|
|
55
|
+
SYNTH_INVALID_RANGE: "An integer range was requested with its maximum below its minimum.",
|
|
56
|
+
SYNTH_EMPTY_POOL: "A value was drawn from an empty pool.",
|
|
57
|
+
SYNTH_INVALID_PROFILE: "defineSynthProfile requires a non-empty string name.",
|
|
58
|
+
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."
|
|
59
|
+
});
|
|
60
|
+
var SynthError = class extends Error {
|
|
61
|
+
/** The stable fatal code. */
|
|
62
|
+
code;
|
|
63
|
+
/**
|
|
64
|
+
* @param code - The stable {@link SynthFatalCode}. The message comes from the frozen registry.
|
|
65
|
+
*/
|
|
66
|
+
constructor(code) {
|
|
67
|
+
super(SYNTH_FATAL_MESSAGES[code]);
|
|
68
|
+
this.name = "SynthError";
|
|
69
|
+
this.code = code;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
32
73
|
// src/rng/rng.ts
|
|
33
74
|
var Sfc32Rng = class {
|
|
34
75
|
seed;
|
|
@@ -46,7 +87,7 @@ var Sfc32Rng = class {
|
|
|
46
87
|
return this.nextUint32() / 4294967296;
|
|
47
88
|
}
|
|
48
89
|
int(min, max) {
|
|
49
|
-
if (max < min) throw new
|
|
90
|
+
if (max < min) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_RANGE);
|
|
50
91
|
const span = max - min + 1;
|
|
51
92
|
return min + Math.floor(this.float() * span);
|
|
52
93
|
}
|
|
@@ -54,7 +95,7 @@ var Sfc32Rng = class {
|
|
|
54
95
|
return this.float() < p;
|
|
55
96
|
}
|
|
56
97
|
pick(items) {
|
|
57
|
-
if (items.length === 0) throw new
|
|
98
|
+
if (items.length === 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_EMPTY_POOL);
|
|
58
99
|
return items[this.int(0, items.length - 1)];
|
|
59
100
|
}
|
|
60
101
|
digits(n) {
|
|
@@ -89,7 +130,7 @@ function makeCorpus(seed, artifacts, quirks = []) {
|
|
|
89
130
|
}
|
|
90
131
|
function dec(value) {
|
|
91
132
|
const d = X12Decimal.fromString(value);
|
|
92
|
-
if (d === void 0) throw new
|
|
133
|
+
if (d === void 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_INVALID_DECIMAL);
|
|
93
134
|
return d;
|
|
94
135
|
}
|
|
95
136
|
function money(n) {
|
|
@@ -467,7 +508,19 @@ var TOOTH_SURFACES = Object.freeze(["M", "O", "D", "B", "L"]);
|
|
|
467
508
|
var CARC_CODES = Object.freeze(["1", "2", "3", "45", "96", "197"]);
|
|
468
509
|
var SERVICE_TYPE_CODES = Object.freeze(["30", "1", "35", "88", "98"]);
|
|
469
510
|
|
|
511
|
+
// src/select.ts
|
|
512
|
+
function resolveKind(allowed, requested) {
|
|
513
|
+
const match = allowed.find((value) => value === requested);
|
|
514
|
+
if (match === void 0) throw new SynthError(SYNTH_FATAL_CODES.SYNTH_UNSUPPORTED_KIND);
|
|
515
|
+
return match;
|
|
516
|
+
}
|
|
517
|
+
function resolveMix(allowed, requested, fallback) {
|
|
518
|
+
if (requested === void 0) return fallback;
|
|
519
|
+
return requested.map((entry) => resolveKind(allowed, entry));
|
|
520
|
+
}
|
|
521
|
+
|
|
470
522
|
// src/x12/claim-837.ts
|
|
523
|
+
var CLAIM_837_VARIANTS = Object.freeze(["P", "I", "D"]);
|
|
471
524
|
function serviceDtp(serviceDate) {
|
|
472
525
|
return { qualifier: "472", formatQualifier: "D8", value: serviceDate };
|
|
473
526
|
}
|
|
@@ -650,11 +703,17 @@ function specOf(rng, variant) {
|
|
|
650
703
|
};
|
|
651
704
|
}
|
|
652
705
|
function generate837(variant, options) {
|
|
706
|
+
const resolved = resolveKind(CLAIM_837_VARIANTS, variant);
|
|
653
707
|
const rng = createRng(options.seed);
|
|
654
|
-
const spec = specOf(rng,
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
708
|
+
const spec = specOf(rng, resolved);
|
|
709
|
+
switch (resolved) {
|
|
710
|
+
case "P":
|
|
711
|
+
return build837P(spec);
|
|
712
|
+
case "I":
|
|
713
|
+
return build837I(spec);
|
|
714
|
+
case "D":
|
|
715
|
+
return build837D(spec);
|
|
716
|
+
}
|
|
658
717
|
}
|
|
659
718
|
function generate837P(options) {
|
|
660
719
|
return generate837("P", options);
|
|
@@ -862,15 +921,25 @@ function roundTrip(interchange) {
|
|
|
862
921
|
}
|
|
863
922
|
|
|
864
923
|
// src/x12/index.ts
|
|
865
|
-
var
|
|
924
|
+
var ALL_KINDS = Object.freeze(["837P", "837I", "837D", "835", "271"]);
|
|
925
|
+
var DEFAULT_MIX = ALL_KINDS;
|
|
866
926
|
function generateKind(kind, seed) {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
927
|
+
switch (kind) {
|
|
928
|
+
case "835":
|
|
929
|
+
return roundTrip(generate835({ seed }));
|
|
930
|
+
case "271":
|
|
931
|
+
return roundTrip(generate271({ seed }));
|
|
932
|
+
case "837P":
|
|
933
|
+
return roundTrip(generate837("P", { seed }));
|
|
934
|
+
case "837I":
|
|
935
|
+
return roundTrip(generate837("I", { seed }));
|
|
936
|
+
case "837D":
|
|
937
|
+
return roundTrip(generate837("D", { seed }));
|
|
938
|
+
}
|
|
871
939
|
}
|
|
872
940
|
function x12Corpus(options) {
|
|
873
|
-
const { seed
|
|
941
|
+
const { seed } = options;
|
|
942
|
+
const mix = resolveMix(ALL_KINDS, options.mix, DEFAULT_MIX);
|
|
874
943
|
const count = options.count ?? mix.length;
|
|
875
944
|
const seedStream = createRng(seed);
|
|
876
945
|
const artifacts = Array.from({ length: count }, (_unused, i) => {
|