@cosyte/synth 0.1.0 → 0.1.2

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +31 -2
  2. package/LICENSE +1 -1
  3. package/README.md +26 -25
  4. package/dist/astm/index.cjs.map +1 -1
  5. package/dist/astm/index.d.cts +6 -6
  6. package/dist/astm/index.d.ts +6 -6
  7. package/dist/astm/index.mjs.map +1 -1
  8. package/dist/ccda/index.cjs.map +1 -1
  9. package/dist/ccda/index.d.cts +2 -2
  10. package/dist/ccda/index.d.ts +2 -2
  11. package/dist/ccda/index.mjs.map +1 -1
  12. package/dist/deid/index.cjs.map +1 -1
  13. package/dist/deid/index.d.cts +3 -3
  14. package/dist/deid/index.d.ts +3 -3
  15. package/dist/deid/index.mjs.map +1 -1
  16. package/dist/fhir/index.cjs.map +1 -1
  17. package/dist/fhir/index.d.cts +1 -1
  18. package/dist/fhir/index.d.ts +1 -1
  19. package/dist/fhir/index.mjs.map +1 -1
  20. package/dist/hl7/index.cjs.map +1 -1
  21. package/dist/hl7/index.d.cts +3 -3
  22. package/dist/hl7/index.d.ts +3 -3
  23. package/dist/hl7/index.mjs.map +1 -1
  24. package/dist/index.cjs +1 -1
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +5 -5
  27. package/dist/index.d.ts +5 -5
  28. package/dist/index.mjs +1 -1
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/ncpdp/index.cjs.map +1 -1
  31. package/dist/ncpdp/index.d.cts +2 -2
  32. package/dist/ncpdp/index.d.ts +2 -2
  33. package/dist/ncpdp/index.mjs.map +1 -1
  34. package/dist/{providers-BQtPk3PN.d.cts → providers-DcPrqmp5.d.cts} +2 -2
  35. package/dist/{providers-BQtPk3PN.d.ts → providers-DcPrqmp5.d.ts} +2 -2
  36. package/dist/{quirk-C_lZrspq.d.cts → quirk-CilFUhwX.d.cts} +1 -1
  37. package/dist/{quirk-Bzx9g8KG.d.ts → quirk-DmqYw3Vk.d.ts} +1 -1
  38. package/dist/x12/index.cjs.map +1 -1
  39. package/dist/x12/index.d.cts +3 -3
  40. package/dist/x12/index.d.ts +3 -3
  41. package/dist/x12/index.mjs.map +1 -1
  42. package/package.json +41 -51
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - be69f2d: Generated C-CDA documents change: the parser peers are bounded to their 0.1 releases, and `@cosyte/ccda` 0.1 builds each CCD and Referral Note differently for the same seed.
8
+
9
+ Output change: every C-CDA document, for every seed, is now built by `@cosyte/ccda` 0.1, whose builder writes more of what C-CDA R2.1 asks for. Against the same seed on the previous release:
10
+ - the patient gains `raceCode` and `ethnicGroupCode` with `nullFlavor="UNK"`;
11
+ - the author gains a `representedOrganization`;
12
+ - a CCD gains a `documentationOf` service event, and a Referral Note an `informationRecipient`, each with unknown values;
13
+ - problem and allergy concern acts gain the `CONC` code;
14
+ - allergy reaction observations gain an `id`, which shifts the generated ids after them;
15
+ - the Medications section's templateIds move to the 2014-06-09 extension;
16
+ - the vital signs organizer is coded with LOINC 74728-7 instead of SNOMED CT 46680005;
17
+ - immunizations carry `negationInd="false"`;
18
+ - results organizers carry an `effectiveTime` interval with an unknown end;
19
+ - the Social History section moves earlier in the document.
20
+ A C-CDA golden file committed from an earlier release no longer matches and has to be regenerated. Every value stays synthetic. HL7 v2, FHIR R4 and US Core, X12, NCPDP, and ASTM documents are byte-identical for the seeds the determinism baseline records, and their committed golden files still match.
21
+
22
+ Peer ranges: `@cosyte/hl7`, `@cosyte/fhir`, `@cosyte/ccda`, `@cosyte/x12`, `@cosyte/ncpdp`, `@cosyte/astm` and `@cosyte/deid` move from `>=0.0.0` (or `>=0.0.1`) to `^0.1.0`, the releases this package is tested against. A project that pins one of them to a 0.0.x release has to move it to 0.1 to install this version.
23
+
24
+ ## 0.1.1
25
+
26
+ ### Patch Changes
27
+
28
+ - 5dcf91e: Doc comments that ship in the type declarations now write a range with "to" instead of an en dash, for example "the `0` to `7` frame number" and "a seeded 1 to 4".
29
+
30
+ No generated value, export, warning code or seed mapping changes. The README and the documentation pages get the same edit, and the repository's dash check now refuses the en dash, literal or encoded, as it already refused the em dash.
31
+
3
32
  ## 0.1.0
4
33
 
5
34
  ### Minor Changes
@@ -164,7 +193,7 @@
164
193
  to write it in the changeset. No runtime code, no public API, no warning code, no generated byte and
165
194
  no synthetic-safety behaviour changed.
166
195
 
167
- - da7cbdb: The package description, the README, the documentation pages and the exported quirk-registry prose no longer use the em dash, matching the cosyte house voice.
196
+ - da7cbdb: The package description, the README, the documentation pages and the exported quirk-registry prose no longer use the em dash, matching the Cosyte house voice.
168
197
 
169
198
  **Nothing about generation changed.** No export was added, removed or renamed, no warning or fatal
170
199
  code moved, and a given seed still produces byte-identical output for every format. The rewrite is
@@ -681,7 +710,7 @@ changesets that release consumed. This package is on the pre-alpha `0.0.x` ladde
681
710
  used to quote were quirk names, format labels, code-system URIs and money strings. What was wrong
682
711
  was the _shape_: every fatal took a value parameter, and the only thing keeping PHI out of a
683
712
  diagnostic was that callers happened to be passing harmless values. The audit of the thirteen
684
- cosyte repos found that the single property separating the packages that leak from the ones that
713
+ Cosyte repos found that the single property separating the packages that leak from the ones that
685
714
  are genuinely prevented is exactly this: whether the message factory takes a value parameter at
686
715
  all. It now does not.
687
716
 
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Cosyte
3
+ Copyright (c) 2026 Cosyte LLC
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,28 +1,27 @@
1
1
  <a href="https://cosyte.com">
2
2
  <picture>
3
3
  <source media="(prefers-color-scheme: dark)" srcset="https://cosyte.com/tile/cosyte-lockup-tile-on-dark-1200x300.png">
4
- <img alt="Cosyte: a plus mark set in two overlapping rounded squares, one solid and one outlined, beside the Cosyte wordmark" src="https://cosyte.com/tile/cosyte-lockup-tile-on-light-1200x300.png">
4
+ <img alt="The Cosyte logo on its own white ground: the icon beside the word Cosyte." src="https://cosyte.com/tile/cosyte-lockup-tile-on-light-1200x300.png">
5
5
  </picture>
6
6
  </a>
7
7
 
8
8
  # @cosyte/synth
9
9
 
10
- > Deterministic, seedable **synthetic healthcare-fixture generator** for Node.js and TypeScript:
11
- > spec-clean by construction, and **never real PHI**.
10
+ > Seeded, reproducible **synthetic healthcare fixtures** for Node.js and TypeScript: spec-clean, never real PHI.
12
11
 
13
- `@cosyte/synth` generates reproducible synthetic test corpora across the six cosyte formats (HL7 v2,
12
+ `@cosyte/synth` generates reproducible synthetic test corpora across the six Cosyte formats (HL7 v2,
14
13
  FHIR R4 / US Core, C-CDA, X12, NCPDP, and ASTM). It is a **consumer** of the
15
- cosyte parsers, not a parser: it builds each artifact **through the parser's own builder/serializer**
16
- (so the output is spec-clean by the same mechanism the parser proves) and draws every identifier, name,
14
+ Cosyte parsers, not a parser: it builds each artifact **through the parser's own builder/serializer**
15
+ (so each artifact re-parses through that parser with zero warnings) and draws every identifier, name,
17
16
  date, phone, and address from a **guaranteed-non-colliding synthetic source**. It is a
18
17
  **format/conformance generator, not a clinical simulator**: it does not model disease progression
19
18
  (that is Synthea).
20
19
 
21
- > **Status:** `0.1`, published to npm. The version shown on the npm package page is the one that is
22
- > live; this page never repeats it. Below 1.0, a breaking change raises the minor version and the
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
23
22
  > changelog says what broke. The generator is **feature-complete**: the
24
- > seeded-PRNG core, the synthetic-safety providers, and the round-trip harness; **spec-clean generation
25
- > across all six formats**, HL7 v2 (`ADT`/`ORU`/`ORM`/`SIU`/`VXU`), FHIR R4 / US Core (the full clinical
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
26
25
  > set + `collection`/`transaction`/`document` Bundles), C-CDA R2.1 (CCD + Referral Note), X12 005010
27
26
  > (837P/I/D, 835, 271), NCPDP (SCRIPT NewRx / RxRenewal / RxChange + Telecom B1/B2/B3), and ASTM (E1394
28
27
  > record reports + E1381 framing), each built **through its parser's own builder/serializer**; **vendor-quirk
@@ -42,6 +41,8 @@ date, phone, and address from a **guaranteed-non-colliding synthetic source**. I
42
41
  npm install @cosyte/synth @cosyte/hl7 @cosyte/fhir @cosyte/ccda @cosyte/x12 @cosyte/ncpdp @cosyte/astm
43
42
  ```
44
43
 
44
+ Node.js 22 or later, tested on 22 and 24.
45
+
45
46
  `@cosyte/hl7`, `@cosyte/fhir`, `@cosyte/ccda`, `@cosyte/x12`, `@cosyte/ncpdp`, `@cosyte/astm`, and
46
47
  `@cosyte/deid` are **optional peer dependencies**, each needed only for its subpath (`@cosyte/synth/hl7`,
47
48
  `@cosyte/synth/fhir`, `@cosyte/synth/ccda`, `@cosyte/synth/x12`, `@cosyte/synth/ncpdp`,
@@ -136,7 +137,7 @@ corpus.artifacts.every((a) => a.warnings.length === 0); // true, all spec-clean
136
137
 
137
138
  `@cosyte/ccda` is an **optional peer dependency**, needed only for the `@cosyte/synth/ccda` subpath.
138
139
 
139
- ## Generate a spec-clean X12 transaction
140
+ ## Generate an X12 transaction
140
141
 
141
142
  The `@cosyte/synth/x12` subpath builds HIPAA **005010** transactions **through `@cosyte/x12`'s domain
142
143
  builders** (`build837P/I/D`, `build835`, `build271`), so the ISA/GS/ST…SE/GE/IEA envelope, the
@@ -159,15 +160,15 @@ roundTrip(generate271({ seed: 3 })).specClean; // true
159
160
 
160
161
  // Or a reproducible mixed corpus (837P/I/D + 835 + 271):
161
162
  const corpus = x12Corpus({ seed: 42 });
162
- corpus.artifacts.every((a) => a.warnings.length === 0); // true, all spec-clean
163
+ corpus.artifacts.every((a) => a.warnings.length === 0); // true
163
164
  ```
164
165
 
165
166
  `@cosyte/x12` is an **optional peer dependency**, needed only for the `@cosyte/synth/x12` subpath.
166
167
 
167
- **Deferred:** the **270** eligibility _request_ (`@cosyte/x12` ships a `build271` but no `build270`, and
168
- `synth` never hand-writes bytes around a missing builder) and **vendor-quirk mode**.
168
+ **Deferred:** the **270** eligibility _request_ (`@cosyte/x12` ships `build270` on its 0.1 line, but `synth`
169
+ does not generate a 270 yet) and **vendor-quirk mode**.
169
170
 
170
- ## Generate a spec-clean NCPDP message
171
+ ## Generate an NCPDP message
171
172
 
172
173
  The `@cosyte/synth/ncpdp` subpath builds both NCPDP standards **through `@cosyte/ncpdp`'s own emit
173
174
  surface**, so each message round-trips through the parser with **zero warnings**. It emits **SCRIPT**
@@ -193,7 +194,7 @@ telecomRoundTrip(generateB1({ seed: 777 })).specClean; // true
193
194
 
194
195
  // Or a reproducible mixed corpus (NewRx + RxRenewal + RxChange + B1 + B2 + B3):
195
196
  const corpus = ncpdpCorpus({ seed: 42 });
196
- corpus.artifacts.every((a) => a.warnings.length === 0); // true, all spec-clean
197
+ corpus.artifacts.every((a) => a.warnings.length === 0); // true
197
198
  ```
198
199
 
199
200
  `@cosyte/ncpdp` is an **optional peer dependency**, needed only for the `@cosyte/synth/ncpdp` subpath.
@@ -201,7 +202,7 @@ corpus.artifacts.every((a) => a.warnings.length === 0); // true, all spec-clean
201
202
  **Deferred:** vendor-quirk mode. SCRIPT coverage tracks the parser's builder surface: the
202
203
  renewal/change _responses_ land as `@cosyte/ncpdp` grows builders.
203
204
 
204
- ## Generate a spec-clean ASTM message
205
+ ## Generate an ASTM message
205
206
 
206
207
  The `@cosyte/synth/astm` subpath builds ASTM laboratory messages **through `@cosyte/astm`'s own emit
207
208
  surface**: `buildAstmMessage` for the E1394 record layer, `composeAstmFrames` for the E1381 frame
@@ -224,12 +225,12 @@ import {
224
225
  // (so they stay DISTINCT, exactly as @cosyte/astm keeps them on parse).
225
226
  astmRoundTrip(generateAstmResult({ seed: 12345 })).specClean; // true, zero warnings, byte-stable
226
227
 
227
- // The E1381-framed twin: the modulo-256 checksum and 0–7 frame numbers are computed by @cosyte/astm.
228
+ // The E1381-framed twin: the modulo-256 checksum and 0 to 7 frame numbers are computed by @cosyte/astm.
228
229
  astmFramedRoundTrip(generateAstmResultFramed({ seed: 12345 })).specClean; // true
229
230
 
230
231
  // Or a reproducible mixed corpus (a result report + an order):
231
232
  const corpus = astmCorpus({ seed: 42 });
232
- corpus.artifacts.every((a) => a.warnings.length === 0); // true, all spec-clean
233
+ corpus.artifacts.every((a) => a.warnings.length === 0); // true
233
234
  ```
234
235
 
235
236
  `@cosyte/astm` is an **optional peer dependency**, needed only for the `@cosyte/synth/astm` subpath.
@@ -265,7 +266,7 @@ astmQuirkRoundTrip(generateAstmQuirk({ seed: 1, quirk: "unknown-escape" })).inte
265
266
  A quirk a format's profile system does not support fails closed with a stable `SYNTH_UNSUPPORTED_QUIRK`
266
267
  diagnostic, never a silently-wrong fixture, and so do the other selectors: a message kind, a
267
268
  document type, a corpus mix entry, an `837` variant, a Bundle type. Each is checked against its own set
268
- before anything is generated, so an unrecognised one is a fatal `SYNTH_UNSUPPORTED_KIND` rather than a
269
+ before anything is generated, so an unrecognized one is a fatal `SYNTH_UNSUPPORTED_KIND` rather than a
269
270
  mislabelled corpus. Every refusal carries a code and a fixed message from a frozen table, and quotes
270
271
  nothing you passed. Every quirk is grounded in a **publicly-documented** deviation or a parser's
271
272
  **public** profile, never a private vendor corpus.
@@ -276,7 +277,7 @@ vendor-attributed corpus** to ground.
276
277
  ## Co-validate with `@cosyte/deid` (the pairing loop)
277
278
 
278
279
  The `@cosyte/synth/deid` subpath is a deterministic **closed-loop co-validation harness** for the
279
- `synth` ⇄ `deid` pair: it **generates** a spec-clean artifact, **plants** distinctive synthetic PHI
280
+ `synth` ⇄ `deid` pair: it **generates** an artifact, **plants** distinctive synthetic PHI
280
281
  sentinels at the patient loci, **de-identifies** it through `@cosyte/deid`, and **verifies** every
281
282
  sentinel is gone from the output (a surviving sentinel is a hard failure) while the clinical payload
282
283
  survives (the over-scrub guard).
@@ -332,14 +333,14 @@ isSyntheticNpi(safe.npi(rng)); // true, always a deliberately-invalid-Luhn NPI (
332
333
  phones, RFC 2606/6761 `example.*` domains, RFC 5737/3849 TEST-NET IPs, a synthetic assigning
333
334
  authority for MRNs). A CI gate proves it.
334
335
  **No generated value can be real or plausibly-real PHI.**
335
- - **Spec-clean by the parser's own judgment**, built through the parser's conservative serializer, and
336
- checked by feeding the artifact straight back in: a spec-clean artifact re-parses with zero warnings.
336
+ - **Checked by the parser's own judgment**, built through the parser's conservative serializer and
337
+ fed straight back in: each artifact re-parses with zero warnings.
337
338
  - **Deterministic**, a hand-rolled seeded PRNG (`sfc32`/`splitmix32`); `Math.random` is lint-banned.
338
339
  A seed, and only the seed, determines the output, byte-for-byte, anywhere.
339
340
  - **Immutable**, generated artifacts and the `Corpus` result are deep-frozen.
340
- - **Zero third-party runtime dependencies**, the parser peers are first-party cosyte packages,
341
+ - **Zero third-party runtime dependencies**, the parser peers are first-party Cosyte packages,
341
342
  vendored for dev/test; dual ESM + CJS, validated with `attw`.
342
343
 
343
344
  ## License
344
345
 
345
- MIT © Cosyte
346
+ MIT, copyright Cosyte LLC. See [LICENSE](https://github.com/cosyte/synth/blob/main/LICENSE).