Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/quickstart-page-matches-readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cosyte/synth": patch
---

The Quickstart page now opens with the same program as the README: an HL7 v2 message generated from a seed and round-tripped through `@cosyte/hl7`, plus a mixed corpus.

Before this, the page opened with the seeded value providers while the README opened with the HL7 v2 generators, so a reader arriving from npm and one arriving from the documentation site met two different first programs. The value-provider, round-trip, corpus and determinism examples follow it. The test suite now fails if the page's first program differs from the README's quickstart, and runs it against the built package. Documentation and test change only.
36 changes: 33 additions & 3 deletions docs-content/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,36 @@ sidebar_position: 1
Generate reproducible, synthetic-by-construction fixtures in a few lines. A **seed** determines the
output entirely, so a fixture set regenerates identically anywhere.

## Generate a spec-clean HL7 v2 message

This is the program the README opens with. The `@cosyte/synth/hl7` subpath builds each message
**through `@cosyte/hl7`'s own `buildMessage`**, so it is spec-clean by construction, and `roundTrip`
feeds it straight back to the parser. `@cosyte/hl7` is the optional peer this subpath needs; see
[Installation](./installation.md):

```ts runnable
import { generateAdt, generateOru, generateHl7, hl7Corpus, roundTrip } from "@cosyte/synth/hl7";

// Same seed → byte-identical message, on any machine, any run.
const adt = generateAdt({ seed: 12345, trigger: "A01" });
const oru = generateOru({ seed: 12345 });

// Spec-clean by construction: it round-trips through @cosyte/hl7 with zero warnings.
console.log(roundTrip(adt).specClean); // true
console.log(roundTrip(oru).specClean); // true

// Or generate a reproducible mixed corpus across every family:
const corpus = hl7Corpus({ seed: 42, count: 7 }); // one of each family, cycled
console.log(corpus.artifacts.every((a) => a.warnings.length === 0)); // true, all spec-clean

// Dispatch by kind when the message type is data:
console.log(roundTrip(generateHl7("VXU^V04", 12345)).content.split("\r")[0]); // its MSH segment
```

The first three lines print `true`, and the last prints the `MSH` segment of a generated `VXU^V04`.
Every identifier, name and date in these messages is drawn from a reserved range or the shipped
fake-name pool.

## Draw a synthetic value

The `safe` providers each draw from a reserved, never-collide source. Everything is a pure function of
Expand All @@ -24,10 +54,10 @@ const nationalId = safe.ssn(rng);
isSyntheticSsn(nationalId); // => true
```

## Generate an HL7 v2 message
## Check the round trip yourself

The `@cosyte/synth/hl7` subpath builds messages **through `@cosyte/hl7`**, so they are spec-clean by
construction and round-trip with zero warnings:
`roundTrip` returns more than the verdict: the warnings the parser raised on the way back, which for
a spec-clean artifact is none at all:

```ts runnable
import { generateAdt, roundTrip } from "@cosyte/synth/hl7";
Expand Down
25 changes: 23 additions & 2 deletions test/docs-content.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { execFileSync } from "node:child_process";
import { readFileSync } from "node:fs";
import { join } from "node:path";

import { beforeAll } from "vitest";
import { beforeAll, describe, expect, it } from "vitest";

import { docSnippetSuite } from "@cosyte/vitest-config/snippets";
import { docSnippetSuite, extractRunnableSnippets } from "@cosyte/vitest-config/snippets";

/**
* Doc/code-agreement gate. Every ```` ```ts runnable ```` block in `docs-content/` is extracted,
Expand Down Expand Up @@ -44,3 +45,23 @@ docSnippetSuite({
return undefined;
},
});

/**
* The README's quickstart (the first TypeScript block after `## Install`) is what a reader runs from
* npm, and the Quickstart page is what the same reader runs from the docs site. Two first programs
* that disagree send a reader two ways at once, so the page must open with the README's program,
* byte for byte, and the sweep above is what executes it.
*/
describe("the Quickstart page opens with the README's quickstart program", () => {
it("carries the README's first TypeScript block after ## Install as its first runnable block", () => {
const readme = readFileSync(join(root, "README.md"), "utf8");
const afterInstall = readme.slice(readme.indexOf("\n## Install\n"));
const readmeFirst = /\n```ts\n([\s\S]*?)\n```\n/.exec(afterInstall)?.[1];
const quickstart = readFileSync(join(root, "docs-content", "quickstart.md"), "utf8");
const pageFirst = extractRunnableSnippets(quickstart)[0]?.code;

expect(readme.includes("\n## Install\n")).toBe(true);
expect(readmeFirst).toBeDefined();
expect(pageFirst).toBe(readmeFirst);
});
});
Loading