src/astm
@cosyte/synth/astm: the ASTM generation surface, exposed as its own subpath so importing the
package root does not pull @cosyte/astm. This is the lazy, per-format boundary: a consumer
who only needs ASTM fixtures imports @cosyte/synth/astm; one who needs only the core primitives
never loads a parser.
@cosyte/astm is an optional peer dependency, present only for this subpath.
This subpath ships spec-clean generation of the E1394 record report and its E1381 framed twin, each
built through @cosyte/astm's own emit surface:
- Records (E1394):
generateAstmResult(H/P/O/R…/C/L) andgenerateAstmOrder(H/P/O/L) viabuildAstmMessage, each round-tripping throughparseAstmRecordswith zero warnings and byte-stable, and carrying aPrecord whose name / DOB / practice+lab IDs are all synthetic-by-construction. The practice- and laboratory-assigned patient IDs are minted independently, so they stay distinct. - Framing (E1381):
generateAstmResultFramedviacomposeAstmFrames, the modulo-256 checksum and the0to7frame number are computed by the parser, never faked, and the bytes round-trip throughparseFramedAstmwith zero frame and record warnings.
Interfaces
AstmCorpusOptions
Options for astmCorpus.
Properties
count?
readonlyoptionalcount?:number
How many messages to generate. Defaults to the length of the mix.
mix?
readonlyoptionalmix?: readonlyAstmCorpusKind[]
The message kinds to cycle through. Defaults to one of each.
seed
readonlyseed:number
The seed for the whole corpus (deterministic).
AstmExampleTest
One example laboratory analyte: its codes, units, reference range, and a seeded value window.
Properties
decimals
readonlydecimals:number
Number of decimal places to render the synthetic value with.
localCode
readonlylocalCode:string
A local analyzer test code (invented, never a real vendor assay id).
loinc
readonlyloinc:string
The public LOINC identifier for the analyte (a fact, not bundled terminology prose).
name
readonlyname:string
The human-readable test name, emitted in the Universal Test ID name component.
referenceRange
readonlyreferenceRange:string
The reference range text, emitted verbatim in R-field 6.
units
readonlyunits:string
The units string, emitted verbatim in R-field 5 (never converted or guessed).
valueHigh
readonlyvalueHigh:number
Inclusive integer high bound of the seeded synthetic value.
valueLow
readonlyvalueLow:number
Inclusive integer low bound of the seeded synthetic value (structural, not clinical).
AstmHeaderIdentity
A synthetic ASTM header identity: the sender and analyzer strings for the H record.
Properties
analyzer
readonlyanalyzer:string
The analyzer / instrument string (clearly synthetic).
sender
readonlysender:string
The sending system id (clearly synthetic).
AstmOrder
A synthetic ASTM order identity: the specimen / accession id and priority.
Properties
priority
readonlypriority:"R"|"S"
Priority code, emitted verbatim (R routine, S stat).
specimenId
readonlyspecimenId:string
Specimen / accession id: synthetic-AA scoped (ACC-prefixed).
AstmPatient
A synthetic ASTM patient: every field drawn from ../safe.
Properties
birthDate
readonlybirthDate:string
Birthdate YYYYMMDD, from the seeded generator (no real event implied).
laboratoryAssignedId
readonlylaboratoryAssignedId:string
Laboratory-assigned patient ID, synthetic-AA scoped (LAB-prefixed). Distinct from the practice ID.
middle
readonlymiddle:string
Middle initial (clearly synthetic).
person
readonlyperson:SyntheticName
Name from the shipped fake-name pool, plus a fictional middle initial.
practiceAssignedId
readonlypracticeAssignedId:string
Practice-assigned patient ID, synthetic-AA scoped (PRA-prefixed). Distinct from the lab ID.
sex
readonlysex:"M"|"F"
Sex code, emitted verbatim (M / F, structural, never defaulted by the builder).
AstmQuirkCorpusOptions
Options for astmQuirkCorpus.
Properties
count?
readonlyoptionalcount?:number
How many quirk artifacts to generate. Defaults to the number of quirks.
profile?
readonlyoptionalprofile?:SynthProfile
A SynthProfile whose quirks drive the corpus (validated). Takes precedence over quirks.
quirks?
readonlyoptionalquirks?: readonlyAstmQuirkName[]
The quirk names to cycle through. Defaults to every ASTM quirk. Validated; unsupported ⇒ fatal.
seed
readonlyseed:number
The seed for the whole corpus (deterministic).
AstmRoundTripResult
The verdict of one round-trip through @cosyte/astm.
Properties
byteStable
readonlybyteStable:boolean
Whether re-serializing the re-parsed message is byte-identical to the input.
content
readonlycontent:string
The serialized ASTM wire text (records: the CR-terminated stream; framed: the raw bytes as latin1).
specClean
readonlyspecClean:boolean
true iff the artifact is spec-clean: zero warnings and byte-stable.
warnings
readonlywarnings: readonlystring[]
The warning codes the parser emitted on re-parse (record + frame layers). Empty ⇒ spec-clean.
GenerateAstmOptions
Options for the ASTM message generators.
Properties
comment?
readonlyoptionalcomment?:boolean
Whether to append a C (comment) record after the results. Defaults to true.
resultCount?
readonlyoptionalresultCount?:number
How many R (result) records to emit. Defaults to a seeded 1 to 4.
seed
readonlyseed:number
The seed (deterministic: same seed yields a byte-identical message).
GenerateAstmQuirkOptions
Options for generateAstmQuirk.
Properties
kind?
readonlyoptionalkind?:"Result"
The spec-clean base report kind. Always "Result" (see AstmQuirkKind).
quirk
readonlyquirk:AstmQuirkName
The quirk to inject. Required.
seed?
readonlyoptionalseed?:number
The seed: the same seed + quirk yields a byte-identical record stream. Defaults to 0.
Type Aliases
AstmCorpusKind
AstmCorpusKind =
"Result"|"Order"
Every ASTM message kind astmCorpus generates: the label used as the corpus kind.
AstmQuirkKind
AstmQuirkKind =
"Result"
Both shipped ASTM quirks are result-report deviations: unknown-escape targets an R record's
units field and unknown-record-type a C (comment) record, neither of which an order report
carries. So the quirk base is always a result report (generateAstmResult).
AstmQuirkName
AstmQuirkName =
"unknown-escape"|"unknown-record-type"
Every ASTM quirk this package ships.
Variables
ASTM_ABNORMAL_FLAGS
constASTM_ABNORMAL_FLAGS: readonlystring[]
HL7 Table 0078 abnormal-flag codes synth draws from (emitted verbatim; never defaulted).
ASTM_COMMENT_TEXT
constASTM_COMMENT_TEXT: readonlystring[]
Free-text result comments: clearly synthetic, carry no PHI.
ASTM_QUIRKS
constASTM_QUIRKS:Readonly<Record<AstmQuirkName,QuirkDescriptor>>
The ASTM quirk registry: each recipe bound to the exact @cosyte/astm warning code it targets.
ASTM_RESULT_STATUSES
constASTM_RESULT_STATUSES: readonlystring[]
Result-status codes synth draws from (F final, P preliminary, C correction).
astmQuirkProfile
constastmQuirkProfile:SynthProfile
A ready-made SynthProfile requesting every built-in ASTM quirk.
EXAMPLE_ASTM_TESTS
constEXAMPLE_ASTM_TESTS: readonlyAstmExampleTest[]
The example test pool. A handful of common chemistry/hematology analytes, each with a public LOINC code, invented local code, units, and a value window the seeded generator samples. Frozen: the pool is shared, immutable data.
Example
import { EXAMPLE_ASTM_TESTS } from "@cosyte/synth/astm";
EXAMPLE_ASTM_TESTS[0]?.name; // "Glucose"
Functions
astmCorpus()
astmCorpus(
options):Corpus
Build a reproducible Corpus of spec-clean ASTM messages. Each message is generated from a
distinct sub-seed derived from the corpus seed (so the set is deterministic) and round-tripped through
@cosyte/astm; the per-artifact warnings record the parser's verdict (empty ⇒ spec-clean).
Parameters
options
Seed, count, and the message mix. See AstmCorpusOptions.
Returns
A deep-frozen Corpus.
Example
import { astmCorpus } from "@cosyte/synth/astm";
const corpus = astmCorpus({ seed: 42 });
corpus.artifacts.every((a) => a.warnings.length === 0); // true, spec-clean
astmFramedRoundTrip()
astmFramedRoundTrip(
bytes):AstmRoundTripResult
Round-trip a generated framed ASTM byte stream (E1381) through decode+parse → re-frame and report the verdict. A spec-clean framed message re-parses with zero record and zero frame warnings (every modulo-256 checksum verifies, no sequence gap, no unterminated/oversize frame) and re-frames byte-identically.
Parameters
bytes
Uint8Array
The framed byte stream (typically from generateAstmResultFramed).
Returns
The AstmRoundTripResult: content holds the framed bytes decoded as latin1.
Example
import { generateAstmResultFramed, astmFramedRoundTrip } from "@cosyte/synth/astm";
const { specClean } = astmFramedRoundTrip(generateAstmResultFramed({ seed: 1 })); // true
astmHeaderIdentity()
astmHeaderIdentity(
rng):AstmHeaderIdentity
Mint a synthetic header identity for the H record: a clearly-synthetic sender and analyzer.
Parameters
rng
The seeded generator.
Returns
A synthetic AstmHeaderIdentity.
Example
import { createRng } from "@cosyte/synth";
import { astmHeaderIdentity } from "@cosyte/synth/astm";
const { sender } = astmHeaderIdentity(createRng(1));
astmOrder()
astmOrder(
rng):AstmOrder
Mint a synthetic order identity for an O record: a synthetic-AA-scoped accession id and a priority.
Parameters
rng
The seeded generator.
Returns
A synthetic AstmOrder.
Example
import { createRng } from "@cosyte/synth";
import { astmOrder } from "@cosyte/synth/astm";
const { specimenId } = astmOrder(createRng(1));
astmPatient()
astmPatient(
rng):AstmPatient
Mint a synthetic patient for a P record. Fixed draw order (name → middle → DOB → sex → practice id
→ lab id) so the same seed yields the same patient. The two patient IDs are minted from
independent synthetic-identifier draws, so they are distinct by construction.
Parameters
rng
The seeded generator.
Returns
A synthetic AstmPatient.
Example
import { createRng } from "@cosyte/synth";
import { astmPatient } from "@cosyte/synth/astm";
const { person, practiceAssignedId, laboratoryAssignedId } = astmPatient(createRng(1));
astmQuirkCorpus()
astmQuirkCorpus(
options):Corpus
Build a reproducible Corpus of ASTM quirk artifacts. Each artifact's warnings record the
intended code for its quirk; the manifest lists the applied quirk names.
Parameters
options
Seed, count, and the quirk selection. See AstmQuirkCorpusOptions.
Returns
A deep-frozen Corpus.
Example
import { astmQuirkCorpus } from "@cosyte/synth/astm";
astmQuirkCorpus({ seed: 42 }).manifest.quirks; // the applied quirk names
astmQuirkRoundTrip()
astmQuirkRoundTrip(
artifact):QuirkRoundTripResult
Round-trip an ASTM quirk artifact through @cosyte/astm and report the intended-warning verdict: a bare
parse must produce exactly the intended code, and, when a built-in public
profile tolerates the quirk, the profiled parse must re-badge it to PROFILE_QUIRK_APPLIED.
Parameters
artifact
The quirk artifact (from generateAstmQuirk).
Returns
The QuirkRoundTripResult.
Example
import { generateAstmQuirk, astmQuirkRoundTrip } from "@cosyte/synth/astm";
astmQuirkRoundTrip(generateAstmQuirk({ seed: 1, quirk: "unknown-escape" })).intendedWarningHeld;
astmRoundTrip()
astmRoundTrip(
raw):AstmRoundTripResult
Round-trip a generated ASTM record stream through parse → serialize and report the verdict. A spec-clean message re-parses with zero warnings and re-serializes byte-identically.
Parameters
raw
string
The ASTM record stream (typically from generateAstmResult / generateAstmOrder).
Returns
The AstmRoundTripResult.
Example
import { generateAstmResult, astmRoundTrip } from "@cosyte/synth/astm";
const { specClean } = astmRoundTrip(generateAstmResult({ seed: 1 })); // specClean === true
generateAstmOrder()
generateAstmOrder(
options):string
Generate a spec-clean ASTM order message: an H/P/O/L record stream with no results, for
the order side of the flow. Built through buildAstmMessage; synthetic-by-construction; round-trips
clean.
Parameters
options
The seed.
Returns
string
The CR-terminated ASTM record stream.
Example
import { generateAstmOrder } from "@cosyte/synth/astm";
const raw = generateAstmOrder({ seed: 7 });
generateAstmQuirk()
generateAstmQuirk(
options):QuirkArtifact
Generate one ASTM quirk artifact: a spec-clean record report (built through @cosyte/astm) with
the requested vendor deviation injected post-serialize. Deterministic in seed + quirk + kind.
Parameters
options
Seed, quirk, and base kind. See GenerateAstmQuirkOptions.
Returns
The QuirkArtifact: its content round-trips to intendedWarnings exactly.
Throws
SynthError SYNTH_UNSUPPORTED_QUIRK if quirk is not a supported ASTM quirk.
Throws
Error if the base report does not contain the structural anchor the quirk targets.
Example
import { generateAstmQuirk, astmQuirkRoundTrip } from "@cosyte/synth/astm";
const rt = astmQuirkRoundTrip(generateAstmQuirk({ seed: 1, quirk: "unknown-escape" }));
rt.withProfile?.tolerated; // true, `referenceCorpus` re-badges ASTM_UNKNOWN_ESCAPE_SEQUENCE
generateAstmResult()
generateAstmResult(
options):string
Generate a spec-clean ASTM result message: an H/P/O/R…/C/L record stream, built
through @cosyte/astm's buildAstmMessage. Every identity value is synthetic-by-construction; the message
round-trips through parseAstmRecords with zero warnings and re-serializes
byte-identically (see ./round-trip).
Parameters
options
The seed, optional result count, and whether to append a comment.
Returns
string
The CR-terminated ASTM record stream.
Example
import { generateAstmResult } from "@cosyte/synth/astm";
const raw = generateAstmResult({ seed: 42 });
generateAstmResultFramed()
generateAstmResultFramed(
options):Uint8Array
Generate a spec-clean framed ASTM result message: the same H/P/O/R…/C/L records,
wrapped in the E1381 / CLSI LIS01 frame envelope (<STX> FN text <ETB|ETX> CS <CR><LF>) via
@cosyte/astm's composeAstmFrames. The modulo-256 checksum and the 0 to 7 frame number are
computed by the parser (never hand-written), and a record over 240 bytes is split across frames,
so the bytes round-trip through parseFramedAstm with zero frame and record warnings (see
./round-trip). Each record is framed independently (one ETX-closed run per record), mirroring what
decodeAstmFrames reassembles.
Parameters
options
The seed, optional result count, and whether to append a comment.
Returns
Uint8Array
The framed byte stream.
Example
import { generateAstmResultFramed } from "@cosyte/synth/astm";
const bytes = generateAstmResultFramed({ seed: 42 }); // Uint8Array, E1381 framed