@cosyte/synth 0.1.9 → 0.1.10
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 +29 -0
- package/README.md +28 -17
- package/dist/animal-code-Bdl_9Jma.d.cts +30 -0
- package/dist/animal-code-Bdl_9Jma.d.ts +30 -0
- package/dist/astm/index.cjs +147 -17
- package/dist/astm/index.cjs.map +1 -1
- package/dist/astm/index.d.cts +22 -9
- package/dist/astm/index.d.ts +22 -9
- package/dist/astm/index.mjs +147 -17
- package/dist/astm/index.mjs.map +1 -1
- package/dist/ccda/index.cjs +147 -17
- package/dist/ccda/index.cjs.map +1 -1
- package/dist/ccda/index.d.cts +12 -3
- package/dist/ccda/index.d.ts +12 -3
- package/dist/ccda/index.mjs +147 -17
- package/dist/ccda/index.mjs.map +1 -1
- package/dist/deid/index.cjs +537 -30
- package/dist/deid/index.cjs.map +1 -1
- package/dist/deid/index.d.cts +2 -1
- package/dist/deid/index.d.ts +2 -1
- package/dist/deid/index.mjs +537 -30
- package/dist/deid/index.mjs.map +1 -1
- package/dist/fhir/index.cjs +142 -14
- package/dist/fhir/index.cjs.map +1 -1
- package/dist/fhir/index.d.cts +4 -1
- package/dist/fhir/index.d.ts +4 -1
- package/dist/fhir/index.mjs +142 -14
- package/dist/fhir/index.mjs.map +1 -1
- package/dist/hl7/index.cjs +566 -39
- package/dist/hl7/index.cjs.map +1 -1
- package/dist/hl7/index.d.cts +402 -111
- package/dist/hl7/index.d.ts +402 -111
- package/dist/hl7/index.mjs +557 -40
- package/dist/hl7/index.mjs.map +1 -1
- package/dist/index.cjs +124 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +183 -10
- package/dist/index.d.ts +183 -10
- package/dist/index.mjs +115 -14
- package/dist/index.mjs.map +1 -1
- package/dist/ncpdp/index.cjs +142 -14
- package/dist/ncpdp/index.cjs.map +1 -1
- package/dist/ncpdp/index.d.cts +4 -1
- package/dist/ncpdp/index.d.ts +4 -1
- package/dist/ncpdp/index.mjs +142 -14
- package/dist/ncpdp/index.mjs.map +1 -1
- package/dist/{quirk-BfObsiWV.d.ts → quirk-CzknuYUo.d.ts} +16 -5
- package/dist/{quirk-BCSs1jPt.d.cts → quirk-Q5AxzHSC.d.cts} +16 -5
- package/dist/x12/index.cjs +142 -14
- package/dist/x12/index.cjs.map +1 -1
- package/dist/x12/index.d.cts +4 -1
- package/dist/x12/index.d.ts +4 -1
- package/dist/x12/index.mjs +142 -14
- package/dist/x12/index.mjs.map +1 -1
- package/package.json +7 -4
package/dist/hl7/index.d.ts
CHANGED
|
@@ -1,27 +1,224 @@
|
|
|
1
1
|
import { Hl7Message, RawField } from '@cosyte/hl7';
|
|
2
|
-
import {
|
|
2
|
+
import { SyntheticIdentifier, SyntheticName, SyntheticAddress, Rng, Corpus } from '../index.js';
|
|
3
|
+
import { AnimalCode } from '../index.js';
|
|
3
4
|
import { QuirkDescriptor, SynthProfile, QuirkArtifact, QuirkRoundTripResult } from '../index.js';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Shared HL7 v2 building blocks for every message family `@cosyte/synth` generates: the MSH scaffold,
|
|
8
|
+
* the seeded timestamp, and the patient-identity bundle + its `PID` segment. Factored out so `ADT`,
|
|
9
|
+
* `ORU`, `ORM`, `SIU`, and `VXU` all mint identity from the **same** synthetic-safety providers in the
|
|
10
|
+
* **same** draw order, and all emit through `@cosyte/hl7`'s conservative serializer. Nothing here draws a
|
|
11
|
+
* value that is not sourced from `../safe`: the synthetic-by-construction
|
|
12
|
+
* invariant holds by construction for every family.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A seeded HL7 `YYYYMMDDHHMMSS` timestamp (message/event time; recent-year range). Strict HL7 DTM, so
|
|
19
|
+
* `@cosyte/hl7` parses it back with no `TIMESTAMP_FALLBACK_FORMAT` warning.
|
|
20
|
+
*
|
|
21
|
+
* @param rng - The seeded generator.
|
|
22
|
+
* @returns A 14-digit `YYYYMMDDHHMMSS` timestamp string.
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { createRng } from "@cosyte/synth";
|
|
26
|
+
* // "20230714…"
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
declare function seededTimestamp(rng: Rng): string;
|
|
30
|
+
/** The MSH scaffold shared by every generated message: the built message plus its seeded MSH values. */
|
|
31
|
+
interface MessageScaffold {
|
|
32
|
+
/** The `Hl7Message` with a complete MSH: chain `.addSegment(...)` to append the payload. */
|
|
33
|
+
readonly message: Hl7Message;
|
|
34
|
+
/** The seeded `YYYYMMDDHHMMSS` message timestamp (MSH-7), reused for event/observation times. */
|
|
35
|
+
readonly timestamp: string;
|
|
36
|
+
/** The seeded message control id (MSH-10). */
|
|
37
|
+
readonly controlId: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Build the MSH scaffold for a message of the given `MSH-9` type through `@cosyte/hl7`'s `buildMessage`,
|
|
41
|
+
* so the delimiters, control id, and header layout are the parser's own conservative emit. Draws the
|
|
42
|
+
* timestamp then the control id from `rng` (a fixed order: the reproducibility contract).
|
|
43
|
+
*
|
|
44
|
+
* @param rng - The seeded generator.
|
|
45
|
+
* @param type - The `MSH-9` message type, e.g. `"ORU^R01"`.
|
|
46
|
+
* @returns The {@link MessageScaffold}.
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { createRng } from "@cosyte/synth";
|
|
50
|
+
* // mshScaffold(createRng(1), "ORU^R01").message.addSegment("PID", […]);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
declare function mshScaffold(rng: Rng, type: string): MessageScaffold;
|
|
54
|
+
/** A complete synthetic patient identity: every field drawn from `../safe`. */
|
|
55
|
+
interface PatientIdentity {
|
|
56
|
+
/** Name from the shipped fake-name pool. */
|
|
57
|
+
readonly person: SyntheticName;
|
|
58
|
+
/** Medical-record identifier scoped to the synthetic assigning authority. */
|
|
59
|
+
readonly mrn: SyntheticIdentifier;
|
|
60
|
+
/** Date of birth (`YYYYMMDD`) from the seeded generator. */
|
|
61
|
+
readonly dob: string;
|
|
62
|
+
/** Administrative sex. */
|
|
63
|
+
readonly sex: "M" | "F";
|
|
64
|
+
/** Synthetic postal address (reserved non-real ZIP). */
|
|
65
|
+
readonly address: SyntheticAddress;
|
|
66
|
+
/** Reserved `555-01xx` phone number. */
|
|
67
|
+
readonly phone: string;
|
|
68
|
+
/** Never-issued SSN as 9 digits (no dashes), for `PID-19`. */
|
|
69
|
+
readonly ssnDigits: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Mint a complete synthetic {@link PatientIdentity}. Every value comes from a synthetic-safety provider,
|
|
73
|
+
* so no code path here can return a real or plausibly-real identifier. The draw order is
|
|
74
|
+
* fixed (name → MRN → DOB → sex → address → phone → SSN) so the same seed yields the same identity.
|
|
75
|
+
*
|
|
76
|
+
* @param rng - The seeded generator.
|
|
77
|
+
* @returns A synthetic {@link PatientIdentity}.
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { createRng } from "@cosyte/synth";
|
|
81
|
+
* // const id = patientIdentity(createRng(1)); // id.person, id.mrn, …
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
declare function patientIdentity(rng: Rng): PatientIdentity;
|
|
85
|
+
/**
|
|
86
|
+
* Lay out a fully-populated `PID` segment from a {@link PatientIdentity} as `addSegment` fields: the
|
|
87
|
+
* PHI-dense segment shared by every family. Components go through {@link componentsField} so the parser
|
|
88
|
+
* lays out the `^` separators (building *through* the parser).
|
|
89
|
+
*
|
|
90
|
+
* @param id - The synthetic identity to render.
|
|
91
|
+
* @returns The `PID` field list for `Hl7Message.addSegment("PID", …)`.
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* // msg.addSegment("PID", pidSegment(patientIdentity(createRng(1))));
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
declare function pidSegment(id: PatientIdentity): readonly (string | RawField)[];
|
|
98
|
+
/**
|
|
99
|
+
* Who a message is about. `"person"`, the default, is the human patient every generator has always
|
|
100
|
+
* written. `"animal"` writes a veterinary patient instead: see {@link AnimalIdentity}.
|
|
101
|
+
*/
|
|
102
|
+
type Hl7Subject = "person" | "animal";
|
|
103
|
+
/** An animal's owner: every value drawn from `../safe`. */
|
|
104
|
+
interface AnimalOwner {
|
|
105
|
+
/** The owner's name, from the shipped fake-name pool. */
|
|
106
|
+
readonly person: SyntheticName;
|
|
107
|
+
/** The owner's synthetic postal address (reserved non-real ZIP), which is also the animal's. */
|
|
108
|
+
readonly address: SyntheticAddress;
|
|
109
|
+
/** The owner's reserved `555-01xx` phone number. */
|
|
110
|
+
readonly phone: string;
|
|
111
|
+
}
|
|
112
|
+
/** A complete synthetic animal patient: every value drawn from `../safe`. */
|
|
113
|
+
interface AnimalIdentity {
|
|
114
|
+
/** The pet's name, from the shipped fake pet-name pool. */
|
|
115
|
+
readonly petName: string;
|
|
116
|
+
/** The record number, scoped to the synthetic assigning authority. */
|
|
117
|
+
readonly record: SyntheticIdentifier;
|
|
118
|
+
/** A 15-digit microchip that begins `999`. */
|
|
119
|
+
readonly microchip: string;
|
|
120
|
+
/** The species, from our own short list. */
|
|
121
|
+
readonly species: AnimalCode;
|
|
122
|
+
/** The breed, one of the species' breeds. */
|
|
123
|
+
readonly breed: AnimalCode;
|
|
124
|
+
/** Birth date (`YYYYMMDD`), 0 to 20 years before the message date. */
|
|
125
|
+
readonly dob: string;
|
|
126
|
+
/** Administrative sex. */
|
|
127
|
+
readonly sex: "M" | "F";
|
|
128
|
+
/** The owner. */
|
|
129
|
+
readonly owner: AnimalOwner;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The identifier type the animal subject writes for a microchip in PID-3 (CX.5): `MCN`, which we
|
|
133
|
+
* use for microchip number. We have not verified it against HL7 table 0203 (identifier type) in any
|
|
134
|
+
* version. Not verified.
|
|
135
|
+
*/
|
|
136
|
+
declare const MICROCHIP_IDENTIFIER_TYPE = "MCN";
|
|
137
|
+
/**
|
|
138
|
+
* The owner relationship the animal subject writes in NK1-3: `OWN^Owner^HL70063`. We have not
|
|
139
|
+
* verified that `OWN` is a value of HL7 table 0063 (relationship). Not verified.
|
|
140
|
+
*/
|
|
141
|
+
declare const OWNER_RELATIONSHIP: Readonly<{
|
|
142
|
+
code: "OWN";
|
|
143
|
+
text: "Owner";
|
|
144
|
+
system: "HL70063";
|
|
145
|
+
}>;
|
|
146
|
+
/**
|
|
147
|
+
* Mint a complete synthetic {@link AnimalIdentity}. The draw order is fixed (owner name, pet name,
|
|
148
|
+
* record number, microchip, species and breed, birth date, sex, address, phone) so the same seed and
|
|
149
|
+
* date yield the same animal.
|
|
150
|
+
*
|
|
151
|
+
* @param rng - The seeded generator.
|
|
152
|
+
* @param onDate - The message date, `YYYYMMDD` or a longer timestamp: the birth date falls from 0
|
|
153
|
+
* to 20 years before it.
|
|
154
|
+
* @returns A synthetic {@link AnimalIdentity}.
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* import { createRng } from "@cosyte/synth";
|
|
158
|
+
* import { animalIdentity } from "@cosyte/synth/hl7";
|
|
159
|
+
* const pet = animalIdentity(createRng(1), "20250101");
|
|
160
|
+
* pet.species.text; // e.g. "Dog"
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
declare function animalIdentity(rng: Rng, onDate: string): AnimalIdentity;
|
|
164
|
+
/**
|
|
165
|
+
* Lay out the `PID` segment of an {@link AnimalIdentity}: the record number and the microchip as two
|
|
166
|
+
* PID-3 repetitions, the owner's family name and the pet's name in PID-5, the owner's address and
|
|
167
|
+
* phone, and the species in PID-35 and breed in PID-36. PID-19 (SSN) stays empty.
|
|
168
|
+
*
|
|
169
|
+
* @param id - The synthetic animal to render.
|
|
170
|
+
* @returns The `PID` field list for `Hl7Message.addSegment("PID", …)`.
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* // msg.addSegment("PID", animalPidSegment(animalIdentity(createRng(1), "20250101")));
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare function animalPidSegment(id: AnimalIdentity): readonly (string | RawField)[];
|
|
177
|
+
/**
|
|
178
|
+
* Lay out the owner's `NK1` segment: the owner's name, relationship {@link OWNER_RELATIONSHIP}
|
|
179
|
+
* (`OWN`, not verified against HL7 table 0063), address and phone.
|
|
180
|
+
*
|
|
181
|
+
* @param id - The synthetic animal whose owner to render.
|
|
182
|
+
* @returns The `NK1` field list for `Hl7Message.addSegment("NK1", …)`.
|
|
183
|
+
* @example
|
|
184
|
+
* ```ts
|
|
185
|
+
* // msg.addSegment("NK1", ownerNk1Segment(animalIdentity(createRng(1), "20250101")));
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
declare function ownerNk1Segment(id: AnimalIdentity): readonly (string | RawField)[];
|
|
189
|
+
|
|
5
190
|
/**
|
|
6
191
|
* Spec-clean HL7 v2 `ADT` generation, built **through `@cosyte/hl7`'s `buildMessage`** so MSH
|
|
7
192
|
* delimiters, segment layout, and escaping are the parser's own conservative emit: spec-clean *by
|
|
8
193
|
* construction*. Every PHI-bearing field (name, DOB, SSN, MRN,
|
|
9
194
|
* address, phone) is drawn from the synthetic-safety providers (`../safe`), so no value can be real.
|
|
10
195
|
*
|
|
11
|
-
*
|
|
12
|
-
* checks for, so a generated message round-trips through `@cosyte/hl7` with **zero
|
|
196
|
+
* Every trigger here requires the `EVN`, `PID` (patient) and `PV1` (visit) segments the parser's
|
|
197
|
+
* structure net checks for, so a generated message round-trips through `@cosyte/hl7` with **zero
|
|
198
|
+
* warnings**. The triggers and the structures they share (HL7 v2 chapter 3):
|
|
199
|
+
*
|
|
200
|
+
* - `A01` admit, `A04` register, `A08` update patient information, `A13` cancel discharge: `ADT_A01`.
|
|
201
|
+
* - `A02` transfer a patient: `ADT_A02`. `A03` discharge or end visit: `ADT_A03`.
|
|
202
|
+
* - `A11` cancel admit or visit notification: `ADT_A09`.
|
|
203
|
+
* - `A28` add person or patient information, `A31` update person information: `ADT_A05`.
|
|
13
204
|
*
|
|
14
205
|
* @module
|
|
15
206
|
*/
|
|
16
207
|
|
|
17
|
-
/** The ADT trigger events this generator produces (all require the PID
|
|
18
|
-
type AdtTrigger = "A01" | "A04" | "A08";
|
|
208
|
+
/** The ADT trigger events this generator produces (all require the EVN, PID and PV1 segments). */
|
|
209
|
+
type AdtTrigger = "A01" | "A04" | "A08" | "A02" | "A03" | "A11" | "A13" | "A28" | "A31";
|
|
19
210
|
/** Options for {@link generateAdt}. */
|
|
20
211
|
interface GenerateAdtOptions {
|
|
21
212
|
/** The seed: the same seed yields a byte-identical message. Defaults to `0`. */
|
|
22
213
|
readonly seed?: number;
|
|
23
214
|
/** The ADT trigger event. Defaults to `"A01"`. */
|
|
24
215
|
readonly trigger?: AdtTrigger;
|
|
216
|
+
/**
|
|
217
|
+
* Who the message is about. Defaults to `"person"`, whose bytes for a seed are what they always
|
|
218
|
+
* were. `"animal"` writes a veterinary patient: the pet's name in PID-5, a microchip in PID-3, the
|
|
219
|
+
* species in PID-35 and breed in PID-36, and the owner in an `NK1` after the `PID`.
|
|
220
|
+
*/
|
|
221
|
+
readonly subject?: Hl7Subject;
|
|
25
222
|
}
|
|
26
223
|
/**
|
|
27
224
|
* Generate a spec-clean `ADT` {@link Hl7Message} through `@cosyte/hl7`. Deterministic in `seed`.
|
|
@@ -29,8 +226,12 @@ interface GenerateAdtOptions {
|
|
|
29
226
|
* The message carries a complete MSH (seeded control id + timestamp, so the bytes are reproducible),
|
|
30
227
|
* `EVN`, a fully-populated `PID` (identity from the synthetic providers), and `PV1` (the visit group),
|
|
31
228
|
* so it parses back through `@cosyte/hl7` with **zero warnings** (proven by {@link ./round-trip}).
|
|
229
|
+
* A trigger added after `A01`, `A04` and `A08` also names its published structure in MSH-9.3 and
|
|
230
|
+
* fills the `PV1` fields its event is about (a transfer's prior location, a discharge's times).
|
|
32
231
|
*
|
|
33
|
-
*
|
|
232
|
+
* With `subject: "animal"` the patient is an animal and its owner follows the `PID` in an `NK1`.
|
|
233
|
+
*
|
|
234
|
+
* @param options - Seed, trigger and subject. See {@link GenerateAdtOptions}.
|
|
34
235
|
* @returns A spec-clean `ADT` `Hl7Message`.
|
|
35
236
|
* @example
|
|
36
237
|
* ```ts
|
|
@@ -56,6 +257,12 @@ declare function generateAdt(options?: GenerateAdtOptions): Hl7Message;
|
|
|
56
257
|
interface GenerateOruOptions {
|
|
57
258
|
/** The seed: the same seed yields a byte-identical message. Defaults to `0`. */
|
|
58
259
|
readonly seed?: number;
|
|
260
|
+
/**
|
|
261
|
+
* Who the result is about. Defaults to `"person"`, whose bytes for a seed are what they always
|
|
262
|
+
* were. `"animal"` writes a veterinary patient: the pet's name in PID-5, a microchip in PID-3, the
|
|
263
|
+
* species in PID-35 and breed in PID-36, and the owner in an `NK1` after the `PID`.
|
|
264
|
+
*/
|
|
265
|
+
readonly subject?: Hl7Subject;
|
|
59
266
|
}
|
|
60
267
|
/**
|
|
61
268
|
* Generate a spec-clean `ORU^R01` {@link Hl7Message} through `@cosyte/hl7`. Deterministic in `seed`.
|
|
@@ -64,7 +271,9 @@ interface GenerateOruOptions {
|
|
|
64
271
|
* rows. The `OBR`/`OBX` result group satisfies the parser's `ORU^R01` structure net, so the message
|
|
65
272
|
* re-parses with **zero warnings** (proven by {@link ./round-trip}).
|
|
66
273
|
*
|
|
67
|
-
*
|
|
274
|
+
* With `subject: "animal"` the patient is an animal and its owner follows the `PID` in an `NK1`.
|
|
275
|
+
*
|
|
276
|
+
* @param options - Seed and subject. See {@link GenerateOruOptions}.
|
|
68
277
|
* @returns A spec-clean `ORU^R01` `Hl7Message`.
|
|
69
278
|
* @example
|
|
70
279
|
* ```ts
|
|
@@ -173,6 +382,160 @@ interface GenerateVxuOptions {
|
|
|
173
382
|
*/
|
|
174
383
|
declare function generateVxu(options?: GenerateVxuOptions): Hl7Message;
|
|
175
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Spec-clean HL7 v2 `MDM^T02` (original document notification and content) generation, built
|
|
387
|
+
* **through `@cosyte/hl7`'s `buildMessage`**. The published `MDM_T02` structure requires `EVN`, `PID`,
|
|
388
|
+
* `PV1`, `TXA` (the document header) and at least one `OBX` (the document body); this generator emits
|
|
389
|
+
* each of them, so the message round-trips with **zero warnings**. Identity comes from `../safe`; the
|
|
390
|
+
* document body is a fixed set of sentences that say they are synthetic.
|
|
391
|
+
*
|
|
392
|
+
* @module
|
|
393
|
+
*/
|
|
394
|
+
|
|
395
|
+
/** Options for {@link generateMdm}. */
|
|
396
|
+
interface GenerateMdmOptions {
|
|
397
|
+
/** The seed: the same seed yields a byte-identical message. Defaults to `0`. */
|
|
398
|
+
readonly seed?: number;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Generate a spec-clean `MDM^T02` {@link Hl7Message} through `@cosyte/hl7`. Deterministic in `seed`.
|
|
402
|
+
*
|
|
403
|
+
* Layout: MSH (`MDM^T02^MDM_T02`), `EVN`, `PID` (synthetic identity), `PV1`, `TXA` (document type
|
|
404
|
+
* from HL7 table 0270, content presentation `TX`, a `SYNTHDOC` unique document number, completion
|
|
405
|
+
* status `DO`, documented) and one to three `OBX` lines of `TX` text, each final (`F`).
|
|
406
|
+
*
|
|
407
|
+
* @param options - Seed. See {@link GenerateMdmOptions}.
|
|
408
|
+
* @returns A spec-clean `MDM^T02` `Hl7Message`.
|
|
409
|
+
* @example
|
|
410
|
+
* ```ts
|
|
411
|
+
* import { generateMdm } from "@cosyte/synth/hl7";
|
|
412
|
+
* const msg = generateMdm({ seed: 12345 });
|
|
413
|
+
* console.log(msg.toString());
|
|
414
|
+
* ```
|
|
415
|
+
*/
|
|
416
|
+
declare function generateMdm(options?: GenerateMdmOptions): Hl7Message;
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Spec-clean HL7 v2 `DFT^P03` (post detail financial transactions) generation, built **through
|
|
420
|
+
* `@cosyte/hl7`'s `buildMessage`**. The published `DFT_P03` structure requires `EVN`, `PID` and at
|
|
421
|
+
* least one `FT1` (the financial transaction); this generator emits them and a `PV1`, so the message
|
|
422
|
+
* round-trips with **zero warnings**. Identity comes from `../safe`; the charge code is a local code
|
|
423
|
+
* that says it is synthetic, never a real chargemaster or procedure code.
|
|
424
|
+
*
|
|
425
|
+
* @module
|
|
426
|
+
*/
|
|
427
|
+
|
|
428
|
+
/** Options for {@link generateDft}. */
|
|
429
|
+
interface GenerateDftOptions {
|
|
430
|
+
/** The seed: the same seed yields a byte-identical message. Defaults to `0`. */
|
|
431
|
+
readonly seed?: number;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Generate a spec-clean `DFT^P03` {@link Hl7Message} through `@cosyte/hl7`. Deterministic in `seed`.
|
|
435
|
+
*
|
|
436
|
+
* Layout: MSH (`DFT^P03^DFT_P03`), `EVN`, `PID` (synthetic identity), `PV1`, and one `FT1`: a
|
|
437
|
+
* `SYNTHTXN` transaction id, the transaction date, type `CG` (charge, HL7 table 0017), a local
|
|
438
|
+
* `SYNTHCHG` charge code and a quantity of one to three.
|
|
439
|
+
*
|
|
440
|
+
* @param options - Seed. See {@link GenerateDftOptions}.
|
|
441
|
+
* @returns A spec-clean `DFT^P03` `Hl7Message`.
|
|
442
|
+
* @example
|
|
443
|
+
* ```ts
|
|
444
|
+
* import { generateDft } from "@cosyte/synth/hl7";
|
|
445
|
+
* const msg = generateDft({ seed: 12345 });
|
|
446
|
+
* console.log(msg.toString());
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
declare function generateDft(options?: GenerateDftOptions): Hl7Message;
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Spec-clean HL7 v2 `OML^O21` (laboratory order) generation, built **through `@cosyte/hl7`'s
|
|
453
|
+
* `buildMessage`**. The published `OML_O21` structure requires the common order (`ORC`); this
|
|
454
|
+
* generator emits `PID`, `ORC` and a matching `OBR`, so the message round-trips with **zero
|
|
455
|
+
* warnings**. Identity comes from `../safe`; the ordered service comes from the license-clean example
|
|
456
|
+
* pool, never bundled terminology.
|
|
457
|
+
*
|
|
458
|
+
* @module
|
|
459
|
+
*/
|
|
460
|
+
|
|
461
|
+
/** Options for {@link generateOml}. */
|
|
462
|
+
interface GenerateOmlOptions {
|
|
463
|
+
/** The seed: the same seed yields a byte-identical message. Defaults to `0`. */
|
|
464
|
+
readonly seed?: number;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Generate a spec-clean `OML^O21` {@link Hl7Message} through `@cosyte/hl7`. Deterministic in `seed`.
|
|
468
|
+
*
|
|
469
|
+
* Layout: MSH (`OML^O21^OML_O21`), `PID` (synthetic identity), `ORC` (order control `NW`, a new
|
|
470
|
+
* order) and an `OBR` carrying the same placer and filler numbers and a laboratory service.
|
|
471
|
+
*
|
|
472
|
+
* @param options - Seed. See {@link GenerateOmlOptions}.
|
|
473
|
+
* @returns A spec-clean `OML^O21` `Hl7Message`.
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* import { generateOml } from "@cosyte/synth/hl7";
|
|
477
|
+
* const msg = generateOml({ seed: 12345 });
|
|
478
|
+
* console.log(msg.toString());
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
declare function generateOml(options?: GenerateOmlOptions): Hl7Message;
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Spec-clean HL7 v2 `ACK` (general acknowledgment) generation, for any message: built **through
|
|
485
|
+
* `@cosyte/hl7`'s `buildMessage`** like every other kind. The published `ACK` structure requires
|
|
486
|
+
* `MSH` and `MSA`; an error acknowledgment adds one `ERR`. The message round-trips with **zero
|
|
487
|
+
* warnings**.
|
|
488
|
+
*
|
|
489
|
+
* `@cosyte/hl7`'s own `buildAck` stamps the current time and a fresh control id, which is right for a
|
|
490
|
+
* live interface and wrong for a fixture. This generator draws both from the seed instead, so the
|
|
491
|
+
* same seed and the same inbound message give the same bytes.
|
|
492
|
+
*
|
|
493
|
+
* @module
|
|
494
|
+
*/
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* An original-mode acknowledgment code (HL7 table 0008, MSA-1): `AA` application accept, `AE`
|
|
498
|
+
* application error, `AR` application reject.
|
|
499
|
+
*/
|
|
500
|
+
type Hl7AckCode = "AA" | "AE" | "AR";
|
|
501
|
+
/** Options for {@link generateAck}. */
|
|
502
|
+
interface GenerateAckOptions {
|
|
503
|
+
/** The seed: the same seed and inbound message yield a byte-identical ACK. Defaults to `0`. */
|
|
504
|
+
readonly seed?: number;
|
|
505
|
+
/**
|
|
506
|
+
* The message being acknowledged. Defaults to the `ADT^A01` {@link generateAdt} makes from the same
|
|
507
|
+
* seed. It must carry an MSH-10 message control id.
|
|
508
|
+
*/
|
|
509
|
+
readonly inbound?: Hl7Message;
|
|
510
|
+
/** The acknowledgment code in MSA-1. Defaults to `"AA"`. */
|
|
511
|
+
readonly code?: Hl7AckCode;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Generate a spec-clean `ACK` {@link Hl7Message} answering `inbound`. Deterministic in `seed` and
|
|
515
|
+
* `inbound`.
|
|
516
|
+
*
|
|
517
|
+
* - **MSH**: the inbound receiver (MSH-5, MSH-6) becomes the sender (MSH-3, MSH-4) and the inbound
|
|
518
|
+
* sender the receiver. MSH-7 is one to fifty-nine seconds after the inbound MSH-7, or a seeded time
|
|
519
|
+
* when that is not a full `YYYYMMDDHHMMSS`. MSH-9 is `ACK^<inbound trigger>^ACK`, or `ACK` when
|
|
520
|
+
* the inbound names no trigger. MSH-10 is a seeded `SYNTHACK` control id. MSH-11 is always `T`, test
|
|
521
|
+
* data, whatever the inbound says. MSH-12 echoes the inbound version, `2.5` when it names none.
|
|
522
|
+
* - **MSA**: MSA-1 is `code`, MSA-2 the inbound MSH-10.
|
|
523
|
+
* - **ERR**, for `AE` and `AR` only: ERR-3 is condition `207`, application internal error (HL7 table
|
|
524
|
+
* 0357), and ERR-4 severity `E`, error.
|
|
525
|
+
*
|
|
526
|
+
* @param options - Seed, inbound message and code. See {@link GenerateAckOptions}.
|
|
527
|
+
* @returns A spec-clean `ACK` `Hl7Message`.
|
|
528
|
+
* @throws SynthError `SYNTH_ACK_UNCORRELATED` when the inbound message has no MSH-10, and
|
|
529
|
+
* `SYNTH_UNSUPPORTED_KIND` when `code` is not `AA`, `AE` or `AR`.
|
|
530
|
+
* @example
|
|
531
|
+
* ```ts
|
|
532
|
+
* import { generateAck, generateOru } from "@cosyte/synth/hl7";
|
|
533
|
+
* const ack = generateAck({ seed: 7, inbound: generateOru({ seed: 7 }) });
|
|
534
|
+
* console.log(ack.toString()); // MSH|...|ACK^R01^ACK|SYNTHACK...|T|2.5 then MSA|AA|SYNTH...
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
537
|
+
declare function generateAck(options?: GenerateAckOptions): Hl7Message;
|
|
538
|
+
|
|
176
539
|
/**
|
|
177
540
|
* The **round-trip-through-the-parser harness**: the headline gate for the synthetic-fixture
|
|
178
541
|
* generator. A generated artifact is "spec-clean" only if `@cosyte/hl7`, not
|
|
@@ -236,99 +599,6 @@ declare function roundTrip(message: Hl7Message): RoundTripResult;
|
|
|
236
599
|
*/
|
|
237
600
|
declare function componentsField(components: readonly string[]): RawField;
|
|
238
601
|
|
|
239
|
-
/**
|
|
240
|
-
* Shared HL7 v2 building blocks for every message family `@cosyte/synth` generates: the MSH scaffold,
|
|
241
|
-
* the seeded timestamp, and the patient-identity bundle + its `PID` segment. Factored out so `ADT`,
|
|
242
|
-
* `ORU`, `ORM`, `SIU`, and `VXU` all mint identity from the **same** synthetic-safety providers in the
|
|
243
|
-
* **same** draw order, and all emit through `@cosyte/hl7`'s conservative serializer. Nothing here draws a
|
|
244
|
-
* value that is not sourced from `../safe`: the synthetic-by-construction
|
|
245
|
-
* invariant holds by construction for every family.
|
|
246
|
-
*
|
|
247
|
-
* @module
|
|
248
|
-
*/
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* A seeded HL7 `YYYYMMDDHHMMSS` timestamp (message/event time; recent-year range). Strict HL7 DTM, so
|
|
252
|
-
* `@cosyte/hl7` parses it back with no `TIMESTAMP_FALLBACK_FORMAT` warning.
|
|
253
|
-
*
|
|
254
|
-
* @param rng - The seeded generator.
|
|
255
|
-
* @returns A 14-digit `YYYYMMDDHHMMSS` timestamp string.
|
|
256
|
-
* @example
|
|
257
|
-
* ```ts
|
|
258
|
-
* import { createRng } from "@cosyte/synth";
|
|
259
|
-
* // "20230714…"
|
|
260
|
-
* ```
|
|
261
|
-
*/
|
|
262
|
-
declare function seededTimestamp(rng: Rng): string;
|
|
263
|
-
/** The MSH scaffold shared by every generated message: the built message plus its seeded MSH values. */
|
|
264
|
-
interface MessageScaffold {
|
|
265
|
-
/** The `Hl7Message` with a complete MSH: chain `.addSegment(...)` to append the payload. */
|
|
266
|
-
readonly message: Hl7Message;
|
|
267
|
-
/** The seeded `YYYYMMDDHHMMSS` message timestamp (MSH-7), reused for event/observation times. */
|
|
268
|
-
readonly timestamp: string;
|
|
269
|
-
/** The seeded message control id (MSH-10). */
|
|
270
|
-
readonly controlId: string;
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Build the MSH scaffold for a message of the given `MSH-9` type through `@cosyte/hl7`'s `buildMessage`,
|
|
274
|
-
* so the delimiters, control id, and header layout are the parser's own conservative emit. Draws the
|
|
275
|
-
* timestamp then the control id from `rng` (a fixed order: the reproducibility contract).
|
|
276
|
-
*
|
|
277
|
-
* @param rng - The seeded generator.
|
|
278
|
-
* @param type - The `MSH-9` message type, e.g. `"ORU^R01"`.
|
|
279
|
-
* @returns The {@link MessageScaffold}.
|
|
280
|
-
* @example
|
|
281
|
-
* ```ts
|
|
282
|
-
* import { createRng } from "@cosyte/synth";
|
|
283
|
-
* // mshScaffold(createRng(1), "ORU^R01").message.addSegment("PID", […]);
|
|
284
|
-
* ```
|
|
285
|
-
*/
|
|
286
|
-
declare function mshScaffold(rng: Rng, type: string): MessageScaffold;
|
|
287
|
-
/** A complete synthetic patient identity: every field drawn from `../safe`. */
|
|
288
|
-
interface PatientIdentity {
|
|
289
|
-
/** Name from the shipped fake-name pool. */
|
|
290
|
-
readonly person: SyntheticName;
|
|
291
|
-
/** Medical-record identifier scoped to the synthetic assigning authority. */
|
|
292
|
-
readonly mrn: SyntheticIdentifier;
|
|
293
|
-
/** Date of birth (`YYYYMMDD`) from the seeded generator. */
|
|
294
|
-
readonly dob: string;
|
|
295
|
-
/** Administrative sex. */
|
|
296
|
-
readonly sex: "M" | "F";
|
|
297
|
-
/** Synthetic postal address (reserved non-real ZIP). */
|
|
298
|
-
readonly address: SyntheticAddress;
|
|
299
|
-
/** Reserved `555-01xx` phone number. */
|
|
300
|
-
readonly phone: string;
|
|
301
|
-
/** Never-issued SSN as 9 digits (no dashes), for `PID-19`. */
|
|
302
|
-
readonly ssnDigits: string;
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Mint a complete synthetic {@link PatientIdentity}. Every value comes from a synthetic-safety provider,
|
|
306
|
-
* so no code path here can return a real or plausibly-real identifier. The draw order is
|
|
307
|
-
* fixed (name → MRN → DOB → sex → address → phone → SSN) so the same seed yields the same identity.
|
|
308
|
-
*
|
|
309
|
-
* @param rng - The seeded generator.
|
|
310
|
-
* @returns A synthetic {@link PatientIdentity}.
|
|
311
|
-
* @example
|
|
312
|
-
* ```ts
|
|
313
|
-
* import { createRng } from "@cosyte/synth";
|
|
314
|
-
* // const id = patientIdentity(createRng(1)); // id.person, id.mrn, …
|
|
315
|
-
* ```
|
|
316
|
-
*/
|
|
317
|
-
declare function patientIdentity(rng: Rng): PatientIdentity;
|
|
318
|
-
/**
|
|
319
|
-
* Lay out a fully-populated `PID` segment from a {@link PatientIdentity} as `addSegment` fields: the
|
|
320
|
-
* PHI-dense segment shared by every family. Components go through {@link componentsField} so the parser
|
|
321
|
-
* lays out the `^` separators (building *through* the parser).
|
|
322
|
-
*
|
|
323
|
-
* @param id - The synthetic identity to render.
|
|
324
|
-
* @returns The `PID` field list for `Hl7Message.addSegment("PID", …)`.
|
|
325
|
-
* @example
|
|
326
|
-
* ```ts
|
|
327
|
-
* // msg.addSegment("PID", pidSegment(patientIdentity(createRng(1))));
|
|
328
|
-
* ```
|
|
329
|
-
*/
|
|
330
|
-
declare function pidSegment(id: PatientIdentity): readonly (string | RawField)[];
|
|
331
|
-
|
|
332
602
|
/**
|
|
333
603
|
* A tiny, curated, **license-clean** pool of example codes used to fill coded fields in generated HL7
|
|
334
604
|
* messages (`OBR`/`OBX` observations, `ORC`/`OBR` orders, `RXA` vaccines). These are **public code
|
|
@@ -445,9 +715,15 @@ interface Hl7QuirkCorpusOptions {
|
|
|
445
715
|
readonly seed: number;
|
|
446
716
|
/** How many quirk artifacts to generate. Defaults to the number of quirks. */
|
|
447
717
|
readonly count?: number;
|
|
448
|
-
/**
|
|
718
|
+
/**
|
|
719
|
+
* The quirk names to cycle through. Defaults to every HL7 quirk. Validated; unsupported ⇒ fatal.
|
|
720
|
+
* An empty list, or a `profile` whose `quirks` is an empty list, throws `SYNTH_EMPTY_POOL`.
|
|
721
|
+
*/
|
|
449
722
|
readonly quirks?: readonly Hl7QuirkName[];
|
|
450
|
-
/**
|
|
723
|
+
/**
|
|
724
|
+
* A {@link SynthProfile} whose `quirks` drive the corpus (validated). Its `quirks`, when set, take
|
|
725
|
+
* precedence over `quirks`; a profile that leaves `quirks` out leaves the selection to `quirks`.
|
|
726
|
+
*/
|
|
451
727
|
readonly profile?: SynthProfile;
|
|
452
728
|
/** The base message family each quirk is injected into. Defaults to `"ORU^R01"`. */
|
|
453
729
|
readonly kind?: Hl7QuirkKind;
|
|
@@ -486,17 +762,30 @@ declare const hl7QuirkProfile: SynthProfile;
|
|
|
486
762
|
* never loads a parser.
|
|
487
763
|
* `@cosyte/hl7` is an **optional peer dependency**, present only for this subpath.
|
|
488
764
|
*
|
|
489
|
-
* The HL7 v2 message set
|
|
490
|
-
* `VXU^V04`,
|
|
765
|
+
* The HL7 v2 message set: `ADT` (A01, A02, A03, A04, A08, A11, A13, A28, A31), `ORU^R01`, `ORM^O01`,
|
|
766
|
+
* `SIU^S12`, `VXU^V04`, `MDM^T02`, `DFT^P03`, `OML^O21`, and an `ACK` for any of them, each built
|
|
767
|
+
* through `@cosyte/hl7`'s `buildMessage`, stamped HL7 v2.5, and round-tripping with zero warnings.
|
|
491
768
|
*
|
|
492
769
|
* @module
|
|
493
770
|
*/
|
|
494
771
|
|
|
495
772
|
/**
|
|
496
773
|
* Every HL7 v2 message kind this subpath generates: the `MSH-9` label used as the corpus `kind`. `ADT`
|
|
497
|
-
* carries its trigger; the other families have a single generated trigger each.
|
|
774
|
+
* carries its trigger; the other families have a single generated trigger each. `ACK` acknowledges
|
|
775
|
+
* an `ADT^A01` generated from the same seed (see {@link generateAck} to acknowledge any message).
|
|
776
|
+
*/
|
|
777
|
+
type Hl7MessageKind = "ADT^A01" | "ADT^A04" | "ADT^A08" | "ORU^R01" | "ORM^O01" | "SIU^S12" | "VXU^V04" | "ACK" | "ADT^A02" | "ADT^A03" | "ADT^A11" | "ADT^A13" | "ADT^A28" | "ADT^A31" | "MDM^T02" | "DFT^P03" | "OML^O21";
|
|
778
|
+
/**
|
|
779
|
+
* Every kind {@link generateHl7} and {@link hl7Corpus} accept, in a fixed order: the first seven
|
|
780
|
+
* kinds, then each kind added since. Pass it as a corpus `mix` to cycle through all of them.
|
|
781
|
+
*
|
|
782
|
+
* @example
|
|
783
|
+
* ```ts
|
|
784
|
+
* import { HL7_MESSAGE_KINDS, hl7Corpus } from "@cosyte/synth/hl7";
|
|
785
|
+
* hl7Corpus({ seed: 1, count: HL7_MESSAGE_KINDS.length, mix: HL7_MESSAGE_KINDS });
|
|
786
|
+
* ```
|
|
498
787
|
*/
|
|
499
|
-
|
|
788
|
+
declare const HL7_MESSAGE_KINDS: readonly Hl7MessageKind[];
|
|
500
789
|
/**
|
|
501
790
|
* Generate one message of the given {@link Hl7MessageKind} from a seed, dispatching to the right
|
|
502
791
|
* family generator. Every kind builds through `@cosyte/hl7` and is deterministic in `seed`.
|
|
@@ -518,13 +807,15 @@ interface Hl7CorpusOptions {
|
|
|
518
807
|
/** How many messages to generate. Defaults to `1`. */
|
|
519
808
|
readonly count?: number;
|
|
520
809
|
/**
|
|
521
|
-
* The message kinds to cycle through. Defaults to one of
|
|
522
|
-
* (`ADT^A01/A04/A08`, `ORU^R01`, `ORM^O01`, `SIU^S12`, `VXU^V04`)
|
|
810
|
+
* The message kinds to cycle through, any of {@link HL7_MESSAGE_KINDS}. Defaults to one each of
|
|
811
|
+
* the first seven kinds (`ADT^A01/A04/A08`, `ORU^R01`, `ORM^O01`, `SIU^S12`, `VXU^V04`), so a seed's
|
|
812
|
+
* default corpus is unchanged as kinds are added. An empty list throws `SYNTH_EMPTY_POOL`.
|
|
523
813
|
*/
|
|
524
814
|
readonly mix?: readonly Hl7MessageKind[];
|
|
525
815
|
/**
|
|
526
816
|
* ADT-only convenience: the triggers to cycle through, kept for back-compat. When
|
|
527
|
-
* supplied it takes precedence over `mix` and restricts the corpus to `ADT` messages.
|
|
817
|
+
* supplied it takes precedence over `mix` and restricts the corpus to `ADT` messages. An empty
|
|
818
|
+
* list throws `SYNTH_EMPTY_POOL`.
|
|
528
819
|
*/
|
|
529
820
|
readonly triggers?: readonly AdtTrigger[];
|
|
530
821
|
/**
|
|
@@ -551,5 +842,5 @@ interface Hl7CorpusOptions {
|
|
|
551
842
|
*/
|
|
552
843
|
declare function hl7Corpus(options: Hl7CorpusOptions): Corpus;
|
|
553
844
|
|
|
554
|
-
export { EXAMPLE_LAB_OBSERVATIONS, EXAMPLE_ORDER_SERVICES, EXAMPLE_VACCINES, HL7_QUIRKS, componentsField, generateAdt, generateHl7, generateHl7Quirk, generateOrm, generateOru, generateSiu, generateVxu, hl7Corpus, hl7QuirkCorpus, hl7QuirkProfile, hl7QuirkRoundTrip, mshScaffold, patientIdentity, pidSegment, roundTrip, seededTimestamp };
|
|
555
|
-
export type { AdtTrigger, ExampleCode, GenerateAdtOptions, GenerateHl7QuirkOptions, GenerateOrmOptions, GenerateOruOptions, GenerateSiuOptions, GenerateVxuOptions, Hl7CorpusOptions, Hl7MessageKind, Hl7QuirkCorpusOptions, Hl7QuirkKind, Hl7QuirkName, MessageScaffold, PatientIdentity, RoundTripResult };
|
|
845
|
+
export { EXAMPLE_LAB_OBSERVATIONS, EXAMPLE_ORDER_SERVICES, EXAMPLE_VACCINES, HL7_MESSAGE_KINDS, HL7_QUIRKS, MICROCHIP_IDENTIFIER_TYPE, OWNER_RELATIONSHIP, animalIdentity, animalPidSegment, componentsField, generateAck, generateAdt, generateDft, generateHl7, generateHl7Quirk, generateMdm, generateOml, generateOrm, generateOru, generateSiu, generateVxu, hl7Corpus, hl7QuirkCorpus, hl7QuirkProfile, hl7QuirkRoundTrip, mshScaffold, ownerNk1Segment, patientIdentity, pidSegment, roundTrip, seededTimestamp };
|
|
846
|
+
export type { AdtTrigger, AnimalIdentity, AnimalOwner, ExampleCode, GenerateAckOptions, GenerateAdtOptions, GenerateDftOptions, GenerateHl7QuirkOptions, GenerateMdmOptions, GenerateOmlOptions, GenerateOrmOptions, GenerateOruOptions, GenerateSiuOptions, GenerateVxuOptions, Hl7AckCode, Hl7CorpusOptions, Hl7MessageKind, Hl7QuirkCorpusOptions, Hl7QuirkKind, Hl7QuirkName, Hl7Subject, MessageScaffold, PatientIdentity, RoundTripResult };
|