@cosyte/cli
Public programmatic entry point for @cosyte/cli (the . subpath export).
@cosyte/cli is a bin package: its primary artifact is the cosyte command on your PATH
(npx @cosyte/cli parse …), not an import surface. This module is the small, honest programmatic
API over the same core the CLI uses: the format autodetector, the exit-code contract, the
value-free diagnostic types, and the dispatcher, so another adapter (the MCP server, or a web
playground) can drive the same logic without shelling out.
The CLI is a thin, PHI-safe skin over the wrapped @cosyte/* parsers: it routes, reads, shapes
output, and owns the exit-code + value-free-diagnostic disciplines; it re-implements no wire-format
parsing.
Classes
CliError
A typed, PHI-safe CLI error. Its CliError.message | message is value-free by construction: callers must build it from codes, indices, offsets, format names, and file paths, never from an input value. It carries the ExitCode the invocation resolves to.
Example
import { CliError, CLI_CODES, EXIT } from "@cosyte/cli";
throw new CliError(CLI_CODES.CLI_NO_INPUT, EXIT.NOINPUT, "cannot read the named file");
Extends
Error
Constructors
Constructor
new CliError(
code,exit,message):CliError
Parameters
code
A stable CliCode.
exit
The ExitCode to resolve to.
message
string
A value-free explanation (positional/structural context only, never PHI).
Returns
Overrides
Error.constructor
Properties
code
readonlycode:CliCode
The stable diagnostic code.
exit
readonlyexit:ExitCode
The exit code this error resolves the invocation to.
Interfaces
DeidAvailability
Whether de-identification is available, and (while it is not) the value-free reason why. The one
function the redact command consults before reading any input, so a redact invocation never
touches the PHI it cannot yet safely strip.
Properties
available
readonlyavailable:boolean
true once @cosyte/deid is wired; false today.
reason
readonlyreason:string
A value-free explanation shown when DeidAvailability.available is false.
DetectResult
How confident autodetection is:
certain: exactly one signature matched (formatnames it);ambiguous: more than one matched (formatisnull;candidatesnames them);none: nothing matched (formatisnull;candidatesis empty).
format is null unless confidence is certain, so a non-certain result can never be mistaken
for a routable format.
Properties
candidates
readonlycandidates: readonlyCosyteFormat[]
The matching candidate formats (0 for none, 1 for certain, ≥2 for ambiguous). Value-free.
confidence
readonlyconfidence:"certain"|"ambiguous"|"none"
The detection confidence.
format
readonlyformat:CosyteFormat|null
The detected format, or null when confidence is not certain.
Finding
A single value-free finding: a stable code, a severity, and a positional locator. Every field is safe to print, log, or serialize. None carries a name, DOB, MRN, or field value.
Properties
code
readonlycode:string
The stable diagnostic/warning code (the wrapped library's or the CLI's).
location
readonlylocation:string
A value-free positional locator: a FHIRPath expression, or an HL7 segment/field index path.
severity
readonlyseverity:string
The R4-style severity (fatal | error | warning | information), or warning for HL7.
FmtResult
The result of a canonical re-serialization (fmt): the spec-clean text + a value-free warning count.
Properties
output
readonlyoutput:string
The wrapped serializer's output text.
warningCount
readonlywarningCount:number
How many parse warnings the round-trip surfaced (value-free count only).
ParseResult
The result of wrapping a parser's parse: the library's parsed model + its value-free warnings.
Properties
model
readonlymodel:unknown
The wrapped library's parsed model: emitted verbatim as JSON on the data channel.
warnings
readonlywarnings: readonlyParseWarning[]
The parser's value-free warnings (code + position).
PhiPosture
The resolved PHI display posture for one invocation. showValues is true only when the user
passed --unsafe-show-values; every value-echoing decision reads this one flag.
Properties
showValues
readonlyshowValues:boolean
true iff --unsafe-show-values was given: a value may appear on a secondary surface.
ResolvedInput
A successfully-resolved input: the format (guaranteed to support the requested op) and the bytes.
Properties
bytes
readonlybytes:Uint8Array
The input bytes (a whole file or a drained stdin buffer); guaranteed non-empty.
format
readonlyformat:CosyteFormat
The resolved format: guaranteed to satisfy supportsOp(format, op) for the requested op.
RunDeps
The injectable input side-effects the dispatcher needs. Kept tiny and pure-ish so tests drive the CLI end to end with in-memory fakes and no real filesystem or stdin.
Properties
readFile
readonlyreadFile: (path) =>Promise<Uint8Array<ArrayBufferLike>>
Read a file's bytes, or raise a CLI_NO_INPUT CliError if it cannot be read.
Parameters
path
string
Returns
Promise<Uint8Array<ArrayBufferLike>>
readStdin
readonlyreadStdin: () =>Promise<Uint8Array<ArrayBufferLike>>
Read all of stdin's bytes.
Returns
Promise<Uint8Array<ArrayBufferLike>>
RunResult
A fully-resolved CLI invocation.
Example
import { EXIT, type RunResult } from "@cosyte/cli";
const r: RunResult = { stdout: "{}\n", stderr: "", exit: EXIT.OK };
r.exit; // => 0
Properties
exit
readonlyexit:ExitCode
The exit code the invocation resolves to.
stderr
readonlystderr:string
The diagnostic channel is value-free: codes, positions, file paths, format names only.
stdout
readonlystdout:string
The data channel: the parsed model or requested output. May contain the user's data by design.
Verdict
The verdict of running a format's validation surface: value-free findings + the validity boolean.
Properties
findings
readonlyfindings: readonlyFinding[]
The value-free findings (code + severity + positional locator).
valid
readonlyvalid:boolean
true iff the input is valid (no error/fatal-severity finding).
Type Aliases
CliCode
A value from CLI_CODES: the stable code carried by a CliError.
CosyteFormat
CosyteFormat =
"hl7"|"fhir"|"dicom"|"x12"|"ccda"|"ncpdp"|"astm"|"mllp"
The set of formats the cosyte command names.
ExitCode
A value from EXIT: the exit code a CLI invocation resolves to.
InputResolution
InputResolution = {
input:ResolvedInput;ok:true; } | {ok:false;result:RunResult; }
The outcome of resolveInput: either the resolved input, or a ready-to-return value-free
RunResult carrying the diagnostic + exit code for whatever went wrong. A discriminated union
so a command reads if (!r.ok) return r.result; and then works with r.input.
InspectSummary
InspectSummary =
Hl7Summary|FhirSummary|X12Summary|AstmSummary|CcdaSummary|DicomSummary|NcpdpSummary|MllpSummary
The discriminated value-free structural summary inspect renders.
Op
Op =
"parse"|"inspect"|"fmt"|"validate"
The four wrapping operations a command can ask a format's adapter to perform.
ParseWarning
ParseWarning =
object&Readonly<Record<string,unknown>>
A value-free parse warning: a stable code plus the parser's positional (index-only) context.
Type Declaration
code
readonlycode:string
Variables
CLI_CODES
constCLI_CODES:object
Stable CLI diagnostic code registry: errors the CLI owns (routing, I/O, argument handling),
distinct from the wrapped library's own warning/issue codes which are passed through unchanged.
Each code is its own value (key === value) so the set survives Object.values(...); renaming or
removing one is a breaking change because scripts branch on the stderr text.
Type Declaration
CLI_EMPTY_INPUT
readonlyCLI_EMPTY_INPUT:"CLI_EMPTY_INPUT"="CLI_EMPTY_INPUT"
The input was empty, no bytes to detect or parse. Exit 65.
CLI_FORMAT_AMBIGUOUS
readonlyCLI_FORMAT_AMBIGUOUS:"CLI_FORMAT_AMBIGUOUS"="CLI_FORMAT_AMBIGUOUS"
More than one format signature matched; the CLI will not guess. Names the candidates, never the bytes. Exit 65.
CLI_FORMAT_UNDETECTED
readonlyCLI_FORMAT_UNDETECTED:"CLI_FORMAT_UNDETECTED"="CLI_FORMAT_UNDETECTED"
No format signature matched; the CLI will not guess. Names the candidates, never the bytes. Exit 65.
CLI_FORMAT_UNSUPPORTED
readonlyCLI_FORMAT_UNSUPPORTED:"CLI_FORMAT_UNSUPPORTED"="CLI_FORMAT_UNSUPPORTED"
A recognised format whose parser does not support the requested operation (e.g. parse on a
format wired only for inspect). Names the format + operation, never the bytes. Exit 65.
CLI_INTERNAL
readonlyCLI_INTERNAL:"CLI_INTERNAL"="CLI_INTERNAL"
An unexpected internal error (a bug). Exit 70.
CLI_MAP_INVALID
readonlyCLI_MAP_INVALID:"CLI_MAP_INVALID"="CLI_MAP_INVALID"
The BYO ConceptMap supplied to map-codes is not valid JSON or not a loadable FHIR ConceptMap.
Names the stable terminology-loader code, never the map's bytes. Exit 65.
CLI_NO_INPUT
readonlyCLI_NO_INPUT:"CLI_NO_INPUT"="CLI_NO_INPUT"
The named file does not exist or could not be read. Exit 66.
CLI_NOT_IMPLEMENTED
readonlyCLI_NOT_IMPLEMENTED:"CLI_NOT_IMPLEMENTED"="CLI_NOT_IMPLEMENTED"
A command whose ground-layer library is not yet built (e.g. redact before @cosyte/deid
ships). Never a fake success: a distinct, value-free "unavailable" signal. Exit 69.
CLI_PARSE_FAILED
readonlyCLI_PARSE_FAILED:"CLI_PARSE_FAILED"="CLI_PARSE_FAILED"
The wrapped parser rejected the input. Positional context only, never the offending bytes. Exit 65.
CLI_PARSER_UNAVAILABLE
readonlyCLI_PARSER_UNAVAILABLE:"CLI_PARSER_UNAVAILABLE"="CLI_PARSER_UNAVAILABLE"
The optional parser package for a recognised format is not installed. The six breadth parsers
(dicom/x12/ccda/ncpdp/astm/mllp) are optionalDependencies: normally installed, but if
one is absent the CLI degrades to this value-free signal rather than crashing. Exit 69.
CLI_USAGE
readonlyCLI_USAGE:"CLI_USAGE"="CLI_USAGE"
A required argument was missing or a flag was invalid. Exit 2.
Example
import { CLI_CODES } from "@cosyte/cli";
if (diagnostic.code === CLI_CODES.CLI_FORMAT_UNDETECTED) {
// ask the user for --format
}
DEID_UNAVAILABLE_REASON
constDEID_UNAVAILABLE_REASON:string
The value-free reason redact/deid reports while the ground-layer library is unavailable.
DETECTABLE_FORMATS
constDETECTABLE_FORMATS: readonlyCosyteFormat[]
The formats content-autodetection can recognise (every format now carries a signature).
EXIT
constEXIT:object
The stable exit-code map. Adding a code is a documented, tested change to the CLI's contract; renaming or repurposing one is a breaking change.
Type Declaration
DATAERR
readonlyDATAERR:65=65
Data error: input could not be parsed or its format could not be detected (EX_DATAERR).
INVALID
readonlyINVALID:1=1
Operation-level failure: validate found the input invalid (parseable but non-conformant):
a real, expected CI signal that the message is bad and the tool worked. Never emitted for
unparseable input (that is DATAERR).
NOINPUT
readonlyNOINPUT:66=66
No input: the named file does not exist or is unreadable (EX_NOINPUT).
OK
readonlyOK:0=0
Success: the operation completed; validate found the input valid.
SOFTWARE
readonlySOFTWARE:70=70
Internal error: an unexpected exception (a bug), distinct from a handled bad input (EX_SOFTWARE).
UNAVAILABLE
readonlyUNAVAILABLE:69=69
Unavailable: a required capability is not yet built (e.g. redact before @cosyte/deid), a
distinct non-zero signal that is never a fake success (EX_UNAVAILABLE).
USAGE
readonlyUSAGE:2=2
Usage error: unknown command, bad flag, missing argument (EX_USAGE).
Example
import { EXIT } from "@cosyte/cli";
process.exitCode = EXIT.OK; // => 0
KNOWN_FORMATS
constKNOWN_FORMATS: readonlyCosyteFormat[]
The full set of format names --format accepts as syntactically valid (a bad value is a usage error).
OP_SUPPORT
constOP_SUPPORT:Readonly<Record<CosyteFormat,ReadonlySet<Op>>>
The honest per-format operation matrix. A (format, op) pair absent here is a value-free
CLI_FORMAT_UNSUPPORTED, never a faked result. The unsupported cells and why:
- dicom
parse/fmt. The model is binary (no faithful JSON view;serializeDicomemits a Part-10 byte stream, not text).inspect/validateare supported. - ccda
parse: the canonical form is XML; there is no library-blessed JSON model, sofmt(XML re-serialize) is the faithful surface.inspect/fmt/validateare supported. - mllp
fmt/validate: MLLP is a transport container the CLI de-frames to HL7;parseyields the enclosed HL7 message(s) andinspectreports the frame count.
Example
import { OP_SUPPORT } from "@cosyte/cli";
OP_SUPPORT.dicom.has("parse"); // => false
OP_SUPPORT.hl7.has("validate"); // => true
SHOW_VALUES
constSHOW_VALUES:PhiPosture
The opted-in, PHI-exposing posture selected by --unsafe-show-values.
UNSAFE_EXCERPT_MAX
constUNSAFE_EXCERPT_MAX:200=200
The maximum number of leading input bytes an --unsafe-show-values diagnostic may echo. Bounded so
an unsafe excerpt stays a single, readable diagnostic line rather than dumping a whole message.
UNSAFE_SHOW_VALUES_FLAG
constUNSAFE_SHOW_VALUES_FLAG:"--unsafe-show-values"="--unsafe-show-values"
The single global flag token that opts into showing values on secondary surfaces.
VALUE_FREE
constVALUE_FREE:PhiPosture
The default, safe posture: no value ever reaches a secondary surface.
VERSION
constVERSION:"0.0.0"="0.0.0"
The @cosyte/cli version. On the uniform v0.0.x-until-first-alpha ladder.
Example
import { VERSION } from "@cosyte/cli";
typeof VERSION; // => "string"
Functions
asCosyteFormat()
asCosyteFormat(
value):CosyteFormat|null
Narrow an arbitrary --format string to a CosyteFormat, or null if it is not a known
format name (which the caller turns into a usage error, exit 2).
Parameters
value
string
The raw --format argument.
Returns
CosyteFormat | null
The narrowed format, or null.
Example
import { asCosyteFormat } from "@cosyte/cli";
asCosyteFormat("hl7"); // => "hl7"
asCosyteFormat("nope"); // => null
classifyCandidates()
classifyCandidates(
candidates):DetectResult
Classify a list of matched candidate formats into a DetectResult: exactly one → certain,
zero → none, two-or-more → ambiguous (all with format null unless certain). Split out and
exported so the ambiguity contract is directly testable. It is otherwise unreachable while
every signature is disjoint, and it must stay a detected ambiguity, never a mis-route.
Parameters
candidates
readonly CosyteFormat[]
The formats whose signatures matched the input.
Returns
The classified DetectResult.
Example
import { classifyCandidates } from "@cosyte/cli";
classifyCandidates(["hl7"]).confidence; // => "certain"
classifyCandidates([]).confidence; // => "none"
classifyCandidates(["hl7", "fhir"]).confidence; // => "ambiguous"
completionCommand()
completionCommand(
args):RunResult
Run the completion command.
Parameters
args
string[]
The arguments after the completion subcommand token; the first is the shell name.
Returns
A RunResult: the completion script on stdout (exit 0), or a value-free usage
error (exit 2) when the shell is missing or unrecognised.
Example
import { completionCommand } from "@cosyte/cli";
completionCommand(["bash"]).exit; // => 0
completionCommand(["powershell"]).exit; // => 2
convertCommand()
convertCommand(
args,deps,posture?):Promise<RunResult>
Run the convert command.
Parameters
args
string[]
The arguments after the convert subcommand token.
deps
Injected input readers (RunDeps).
posture?
PhiPosture = VALUE_FREE
The resolved PhiPosture (governs only the opt-in unsafe excerpt on an HL7 parse-failure diagnostic; the converted bundle and the value-free findings are unaffected).
Returns
Promise<RunResult>
A RunResult: the converted FHIR Bundle on stdout (the data channel), value-free
findings on stderr (or JSON under --json), and an exit code that carries the outcome: 0
clean · 1 an error-severity conversion issue · 65 the HL7 input could not be parsed or is not
an HL7 v2 source · 66 no input · 2 usage.
Throws
Never CliError; may propagate a truly unexpected error for the dispatcher to map to
CLI_INTERNAL.
Example
import { convertCommand } from "@cosyte/cli";
const deps = {
readFile: async () => new TextEncoder().encode("MSH|^~\\&|A|B|C|D|20240101||ADT^A01|1|P|2.5\r"),
readStdin: async () => new Uint8Array(),
};
(await convertCommand(["adt.hl7", "--to", "fhir"], deps)).exit; // => 0
convertOutcome()
convertOutcome(
findings):object
Decide the conversion outcome from the library's value-free findings: whether any is
error-severity (which drives a non-zero exit: the load-bearing "a conversion error is never
exit 0" rule) and the value-free human report. The severity classification is
the library's: @cosyte/transform fixes each issue's severity; the CLI only reads it. Exported so
the exit-verdict and report logic is unit-testable with synthetic findings, independent of which HL7
message happens to produce an error.
Parameters
findings
readonly Finding[]
The value-free Findings the conversion produced.
Returns
object
hasError (true iff any finding is error/fatal severity) and the rendered value-free
report (one line per finding + a summary line).
hasError
readonlyhasError:boolean
report
readonlyreport:string
Example
import { convertOutcome } from "@cosyte/cli";
convertOutcome([{ code: "TRANSFORM_RESOURCE_INVALID", severity: "error", location: "PID" }])
.hasError; // => true
convertOutcome([{ code: "TRANSFORM_ELEMENT_DROPPED", severity: "information", location: "PID.13" }])
.hasError; // => false
deframeMllp()
deframeMllp(
bytes):Promise<{payloads:Buffer<ArrayBufferLike>[];warningCount:number; }>
De-frame an MLLP byte stream into its enclosed HL7 payloads via @cosyte/mllp's FrameReader. MLLP
is a transport container, not a document format: each frame's payload is an HL7 v2 message the CLI
then parses/inspects with the hl7 adapter. Multi-frame streams are the CLI's multi-message surface.
Parameters
bytes
Uint8Array
The MLLP-framed input.
Returns
Promise<{ payloads: Buffer<ArrayBufferLike>[]; warningCount: number; }>
The de-framed HL7 payloads (in stream order) + a value-free framing-warning count.
Truncation is a data error, never a silent drop. The FrameReader is a streaming decoder: an
unterminated trailing frame (a VT opened with no closing FS/CR) is left buffered and delivered by
no callback, so feeding a whole file and reading only onFrame would silently lose the partial
message with a green exit. We therefore detect an open trailing frame at the byte level (the last
VT sits after the last FS: MLLP payloads are HL7 v2 text and never carry the 0x0B/0x1C framing
bytes) and reject the whole stream as a value-free CLI_PARSE_FAILED data error.
Throws
CLI_PARSER_UNAVAILABLE if @cosyte/mllp is absent; CLI_PARSE_FAILED (exit
65) on a truncated stream; a hard framing error propagates for the caller's value-free boundary.
Example
import { deframeMllp } from "@cosyte/cli";
// a VT-framed "MSH|..." message → one payload
(await deframeMllp(new Uint8Array([0x0b, 0x4d, 0x53, 0x48, 0x1c, 0x0d]))).payloads.length; // => 1
deidStatus()
deidStatus():
DeidAvailability
Report the current de-identification availability. Today it is always unavailable (see the module
docs); this is the single line that flips when @cosyte/deid is wired.
Returns
The DeidAvailability: { available: false, reason } until @cosyte/deid ships.
Example
import { deidStatus } from "@cosyte/cli";
deidStatus().available; // => false
detectFormat()
detectFormat(
bytes):DetectResult
Detect the healthcare format of bytes by content, conservatively.
Parameters
bytes
Uint8Array
The input bytes (a whole file or a stdin buffer). Only the leading prefix is sniffed.
Returns
A DetectResult: certain + a format on a single match, else ambiguous/none
with format: null and the value-free candidates list. Never guesses.
Example
import { detectFormat } from "@cosyte/cli";
const enc = new TextEncoder();
detectFormat(enc.encode("MSH|^~\\&|A|B\r")).format; // => "hl7"
detectFormat(enc.encode('{"resourceType":"Patient"}')).format; // => "fhir"
detectFormat(enc.encode("hello")).confidence; // => "none"
detectionError()
detectionError(
detected):CliError
Build the value-free CliError for a non-certain detection: the data error the caller
returns instead of guessing a parser. ambiguous names the matching candidates (a value-free code
list); none asks for --format. Both map to the data-error exit (65). Never echoes input bytes.
Parameters
detected
A DetectResult whose format is null (i.e. not certain).
Returns
A value-free CLI_FORMAT_AMBIGUOUS or CLI_FORMAT_UNDETECTED error.
Example
import { classifyCandidates, detectionError } from "@cosyte/cli";
detectionError(classifyCandidates([])).code; // => "CLI_FORMAT_UNDETECTED"
detectionError(classifyCandidates(["hl7", "fhir"])).code; // => "CLI_FORMAT_AMBIGUOUS"
errorResult()
errorResult(
err):RunResult
Resolve a CliError into a value-free RunResult: empty stdout (nothing reaches the
data channel on an error), the rendered diagnostic on stderr, and the error's exit code. The
single place the CLI turns an owned error into a result, so every command and the dispatcher render
errors identically.
Parameters
err
The CLI error to resolve.
Returns
The value-free RunResult.
Example
import { CliError, CLI_CODES, EXIT, errorResult } from "@cosyte/cli";
errorResult(new CliError(CLI_CODES.CLI_USAGE, EXIT.USAGE, "missing <file>")).exit; // => 2
extractPhiPosture()
extractPhiPosture(
argv):object
Resolve the global --unsafe-show-values flag out of an argument vector, order-independently
(it may appear before or after the subcommand), and return the posture plus the argv with every
occurrence of the flag removed, so each command's own parseArgs never sees it and cannot reject
it as unknown. This is the one place the flag is recognised.
Parameters
argv
readonly string[]
The raw arguments (after the program name).
Returns
object
The resolved PhiPosture and the flag-stripped argv.
argv
argv:
string[]
posture
posture:
PhiPosture
Example
import { extractPhiPosture } from "@cosyte/cli";
extractPhiPosture(["parse", "x.hl7"]).posture.showValues; // => false
extractPhiPosture(["--unsafe-show-values", "parse", "x.hl7"]).posture.showValues; // => true
extractPhiPosture(["parse", "x.hl7", "--unsafe-show-values"]).argv; // => ["parse", "x.hl7"]
extractStableCode()
extractStableCode(
e):string|null
Pull a code off a thrown value only when it is a PHI-free constant token
(^[A-Z][A-Z0-9_]*$: a letter-led UPPER_SNAKE code like MALFORMED_JSON), e.g. a wrapped
parser's stable fatal code. Anything else (no code, a non-string, a non-token, or a pure-digit
value that could be a raw identifier) yields null, so a parser exception that embedded input bytes
in a code-shaped field can never reach a diagnostic.
Parameters
e
unknown
A caught value.
Returns
string | null
The stable code token, or null.
Example
import { extractStableCode } from "@cosyte/cli";
extractStableCode({ code: "MALFORMED_JSON" }); // => "MALFORMED_JSON"
extractStableCode(new Error("boom")); // => null
fmtCommand()
fmtCommand(
args,deps,posture?):Promise<RunResult>
Run the fmt command.
Parameters
args
string[]
The arguments after the fmt subcommand token.
deps
Injected input readers (RunDeps).
posture?
PhiPosture = VALUE_FREE
The resolved PhiPosture (governs only the opt-in unsafe excerpt on a parse-failure diagnostic).
Returns
Promise<RunResult>
A RunResult: the canonical re-serialization on stdout (exit 0), a value-free
warning-count note on stderr unless --quiet; an unparseable input is a data error (65) with
no partial emit, an unreadable file 66, a bad flag 2.
Throws
Never CliError; may propagate a truly unexpected error for the dispatcher to map.
Example
import { fmtCommand } from "@cosyte/cli";
const deps = {
readFile: async () => new TextEncoder().encode('{ "resourceType":"Patient" , "id":"x" }'),
readStdin: async () => new Uint8Array(),
};
(await fmtCommand(["patient.json"], deps)).exit; // => 0
fmtFormat()
fmtFormat(
format,bytes):Promise<FmtResult>
Canonically re-serialize one input of format via the wrapped library's spec-clean serializer. The
CLI never re-canonicalizes on its own; the output is exactly the serializer's.
Parameters
format
A format for which supportsOp(format, "fmt") is true.
bytes
Uint8Array
The input bytes.
Returns
Promise<FmtResult>
The serialized text + a value-free warning count.
Throws
CLI_PARSER_UNAVAILABLE if the optional parser is absent; the wrapped parser's
rejection propagates for the command's value-free failure boundary (no partial emit).
Example
import { fmtFormat } from "@cosyte/cli";
const bytes = new TextEncoder().encode('{ "resourceType":"Patient" , "id":"x" }');
(await fmtFormat("fhir", bytes)).output.startsWith("{"); // => true
formatDiagnostic()
formatDiagnostic(
err):string
Render a CliError as a single value-free stderr line: cosyte: <CODE>: <message>. The
message is already value-free by the CliError contract; this only prefixes the tool name
and the code so scripts and humans can branch on a stable token.
Parameters
err
The CLI error to render.
Returns
string
The stderr line (no trailing newline).
Example
import { CliError, CLI_CODES, EXIT, formatDiagnostic } from "@cosyte/cli";
formatDiagnostic(new CliError(CLI_CODES.CLI_USAGE, EXIT.USAGE, "missing <file> argument"));
// => "cosyte: CLI_USAGE: missing <file> argument"
formatHl7Position()
formatHl7Position(
pos):string
Render an HL7 warning position as a value-free locator string built only from its numeric
indices: e.g. seg[3].field[5].comp[1]. No segment content, no field value, ever appears; only the
structural coordinates the parser reported.
Parameters
pos
Hl7PositionLike
The HL7 position (segment/field/repetition/component/subcomponent indices).
Returns
string
A value-free locator, e.g. "seg[3].field[5]".
Example
import { formatHl7Position } from "@cosyte/cli";
formatHl7Position({ segmentIndex: 3, fieldIndex: 5 }); // => "seg[3].field[5]"
formatHl7Position({ segmentIndex: 0 }); // => "seg[0]"
formatsSupporting()
formatsSupporting(
op): readonlyCosyteFormat[]
The formats that support op, as a sorted, value-free list: used to build the "does not support"
diagnostic so the user is told which formats do support the operation they asked for.
Parameters
op
The wrapping operation.
Returns
readonly CosyteFormat[]
The supporting format names, sorted.
Example
import { formatsSupporting } from "@cosyte/cli";
formatsSupporting("fmt"); // => ["astm", "ccda", "fhir", "hl7", "ncpdp", "x12"]
inspectCommand()
inspectCommand(
args,deps,posture?):Promise<RunResult>
Run the inspect command.
Parameters
args
string[]
The arguments after the inspect subcommand token.
deps
Injected input readers (RunDeps).
posture?
PhiPosture = VALUE_FREE
The resolved PhiPosture (governs only the opt-in unsafe excerpt on a parse-failure diagnostic; the summary itself is always value-free).
Returns
Promise<RunResult>
A RunResult: the value-free structural summary on stdout (human, or JSON under
--json), exit 0; a parse failure is a data error (65), an unreadable file 66, a bad flag 2.
Throws
Never CliError; may propagate a truly unexpected error for the dispatcher to map.
Example
import { inspectCommand } from "@cosyte/cli";
const deps = {
readFile: async () => new TextEncoder().encode('{"resourceType":"Patient"}'),
readStdin: async () => new Uint8Array(),
};
(await inspectCommand(["patient.json", "--json"], deps)).exit; // => 0
inspectFormat()
inspectFormat(
format,bytes):Promise<InspectSummary>
Build the value-free structural summary of one input of format: counts and structural type codes
only, never a field value.
Parameters
format
A format for which supportsOp(format, "inspect") is true.
bytes
Uint8Array
The input bytes.
Returns
Promise<InspectSummary>
A InspectSummary variant for the format.
Throws
CLI_PARSER_UNAVAILABLE if the optional parser is absent; the wrapped parser's
rejection propagates for the command's value-free failure boundary.
Example
import { inspectFormat } from "@cosyte/cli";
const bytes = new TextEncoder().encode('{"resourceType":"Patient"}');
(await inspectFormat("fhir", bytes)).format; // => "fhir"
loadOptional()
loadOptional<
T>(format,load):Promise<T>
Lazy-import an optional parser package, mapping an absent package to a value-free
CLI_PARSER_UNAVAILABLE (exit 69): the graceful-degradation path for the optionalDependencies
breadth parsers. A genuine import that succeeds passes straight through; any error whose
shape is "module not found" becomes the value-free CLI error. Other errors propagate unchanged.
Type Parameters
T
T
The imported module's type.
Parameters
format
The format whose optional parser is being loaded (named in the diagnostic).
load
() => Promise<T>
A thunk performing the dynamic import.
Returns
Promise<T>
The imported module.
Throws
CLI_PARSER_UNAVAILABLE (exit 69) when the package is absent; any other error
propagates unchanged.
Example
import { loadOptional } from "@cosyte/cli";
// a present parser resolves; an absent one throws CLI_PARSER_UNAVAILABLE
await loadOptional("x12", () => import("@cosyte/x12"));
mapCodesCommand()
mapCodesCommand(
args,deps):Promise<RunResult>
Run the map-codes command.
Parameters
args
string[]
The arguments after the map-codes subcommand token.
deps
Injected input readers (RunDeps); the positional argument (or -) is the BYO
ConceptMap document.
Returns
Promise<RunResult>
A RunResult: the translation result on stdout (matched target coding(s) or the
value-free unmapped signal), a value-free note on stderr (unless --quiet), and an exit code
carrying the outcome: 0 mapped · 1 unmapped · 65 unloadable ConceptMap · 66 no input ·
2 usage.
Throws
Never CliError; may propagate a truly unexpected error for the dispatcher to map to
CLI_INTERNAL.
Example
import { mapCodesCommand } from "@cosyte/cli";
const cm = JSON.stringify({
resourceType: "ConceptMap",
group: [
{
source: "http://hl7.org/fhir/administrative-gender",
target: "http://terminology.hl7.org/CodeSystem/v2-0001",
element: [{ code: "male", target: [{ code: "M", equivalence: "equivalent" }] }],
},
],
});
const deps = {
readFile: async () => new TextEncoder().encode(cm),
readStdin: async () => new Uint8Array(),
};
const r = await mapCodesCommand(
["gender.json", "--system", "http://hl7.org/fhir/administrative-gender", "--code", "male"],
deps,
);
r.exit; // => 0
parseCommand()
parseCommand(
args,deps,posture?):Promise<RunResult>
Run the parse command.
Parameters
args
string[]
The arguments after the parse subcommand token.
deps
Injected input readers (RunDeps).
posture?
PhiPosture = VALUE_FREE
The resolved PhiPosture. Defaults to VALUE_FREE; under
--unsafe-show-values a bounded excerpt of the offending input is appended to a CLI_PARSE_FAILED
diagnostic (the single, opt-in value-echoing surface): single-record mode only.
Returns
Promise<RunResult>
A RunResult: the typed-JSON model (or NDJSON records) on stdout, a value-free note
(or nothing) on stderr, and the resolved exit code. Never throws a CliError: it resolves
it to a result; unexpected exceptions are caught by the dispatcher and mapped to CLI_INTERNAL.
Throws
Never CliError; may propagate a truly unexpected error for the dispatcher to map.
Example
import { parseCommand } from "@cosyte/cli";
const enc = new TextEncoder();
const deps = {
readFile: async () => enc.encode('{"resourceType":"Patient","id":"x"}'),
readStdin: async () => new Uint8Array(),
};
(await parseCommand(["patient.json"], deps)).exit; // => 0
parseFailureResult()
parseFailureResult(
format,bytes,posture,e):RunResult
Build the value-free RunResult for a wrapped-parser rejection: a CLI_PARSE_FAILED
data error (exit 65). The stderr line names the format and, when the thrown value carried one, a
stable code token in parentheses; it never echoes the parser's message or the input bytes. Under
--unsafe-show-values (and only then) a bounded excerpt of the offending input is appended via the
single unsafeInputSuffix chokepoint.
Parameters
format
The format whose parser rejected the input.
bytes
Uint8Array
The offending input (only consulted for the opt-in unsafe excerpt).
posture
The resolved PhiPosture; the excerpt is appended only when it opts in.
e
unknown
The caught exception (its code, if a stable token, is surfaced: nothing else).
Returns
A value-free CLI_PARSE_FAILED / exit-65 RunResult.
Example
import { parseFailureResult, VALUE_FREE } from "@cosyte/cli";
const bytes = new TextEncoder().encode("not hl7");
parseFailureResult("hl7", bytes, VALUE_FREE, { code: "MISSING_MSH" }).exit; // => 65
parseFormat()
parseFormat(
format,bytes):Promise<ParseResult>
Parse one record of format into the wrapped library's model + its value-free warnings. The model
is emitted verbatim on the data channel; the CLI adds no parsing of its own.
Parameters
format
A format for which supportsOp(format, "parse") is true.
bytes
Uint8Array
The single record's bytes (already de-framed for MLLP: callers pass "hl7" there).
Returns
Promise<ParseResult>
The parsed model + value-free warnings.
Throws
CLI_PARSER_UNAVAILABLE if the optional parser is absent; the wrapped parser's
own rejection propagates for the command's value-free failure boundary to catch.
Example
import { parseFormat } from "@cosyte/cli";
const bytes = new TextEncoder().encode('{"resourceType":"Patient","id":"x"}');
(await parseFormat("fhir", bytes)).warnings.length; // => 0
readFileBytes()
readFileBytes(
path):Promise<Uint8Array<ArrayBufferLike>>
Read a file into bytes, mapping any read failure to a value-free CLI_NO_INPUT /
EXIT.NOINPUT error. The path is structural context (the user supplied it), so it may appear
in the message; the file contents never do.
Parameters
path
string
The file path to read.
Returns
Promise<Uint8Array<ArrayBufferLike>>
The file bytes.
Throws
CLI_NO_INPUT (exit 66) when the file is missing, a directory, or unreadable.
Example
import { readFileBytes } from "@cosyte/cli";
await readFileBytes("/no/such/file"); // throws CliError CLI_NO_INPUT
readStreamBytes()
readStreamBytes(
stream):Promise<Uint8Array<ArrayBufferLike>>
Drain a readable stream (e.g. process.stdin) into a single byte buffer.
Parameters
stream
Readable
The readable stream to drain.
Returns
Promise<Uint8Array<ArrayBufferLike>>
The concatenated bytes.
Example
import { Readable } from "node:stream";
import { readStreamBytes } from "@cosyte/cli";
const bytes = await readStreamBytes(Readable.from([Buffer.from("MSH|")]));
bytes.length; // => 4
redactCommand()
redactCommand(
args):RunResult
Run the redact / deid command.
Parameters
args
string[]
The arguments after the redact/deid subcommand token.
Returns
A RunResult. While @cosyte/deid is unavailable: empty stdout, a value-free
CLI_NOT_IMPLEMENTED diagnostic on stderr, and exit EX_UNAVAILABLE (69). A malformed
invocation (an unknown flag) is a usage error (exit 2). The input is never read.
Example
import { redactCommand } from "@cosyte/cli";
const r = redactCommand(["message.hl7"]);
r.exit; // => 69
resolveInput()
resolveInput(
source,formatOverride,deps,op):Promise<InputResolution>
Resolve and read the input, and resolve its format, for a file-consuming command.
Parameters
source
string | undefined
The positional <file|-> argument (or undefined when it was omitted).
formatOverride
string | undefined
The raw --format value, or undefined to autodetect by content.
deps
Injected input readers (RunDeps).
op
The wrapping operation the caller will run; the resolved format is confirmed to support
it (else a value-free CLI_FORMAT_UNSUPPORTED naming the supporting formats).
Returns
Promise<InputResolution>
{ ok: true, input } when the bytes read and the format resolved to a parser supporting
op; else { ok: false, result } with a value-free usage/no-input/data-error RunResult.
Throws
Propagates a non-CliError read failure unchanged, so the dispatcher maps it to
CLI_INTERNAL (a CliError read failure, e.g. a missing file, is caught and returned).
Example
import { resolveInput } from "@cosyte/cli";
const deps = {
readFile: async () => new TextEncoder().encode('{"resourceType":"Patient"}'),
readStdin: async () => new Uint8Array(),
};
const r = await resolveInput("patient.json", undefined, deps, "parse");
if (r.ok) r.input.format; // => "fhir"
run()
run(
argv,deps):Promise<RunResult>
Run a full cosyte invocation as data.
Parameters
argv
string[]
The arguments after the program name (i.e. process.argv.slice(2)).
deps
Injected input readers (RunDeps).
Returns
Promise<RunResult>
The RunResult to write to the process streams and exit with.
Example
import { run } from "@cosyte/cli";
const deps = { readFile: async () => new Uint8Array(), readStdin: async () => new Uint8Array() };
const { exit } = await run(["--version"], deps);
exit; // => 0
supportsOp()
supportsOp(
format,op):boolean
True iff format's wrapped parser supports op in this build (see OP_SUPPORT).
Parameters
format
The resolved format.
op
The wrapping operation.
Returns
boolean
Whether the (format, op) pair is wired.
Example
import { supportsOp } from "@cosyte/cli";
supportsOp("x12", "fmt"); // => true
supportsOp("dicom", "parse"); // => false
toCliError()
toCliError(
err):CliError
Coerce an unknown thrown value into a CliError. A CliError passes through; anything
else becomes a CLI_INTERNAL / EXIT.SOFTWARE error whose message is a fixed, value-free
string: the original message is deliberately discarded so a parser exception that embedded input
bytes can never reach stderr.
Parameters
err
unknown
The caught value.
Returns
A CliError safe to render to stderr.
Example
import { toCliError } from "@cosyte/cli";
toCliError(new Error("boom")).code; // => "CLI_INTERNAL"
unsafeInputSuffix()
unsafeInputSuffix(
bytes,posture):string
Build the only value-bearing addition the CLI ever appends to a secondary (stderr) surface: a
bounded, single-line excerpt of the offending input, shown iff --unsafe-show-values is set.
Under the default value-free posture it returns the empty string, so a diagnostic stays value-free
unless the user explicitly opted in. This is the single chokepoint the PHI-leak matrix pins.
Parameters
bytes
Uint8Array
The input the CLI is operating on (only the leading UNSAFE_EXCERPT_MAX bytes are considered).
posture
The resolved PhiPosture.
Returns
string
"" under the value-free default; otherwise a [unsafe-show-values] … suffix carrying a
bounded, newline-flattened prefix of bytes.
Example
import { unsafeInputSuffix, VALUE_FREE, SHOW_VALUES } from "@cosyte/cli";
const bytes = new TextEncoder().encode("bad message");
unsafeInputSuffix(bytes, VALUE_FREE); // => ""
unsafeInputSuffix(bytes, SHOW_VALUES); // => " [unsafe-show-values] offending input …: bad message"
validateCommand()
validateCommand(
args,deps,posture?):Promise<RunResult>
Run the validate command.
Parameters
args
string[]
The arguments after the validate subcommand token.
deps
Injected input readers (RunDeps).
posture?
PhiPosture = VALUE_FREE
The resolved PhiPosture (governs only the opt-in unsafe excerpt on a parse-failure diagnostic; a validation verdict is always value-free).
Returns
Promise<RunResult>
A RunResult whose exit code carries the verdict (0 valid / 1 invalid /
65 unparseable / 66 no input / 2 usage). Value-free findings on stderr, or value-free
JSON on stdout under --json.
Throws
Never CliError; may propagate a truly unexpected error for the dispatcher to map.
Example
import { validateCommand } from "@cosyte/cli";
const deps = {
readFile: async () => new TextEncoder().encode('{"resourceType":"Patient","gender":"male"}'),
readStdin: async () => new Uint8Array(),
};
(await validateCommand(["patient.json"], deps)).exit; // => 0
validateFormat()
validateFormat(
format,bytes):Promise<Verdict>
Run the format's validation surface and return a value-free Verdict. For the Postel's-Law
lenient parsers, a parseable input is valid: recovered deviations are non-fatal warnings the
library surfaces, never a stricter verdict the CLI invents. FHIR additionally runs validateResource
and is invalid on any error/fatal-severity issue.
Parameters
format
A format for which supportsOp(format, "validate") is true.
bytes
Uint8Array
The input bytes.
Returns
Promise<Verdict>
The value-free verdict (findings + validity).
Throws
CLI_PARSER_UNAVAILABLE if the optional parser is absent; an unparseable input
propagates as the wrapped parser's throw for the command to map to a data error (65).
Example
import { validateFormat } from "@cosyte/cli";
const bytes = new TextEncoder().encode('{"resourceType":"Patient","gender":"male"}');
(await validateFormat("fhir", bytes)).valid; // => true
valueFreeLocator()
valueFreeLocator(
pos):string
Render an arbitrary parser position object as a value-free locator string, keeping only
number-valued own properties (the parsers' positions are index-only): e.g. { segmentIndex: 3, elementIndex: 2 } → segmentIndex[3].elementIndex[2]. A non-number field (which a position should
never carry) is dropped, so a stray value can never reach a diagnostic. Falls back to "?" when no
numeric index is present.
Parameters
pos
unknown
A parser position object (index-only by the parser's contract).
Returns
string
A value-free locator built solely from numeric indices.
Example
import { valueFreeLocator } from "@cosyte/cli";
valueFreeLocator({ segmentIndex: 3, elementIndex: 2 }); // => "segmentIndex[3].elementIndex[2]"
valueFreeLocator({}); // => "?"