@cosyte/synth 0.0.6 → 0.0.8
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 +165 -17
- package/README.md +47 -45
- package/dist/astm/index.cjs +7 -7
- package/dist/astm/index.cjs.map +1 -1
- package/dist/astm/index.d.cts +47 -47
- package/dist/astm/index.d.ts +47 -47
- package/dist/astm/index.mjs +7 -7
- package/dist/astm/index.mjs.map +1 -1
- package/dist/ccda/index.cjs +15 -15
- package/dist/ccda/index.cjs.map +1 -1
- package/dist/ccda/index.d.cts +31 -31
- package/dist/ccda/index.d.ts +31 -31
- package/dist/ccda/index.mjs +15 -15
- package/dist/ccda/index.mjs.map +1 -1
- package/dist/deid/index.cjs +15 -15
- package/dist/deid/index.cjs.map +1 -1
- package/dist/deid/index.d.cts +37 -37
- package/dist/deid/index.d.ts +37 -37
- package/dist/deid/index.mjs +15 -15
- package/dist/deid/index.mjs.map +1 -1
- package/dist/{example-codes-DeXcnCSK.d.cts → example-codes-88f3_bQZ.d.cts} +8 -8
- package/dist/{example-codes-DeXcnCSK.d.ts → example-codes-88f3_bQZ.d.ts} +8 -8
- package/dist/fhir/index.cjs +12 -12
- package/dist/fhir/index.cjs.map +1 -1
- package/dist/fhir/index.d.cts +46 -46
- package/dist/fhir/index.d.ts +46 -46
- package/dist/fhir/index.mjs +12 -12
- package/dist/fhir/index.mjs.map +1 -1
- package/dist/hl7/index.cjs +6 -6
- package/dist/hl7/index.cjs.map +1 -1
- package/dist/hl7/index.d.cts +45 -45
- package/dist/hl7/index.d.ts +45 -45
- package/dist/hl7/index.mjs +6 -6
- package/dist/hl7/index.mjs.map +1 -1
- package/dist/index.cjs +9 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -49
- package/dist/index.d.ts +49 -49
- package/dist/index.mjs +9 -9
- package/dist/index.mjs.map +1 -1
- package/dist/ncpdp/index.cjs +3 -3
- package/dist/ncpdp/index.cjs.map +1 -1
- package/dist/ncpdp/index.d.cts +42 -42
- package/dist/ncpdp/index.d.ts +42 -42
- package/dist/ncpdp/index.mjs +3 -3
- package/dist/ncpdp/index.mjs.map +1 -1
- package/dist/{providers-OLz3zAc-.d.cts → providers-B9uVinAe.d.cts} +24 -24
- package/dist/{providers-OLz3zAc-.d.ts → providers-B9uVinAe.d.ts} +24 -24
- package/dist/{quirk-C9t9CkPS.d.ts → quirk-HZdznAkM.d.ts} +23 -23
- package/dist/{quirk-DYMDojVw.d.cts → quirk-IaHp4z7N.d.cts} +23 -23
- package/dist/x12/index.cjs +6 -6
- package/dist/x12/index.cjs.map +1 -1
- package/dist/x12/index.d.cts +44 -44
- package/dist/x12/index.d.ts +44 -44
- package/dist/x12/index.mjs +6 -6
- package/dist/x12/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/ncpdp/index.d.cts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { S as SyntheticName, b as SyntheticAddress, R as Rng, C as Corpus } from '../providers-
|
|
1
|
+
import { S as SyntheticName, b as SyntheticAddress, R as Rng, C as Corpus } from '../providers-B9uVinAe.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Spec-clean NCPDP **SCRIPT** (XML ePrescribing) generation
|
|
5
|
-
* `RxChangeRequest
|
|
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
6
|
* same mechanism that makes the parser's serializer spec-clean:
|
|
7
7
|
*
|
|
8
8
|
* - **NewRx** is built through the validated `buildNewRx` builder (it refuses a NewRx with no
|
|
9
9
|
* medication description) and serialized by `serializeScript`.
|
|
10
10
|
* - **RxRenewalRequest / RxChangeRequest** have no dedicated builder in `@cosyte/ncpdp` (its builders
|
|
11
|
-
* cover NewRx + the Status/Error/Verify responses), so
|
|
12
|
-
* typed model and lets `serializeX12` emit it
|
|
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
13
|
* `ScriptMessage` model** (the same immutable model `buildNewRx` returns) and serialized by
|
|
14
14
|
* `serializeScript`. No byte is hand-written; the round-trip harness ({@link ./round-trip.scriptRoundTrip})
|
|
15
15
|
* re-parses every message through `parseScript` and asserts **zero warnings**, so spec-cleanliness is
|
|
@@ -23,7 +23,7 @@ import { S as SyntheticName, b as SyntheticAddress, R as Rng, C as Corpus } from
|
|
|
23
23
|
*/
|
|
24
24
|
/** Options for the SCRIPT generators. */
|
|
25
25
|
interface GenerateScriptOptions {
|
|
26
|
-
/** The seed (deterministic
|
|
26
|
+
/** The seed (deterministic: same seed yields a byte-identical message). */
|
|
27
27
|
readonly seed: number;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -72,8 +72,8 @@ declare function generateRxRenewalRequest(options: GenerateScriptOptions): strin
|
|
|
72
72
|
declare function generateRxChangeRequest(options: GenerateScriptOptions): string;
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
|
-
* Spec-clean NCPDP **Telecommunication vD.0** claim generation
|
|
76
|
-
* `B3` (rebill)
|
|
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
77
|
* fixed Transaction Header, the FS/GS/RS framing, and every field are the parser's own conservative
|
|
78
78
|
* emit. Every field id below is a real 2-character NCPDP field identifier, and every
|
|
79
79
|
* value at a PHI-bearing locus is drawn from the synthetic-safety providers via {@link ./identity}: the
|
|
@@ -88,7 +88,7 @@ declare function generateRxChangeRequest(options: GenerateScriptOptions): string
|
|
|
88
88
|
type TelecomTransactionCode = "B1" | "B2" | "B3";
|
|
89
89
|
/** Options for the Telecom generators. */
|
|
90
90
|
interface GenerateTelecomOptions {
|
|
91
|
-
/** The seed (deterministic
|
|
91
|
+
/** The seed (deterministic: same seed yields a byte-identical transaction). */
|
|
92
92
|
readonly seed: number;
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
@@ -147,9 +147,9 @@ declare function generateB2(options: GenerateTelecomOptions): string;
|
|
|
147
147
|
declare function generateB3(options: GenerateTelecomOptions): string;
|
|
148
148
|
|
|
149
149
|
/**
|
|
150
|
-
* The **round-trip-through-the-parser harness** for NCPDP
|
|
150
|
+
* The **round-trip-through-the-parser harness** for NCPDP: the headline gate for the synthetic-fixture
|
|
151
151
|
* generator. A generated SCRIPT XML or Telecom claim is "spec-clean" only if
|
|
152
|
-
* `@cosyte/ncpdp
|
|
152
|
+
* `@cosyte/ncpdp`, not `@cosyte/synth`'s own opinion, reads it back cleanly. Each harness parses the
|
|
153
153
|
* generated wire text straight back through the parser and reports what it found, so a false
|
|
154
154
|
* "spec-clean" claim cannot hide.
|
|
155
155
|
*
|
|
@@ -197,41 +197,41 @@ declare function scriptRoundTrip(xml: string): RoundTripResult;
|
|
|
197
197
|
declare function telecomRoundTrip(wire: string): RoundTripResult;
|
|
198
198
|
|
|
199
199
|
/**
|
|
200
|
-
* Synthetic identity for NCPDP transactions
|
|
200
|
+
* Synthetic identity for NCPDP transactions: every patient, prescriber, pharmacy, and cardholder
|
|
201
201
|
* identifier `synth` puts into a SCRIPT ePrescription or a Telecom claim is minted here, and **only**
|
|
202
202
|
* from the synthetic-safety providers. NCPDP is identity-dense in a way the refuter
|
|
203
203
|
* attacks hardest: a NewRx carries the **patient** (name, DOB, gender) *and* the **prescriber** (name,
|
|
204
204
|
* NPI, **DEA**); a Telecom claim adds the **cardholder / member** (name, member id). Every locus below
|
|
205
205
|
* has a construction-level guarantee, not a heuristic:
|
|
206
206
|
*
|
|
207
|
-
* - **NPI
|
|
207
|
+
* - **NPI**: a deliberately **invalid Luhn** check digit, so it can never be a NPPES-issued NPI
|
|
208
208
|
* ({@link ../safe/reserved.isSyntheticNpi}).
|
|
209
|
-
* - **DEA
|
|
209
|
+
* - **DEA**: a deliberately **invalid checksum**, so it can never be a validly-issued DEA registration
|
|
210
210
|
* ({@link ../safe/reserved.isSyntheticDea}). This is the NCPDP-specific identity locus X12 did not have.
|
|
211
|
-
* - **member / cardholder / patient id
|
|
211
|
+
* - **member / cardholder / patient id**: minted under the synthetic assigning authority with an
|
|
212
212
|
* `MBR` prefix (no reserved range exists; the *namespace* is the guarantee).
|
|
213
|
-
* - **name
|
|
214
|
-
* **phone
|
|
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
215
|
*
|
|
216
216
|
* @module
|
|
217
217
|
*/
|
|
218
218
|
|
|
219
|
-
/** A synthetic patient
|
|
219
|
+
/** A synthetic patient: every field from `../safe`. */
|
|
220
220
|
interface NcpdpPatient {
|
|
221
221
|
/** Name from the shipped fake-name pool. */
|
|
222
222
|
readonly person: SyntheticName;
|
|
223
223
|
/** Date of birth `CCYYMMDD` from the seeded generator. */
|
|
224
224
|
readonly dob: string;
|
|
225
|
-
/** Administrative gender code (`1` = male, `2` = female
|
|
225
|
+
/** Administrative gender code (`1` = male, `2` = female, NCPDP gender codes). */
|
|
226
226
|
readonly gender: "1" | "2";
|
|
227
|
-
/** Patient id, synthetic-AA scoped (`MBR`-prefixed
|
|
227
|
+
/** Patient id, synthetic-AA scoped (`MBR`-prefixed, never a bare SSN). */
|
|
228
228
|
readonly patientId: string;
|
|
229
229
|
/** Reserved `555-01xx` phone. */
|
|
230
230
|
readonly phone: string;
|
|
231
231
|
/** Synthetic postal address (reserved non-real ZIP). */
|
|
232
232
|
readonly address: SyntheticAddress;
|
|
233
233
|
}
|
|
234
|
-
/** A synthetic prescriber
|
|
234
|
+
/** A synthetic prescriber: name + invalid-Luhn NPI + invalid-checksum DEA. */
|
|
235
235
|
interface NcpdpPrescriber {
|
|
236
236
|
/** A clearly-fake prescriber name. */
|
|
237
237
|
readonly person: SyntheticName;
|
|
@@ -240,16 +240,16 @@ interface NcpdpPrescriber {
|
|
|
240
240
|
/** A DEA number with a deliberately-invalid checksum (never a real DEA registration). */
|
|
241
241
|
readonly dea: string;
|
|
242
242
|
}
|
|
243
|
-
/** A synthetic dispensing pharmacy
|
|
243
|
+
/** A synthetic dispensing pharmacy: business name + invalid-Luhn NPI + synthetic NCPDP id. */
|
|
244
244
|
interface NcpdpPharmacy {
|
|
245
245
|
/** A clearly-fictional pharmacy business name. */
|
|
246
246
|
readonly businessName: string;
|
|
247
247
|
/** A 10-digit NPI with a deliberately-invalid Luhn check digit. */
|
|
248
248
|
readonly npi: string;
|
|
249
|
-
/** A 7-digit NCPDP provider id (synthetic
|
|
249
|
+
/** A 7-digit NCPDP provider id (synthetic, an all-digit id under no real chain). */
|
|
250
250
|
readonly ncpdpId: string;
|
|
251
251
|
}
|
|
252
|
-
/** A synthetic cardholder / insurance identity
|
|
252
|
+
/** A synthetic cardholder / insurance identity: the covered person on a Telecom claim. */
|
|
253
253
|
interface NcpdpCardholder {
|
|
254
254
|
/** The cardholder name (may differ from the patient). */
|
|
255
255
|
readonly person: SyntheticName;
|
|
@@ -257,7 +257,7 @@ interface NcpdpCardholder {
|
|
|
257
257
|
readonly cardholderId: string;
|
|
258
258
|
/** Group id, synthetic. */
|
|
259
259
|
readonly groupId: string;
|
|
260
|
-
/** Person code (`01` = cardholder, `02` = spouse, `03` = child
|
|
260
|
+
/** Person code (`01` = cardholder, `02` = spouse, `03` = child, structural). */
|
|
261
261
|
readonly personCode: string;
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
@@ -275,7 +275,7 @@ interface NcpdpCardholder {
|
|
|
275
275
|
*/
|
|
276
276
|
declare function ncpdpPatient(rng: Rng): NcpdpPatient;
|
|
277
277
|
/**
|
|
278
|
-
* Mint a synthetic prescriber
|
|
278
|
+
* Mint a synthetic prescriber: a person name, an invalid-Luhn NPI, and an invalid-checksum DEA (the
|
|
279
279
|
* DEA's second letter is derived from the prescriber's family name so it reads plausibly).
|
|
280
280
|
*
|
|
281
281
|
* @param rng - The seeded generator.
|
|
@@ -289,7 +289,7 @@ declare function ncpdpPatient(rng: Rng): NcpdpPatient;
|
|
|
289
289
|
*/
|
|
290
290
|
declare function ncpdpPrescriber(rng: Rng): NcpdpPrescriber;
|
|
291
291
|
/**
|
|
292
|
-
* Mint a synthetic dispensing pharmacy
|
|
292
|
+
* Mint a synthetic dispensing pharmacy: a fictional business name, an invalid-Luhn NPI, and a 7-digit
|
|
293
293
|
* synthetic NCPDP provider id.
|
|
294
294
|
*
|
|
295
295
|
* @param rng - The seeded generator.
|
|
@@ -315,13 +315,13 @@ declare function ncpdpPharmacy(rng: Rng): NcpdpPharmacy;
|
|
|
315
315
|
* ```
|
|
316
316
|
*/
|
|
317
317
|
declare function ncpdpCardholder(rng: Rng): NcpdpCardholder;
|
|
318
|
-
/** A seeded SCRIPT routing/correlation bundle
|
|
318
|
+
/** A seeded SCRIPT routing/correlation bundle: message ids + timestamps, all reproducible. */
|
|
319
319
|
interface NcpdpScriptRouting {
|
|
320
|
-
/** `<MessageID
|
|
320
|
+
/** `<MessageID>`: a synthetic message id. */
|
|
321
321
|
readonly messageId: string;
|
|
322
|
-
/** `<SentTime
|
|
322
|
+
/** `<SentTime>`, a seeded ISO-8601 timestamp (never wall-clock). */
|
|
323
323
|
readonly sentTime: string;
|
|
324
|
-
/** `<PrescriberOrderNumber
|
|
324
|
+
/** `<PrescriberOrderNumber>`, a synthetic order number. */
|
|
325
325
|
readonly prescriberOrderNumber: string;
|
|
326
326
|
/** A `CCYYMMDD` written / service date (seeded, recent window). */
|
|
327
327
|
readonly date: string;
|
|
@@ -343,11 +343,11 @@ declare function ncpdpScriptRouting(rng: Rng): NcpdpScriptRouting;
|
|
|
343
343
|
|
|
344
344
|
/**
|
|
345
345
|
* License-clean example drug + code pools for synthetic NCPDP generation. NCPDP charges for its
|
|
346
|
-
* standards and is protective of their prose, so
|
|
346
|
+
* standards and is protective of their prose, so, like every other `synth` format, **no NCPDP
|
|
347
347
|
* copyrighted text is bundled**: these are widely-known generic drug descriptions and invented,
|
|
348
348
|
* clearly-example product codes, not lifted from any NCPDP data dictionary.
|
|
349
349
|
*
|
|
350
|
-
* A drug code is **not** PHI
|
|
350
|
+
* A drug code is **not** PHI: it names a product, never a patient, so realism here carries no
|
|
351
351
|
* synthetic-safety hazard; the pool exists only to give a generated NewRx / claim a plausible,
|
|
352
352
|
* license-clean drug. Patient / prescriber identity comes from the synthetic-safety providers
|
|
353
353
|
* (`../safe`), never from here.
|
|
@@ -360,7 +360,7 @@ declare function ncpdpScriptRouting(rng: Rng): NcpdpScriptRouting;
|
|
|
360
360
|
interface NcpdpExampleDrug {
|
|
361
361
|
/** A widely-known generic drug description (RxNorm-style; public knowledge, not NCPDP prose). */
|
|
362
362
|
readonly description: string;
|
|
363
|
-
/** An invented 11-digit NDC (`5-4-2`, digits only)
|
|
363
|
+
/** An invented 11-digit NDC (`5-4-2`, digits only), an example product code, never a real NDC. */
|
|
364
364
|
readonly ndc: string;
|
|
365
365
|
/** The dispense quantity unit-of-measure qualifier hint (structural only). */
|
|
366
366
|
readonly form: string;
|
|
@@ -371,30 +371,30 @@ interface NcpdpExampleDrug {
|
|
|
371
371
|
* generics anyone can name without a licensed database.
|
|
372
372
|
*/
|
|
373
373
|
declare const EXAMPLE_DRUGS: readonly NcpdpExampleDrug[];
|
|
374
|
-
/** Example free-text SIG directions (public, common-sense dosing text
|
|
374
|
+
/** Example free-text SIG directions (public, common-sense dosing text, not NCPDP prose). */
|
|
375
375
|
declare const EXAMPLE_SIG_TEXT: readonly string[];
|
|
376
376
|
/** Dispense-as-written / product-selection codes (single-digit, structural). */
|
|
377
377
|
declare const DAW_CODES: readonly string[];
|
|
378
378
|
|
|
379
379
|
/**
|
|
380
|
-
* `@cosyte/synth/ncpdp
|
|
380
|
+
* `@cosyte/synth/ncpdp`: the NCPDP generation surface, exposed as its own subpath so importing the
|
|
381
381
|
* package root does **not** pull `@cosyte/ncpdp`. This is the **lazy, per-format** boundary: a consumer
|
|
382
382
|
* who only needs NCPDP fixtures imports `@cosyte/synth/ncpdp`; one who needs only the core primitives
|
|
383
383
|
* never loads a parser.
|
|
384
|
-
* `@cosyte/ncpdp` is an **optional peer dependency
|
|
384
|
+
* `@cosyte/ncpdp` is an **optional peer dependency**, present only for this subpath.
|
|
385
385
|
*
|
|
386
386
|
* This subpath ships spec-clean generation across both NCPDP standards, each built through
|
|
387
387
|
* `@cosyte/ncpdp`'s own emit surface:
|
|
388
388
|
*
|
|
389
389
|
* - **SCRIPT** ePrescribing (`@cosyte/ncpdp/script`): `generateNewRx` (via the validated `buildNewRx`
|
|
390
390
|
* builder), `generateRxRenewalRequest`, and `generateRxChangeRequest` (via the parser's public typed
|
|
391
|
-
* `ScriptMessage` model + `serializeScript`)
|
|
391
|
+
* `ScriptMessage` model + `serializeScript`), each round-tripping through `parseScript` with zero
|
|
392
392
|
* warnings, and carrying a prescriber whose NPI is invalid-Luhn and whose **DEA is invalid-checksum**.
|
|
393
393
|
* - **Telecom** claims (`@cosyte/ncpdp/telecom`): `generateB1` (billing), `generateB2` (reversal), and
|
|
394
|
-
* `generateB3` (rebill) via `buildTelecomRequest` + `serializeTelecom
|
|
394
|
+
* `generateB3` (rebill) via `buildTelecomRequest` + `serializeTelecom`, each round-tripping through
|
|
395
395
|
* `parseTelecom` with zero warnings, with patient / cardholder identity from the synthetic providers.
|
|
396
396
|
*
|
|
397
|
-
* **Deferred:** **quirk mode**. SCRIPT is limited to the transactions `@cosyte/ncpdp` can *build
|
|
397
|
+
* **Deferred:** **quirk mode**. SCRIPT is limited to the transactions `@cosyte/ncpdp` can *build*: NewRx
|
|
398
398
|
* plus the
|
|
399
399
|
* renewal/change **requests**; the renewal/change *responses* and the reversal cases beyond B2's
|
|
400
400
|
* reference set track the parser's builder surface, never hand-written bytes.
|
|
@@ -402,7 +402,7 @@ declare const DAW_CODES: readonly string[];
|
|
|
402
402
|
* @module
|
|
403
403
|
*/
|
|
404
404
|
|
|
405
|
-
/** Every NCPDP transaction kind {@link ncpdpCorpus} generates
|
|
405
|
+
/** Every NCPDP transaction kind {@link ncpdpCorpus} generates: the label used as the corpus `kind`. */
|
|
406
406
|
type NcpdpCorpusKind = "NewRx" | "RxRenewalRequest" | "RxChangeRequest" | "B1" | "B2" | "B3";
|
|
407
407
|
/** Options for {@link ncpdpCorpus}. */
|
|
408
408
|
interface NcpdpCorpusOptions {
|
|
@@ -424,7 +424,7 @@ interface NcpdpCorpusOptions {
|
|
|
424
424
|
* ```ts
|
|
425
425
|
* import { ncpdpCorpus } from "@cosyte/synth/ncpdp";
|
|
426
426
|
* const corpus = ncpdpCorpus({ seed: 42 });
|
|
427
|
-
* corpus.artifacts.every((a) => a.warnings.length === 0); // true
|
|
427
|
+
* corpus.artifacts.every((a) => a.warnings.length === 0); // true, spec-clean
|
|
428
428
|
* ```
|
|
429
429
|
*/
|
|
430
430
|
declare function ncpdpCorpus(options: NcpdpCorpusOptions): Corpus;
|
package/dist/ncpdp/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { S as SyntheticName, b as SyntheticAddress, R as Rng, C as Corpus } from '../providers-
|
|
1
|
+
import { S as SyntheticName, b as SyntheticAddress, R as Rng, C as Corpus } from '../providers-B9uVinAe.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Spec-clean NCPDP **SCRIPT** (XML ePrescribing) generation
|
|
5
|
-
* `RxChangeRequest
|
|
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
6
|
* same mechanism that makes the parser's serializer spec-clean:
|
|
7
7
|
*
|
|
8
8
|
* - **NewRx** is built through the validated `buildNewRx` builder (it refuses a NewRx with no
|
|
9
9
|
* medication description) and serialized by `serializeScript`.
|
|
10
10
|
* - **RxRenewalRequest / RxChangeRequest** have no dedicated builder in `@cosyte/ncpdp` (its builders
|
|
11
|
-
* cover NewRx + the Status/Error/Verify responses), so
|
|
12
|
-
* typed model and lets `serializeX12` emit it
|
|
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
13
|
* `ScriptMessage` model** (the same immutable model `buildNewRx` returns) and serialized by
|
|
14
14
|
* `serializeScript`. No byte is hand-written; the round-trip harness ({@link ./round-trip.scriptRoundTrip})
|
|
15
15
|
* re-parses every message through `parseScript` and asserts **zero warnings**, so spec-cleanliness is
|
|
@@ -23,7 +23,7 @@ import { S as SyntheticName, b as SyntheticAddress, R as Rng, C as Corpus } from
|
|
|
23
23
|
*/
|
|
24
24
|
/** Options for the SCRIPT generators. */
|
|
25
25
|
interface GenerateScriptOptions {
|
|
26
|
-
/** The seed (deterministic
|
|
26
|
+
/** The seed (deterministic: same seed yields a byte-identical message). */
|
|
27
27
|
readonly seed: number;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -72,8 +72,8 @@ declare function generateRxRenewalRequest(options: GenerateScriptOptions): strin
|
|
|
72
72
|
declare function generateRxChangeRequest(options: GenerateScriptOptions): string;
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
|
-
* Spec-clean NCPDP **Telecommunication vD.0** claim generation
|
|
76
|
-
* `B3` (rebill)
|
|
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
77
|
* fixed Transaction Header, the FS/GS/RS framing, and every field are the parser's own conservative
|
|
78
78
|
* emit. Every field id below is a real 2-character NCPDP field identifier, and every
|
|
79
79
|
* value at a PHI-bearing locus is drawn from the synthetic-safety providers via {@link ./identity}: the
|
|
@@ -88,7 +88,7 @@ declare function generateRxChangeRequest(options: GenerateScriptOptions): string
|
|
|
88
88
|
type TelecomTransactionCode = "B1" | "B2" | "B3";
|
|
89
89
|
/** Options for the Telecom generators. */
|
|
90
90
|
interface GenerateTelecomOptions {
|
|
91
|
-
/** The seed (deterministic
|
|
91
|
+
/** The seed (deterministic: same seed yields a byte-identical transaction). */
|
|
92
92
|
readonly seed: number;
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
@@ -147,9 +147,9 @@ declare function generateB2(options: GenerateTelecomOptions): string;
|
|
|
147
147
|
declare function generateB3(options: GenerateTelecomOptions): string;
|
|
148
148
|
|
|
149
149
|
/**
|
|
150
|
-
* The **round-trip-through-the-parser harness** for NCPDP
|
|
150
|
+
* The **round-trip-through-the-parser harness** for NCPDP: the headline gate for the synthetic-fixture
|
|
151
151
|
* generator. A generated SCRIPT XML or Telecom claim is "spec-clean" only if
|
|
152
|
-
* `@cosyte/ncpdp
|
|
152
|
+
* `@cosyte/ncpdp`, not `@cosyte/synth`'s own opinion, reads it back cleanly. Each harness parses the
|
|
153
153
|
* generated wire text straight back through the parser and reports what it found, so a false
|
|
154
154
|
* "spec-clean" claim cannot hide.
|
|
155
155
|
*
|
|
@@ -197,41 +197,41 @@ declare function scriptRoundTrip(xml: string): RoundTripResult;
|
|
|
197
197
|
declare function telecomRoundTrip(wire: string): RoundTripResult;
|
|
198
198
|
|
|
199
199
|
/**
|
|
200
|
-
* Synthetic identity for NCPDP transactions
|
|
200
|
+
* Synthetic identity for NCPDP transactions: every patient, prescriber, pharmacy, and cardholder
|
|
201
201
|
* identifier `synth` puts into a SCRIPT ePrescription or a Telecom claim is minted here, and **only**
|
|
202
202
|
* from the synthetic-safety providers. NCPDP is identity-dense in a way the refuter
|
|
203
203
|
* attacks hardest: a NewRx carries the **patient** (name, DOB, gender) *and* the **prescriber** (name,
|
|
204
204
|
* NPI, **DEA**); a Telecom claim adds the **cardholder / member** (name, member id). Every locus below
|
|
205
205
|
* has a construction-level guarantee, not a heuristic:
|
|
206
206
|
*
|
|
207
|
-
* - **NPI
|
|
207
|
+
* - **NPI**: a deliberately **invalid Luhn** check digit, so it can never be a NPPES-issued NPI
|
|
208
208
|
* ({@link ../safe/reserved.isSyntheticNpi}).
|
|
209
|
-
* - **DEA
|
|
209
|
+
* - **DEA**: a deliberately **invalid checksum**, so it can never be a validly-issued DEA registration
|
|
210
210
|
* ({@link ../safe/reserved.isSyntheticDea}). This is the NCPDP-specific identity locus X12 did not have.
|
|
211
|
-
* - **member / cardholder / patient id
|
|
211
|
+
* - **member / cardholder / patient id**: minted under the synthetic assigning authority with an
|
|
212
212
|
* `MBR` prefix (no reserved range exists; the *namespace* is the guarantee).
|
|
213
|
-
* - **name
|
|
214
|
-
* **phone
|
|
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
215
|
*
|
|
216
216
|
* @module
|
|
217
217
|
*/
|
|
218
218
|
|
|
219
|
-
/** A synthetic patient
|
|
219
|
+
/** A synthetic patient: every field from `../safe`. */
|
|
220
220
|
interface NcpdpPatient {
|
|
221
221
|
/** Name from the shipped fake-name pool. */
|
|
222
222
|
readonly person: SyntheticName;
|
|
223
223
|
/** Date of birth `CCYYMMDD` from the seeded generator. */
|
|
224
224
|
readonly dob: string;
|
|
225
|
-
/** Administrative gender code (`1` = male, `2` = female
|
|
225
|
+
/** Administrative gender code (`1` = male, `2` = female, NCPDP gender codes). */
|
|
226
226
|
readonly gender: "1" | "2";
|
|
227
|
-
/** Patient id, synthetic-AA scoped (`MBR`-prefixed
|
|
227
|
+
/** Patient id, synthetic-AA scoped (`MBR`-prefixed, never a bare SSN). */
|
|
228
228
|
readonly patientId: string;
|
|
229
229
|
/** Reserved `555-01xx` phone. */
|
|
230
230
|
readonly phone: string;
|
|
231
231
|
/** Synthetic postal address (reserved non-real ZIP). */
|
|
232
232
|
readonly address: SyntheticAddress;
|
|
233
233
|
}
|
|
234
|
-
/** A synthetic prescriber
|
|
234
|
+
/** A synthetic prescriber: name + invalid-Luhn NPI + invalid-checksum DEA. */
|
|
235
235
|
interface NcpdpPrescriber {
|
|
236
236
|
/** A clearly-fake prescriber name. */
|
|
237
237
|
readonly person: SyntheticName;
|
|
@@ -240,16 +240,16 @@ interface NcpdpPrescriber {
|
|
|
240
240
|
/** A DEA number with a deliberately-invalid checksum (never a real DEA registration). */
|
|
241
241
|
readonly dea: string;
|
|
242
242
|
}
|
|
243
|
-
/** A synthetic dispensing pharmacy
|
|
243
|
+
/** A synthetic dispensing pharmacy: business name + invalid-Luhn NPI + synthetic NCPDP id. */
|
|
244
244
|
interface NcpdpPharmacy {
|
|
245
245
|
/** A clearly-fictional pharmacy business name. */
|
|
246
246
|
readonly businessName: string;
|
|
247
247
|
/** A 10-digit NPI with a deliberately-invalid Luhn check digit. */
|
|
248
248
|
readonly npi: string;
|
|
249
|
-
/** A 7-digit NCPDP provider id (synthetic
|
|
249
|
+
/** A 7-digit NCPDP provider id (synthetic, an all-digit id under no real chain). */
|
|
250
250
|
readonly ncpdpId: string;
|
|
251
251
|
}
|
|
252
|
-
/** A synthetic cardholder / insurance identity
|
|
252
|
+
/** A synthetic cardholder / insurance identity: the covered person on a Telecom claim. */
|
|
253
253
|
interface NcpdpCardholder {
|
|
254
254
|
/** The cardholder name (may differ from the patient). */
|
|
255
255
|
readonly person: SyntheticName;
|
|
@@ -257,7 +257,7 @@ interface NcpdpCardholder {
|
|
|
257
257
|
readonly cardholderId: string;
|
|
258
258
|
/** Group id, synthetic. */
|
|
259
259
|
readonly groupId: string;
|
|
260
|
-
/** Person code (`01` = cardholder, `02` = spouse, `03` = child
|
|
260
|
+
/** Person code (`01` = cardholder, `02` = spouse, `03` = child, structural). */
|
|
261
261
|
readonly personCode: string;
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
@@ -275,7 +275,7 @@ interface NcpdpCardholder {
|
|
|
275
275
|
*/
|
|
276
276
|
declare function ncpdpPatient(rng: Rng): NcpdpPatient;
|
|
277
277
|
/**
|
|
278
|
-
* Mint a synthetic prescriber
|
|
278
|
+
* Mint a synthetic prescriber: a person name, an invalid-Luhn NPI, and an invalid-checksum DEA (the
|
|
279
279
|
* DEA's second letter is derived from the prescriber's family name so it reads plausibly).
|
|
280
280
|
*
|
|
281
281
|
* @param rng - The seeded generator.
|
|
@@ -289,7 +289,7 @@ declare function ncpdpPatient(rng: Rng): NcpdpPatient;
|
|
|
289
289
|
*/
|
|
290
290
|
declare function ncpdpPrescriber(rng: Rng): NcpdpPrescriber;
|
|
291
291
|
/**
|
|
292
|
-
* Mint a synthetic dispensing pharmacy
|
|
292
|
+
* Mint a synthetic dispensing pharmacy: a fictional business name, an invalid-Luhn NPI, and a 7-digit
|
|
293
293
|
* synthetic NCPDP provider id.
|
|
294
294
|
*
|
|
295
295
|
* @param rng - The seeded generator.
|
|
@@ -315,13 +315,13 @@ declare function ncpdpPharmacy(rng: Rng): NcpdpPharmacy;
|
|
|
315
315
|
* ```
|
|
316
316
|
*/
|
|
317
317
|
declare function ncpdpCardholder(rng: Rng): NcpdpCardholder;
|
|
318
|
-
/** A seeded SCRIPT routing/correlation bundle
|
|
318
|
+
/** A seeded SCRIPT routing/correlation bundle: message ids + timestamps, all reproducible. */
|
|
319
319
|
interface NcpdpScriptRouting {
|
|
320
|
-
/** `<MessageID
|
|
320
|
+
/** `<MessageID>`: a synthetic message id. */
|
|
321
321
|
readonly messageId: string;
|
|
322
|
-
/** `<SentTime
|
|
322
|
+
/** `<SentTime>`, a seeded ISO-8601 timestamp (never wall-clock). */
|
|
323
323
|
readonly sentTime: string;
|
|
324
|
-
/** `<PrescriberOrderNumber
|
|
324
|
+
/** `<PrescriberOrderNumber>`, a synthetic order number. */
|
|
325
325
|
readonly prescriberOrderNumber: string;
|
|
326
326
|
/** A `CCYYMMDD` written / service date (seeded, recent window). */
|
|
327
327
|
readonly date: string;
|
|
@@ -343,11 +343,11 @@ declare function ncpdpScriptRouting(rng: Rng): NcpdpScriptRouting;
|
|
|
343
343
|
|
|
344
344
|
/**
|
|
345
345
|
* License-clean example drug + code pools for synthetic NCPDP generation. NCPDP charges for its
|
|
346
|
-
* standards and is protective of their prose, so
|
|
346
|
+
* standards and is protective of their prose, so, like every other `synth` format, **no NCPDP
|
|
347
347
|
* copyrighted text is bundled**: these are widely-known generic drug descriptions and invented,
|
|
348
348
|
* clearly-example product codes, not lifted from any NCPDP data dictionary.
|
|
349
349
|
*
|
|
350
|
-
* A drug code is **not** PHI
|
|
350
|
+
* A drug code is **not** PHI: it names a product, never a patient, so realism here carries no
|
|
351
351
|
* synthetic-safety hazard; the pool exists only to give a generated NewRx / claim a plausible,
|
|
352
352
|
* license-clean drug. Patient / prescriber identity comes from the synthetic-safety providers
|
|
353
353
|
* (`../safe`), never from here.
|
|
@@ -360,7 +360,7 @@ declare function ncpdpScriptRouting(rng: Rng): NcpdpScriptRouting;
|
|
|
360
360
|
interface NcpdpExampleDrug {
|
|
361
361
|
/** A widely-known generic drug description (RxNorm-style; public knowledge, not NCPDP prose). */
|
|
362
362
|
readonly description: string;
|
|
363
|
-
/** An invented 11-digit NDC (`5-4-2`, digits only)
|
|
363
|
+
/** An invented 11-digit NDC (`5-4-2`, digits only), an example product code, never a real NDC. */
|
|
364
364
|
readonly ndc: string;
|
|
365
365
|
/** The dispense quantity unit-of-measure qualifier hint (structural only). */
|
|
366
366
|
readonly form: string;
|
|
@@ -371,30 +371,30 @@ interface NcpdpExampleDrug {
|
|
|
371
371
|
* generics anyone can name without a licensed database.
|
|
372
372
|
*/
|
|
373
373
|
declare const EXAMPLE_DRUGS: readonly NcpdpExampleDrug[];
|
|
374
|
-
/** Example free-text SIG directions (public, common-sense dosing text
|
|
374
|
+
/** Example free-text SIG directions (public, common-sense dosing text, not NCPDP prose). */
|
|
375
375
|
declare const EXAMPLE_SIG_TEXT: readonly string[];
|
|
376
376
|
/** Dispense-as-written / product-selection codes (single-digit, structural). */
|
|
377
377
|
declare const DAW_CODES: readonly string[];
|
|
378
378
|
|
|
379
379
|
/**
|
|
380
|
-
* `@cosyte/synth/ncpdp
|
|
380
|
+
* `@cosyte/synth/ncpdp`: the NCPDP generation surface, exposed as its own subpath so importing the
|
|
381
381
|
* package root does **not** pull `@cosyte/ncpdp`. This is the **lazy, per-format** boundary: a consumer
|
|
382
382
|
* who only needs NCPDP fixtures imports `@cosyte/synth/ncpdp`; one who needs only the core primitives
|
|
383
383
|
* never loads a parser.
|
|
384
|
-
* `@cosyte/ncpdp` is an **optional peer dependency
|
|
384
|
+
* `@cosyte/ncpdp` is an **optional peer dependency**, present only for this subpath.
|
|
385
385
|
*
|
|
386
386
|
* This subpath ships spec-clean generation across both NCPDP standards, each built through
|
|
387
387
|
* `@cosyte/ncpdp`'s own emit surface:
|
|
388
388
|
*
|
|
389
389
|
* - **SCRIPT** ePrescribing (`@cosyte/ncpdp/script`): `generateNewRx` (via the validated `buildNewRx`
|
|
390
390
|
* builder), `generateRxRenewalRequest`, and `generateRxChangeRequest` (via the parser's public typed
|
|
391
|
-
* `ScriptMessage` model + `serializeScript`)
|
|
391
|
+
* `ScriptMessage` model + `serializeScript`), each round-tripping through `parseScript` with zero
|
|
392
392
|
* warnings, and carrying a prescriber whose NPI is invalid-Luhn and whose **DEA is invalid-checksum**.
|
|
393
393
|
* - **Telecom** claims (`@cosyte/ncpdp/telecom`): `generateB1` (billing), `generateB2` (reversal), and
|
|
394
|
-
* `generateB3` (rebill) via `buildTelecomRequest` + `serializeTelecom
|
|
394
|
+
* `generateB3` (rebill) via `buildTelecomRequest` + `serializeTelecom`, each round-tripping through
|
|
395
395
|
* `parseTelecom` with zero warnings, with patient / cardholder identity from the synthetic providers.
|
|
396
396
|
*
|
|
397
|
-
* **Deferred:** **quirk mode**. SCRIPT is limited to the transactions `@cosyte/ncpdp` can *build
|
|
397
|
+
* **Deferred:** **quirk mode**. SCRIPT is limited to the transactions `@cosyte/ncpdp` can *build*: NewRx
|
|
398
398
|
* plus the
|
|
399
399
|
* renewal/change **requests**; the renewal/change *responses* and the reversal cases beyond B2's
|
|
400
400
|
* reference set track the parser's builder surface, never hand-written bytes.
|
|
@@ -402,7 +402,7 @@ declare const DAW_CODES: readonly string[];
|
|
|
402
402
|
* @module
|
|
403
403
|
*/
|
|
404
404
|
|
|
405
|
-
/** Every NCPDP transaction kind {@link ncpdpCorpus} generates
|
|
405
|
+
/** Every NCPDP transaction kind {@link ncpdpCorpus} generates: the label used as the corpus `kind`. */
|
|
406
406
|
type NcpdpCorpusKind = "NewRx" | "RxRenewalRequest" | "RxChangeRequest" | "B1" | "B2" | "B3";
|
|
407
407
|
/** Options for {@link ncpdpCorpus}. */
|
|
408
408
|
interface NcpdpCorpusOptions {
|
|
@@ -424,7 +424,7 @@ interface NcpdpCorpusOptions {
|
|
|
424
424
|
* ```ts
|
|
425
425
|
* import { ncpdpCorpus } from "@cosyte/synth/ncpdp";
|
|
426
426
|
* const corpus = ncpdpCorpus({ seed: 42 });
|
|
427
|
-
* corpus.artifacts.every((a) => a.warnings.length === 0); // true
|
|
427
|
+
* corpus.artifacts.every((a) => a.warnings.length === 0); // true, spec-clean
|
|
428
428
|
* ```
|
|
429
429
|
*/
|
|
430
430
|
declare function ncpdpCorpus(options: NcpdpCorpusOptions): Corpus;
|
package/dist/ncpdp/index.mjs
CHANGED
|
@@ -35,11 +35,11 @@ function sfc32Next(s) {
|
|
|
35
35
|
var SYNTH_FATAL_CODES = {
|
|
36
36
|
/** An integer range was requested with its maximum below its minimum. Fatal. */
|
|
37
37
|
SYNTH_INVALID_RANGE: "SYNTH_INVALID_RANGE",
|
|
38
|
-
/** A value was drawn from an empty pool. Fatal
|
|
38
|
+
/** A value was drawn from an empty pool. Fatal, never a fabricated substitute. */
|
|
39
39
|
SYNTH_EMPTY_POOL: "SYNTH_EMPTY_POOL",
|
|
40
40
|
/**
|
|
41
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
|
|
42
|
+
* variant, a Bundle type, a resource profile) is not in the closed set that governs it. Fatal:
|
|
43
43
|
* see `resolveKind`: a selector union is erased at run time, and a selector that falls through
|
|
44
44
|
* either mislabels the fixture or hands the value to a peer builder that quotes it back.
|
|
45
45
|
*/
|
|
@@ -133,7 +133,7 @@ function makeCorpus(seed, artifacts, quirks = []) {
|
|
|
133
133
|
var SYNTHETIC_ASSIGNING_AUTHORITY = Object.freeze({
|
|
134
134
|
/** The human-readable assigning-authority namespace id (HL7 HD.1). */
|
|
135
135
|
namespaceId: "COSYTE-SYNTH",
|
|
136
|
-
/** The universal id
|
|
136
|
+
/** The universal id, an OID under HL7's example arc `2.16.840.1.113883.19` (HD.2). */
|
|
137
137
|
universalId: "2.16.840.1.113883.19.999",
|
|
138
138
|
/** The universal id type (HD.3). */
|
|
139
139
|
universalIdType: "ISO"
|