@cosyte/synth 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.4
4
+
5
+ ### Patch Changes
6
+
7
+ - b6ac062: Type declarations are now bundled by tsup 9; the JavaScript is unchanged and the bytes every seed
8
+ produces are unchanged. Each declaration file lists its type-only exports in a separate
9
+ `export type` statement and the shared declaration chunks have new file names. Every subpath
10
+ exports the same names with the same types as before. The source maps of the `hl7`, `ccda` and
11
+ `deid` subpaths embed source that was reformatted, with no change to the code.
12
+
13
+ ## 0.1.3
14
+
15
+ ### Patch Changes
16
+
17
+ - 4008c31: The npm description lists the six formats with a serial comma.
18
+ - 4153d08: The README follows the house layout, with sections for support, security, and contributing, and the installation page names Node 26, which CI now tests.
19
+
3
20
  ## 0.1.2
4
21
 
5
22
  ### Patch Changes
package/README.md CHANGED
@@ -9,6 +9,20 @@
9
9
 
10
10
  > Seeded, reproducible **synthetic healthcare fixtures** for Node.js and TypeScript: spec-clean, never real PHI.
11
11
 
12
+ [![npm version](https://img.shields.io/npm/v/@cosyte/synth.svg)](https://www.npmjs.com/package/@cosyte/synth)
13
+ [![CI](https://img.shields.io/github/actions/workflow/status/cosyte/synth/ci.yml?branch=main&label=CI)](https://github.com/cosyte/synth/actions/workflows/ci.yml)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/cosyte/synth/blob/main/LICENSE)
15
+ [![Node](https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen.svg)](https://nodejs.org)
16
+
17
+ Deterministic, seedable synthetic healthcare test fixtures for Node.js and TypeScript: HL7 v2, FHIR R4 and US Core, C-CDA, X12, NCPDP, and ASTM, spec-clean by construction and never real PHI.
18
+
19
+ ## Why this exists
20
+
21
+ A test suite for a healthcare integration needs messages and documents that look like what a
22
+ sending system produces, and it must never hold a real patient's data. Copying production samples
23
+ and scrubbing them by hand risks the second; writing fixtures by hand rarely gets the first. And a
24
+ fixture that changes on every run cannot be committed as a golden file.
25
+
12
26
  `@cosyte/synth` generates reproducible synthetic test corpora across the six Cosyte formats (HL7 v2,
13
27
  FHIR R4 / US Core, C-CDA, X12, NCPDP, and ASTM). It is a **consumer** of the
14
28
  Cosyte parsers, not a parser: it builds each artifact **through the parser's own builder/serializer**
@@ -17,23 +31,25 @@ date, phone, and address from a **guaranteed-non-colliding synthetic source**. I
17
31
  **format/conformance generator, not a clinical simulator**: it does not model disease progression
18
32
  (that is Synthea).
19
33
 
20
- > **Status:** the 0.1 line, published to npm. The version shown on the npm package page is the one
21
- > that is live; this page never repeats it. Below 1.0, a breaking change raises the minor version and the
22
- > changelog says what broke. The generator is **feature-complete**: the
23
- > seeded-PRNG core, the synthetic-safety providers, and the round-trip harness; **generation across all
24
- > six formats**, HL7 v2 (`ADT`/`ORU`/`ORM`/`SIU`/`VXU`), FHIR R4 / US Core (the full clinical
25
- > set + `collection`/`transaction`/`document` Bundles), C-CDA R2.1 (CCD + Referral Note), X12 005010
26
- > (837P/I/D, 835, 271), NCPDP (SCRIPT NewRx / RxRenewal / RxChange + Telecom B1/B2/B3), and ASTM (E1394
27
- > record reports + E1381 framing), each built **through its parser's own builder/serializer**; **vendor-quirk
28
- > mode**, profile-driven off-spec fixtures for the three richest profile systems (**HL7 v2, C-CDA, ASTM**),
29
- > each round-tripping to exactly the intended parser warning (the intended-warning contract); and the
30
- > **`@cosyte/deid` pairing loop**, a closed-loop co-validation harness that de-identifies generated output
31
- > and proves every planted synthetic PHI sentinel is removed.
32
- >
33
- > **Deferred (honestly out of scope for now):** quirk recipes for **FHIR / X12 / NCPDP** (and any quirk
34
- > needing a private vendor corpus); the X12 **270** eligibility _request_ and NCPDP SCRIPT lifecycle
35
- > **responses** (both track the parsers' builder surfaces); **NCPDP SCRIPT / ASTM / DICOM** de-identify
36
- > pairing (no `@cosyte/deid` adapter, or not generated); and optional **Synthea** clinical-content ingestion.
34
+ ## Status
35
+
36
+ The 0.1 line, published to npm. The version shown on the npm package page is the one
37
+ that is live; this page never repeats it. Below 1.0, a breaking change raises the minor version and the
38
+ changelog says what broke. The generator is **feature-complete**: the
39
+ seeded-PRNG core, the synthetic-safety providers, and the round-trip harness; **generation across all
40
+ six formats**, HL7 v2 (`ADT`/`ORU`/`ORM`/`SIU`/`VXU`), FHIR R4 / US Core (the full clinical
41
+ set + `collection`/`transaction`/`document` Bundles), C-CDA R2.1 (CCD + Referral Note), X12 005010
42
+ (837P/I/D, 835, 271), NCPDP (SCRIPT NewRx / RxRenewal / RxChange + Telecom B1/B2/B3), and ASTM (E1394
43
+ record reports + E1381 framing), each built **through its parser's own builder/serializer**; **vendor-quirk
44
+ mode**, profile-driven off-spec fixtures for the three richest profile systems (**HL7 v2, C-CDA, ASTM**),
45
+ each round-tripping to exactly the intended parser warning (the intended-warning contract); and the
46
+ **`@cosyte/deid` pairing loop**, a closed-loop co-validation harness that de-identifies generated output
47
+ and proves every planted synthetic PHI sentinel is removed.
48
+
49
+ **Deferred (honestly out of scope for now):** quirk recipes for **FHIR / X12 / NCPDP** (and any quirk
50
+ needing a private vendor corpus); the X12 **270** eligibility _request_ and NCPDP SCRIPT lifecycle
51
+ **responses** (both track the parsers' builder surfaces); **NCPDP SCRIPT / ASTM / DICOM** de-identify
52
+ pairing (no `@cosyte/deid` adapter, or not generated); and optional **Synthea** clinical-content ingestion.
37
53
 
38
54
  ## Install
39
55
 
@@ -41,7 +57,7 @@ date, phone, and address from a **guaranteed-non-colliding synthetic source**. I
41
57
  npm install @cosyte/synth @cosyte/hl7 @cosyte/fhir @cosyte/ccda @cosyte/x12 @cosyte/ncpdp @cosyte/astm
42
58
  ```
43
59
 
44
- Node.js 22 or later, tested on 22 and 24.
60
+ Node.js 22 or later, tested on 22, 24, and 26.
45
61
 
46
62
  `@cosyte/hl7`, `@cosyte/fhir`, `@cosyte/ccda`, `@cosyte/x12`, `@cosyte/ncpdp`, `@cosyte/astm`, and
47
63
  `@cosyte/deid` are **optional peer dependencies**, each needed only for its subpath (`@cosyte/synth/hl7`,
@@ -50,7 +66,12 @@ Node.js 22 or later, tested on 22 and 24.
50
66
  the formats it pairs): install only the packages whose fixtures you generate. The package core has
51
67
  **zero third-party runtime dependencies**.
52
68
 
53
- ## Generate a spec-clean HL7 v2 message
69
+ ## Usage
70
+
71
+ Every value below is synthetic by construction. The full reference, with a guide per format, is
72
+ on [docs.cosyte.com/synth](https://docs.cosyte.com/synth).
73
+
74
+ ### Generate a spec-clean HL7 v2 message
54
75
 
55
76
  The HL7 v2 set covers `ADT` (`A01`/`A04`/`A08`), `ORU^R01`, `ORM^O01`, `SIU^S12`, and `VXU^V04`:
56
77
  each built through `@cosyte/hl7`'s `buildMessage`, so it is spec-clean by construction.
@@ -74,7 +95,7 @@ console.log(corpus.artifacts.every((a) => a.warnings.length === 0)); // true, al
74
95
  console.log(roundTrip(generateHl7("VXU^V04", 12345)).content.split("\r")[0]); // its MSH segment
75
96
  ```
76
97
 
77
- ## Generate a spec-clean FHIR R4 / US Core resource
98
+ ### Generate a spec-clean FHIR R4 / US Core resource
78
99
 
79
100
  The `@cosyte/synth/fhir` subpath builds resources **through `@cosyte/fhir`'s model constructors**, so
80
101
  they are spec-clean by construction: validating under `validateResource` and, against the **real US
@@ -108,7 +129,7 @@ corpus.artifacts.every((a) => a.warnings.length === 0); // true, all spec-clean
108
129
 
109
130
  `@cosyte/fhir` is an **optional peer dependency**, needed only for the `@cosyte/synth/fhir` subpath.
110
131
 
111
- ## Generate a spec-clean C-CDA document
132
+ ### Generate a spec-clean C-CDA document
112
133
 
113
134
  The `@cosyte/synth/ccda` subpath builds Consolidated CDA R2.1 documents **through `@cosyte/ccda`'s
114
135
  `buildCcda`**, so template IDs, LOINC section codes, and structured/narrative agreement are the
@@ -137,7 +158,7 @@ corpus.artifacts.every((a) => a.warnings.length === 0); // true, all spec-clean
137
158
 
138
159
  `@cosyte/ccda` is an **optional peer dependency**, needed only for the `@cosyte/synth/ccda` subpath.
139
160
 
140
- ## Generate an X12 transaction
161
+ ### Generate an X12 transaction
141
162
 
142
163
  The `@cosyte/synth/x12` subpath builds HIPAA **005010** transactions **through `@cosyte/x12`'s domain
143
164
  builders** (`build837P/I/D`, `build835`, `build271`), so the ISA/GS/ST…SE/GE/IEA envelope, the
@@ -168,7 +189,7 @@ corpus.artifacts.every((a) => a.warnings.length === 0); // true
168
189
  **Deferred:** the **270** eligibility _request_ (`@cosyte/x12` ships `build270` on its 0.1 line, but `synth`
169
190
  does not generate a 270 yet) and **vendor-quirk mode**.
170
191
 
171
- ## Generate an NCPDP message
192
+ ### Generate an NCPDP message
172
193
 
173
194
  The `@cosyte/synth/ncpdp` subpath builds both NCPDP standards **through `@cosyte/ncpdp`'s own emit
174
195
  surface**, so each message round-trips through the parser with **zero warnings**. It emits **SCRIPT**
@@ -202,7 +223,7 @@ corpus.artifacts.every((a) => a.warnings.length === 0); // true
202
223
  **Deferred:** vendor-quirk mode. SCRIPT coverage tracks the parser's builder surface: the
203
224
  renewal/change _responses_ land as `@cosyte/ncpdp` grows builders.
204
225
 
205
- ## Generate an ASTM message
226
+ ### Generate an ASTM message
206
227
 
207
228
  The `@cosyte/synth/astm` subpath builds ASTM laboratory messages **through `@cosyte/astm`'s own emit
208
229
  surface**: `buildAstmMessage` for the E1394 record layer, `composeAstmFrames` for the E1381 frame
@@ -235,7 +256,7 @@ corpus.artifacts.every((a) => a.warnings.length === 0); // true
235
256
 
236
257
  `@cosyte/astm` is an **optional peer dependency**, needed only for the `@cosyte/synth/astm` subpath.
237
258
 
238
- ## Generate a vendor-quirk fixture
259
+ ### Generate a vendor-quirk fixture
239
260
 
240
261
  Spec-clean fixtures test that a parser reads a _correct_ message; **quirk mode** tests that it tolerates
241
262
  the realistic vendor deviations real traffic carries, and surfaces exactly the right diagnostic. The
@@ -274,7 +295,7 @@ nothing you passed. Every quirk is grounded in a **publicly-documented** deviati
274
295
  **Deferred:** quirk recipes for **FHIR, X12, and NCPDP**, and any quirk that would need a **private,
275
296
  vendor-attributed corpus** to ground.
276
297
 
277
- ## Co-validate with `@cosyte/deid` (the pairing loop)
298
+ ### Co-validate with `@cosyte/deid` (the pairing loop)
278
299
 
279
300
  The `@cosyte/synth/deid` subpath is a deterministic **closed-loop co-validation harness** for the
280
301
  `synth` ⇄ `deid` pair: it **generates** an artifact, **plants** distinctive synthetic PHI
@@ -314,7 +335,7 @@ identity a de-identifier legitimately retains never reads as a false survivor. `
314
335
  **optional peer dependency**, needed only for this subpath. **Skipped and named** (`DEID_LOOP_SKIPPED`):
315
336
  NCPDP **SCRIPT** and **ASTM** (no `@cosyte/deid` adapter) and **DICOM** (not generated by `synth`).
316
337
 
317
- ## Draw a synthetic value
338
+ ### Draw a synthetic value
318
339
 
319
340
  ```ts
320
341
  import { createRng, safe, isSyntheticSsn, isItinFormatted, isSyntheticNpi } from "@cosyte/synth";
@@ -336,11 +357,71 @@ isSyntheticNpi(safe.npi(rng)); // true, always a deliberately-invalid-Luhn NPI (
336
357
  - **Checked by the parser's own judgment**, built through the parser's conservative serializer and
337
358
  fed straight back in: each artifact re-parses with zero warnings.
338
359
  - **Deterministic**, a hand-rolled seeded PRNG (`sfc32`/`splitmix32`); `Math.random` is lint-banned.
339
- A seed, and only the seed, determines the output, byte-for-byte, anywhere.
360
+ A seed determines the output, byte for byte, on the same parser versions, and CI compares those
361
+ bytes across Node 22, 24, and 26.
340
362
  - **Immutable**, generated artifacts and the `Corpus` result are deep-frozen.
341
363
  - **Zero third-party runtime dependencies**, the parser peers are first-party Cosyte packages,
342
- vendored for dev/test; dual ESM + CJS, validated with `attw`.
364
+ installed from npm for the tests; dual ESM + CJS, validated with `attw`.
365
+
366
+ ## Documentation
367
+
368
+ The full reference is on [docs.cosyte.com/synth](https://docs.cosyte.com/synth):
369
+
370
+ - [Installation](https://docs.cosyte.com/synth/installation) and the [quickstart](https://docs.cosyte.com/synth/quickstart).
371
+ - Core concepts: [the archetype](https://docs.cosyte.com/synth/concepts-archetype) and the [limitations](https://docs.cosyte.com/synth/limitations).
372
+ - Guides: [the overview](https://docs.cosyte.com/synth/guides-overview), [FHIR R4 and US Core](https://docs.cosyte.com/synth/guides-fhir),
373
+ [C-CDA](https://docs.cosyte.com/synth/guides-ccda), [X12](https://docs.cosyte.com/synth/guides-x12), [NCPDP](https://docs.cosyte.com/synth/guides-ncpdp),
374
+ [ASTM](https://docs.cosyte.com/synth/guides-astm), [vendor quirks](https://docs.cosyte.com/synth/guides-quirks), and
375
+ [the `@cosyte/deid` pairing loop](https://docs.cosyte.com/synth/guides-deid).
376
+ - [Troubleshooting](https://docs.cosyte.com/synth/troubleshooting).
377
+ - [`CHANGELOG.md`](https://github.com/cosyte/synth/blob/main/CHANGELOG.md): every release.
378
+
379
+ ## Support
380
+
381
+ Questions, bug reports, and requests for a format or a quirk go in
382
+ [GitHub issues](https://github.com/cosyte/synth/issues). Every fixture this package makes is
383
+ synthetic: never attach a real patient's data to an issue. For help with an integration test suite,
384
+ see our [integration services](https://cosyte.com/integration-services).
385
+
386
+ ## Security
387
+
388
+ Report a vulnerability privately, never in a public issue, and with no real patient data in it. Our
389
+ [security policy](https://github.com/cosyte/synth/security/policy) says how. A generated value that
390
+ is real, or realistic enough to pass for real, is a vulnerability: report it that way.
391
+
392
+ ## Contributing
393
+
394
+ **Where to ask:** open an issue at
395
+ [https://github.com/cosyte/synth/issues](https://github.com/cosyte/synth/issues). A report is most
396
+ useful with the seed, the generator call, and the parser warnings you got back.
397
+
398
+ **Unsolicited pull requests are accepted.** For anything that changes the bytes a seed produces, adds
399
+ a generator option, or moves the public API, open an issue first so the behavior can be agreed
400
+ before you write it: a seed that maps to different bytes breaks every golden file built on it.
401
+ Typo, link, and test fixes can go straight to a pull request.
402
+
403
+ **What a contribution has to clear**, every one of them a script this package declares:
404
+
405
+ | check | what it is |
406
+ | ----------------------------- | ----------------------------------------------------- |
407
+ | `pnpm typecheck` | `tsc --noEmit`, strict (the examples: in `pnpm test`) |
408
+ | `pnpm lint` | ESLint, at `--max-warnings=0` |
409
+ | `pnpm format:check` | Prettier |
410
+ | `pnpm phi-scan` | no patient-shaped value anywhere in a tracked file |
411
+ | `pnpm test` | Vitest, including the synthetic-safety suites |
412
+ | `pnpm test:coverage` | the coverage gate |
413
+ | `pnpm build` | the dual ESM and CJS bundle |
414
+ | `pnpm attw` | per-condition type resolution for consumers |
415
+ | `pnpm run determinism:digest` | the bytes each seed produces, against the baseline |
416
+ | `pnpm check:no-emdash` | the house punctuation rule |
417
+ | `pnpm check:no-internal-refs` | no internal bookkeeping on the public surface |
418
+
419
+ New behavior needs a test beside it, and a change a consumer would notice needs a changeset
420
+ (`pnpm changeset`), whose summary becomes the changelog entry. A change to the bytes a seed produces
421
+ says so in its changeset.
343
422
 
344
423
  ## License
345
424
 
346
- MIT, copyright Cosyte LLC. See [LICENSE](https://github.com/cosyte/synth/blob/main/LICENSE).
425
+ MIT, copyright Cosyte LLC. See [LICENSE](https://github.com/cosyte/synth/blob/main/LICENSE). The
426
+ standards this package names belong to their owners; see
427
+ [TRADEMARKS.md](https://github.com/cosyte/synth/blob/main/TRADEMARKS.md).
@@ -1,5 +1,5 @@
1
- import { S as SyntheticName, R as Rng, C as Corpus } from '../providers-DcPrqmp5.cjs';
2
- import { Q as QuirkDescriptor, S as SynthProfile, a as QuirkArtifact, b as QuirkRoundTripResult } from '../quirk-CilFUhwX.cjs';
1
+ import { SyntheticName, Rng, Corpus } from '../index.cjs';
2
+ import { QuirkDescriptor, SynthProfile, QuirkArtifact, QuirkRoundTripResult } from '../index.cjs';
3
3
 
4
4
  /**
5
5
  * Spec-clean ASTM (E1394 / CLSI LIS02) message generation: the `H`/`P`/`O`/`R`/`C`/`L` record report,
@@ -415,4 +415,5 @@ interface AstmCorpusOptions {
415
415
  */
416
416
  declare function astmCorpus(options: AstmCorpusOptions): Corpus;
417
417
 
418
- export { ASTM_ABNORMAL_FLAGS, ASTM_COMMENT_TEXT, ASTM_QUIRKS, ASTM_RESULT_STATUSES, type AstmCorpusKind, type AstmCorpusOptions, type AstmExampleTest, type AstmHeaderIdentity, type AstmOrder, type AstmPatient, type AstmQuirkCorpusOptions, type AstmQuirkKind, type AstmQuirkName, type AstmRoundTripResult, EXAMPLE_ASTM_TESTS, type GenerateAstmOptions, type GenerateAstmQuirkOptions, astmCorpus, astmFramedRoundTrip, astmHeaderIdentity, astmOrder, astmPatient, astmQuirkCorpus, astmQuirkProfile, astmQuirkRoundTrip, astmRoundTrip, generateAstmOrder, generateAstmQuirk, generateAstmResult, generateAstmResultFramed };
418
+ export { ASTM_ABNORMAL_FLAGS, ASTM_COMMENT_TEXT, ASTM_QUIRKS, ASTM_RESULT_STATUSES, EXAMPLE_ASTM_TESTS, astmCorpus, astmFramedRoundTrip, astmHeaderIdentity, astmOrder, astmPatient, astmQuirkCorpus, astmQuirkProfile, astmQuirkRoundTrip, astmRoundTrip, generateAstmOrder, generateAstmQuirk, generateAstmResult, generateAstmResultFramed };
419
+ export type { AstmCorpusKind, AstmCorpusOptions, AstmExampleTest, AstmHeaderIdentity, AstmOrder, AstmPatient, AstmQuirkCorpusOptions, AstmQuirkKind, AstmQuirkName, AstmRoundTripResult, GenerateAstmOptions, GenerateAstmQuirkOptions };
@@ -1,5 +1,5 @@
1
- import { S as SyntheticName, R as Rng, C as Corpus } from '../providers-DcPrqmp5.js';
2
- import { Q as QuirkDescriptor, S as SynthProfile, a as QuirkArtifact, b as QuirkRoundTripResult } from '../quirk-DmqYw3Vk.js';
1
+ import { SyntheticName, Rng, Corpus } from '../index.js';
2
+ import { QuirkDescriptor, SynthProfile, QuirkArtifact, QuirkRoundTripResult } from '../index.js';
3
3
 
4
4
  /**
5
5
  * Spec-clean ASTM (E1394 / CLSI LIS02) message generation: the `H`/`P`/`O`/`R`/`C`/`L` record report,
@@ -415,4 +415,5 @@ interface AstmCorpusOptions {
415
415
  */
416
416
  declare function astmCorpus(options: AstmCorpusOptions): Corpus;
417
417
 
418
- export { ASTM_ABNORMAL_FLAGS, ASTM_COMMENT_TEXT, ASTM_QUIRKS, ASTM_RESULT_STATUSES, type AstmCorpusKind, type AstmCorpusOptions, type AstmExampleTest, type AstmHeaderIdentity, type AstmOrder, type AstmPatient, type AstmQuirkCorpusOptions, type AstmQuirkKind, type AstmQuirkName, type AstmRoundTripResult, EXAMPLE_ASTM_TESTS, type GenerateAstmOptions, type GenerateAstmQuirkOptions, astmCorpus, astmFramedRoundTrip, astmHeaderIdentity, astmOrder, astmPatient, astmQuirkCorpus, astmQuirkProfile, astmQuirkRoundTrip, astmRoundTrip, generateAstmOrder, generateAstmQuirk, generateAstmResult, generateAstmResultFramed };
418
+ export { ASTM_ABNORMAL_FLAGS, ASTM_COMMENT_TEXT, ASTM_QUIRKS, ASTM_RESULT_STATUSES, EXAMPLE_ASTM_TESTS, astmCorpus, astmFramedRoundTrip, astmHeaderIdentity, astmOrder, astmPatient, astmQuirkCorpus, astmQuirkProfile, astmQuirkRoundTrip, astmRoundTrip, generateAstmOrder, generateAstmQuirk, generateAstmResult, generateAstmResultFramed };
419
+ export type { AstmCorpusKind, AstmCorpusOptions, AstmExampleTest, AstmHeaderIdentity, AstmOrder, AstmPatient, AstmQuirkCorpusOptions, AstmQuirkKind, AstmQuirkName, AstmRoundTripResult, GenerateAstmOptions, GenerateAstmQuirkOptions };