@cosyte/synth 0.0.1
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 +414 -0
- package/LICENSE +21 -0
- package/README.md +325 -0
- package/dist/astm/index.cjs +847 -0
- package/dist/astm/index.cjs.map +1 -0
- package/dist/astm/index.d.cts +418 -0
- package/dist/astm/index.d.ts +418 -0
- package/dist/astm/index.mjs +828 -0
- package/dist/astm/index.mjs.map +1 -0
- package/dist/ccda/index.cjs +1103 -0
- package/dist/ccda/index.cjs.map +1 -0
- package/dist/ccda/index.d.cts +380 -0
- package/dist/ccda/index.d.ts +380 -0
- package/dist/ccda/index.mjs +1077 -0
- package/dist/ccda/index.mjs.map +1 -0
- package/dist/deid/index.cjs +2809 -0
- package/dist/deid/index.cjs.map +1 -0
- package/dist/deid/index.d.cts +464 -0
- package/dist/deid/index.d.ts +464 -0
- package/dist/deid/index.mjs +2793 -0
- package/dist/deid/index.mjs.map +1 -0
- package/dist/example-codes-DeXcnCSK.d.cts +105 -0
- package/dist/example-codes-DeXcnCSK.d.ts +105 -0
- package/dist/fhir/index.cjs +1429 -0
- package/dist/fhir/index.cjs.map +1 -0
- package/dist/fhir/index.d.cts +772 -0
- package/dist/fhir/index.d.ts +772 -0
- package/dist/fhir/index.mjs +1384 -0
- package/dist/fhir/index.mjs.map +1 -0
- package/dist/hl7/index.cjs +1012 -0
- package/dist/hl7/index.cjs.map +1 -0
- package/dist/hl7/index.d.cts +548 -0
- package/dist/hl7/index.d.ts +548 -0
- package/dist/hl7/index.mjs +990 -0
- package/dist/hl7/index.mjs.map +1 -0
- package/dist/index.cjs +535 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +407 -0
- package/dist/index.d.ts +407 -0
- package/dist/index.mjs +488 -0
- package/dist/index.mjs.map +1 -0
- package/dist/ncpdp/index.cjs +714 -0
- package/dist/ncpdp/index.cjs.map +1 -0
- package/dist/ncpdp/index.d.cts +432 -0
- package/dist/ncpdp/index.d.ts +432 -0
- package/dist/ncpdp/index.mjs +695 -0
- package/dist/ncpdp/index.mjs.map +1 -0
- package/dist/providers-OLz3zAc-.d.cts +343 -0
- package/dist/providers-OLz3zAc-.d.ts +343 -0
- package/dist/quirk-DmkgoZdh.d.cts +239 -0
- package/dist/quirk-JLyO1Ncj.d.ts +239 -0
- package/dist/x12/index.cjs +920 -0
- package/dist/x12/index.cjs.map +1 -0
- package/dist/x12/index.d.cts +484 -0
- package/dist/x12/index.d.ts +484 -0
- package/dist/x12/index.mjs +892 -0
- package/dist/x12/index.mjs.map +1 -0
- package/package.json +210 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { m as SynthFormat } from './providers-OLz3zAc-.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `defineSynthProfile` — the growth-loop hook for site/vendor fixture recipes. A profile bundles the
|
|
5
|
+
* value pools and the quirk recipe a fixture set should use, authored through the same public API as
|
|
6
|
+
* the built-ins: a validated, frozen `SynthProfile` carrying a name, optional value overrides, and the
|
|
7
|
+
* quirk names a format's quirk corpus should apply.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
/** The user-authored spec passed to {@link defineSynthProfile}. */
|
|
12
|
+
interface SynthProfileSpec {
|
|
13
|
+
/** A stable, human-readable profile name (e.g. `"acme-hospital"`). Required, non-empty. */
|
|
14
|
+
readonly name: string;
|
|
15
|
+
/** Optional given-name pool override (clearly-synthetic names only — see the safety invariant). */
|
|
16
|
+
readonly givenNames?: readonly string[];
|
|
17
|
+
/** Optional family-name pool override (clearly-synthetic names only). */
|
|
18
|
+
readonly familyNames?: readonly string[];
|
|
19
|
+
/**
|
|
20
|
+
* The vendor quirk recipe names this profile requests. Validated against the target format's quirk
|
|
21
|
+
* registry when the profile drives a quirk corpus (an unsupported quirk is a fatal
|
|
22
|
+
* `SYNTH_UNSUPPORTED_QUIRK`, never a silent no-op).
|
|
23
|
+
*/
|
|
24
|
+
readonly quirks?: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
/** A frozen, validated fixture recipe produced by {@link defineSynthProfile}. */
|
|
27
|
+
interface SynthProfile {
|
|
28
|
+
/** The profile name. */
|
|
29
|
+
readonly name: string;
|
|
30
|
+
/** The given-name pool this profile draws from (overrides or the built-in default). */
|
|
31
|
+
readonly givenNames?: readonly string[];
|
|
32
|
+
/** The family-name pool this profile draws from. */
|
|
33
|
+
readonly familyNames?: readonly string[];
|
|
34
|
+
/** The requested quirk recipe names. */
|
|
35
|
+
readonly quirks: readonly string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Define a reusable, frozen synthetic-fixture profile.
|
|
39
|
+
*
|
|
40
|
+
* @param spec - The profile spec; `name` is required and non-empty.
|
|
41
|
+
* @returns A deep-frozen {@link SynthProfile}.
|
|
42
|
+
* @throws TypeError when `name` is missing or blank.
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { defineSynthProfile } from "@cosyte/synth";
|
|
46
|
+
* const acme = defineSynthProfile({ name: "acme-hospital", quirks: [] });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare function defineSynthProfile(spec: SynthProfileSpec): SynthProfile;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The **quirk core**. Where the spec-clean generators prove
|
|
53
|
+
* *synthetic-by-construction* through each parser's own builder, the quirk layer proves the mirror
|
|
54
|
+
* property: a **deliberately off-spec** fixture round-trips to **exactly the intended parser warning
|
|
55
|
+
* code(s)** — no more, no fewer. The quirk vocabulary **is the parsers' own profile systems**
|
|
56
|
+
* (`hl7.defineProfile`, `ccda.defineCcdaProfile`, `astm.defineAstmProfile`): a quirk exercises exactly
|
|
57
|
+
* the tolerance the corresponding parser profile encodes, so a quirk fixture is never a fiction — it
|
|
58
|
+
* targets a documented, coded leniency (the **intended-warning contract**).
|
|
59
|
+
*
|
|
60
|
+
* This module is the **format-agnostic** part: the descriptor a quirk carries, the artifact a quirk
|
|
61
|
+
* generator returns, the round-trip verdict shape, and the `SYNTH_UNSUPPORTED_QUIRK` fail-closed. Each
|
|
62
|
+
* format's concrete quirk recipes + transforms live behind its own subpath (`@cosyte/synth/hl7`, …).
|
|
63
|
+
*
|
|
64
|
+
* @module
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* How the parser's matching profile treats a quirk once it is active — the three shapes the parsers'
|
|
69
|
+
* profile systems actually exhibit (verified firsthand against each parser):
|
|
70
|
+
*
|
|
71
|
+
* - `"suppressed"` — the profile makes the warning **disappear** (HL7 v2: a `defineProfile`
|
|
72
|
+
* `customSegments` claim suppresses `UNKNOWN_SEGMENT` for a declared Z-segment).
|
|
73
|
+
* - `"rebadged"` — the profile **downgrades** the warning to the value-free `PROFILE_QUIRK_APPLIED`
|
|
74
|
+
* marker with `expected: true` (C-CDA `defineCcdaProfile` / ASTM `defineAstmProfile`
|
|
75
|
+
* `profileQuirkApplied`).
|
|
76
|
+
* - `"bare"` — no shipped profile tolerates it; the quirk targets a real coded leniency a consumer can
|
|
77
|
+
* tolerate via their own `defineProfile`/`defineAstmProfile`, but no built-in re-badges it.
|
|
78
|
+
*/
|
|
79
|
+
type QuirkProfileDisposition = "suppressed" | "rebadged" | "bare";
|
|
80
|
+
/**
|
|
81
|
+
* The stable, value-free re-badge code the C-CDA and ASTM parsers emit when a profile tolerates a
|
|
82
|
+
* quirk. HL7 v2 has no equivalent (it suppresses instead — see {@link QuirkProfileDisposition}).
|
|
83
|
+
*/
|
|
84
|
+
declare const PROFILE_QUIRK_APPLIED = "PROFILE_QUIRK_APPLIED";
|
|
85
|
+
/**
|
|
86
|
+
* A public, grounded description of one vendor quirk — the metadata that binds a quirk recipe to a real
|
|
87
|
+
* parser warning code and a **publicly-groundable** deviation (cited-public, never a private
|
|
88
|
+
* vendor corpus).
|
|
89
|
+
*/
|
|
90
|
+
interface QuirkDescriptor {
|
|
91
|
+
/** The quirk recipe name (e.g. `"unknown-zsegment"`). Stable; part of the public contract. */
|
|
92
|
+
readonly name: string;
|
|
93
|
+
/** The format this quirk applies to. */
|
|
94
|
+
readonly format: SynthFormat;
|
|
95
|
+
/**
|
|
96
|
+
* The **exact** parser warning code(s) a bare parse (no profile) surfaces for this quirk — the
|
|
97
|
+
* intended-warning contract. A quirk that produces any other code, or none, is a generation bug.
|
|
98
|
+
*/
|
|
99
|
+
readonly intendedWarnings: readonly string[];
|
|
100
|
+
/**
|
|
101
|
+
* The **public** grounding for this quirk — the spec clause or the parser's public profile that
|
|
102
|
+
* documents the tolerance. Never a private vendor-attributed corpus.
|
|
103
|
+
*/
|
|
104
|
+
readonly grounding: string;
|
|
105
|
+
/** The parser profile that tolerates this quirk (when a built-in public one exists). */
|
|
106
|
+
readonly toleratingProfile?: string;
|
|
107
|
+
/** How {@link toleratingProfile} treats the quirk. */
|
|
108
|
+
readonly disposition: QuirkProfileDisposition;
|
|
109
|
+
}
|
|
110
|
+
/** One generated quirk artifact — the off-spec wire text plus the contract it is meant to satisfy. */
|
|
111
|
+
interface QuirkArtifact {
|
|
112
|
+
/** The format this artifact belongs to. */
|
|
113
|
+
readonly format: SynthFormat;
|
|
114
|
+
/** The quirk recipe applied. */
|
|
115
|
+
readonly quirk: string;
|
|
116
|
+
/** The underlying spec-clean message kind the quirk was injected into (e.g. `"ORU^R01"`). */
|
|
117
|
+
readonly kind: string;
|
|
118
|
+
/** The **quirked** wire text (deterministic in the seed + quirk). */
|
|
119
|
+
readonly content: string;
|
|
120
|
+
/** The exact parser warning code(s) this artifact is meant to round-trip to. */
|
|
121
|
+
readonly intendedWarnings: readonly string[];
|
|
122
|
+
}
|
|
123
|
+
/** The verdict of a bare parse under the tolerating profile, if any. */
|
|
124
|
+
interface QuirkProfiledVerdict {
|
|
125
|
+
/** The profile applied. */
|
|
126
|
+
readonly profileName: string;
|
|
127
|
+
/** How the profile treats the quirk. */
|
|
128
|
+
readonly disposition: QuirkProfileDisposition;
|
|
129
|
+
/** The warning codes the parser emitted with the profile active. */
|
|
130
|
+
readonly warnings: readonly string[];
|
|
131
|
+
/**
|
|
132
|
+
* `true` iff the profile handled the quirk as its disposition declares: `"suppressed"` ⇒ the intended
|
|
133
|
+
* code is gone; `"rebadged"` ⇒ the intended code is gone and `PROFILE_QUIRK_APPLIED` is present.
|
|
134
|
+
*/
|
|
135
|
+
readonly tolerated: boolean;
|
|
136
|
+
}
|
|
137
|
+
/** The verdict of round-tripping a quirk artifact through its parser. */
|
|
138
|
+
interface QuirkRoundTripResult {
|
|
139
|
+
/** The quirked wire text that was parsed. */
|
|
140
|
+
readonly content: string;
|
|
141
|
+
/** The warning codes a **bare** parse (no profile) emitted. */
|
|
142
|
+
readonly warnings: readonly string[];
|
|
143
|
+
/** The exact code(s) the quirk is meant to produce. */
|
|
144
|
+
readonly intendedWarnings: readonly string[];
|
|
145
|
+
/**
|
|
146
|
+
* `true` iff the bare parse produced **exactly** the intended code(s) — the intended-warning contract.
|
|
147
|
+
*/
|
|
148
|
+
readonly intendedWarningHeld: boolean;
|
|
149
|
+
/** The verdict under the tolerating profile, when a built-in public one exists. */
|
|
150
|
+
readonly withProfile?: QuirkProfiledVerdict;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Exact multiset (order-independent) equality of two code lists — the intended-warning comparison.
|
|
154
|
+
*
|
|
155
|
+
* @param a - The first code list.
|
|
156
|
+
* @param b - The second code list.
|
|
157
|
+
* @returns `true` iff the two lists contain the same codes with the same multiplicities.
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { sameCodeSet } from "@cosyte/synth";
|
|
161
|
+
* sameCodeSet(["A", "B"], ["B", "A"]); // true
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
declare function sameCodeSet(a: readonly string[], b: readonly string[]): boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Resolve a requested quirk name against a format's registry, or **fail closed**. A quirk the format's
|
|
167
|
+
* profile system does not support is a fatal `SYNTH_UNSUPPORTED_QUIRK` — never a silent no-op and never
|
|
168
|
+
* a fabricated quirk with a made-up warning.
|
|
169
|
+
*
|
|
170
|
+
* @param registry - The format's quirk descriptors, keyed by name.
|
|
171
|
+
* @param format - The format being generated (for the error message).
|
|
172
|
+
* @param name - The requested quirk name.
|
|
173
|
+
* @returns The matching {@link QuirkDescriptor}.
|
|
174
|
+
* @throws SynthError with code `SYNTH_UNSUPPORTED_QUIRK` when `name` is not a supported quirk.
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* import { resolveQuirk } from "@cosyte/synth";
|
|
178
|
+
* import { HL7_QUIRKS } from "@cosyte/synth/hl7";
|
|
179
|
+
* resolveQuirk(HL7_QUIRKS, "hl7v2", "unknown-zsegment").intendedWarnings; // ["UNKNOWN_SEGMENT"]
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
declare function resolveQuirk(registry: Readonly<Record<string, QuirkDescriptor>>, format: SynthFormat, name: string): QuirkDescriptor;
|
|
183
|
+
/**
|
|
184
|
+
* Evaluate whether a profiled parse tolerated a quirk as its disposition declares. Shared across the
|
|
185
|
+
* formats so the "suppressed vs re-badged" logic lives in exactly one place.
|
|
186
|
+
*
|
|
187
|
+
* @param disposition - The quirk's declared profile disposition.
|
|
188
|
+
* @param intendedWarnings - The bare-parse intended code(s).
|
|
189
|
+
* @param warningsUnderProfile - The code(s) the parser emitted with the profile active.
|
|
190
|
+
* @returns `true` iff the profile handled the quirk correctly for its disposition.
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* import { profileTolerated } from "@cosyte/synth";
|
|
194
|
+
* profileTolerated("suppressed", ["UNKNOWN_SEGMENT"], []); // true — the profile suppressed it
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
declare function profileTolerated(disposition: QuirkProfileDisposition, intendedWarnings: readonly string[], warningsUnderProfile: readonly string[]): boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Assert a freshly-generated quirk artifact **actually** round-trips to its intended warning(s), or
|
|
200
|
+
* **fail closed**. This is the generator's self-check on the intended-warning contract: a
|
|
201
|
+
* fixture whose bare parse does not produce exactly the declared code(s) is a *mislabeled* fixture — a
|
|
202
|
+
* golden file that lies about the parser verdict it anchors — and must never be emitted. It is a
|
|
203
|
+
* stronger guard than "the transform changed some bytes": a transform can mutate the wrong element (a
|
|
204
|
+
* template a given document type does not key its warning on) and still change bytes while producing no
|
|
205
|
+
* warning. Every format's `generate*Quirk` calls this after transforming, so the contract is enforced at
|
|
206
|
+
* generation time, not merely at round-trip time.
|
|
207
|
+
*
|
|
208
|
+
* @param quirk - The quirk name (for the error message).
|
|
209
|
+
* @param intendedWarnings - The declared intended code(s).
|
|
210
|
+
* @param bareWarnings - The code(s) a bare parse of the generated artifact actually produced.
|
|
211
|
+
* @throws Error when the bare parse did not produce exactly the intended code(s).
|
|
212
|
+
* @example
|
|
213
|
+
* ```ts
|
|
214
|
+
* import { assertIntendedWarnings } from "@cosyte/synth";
|
|
215
|
+
* assertIntendedWarnings("unknown-zsegment", ["UNKNOWN_SEGMENT"], ["UNKNOWN_SEGMENT"]); // ok
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
declare function assertIntendedWarnings(quirk: string, intendedWarnings: readonly string[], bareWarnings: readonly string[]): void;
|
|
219
|
+
/**
|
|
220
|
+
* Validate the quirk names carried by a {@link SynthProfile} against a format's registry, failing closed
|
|
221
|
+
* on the first unsupported one. Lets a consumer author a fixture recipe with `defineSynthProfile` and
|
|
222
|
+
* have its quirks checked against the *parser's* real tolerance before any fixture is generated.
|
|
223
|
+
*
|
|
224
|
+
* @param profile - The synth profile whose `quirks` to validate.
|
|
225
|
+
* @param registry - The format's quirk descriptors.
|
|
226
|
+
* @param format - The format being generated.
|
|
227
|
+
* @returns The validated quirk names (the profile's, in order).
|
|
228
|
+
* @throws SynthError `SYNTH_UNSUPPORTED_QUIRK` for the first unsupported quirk.
|
|
229
|
+
* @example
|
|
230
|
+
* ```ts
|
|
231
|
+
* import { validateProfileQuirks, defineSynthProfile } from "@cosyte/synth";
|
|
232
|
+
* import { HL7_QUIRKS } from "@cosyte/synth/hl7";
|
|
233
|
+
* const p = defineSynthProfile({ name: "site", quirks: ["unknown-zsegment"] });
|
|
234
|
+
* validateProfileQuirks(p, HL7_QUIRKS, "hl7v2"); // ["unknown-zsegment"]
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
declare function validateProfileQuirks(profile: SynthProfile, registry: Readonly<Record<string, QuirkDescriptor>>, format: SynthFormat): readonly string[];
|
|
238
|
+
|
|
239
|
+
export { PROFILE_QUIRK_APPLIED as P, type QuirkDescriptor as Q, type SynthProfile as S, type QuirkArtifact as a, type QuirkRoundTripResult as b, type QuirkProfileDisposition as c, type QuirkProfiledVerdict as d, type SynthProfileSpec as e, assertIntendedWarnings as f, defineSynthProfile as g, profileTolerated as p, resolveQuirk as r, sameCodeSet as s, validateProfileQuirks as v };
|