@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,432 @@
|
|
|
1
|
+
import { S as SyntheticName, b as SyntheticAddress, R as Rng, C as Corpus } from '../providers-OLz3zAc-.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Spec-clean NCPDP **SCRIPT** (XML ePrescribing) generation — `NewRx`, `RxRenewalRequest`, and
|
|
5
|
+
* `RxChangeRequest` — built through `@cosyte/ncpdp`'s own emit surface so the XML is spec-clean by the
|
|
6
|
+
* same mechanism that makes the parser's serializer spec-clean:
|
|
7
|
+
*
|
|
8
|
+
* - **NewRx** is built through the validated `buildNewRx` builder (it refuses a NewRx with no
|
|
9
|
+
* medication description) and serialized by `serializeScript`.
|
|
10
|
+
* - **RxRenewalRequest / RxChangeRequest** have no dedicated builder in `@cosyte/ncpdp` (its builders
|
|
11
|
+
* cover NewRx + the Status/Error/Verify responses), so — exactly as the X12 generator constructs a
|
|
12
|
+
* typed model and lets `serializeX12` emit it — these are built as the parser's **public, typed
|
|
13
|
+
* `ScriptMessage` model** (the same immutable model `buildNewRx` returns) and serialized by
|
|
14
|
+
* `serializeScript`. No byte is hand-written; the round-trip harness ({@link ./round-trip.scriptRoundTrip})
|
|
15
|
+
* re-parses every message through `parseScript` and asserts **zero warnings**, so spec-cleanliness is
|
|
16
|
+
* the parser's judgment, not `synth`'s.
|
|
17
|
+
*
|
|
18
|
+
* Every patient / prescriber / pharmacy identifier is drawn from the synthetic-safety providers via
|
|
19
|
+
* {@link ./identity}; the prescriber NPI is invalid-Luhn and the **DEA is invalid-checksum**, so
|
|
20
|
+
* neither can denote a real provider.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
/** Options for the SCRIPT generators. */
|
|
25
|
+
interface GenerateScriptOptions {
|
|
26
|
+
/** The seed (deterministic — same seed yields a byte-identical message). */
|
|
27
|
+
readonly seed: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate a spec-clean SCRIPT **NewRx** ePrescription, built through `@cosyte/ncpdp`'s validated
|
|
31
|
+
* `buildNewRx` and serialized by `serializeScript`. Every identity value is synthetic-by-construction; the
|
|
32
|
+
* message round-trips through `parseScript` with zero warnings.
|
|
33
|
+
*
|
|
34
|
+
* @param options - The seed. See {@link GenerateScriptOptions}.
|
|
35
|
+
* @returns The serialized SCRIPT XML.
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { generateNewRx } from "@cosyte/synth/ncpdp";
|
|
39
|
+
* const xml = generateNewRx({ seed: 42 });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
declare function generateNewRx(options: GenerateScriptOptions): string;
|
|
43
|
+
/**
|
|
44
|
+
* Generate a spec-clean SCRIPT **RxRenewalRequest** (a pharmacy-initiated renewal), built as
|
|
45
|
+
* `@cosyte/ncpdp`'s public typed `ScriptMessage` model and serialized by `serializeScript`. Every
|
|
46
|
+
* identity value is synthetic-by-construction; the message round-trips through `parseScript` with zero
|
|
47
|
+
* warnings (verified by {@link ./round-trip.scriptRoundTrip}).
|
|
48
|
+
*
|
|
49
|
+
* @param options - The seed. See {@link GenerateScriptOptions}.
|
|
50
|
+
* @returns The serialized SCRIPT XML.
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { generateRxRenewalRequest } from "@cosyte/synth/ncpdp";
|
|
54
|
+
* const xml = generateRxRenewalRequest({ seed: 7 });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function generateRxRenewalRequest(options: GenerateScriptOptions): string;
|
|
58
|
+
/**
|
|
59
|
+
* Generate a spec-clean SCRIPT **RxChangeRequest** (a pharmacy-initiated change request), built as
|
|
60
|
+
* `@cosyte/ncpdp`'s public typed `ScriptMessage` model and serialized by `serializeScript`. Every
|
|
61
|
+
* identity value is synthetic-by-construction; the message round-trips through `parseScript` with zero
|
|
62
|
+
* warnings.
|
|
63
|
+
*
|
|
64
|
+
* @param options - The seed. See {@link GenerateScriptOptions}.
|
|
65
|
+
* @returns The serialized SCRIPT XML.
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { generateRxChangeRequest } from "@cosyte/synth/ncpdp";
|
|
69
|
+
* const xml = generateRxChangeRequest({ seed: 7 });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
declare function generateRxChangeRequest(options: GenerateScriptOptions): string;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Spec-clean NCPDP **Telecommunication vD.0** claim generation — `B1` (billing), `B2` (reversal), and
|
|
76
|
+
* `B3` (rebill) — built through `@cosyte/ncpdp`'s `buildTelecomRequest` + `serializeTelecom` so the
|
|
77
|
+
* fixed Transaction Header, the FS/GS/RS framing, and every field are the parser's own conservative
|
|
78
|
+
* emit. Every field id below is a real 2-character NCPDP field identifier, and every
|
|
79
|
+
* value at a PHI-bearing locus is drawn from the synthetic-safety providers via {@link ./identity}: the
|
|
80
|
+
* patient / cardholder names come from the fake-name pool, the DOB / dates from the seeded generator,
|
|
81
|
+
* the phone from the reserved `555-01xx` block, the member / cardholder ids under the synthetic
|
|
82
|
+
* assigning authority, and the prescriber NPI with an invalid Luhn check digit. Each transaction
|
|
83
|
+
* round-trips through `parseTelecom` with zero warnings.
|
|
84
|
+
*
|
|
85
|
+
* @module
|
|
86
|
+
*/
|
|
87
|
+
/** The Telecom transaction codes `synth` generates. */
|
|
88
|
+
type TelecomTransactionCode = "B1" | "B2" | "B3";
|
|
89
|
+
/** Options for the Telecom generators. */
|
|
90
|
+
interface GenerateTelecomOptions {
|
|
91
|
+
/** The seed (deterministic — same seed yields a byte-identical transaction). */
|
|
92
|
+
readonly seed: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Generate a spec-clean Telecom transaction of the given code, built through
|
|
96
|
+
* `@cosyte/ncpdp`'s `buildTelecomRequest` + `serializeTelecom`. `B1`/`B3` carry the full
|
|
97
|
+
* patient / insurance / prescriber / claim segment set; `B2` (reversal) is the minimal
|
|
98
|
+
* insurance + claim-reference set a reversal actually carries. Every identity value is
|
|
99
|
+
* synthetic-by-construction; the transaction round-trips through `parseTelecom` with zero
|
|
100
|
+
* warnings.
|
|
101
|
+
*
|
|
102
|
+
* @param code - `"B1"` billing, `"B2"` reversal, or `"B3"` rebill.
|
|
103
|
+
* @param options - The seed. See {@link GenerateTelecomOptions}.
|
|
104
|
+
* @returns The serialized Telecom wire string.
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* import { generateTelecom } from "@cosyte/synth/ncpdp";
|
|
108
|
+
* const wire = generateTelecom("B1", { seed: 42 });
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
declare function generateTelecom(code: TelecomTransactionCode, options: GenerateTelecomOptions): string;
|
|
112
|
+
/**
|
|
113
|
+
* Generate a spec-clean Telecom **B1** billing claim.
|
|
114
|
+
*
|
|
115
|
+
* @param options - The seed.
|
|
116
|
+
* @returns The serialized Telecom wire string.
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* import { generateB1 } from "@cosyte/synth/ncpdp";
|
|
120
|
+
* const wire = generateB1({ seed: 1 });
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
declare function generateB1(options: GenerateTelecomOptions): string;
|
|
124
|
+
/**
|
|
125
|
+
* Generate a spec-clean Telecom **B2** reversal.
|
|
126
|
+
*
|
|
127
|
+
* @param options - The seed.
|
|
128
|
+
* @returns The serialized Telecom wire string.
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* import { generateB2 } from "@cosyte/synth/ncpdp";
|
|
132
|
+
* const wire = generateB2({ seed: 1 });
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
declare function generateB2(options: GenerateTelecomOptions): string;
|
|
136
|
+
/**
|
|
137
|
+
* Generate a spec-clean Telecom **B3** rebill.
|
|
138
|
+
*
|
|
139
|
+
* @param options - The seed.
|
|
140
|
+
* @returns The serialized Telecom wire string.
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* import { generateB3 } from "@cosyte/synth/ncpdp";
|
|
144
|
+
* const wire = generateB3({ seed: 1 });
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
declare function generateB3(options: GenerateTelecomOptions): string;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* The **round-trip-through-the-parser harness** for NCPDP — the headline gate for the synthetic-fixture
|
|
151
|
+
* generator. A generated SCRIPT XML or Telecom claim is "spec-clean" only if
|
|
152
|
+
* `@cosyte/ncpdp` — not `@cosyte/synth`'s own opinion — reads it back cleanly. Each harness parses the
|
|
153
|
+
* generated wire text straight back through the parser and reports what it found, so a false
|
|
154
|
+
* "spec-clean" claim cannot hide.
|
|
155
|
+
*
|
|
156
|
+
* SCRIPT and Telecom are two structurally unrelated standards, so each gets its own harness; both
|
|
157
|
+
* report the same {@link RoundTripResult} shape.
|
|
158
|
+
*
|
|
159
|
+
* @module
|
|
160
|
+
*/
|
|
161
|
+
/** The verdict of one round-trip through `@cosyte/ncpdp`. */
|
|
162
|
+
interface RoundTripResult {
|
|
163
|
+
/** The serialized NCPDP wire text (the serializer's own conservative emit). */
|
|
164
|
+
readonly content: string;
|
|
165
|
+
/** The warning codes the parser emitted on re-parse. Empty ⇒ spec-clean. */
|
|
166
|
+
readonly warnings: readonly string[];
|
|
167
|
+
/** Whether re-serializing the re-parsed message is byte-identical to `content`. */
|
|
168
|
+
readonly byteStable: boolean;
|
|
169
|
+
/** `true` iff the artifact is spec-clean: zero warnings **and** byte-stable. */
|
|
170
|
+
readonly specClean: boolean;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Round-trip a generated **SCRIPT** XML string through parse → serialize and report the verdict. A
|
|
174
|
+
* spec-clean message re-parses with **zero warnings** and re-serializes byte-identically.
|
|
175
|
+
*
|
|
176
|
+
* @param xml - The SCRIPT XML (typically from `generateNewRx` / `generateRxRenewalRequest` / …).
|
|
177
|
+
* @returns The {@link RoundTripResult}.
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* import { generateNewRx, scriptRoundTrip } from "@cosyte/synth/ncpdp";
|
|
181
|
+
* const { specClean } = scriptRoundTrip(generateNewRx({ seed: 1 })); // specClean === true
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
declare function scriptRoundTrip(xml: string): RoundTripResult;
|
|
185
|
+
/**
|
|
186
|
+
* Round-trip a generated **Telecom** wire string through parse → serialize and report the verdict. A
|
|
187
|
+
* spec-clean transaction re-parses with **zero warnings** and re-serializes byte-identically.
|
|
188
|
+
*
|
|
189
|
+
* @param wire - The Telecom wire string (typically from `generateB1` / `generateB2` / `generateB3`).
|
|
190
|
+
* @returns The {@link RoundTripResult}.
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* import { generateB1, telecomRoundTrip } from "@cosyte/synth/ncpdp";
|
|
194
|
+
* const { specClean } = telecomRoundTrip(generateB1({ seed: 1 })); // specClean === true
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
declare function telecomRoundTrip(wire: string): RoundTripResult;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Synthetic identity for NCPDP transactions — every patient, prescriber, pharmacy, and cardholder
|
|
201
|
+
* identifier `synth` puts into a SCRIPT ePrescription or a Telecom claim is minted here, and **only**
|
|
202
|
+
* from the synthetic-safety providers. NCPDP is identity-dense in a way the refuter
|
|
203
|
+
* attacks hardest: a NewRx carries the **patient** (name, DOB, gender) *and* the **prescriber** (name,
|
|
204
|
+
* NPI, **DEA**); a Telecom claim adds the **cardholder / member** (name, member id). Every locus below
|
|
205
|
+
* has a construction-level guarantee, not a heuristic:
|
|
206
|
+
*
|
|
207
|
+
* - **NPI** — a deliberately **invalid Luhn** check digit, so it can never be a NPPES-issued NPI
|
|
208
|
+
* ({@link ../safe/reserved.isSyntheticNpi}).
|
|
209
|
+
* - **DEA** — a deliberately **invalid checksum**, so it can never be a validly-issued DEA registration
|
|
210
|
+
* ({@link ../safe/reserved.isSyntheticDea}). This is the NCPDP-specific identity locus X12 did not have.
|
|
211
|
+
* - **member / cardholder / patient id** — minted under the synthetic assigning authority with an
|
|
212
|
+
* `MBR` prefix (no reserved range exists; the *namespace* is the guarantee).
|
|
213
|
+
* - **name** — the shipped clearly-fake pool; **DOB** — the seeded generator (no real event implied);
|
|
214
|
+
* **phone** — the reserved `555-01xx` block; **address** — synthetic street + reserved ZIP.
|
|
215
|
+
*
|
|
216
|
+
* @module
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
/** A synthetic patient — every field from `../safe`. */
|
|
220
|
+
interface NcpdpPatient {
|
|
221
|
+
/** Name from the shipped fake-name pool. */
|
|
222
|
+
readonly person: SyntheticName;
|
|
223
|
+
/** Date of birth `CCYYMMDD` from the seeded generator. */
|
|
224
|
+
readonly dob: string;
|
|
225
|
+
/** Administrative gender code (`1` = male, `2` = female — NCPDP gender codes). */
|
|
226
|
+
readonly gender: "1" | "2";
|
|
227
|
+
/** Patient id, synthetic-AA scoped (`MBR`-prefixed — never a bare SSN). */
|
|
228
|
+
readonly patientId: string;
|
|
229
|
+
/** Reserved `555-01xx` phone. */
|
|
230
|
+
readonly phone: string;
|
|
231
|
+
/** Synthetic postal address (reserved non-real ZIP). */
|
|
232
|
+
readonly address: SyntheticAddress;
|
|
233
|
+
}
|
|
234
|
+
/** A synthetic prescriber — name + invalid-Luhn NPI + invalid-checksum DEA. */
|
|
235
|
+
interface NcpdpPrescriber {
|
|
236
|
+
/** A clearly-fake prescriber name. */
|
|
237
|
+
readonly person: SyntheticName;
|
|
238
|
+
/** A 10-digit NPI with a deliberately-invalid Luhn check digit (never a real NPI). */
|
|
239
|
+
readonly npi: string;
|
|
240
|
+
/** A DEA number with a deliberately-invalid checksum (never a real DEA registration). */
|
|
241
|
+
readonly dea: string;
|
|
242
|
+
}
|
|
243
|
+
/** A synthetic dispensing pharmacy — business name + invalid-Luhn NPI + synthetic NCPDP id. */
|
|
244
|
+
interface NcpdpPharmacy {
|
|
245
|
+
/** A clearly-fictional pharmacy business name. */
|
|
246
|
+
readonly businessName: string;
|
|
247
|
+
/** A 10-digit NPI with a deliberately-invalid Luhn check digit. */
|
|
248
|
+
readonly npi: string;
|
|
249
|
+
/** A 7-digit NCPDP provider id (synthetic — an all-digit id under no real chain). */
|
|
250
|
+
readonly ncpdpId: string;
|
|
251
|
+
}
|
|
252
|
+
/** A synthetic cardholder / insurance identity — the covered person on a Telecom claim. */
|
|
253
|
+
interface NcpdpCardholder {
|
|
254
|
+
/** The cardholder name (may differ from the patient). */
|
|
255
|
+
readonly person: SyntheticName;
|
|
256
|
+
/** Cardholder / member id, synthetic-AA scoped (`MBR`-prefixed). */
|
|
257
|
+
readonly cardholderId: string;
|
|
258
|
+
/** Group id, synthetic. */
|
|
259
|
+
readonly groupId: string;
|
|
260
|
+
/** Person code (`01` = cardholder, `02` = spouse, `03` = child — structural). */
|
|
261
|
+
readonly personCode: string;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Mint a synthetic patient. Fixed draw order (name → DOB → gender → id → phone → address) so the same
|
|
265
|
+
* seed yields the same patient.
|
|
266
|
+
*
|
|
267
|
+
* @param rng - The seeded generator.
|
|
268
|
+
* @returns A synthetic {@link NcpdpPatient}.
|
|
269
|
+
* @example
|
|
270
|
+
* ```ts
|
|
271
|
+
* import { createRng } from "@cosyte/synth";
|
|
272
|
+
* import { ncpdpPatient } from "@cosyte/synth/ncpdp";
|
|
273
|
+
* const { person, patientId } = ncpdpPatient(createRng(1));
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
declare function ncpdpPatient(rng: Rng): NcpdpPatient;
|
|
277
|
+
/**
|
|
278
|
+
* Mint a synthetic prescriber — a person name, an invalid-Luhn NPI, and an invalid-checksum DEA (the
|
|
279
|
+
* DEA's second letter is derived from the prescriber's family name so it reads plausibly).
|
|
280
|
+
*
|
|
281
|
+
* @param rng - The seeded generator.
|
|
282
|
+
* @returns A synthetic {@link NcpdpPrescriber}.
|
|
283
|
+
* @example
|
|
284
|
+
* ```ts
|
|
285
|
+
* import { createRng } from "@cosyte/synth";
|
|
286
|
+
* import { ncpdpPrescriber } from "@cosyte/synth/ncpdp";
|
|
287
|
+
* const p = ncpdpPrescriber(createRng(1)); // p.npi invalid-Luhn; p.dea invalid-checksum
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
declare function ncpdpPrescriber(rng: Rng): NcpdpPrescriber;
|
|
291
|
+
/**
|
|
292
|
+
* Mint a synthetic dispensing pharmacy — a fictional business name, an invalid-Luhn NPI, and a 7-digit
|
|
293
|
+
* synthetic NCPDP provider id.
|
|
294
|
+
*
|
|
295
|
+
* @param rng - The seeded generator.
|
|
296
|
+
* @returns A synthetic {@link NcpdpPharmacy}.
|
|
297
|
+
* @example
|
|
298
|
+
* ```ts
|
|
299
|
+
* import { createRng } from "@cosyte/synth";
|
|
300
|
+
* import { ncpdpPharmacy } from "@cosyte/synth/ncpdp";
|
|
301
|
+
* const rx = ncpdpPharmacy(createRng(1));
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
declare function ncpdpPharmacy(rng: Rng): NcpdpPharmacy;
|
|
305
|
+
/**
|
|
306
|
+
* Mint a synthetic cardholder / insurance identity for a Telecom claim.
|
|
307
|
+
*
|
|
308
|
+
* @param rng - The seeded generator.
|
|
309
|
+
* @returns A synthetic {@link NcpdpCardholder}.
|
|
310
|
+
* @example
|
|
311
|
+
* ```ts
|
|
312
|
+
* import { createRng } from "@cosyte/synth";
|
|
313
|
+
* import { ncpdpCardholder } from "@cosyte/synth/ncpdp";
|
|
314
|
+
* const c = ncpdpCardholder(createRng(1));
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
declare function ncpdpCardholder(rng: Rng): NcpdpCardholder;
|
|
318
|
+
/** A seeded SCRIPT routing/correlation bundle — message ids + timestamps, all reproducible. */
|
|
319
|
+
interface NcpdpScriptRouting {
|
|
320
|
+
/** `<MessageID>` — a synthetic message id. */
|
|
321
|
+
readonly messageId: string;
|
|
322
|
+
/** `<SentTime>` — a seeded ISO-8601 timestamp (never wall-clock). */
|
|
323
|
+
readonly sentTime: string;
|
|
324
|
+
/** `<PrescriberOrderNumber>` — a synthetic order number. */
|
|
325
|
+
readonly prescriberOrderNumber: string;
|
|
326
|
+
/** A `CCYYMMDD` written / service date (seeded, recent window). */
|
|
327
|
+
readonly date: string;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Mint a seeded SCRIPT routing bundle. The timestamp is drawn from the seeded generator in a recent
|
|
331
|
+
* window (2024–2026) so a message reads current while staying byte-reproducible.
|
|
332
|
+
*
|
|
333
|
+
* @param rng - The seeded generator.
|
|
334
|
+
* @returns A synthetic {@link NcpdpScriptRouting}.
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* import { createRng } from "@cosyte/synth";
|
|
338
|
+
* import { ncpdpScriptRouting } from "@cosyte/synth/ncpdp";
|
|
339
|
+
* const r = ncpdpScriptRouting(createRng(1));
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
declare function ncpdpScriptRouting(rng: Rng): NcpdpScriptRouting;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* License-clean example drug + code pools for synthetic NCPDP generation. NCPDP charges for its
|
|
346
|
+
* standards and is protective of their prose, so — like every other `synth` format — **no NCPDP
|
|
347
|
+
* copyrighted text is bundled**: these are widely-known generic drug descriptions and invented,
|
|
348
|
+
* clearly-example product codes, not lifted from any NCPDP data dictionary.
|
|
349
|
+
*
|
|
350
|
+
* A drug code is **not** PHI — it names a product, never a patient — so realism here carries no
|
|
351
|
+
* synthetic-safety hazard; the pool exists only to give a generated NewRx / claim a plausible,
|
|
352
|
+
* license-clean drug. Patient / prescriber identity comes from the synthetic-safety providers
|
|
353
|
+
* (`../safe`), never from here.
|
|
354
|
+
*
|
|
355
|
+
* `# synthetic: true`
|
|
356
|
+
*
|
|
357
|
+
* @module
|
|
358
|
+
*/
|
|
359
|
+
/** One example drug: a widely-known generic description + an invented, clearly-example NDC. */
|
|
360
|
+
interface NcpdpExampleDrug {
|
|
361
|
+
/** A widely-known generic drug description (RxNorm-style; public knowledge, not NCPDP prose). */
|
|
362
|
+
readonly description: string;
|
|
363
|
+
/** An invented 11-digit NDC (`5-4-2`, digits only) — an example product code, never a real NDC. */
|
|
364
|
+
readonly ndc: string;
|
|
365
|
+
/** The dispense quantity unit-of-measure qualifier hint (structural only). */
|
|
366
|
+
readonly form: string;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* A small pool of license-clean example drugs. The NDCs use the invented labeler prefix `00000`
|
|
370
|
+
* (never an FDA-assigned labeler), so they are transparently examples; the descriptions are common
|
|
371
|
+
* generics anyone can name without a licensed database.
|
|
372
|
+
*/
|
|
373
|
+
declare const EXAMPLE_DRUGS: readonly NcpdpExampleDrug[];
|
|
374
|
+
/** Example free-text SIG directions (public, common-sense dosing text — not NCPDP prose). */
|
|
375
|
+
declare const EXAMPLE_SIG_TEXT: readonly string[];
|
|
376
|
+
/** Dispense-as-written / product-selection codes (single-digit, structural). */
|
|
377
|
+
declare const DAW_CODES: readonly string[];
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* `@cosyte/synth/ncpdp` — the NCPDP generation surface, exposed as its own subpath so importing the
|
|
381
|
+
* package root does **not** pull `@cosyte/ncpdp`. This is the **lazy, per-format** boundary: a consumer
|
|
382
|
+
* who only needs NCPDP fixtures imports `@cosyte/synth/ncpdp`; one who needs only the core primitives
|
|
383
|
+
* never loads a parser.
|
|
384
|
+
* `@cosyte/ncpdp` is an **optional peer dependency** — present only for this subpath.
|
|
385
|
+
*
|
|
386
|
+
* This subpath ships spec-clean generation across both NCPDP standards, each built through
|
|
387
|
+
* `@cosyte/ncpdp`'s own emit surface:
|
|
388
|
+
*
|
|
389
|
+
* - **SCRIPT** ePrescribing (`@cosyte/ncpdp/script`): `generateNewRx` (via the validated `buildNewRx`
|
|
390
|
+
* builder), `generateRxRenewalRequest`, and `generateRxChangeRequest` (via the parser's public typed
|
|
391
|
+
* `ScriptMessage` model + `serializeScript`) — each round-tripping through `parseScript` with zero
|
|
392
|
+
* warnings, and carrying a prescriber whose NPI is invalid-Luhn and whose **DEA is invalid-checksum**.
|
|
393
|
+
* - **Telecom** claims (`@cosyte/ncpdp/telecom`): `generateB1` (billing), `generateB2` (reversal), and
|
|
394
|
+
* `generateB3` (rebill) via `buildTelecomRequest` + `serializeTelecom` — each round-tripping through
|
|
395
|
+
* `parseTelecom` with zero warnings, with patient / cardholder identity from the synthetic providers.
|
|
396
|
+
*
|
|
397
|
+
* **Deferred:** **quirk mode**. SCRIPT is limited to the transactions `@cosyte/ncpdp` can *build* — NewRx
|
|
398
|
+
* plus the
|
|
399
|
+
* renewal/change **requests**; the renewal/change *responses* and the reversal cases beyond B2's
|
|
400
|
+
* reference set track the parser's builder surface, never hand-written bytes.
|
|
401
|
+
*
|
|
402
|
+
* @module
|
|
403
|
+
*/
|
|
404
|
+
|
|
405
|
+
/** Every NCPDP transaction kind {@link ncpdpCorpus} generates — the label used as the corpus `kind`. */
|
|
406
|
+
type NcpdpCorpusKind = "NewRx" | "RxRenewalRequest" | "RxChangeRequest" | "B1" | "B2" | "B3";
|
|
407
|
+
/** Options for {@link ncpdpCorpus}. */
|
|
408
|
+
interface NcpdpCorpusOptions {
|
|
409
|
+
/** The seed for the whole corpus (deterministic). */
|
|
410
|
+
readonly seed: number;
|
|
411
|
+
/** How many transactions to generate. Defaults to the length of the mix. */
|
|
412
|
+
readonly count?: number;
|
|
413
|
+
/** The transaction kinds to cycle through. Defaults to one of each. */
|
|
414
|
+
readonly mix?: readonly NcpdpCorpusKind[];
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Build a reproducible {@link Corpus} of spec-clean NCPDP transactions. Each transaction is generated
|
|
418
|
+
* from a distinct sub-seed derived from the corpus seed (so the set is deterministic) and round-tripped
|
|
419
|
+
* through `@cosyte/ncpdp`; the per-artifact `warnings` record the parser's verdict (empty ⇒ spec-clean).
|
|
420
|
+
*
|
|
421
|
+
* @param options - Seed, count, and the transaction mix. See {@link NcpdpCorpusOptions}.
|
|
422
|
+
* @returns A deep-frozen {@link Corpus}.
|
|
423
|
+
* @example
|
|
424
|
+
* ```ts
|
|
425
|
+
* import { ncpdpCorpus } from "@cosyte/synth/ncpdp";
|
|
426
|
+
* const corpus = ncpdpCorpus({ seed: 42 });
|
|
427
|
+
* corpus.artifacts.every((a) => a.warnings.length === 0); // true — spec-clean
|
|
428
|
+
* ```
|
|
429
|
+
*/
|
|
430
|
+
declare function ncpdpCorpus(options: NcpdpCorpusOptions): Corpus;
|
|
431
|
+
|
|
432
|
+
export { DAW_CODES, EXAMPLE_DRUGS, EXAMPLE_SIG_TEXT, type GenerateScriptOptions, type GenerateTelecomOptions, type NcpdpCardholder, type NcpdpCorpusKind, type NcpdpCorpusOptions, type NcpdpExampleDrug, type NcpdpPatient, type NcpdpPharmacy, type NcpdpPrescriber, type NcpdpScriptRouting, type RoundTripResult, type TelecomTransactionCode, generateB1, generateB2, generateB3, generateNewRx, generateRxChangeRequest, generateRxRenewalRequest, generateTelecom, ncpdpCardholder, ncpdpCorpus, ncpdpPatient, ncpdpPharmacy, ncpdpPrescriber, ncpdpScriptRouting, scriptRoundTrip, telecomRoundTrip };
|