quario
The engine. Compiles a definition into a tree of closures and emits an event stream that every render target consumes.
Creating an instance
quario(options?)
function quario(options?: QuarioOptions): QuarioCreates a configured instance. Host-level configuration only.
QuarioOptions
| Field | Type | Meaning |
|---|---|---|
license |
string |
License key, verified offline once at creation. |
locale |
string |
Locale for format. Defaults to "en-US". |
currency |
string |
Default ISO 4217 code for format: "currency". |
timeZone |
string |
Timezone for format: "date". Defaults to "UTC". |
query |
QueryOptions |
Budgets for the JSONPath selection. |
Quario
interface Quario {
readonly license: Promise<LicenseInfo>
report(schema: ReportSchema, functions?: FunctionRegistry): CompiledReport
plan(schema: unknown, functions?: FunctionRegistry): Plan
}license settles with the verification result and never rejects. report
throws on the first definition problem. plan returns everything one traversal
produced.
LicenseInfo
interface LicenseInfo {
licensed: boolean
licensee?: string
id?: string
}Compiling and rendering
CompiledReport
interface CompiledReport {
stream(data?: unknown): Generator<ReportEvent, void, undefined>
readonly names: readonly string[]
readonly functions: readonly FunctionSignature[]
readonly paths: readonly QueryPath[]
render<Out>(target: Target<string, Out>, data?: unknown): Promise<Awaited<Out>>
}render resolves the target’s output whether the target renders synchronously
or not. A malformed target throws synchronously as a definition error.
names is the union of free variables excluding engine anchors and group
handles. functions lists the registry functions called, in call-first-seen
order. paths is the frozen dependency topology of the data query.
Target<Name, Out>
interface Target<Name extends string = string, Out = unknown> {
name: Name
compile: (stream: ReportEventStream) => (data?: unknown) => Out
}The contract every render target honours. The engine calls compile once per
render call, so it must be cheap and stateless. Per-render work belongs in
the renderer it returns.
FunctionRegistry
type FunctionRegistry = Record<string, (...args: any[]) => any>Host functions a definition may call. A registered name shadows a built-in of the same name.
Checking a definition
validate(schema, functions?)
function validate(schema: unknown, functions?: FunctionRegistry): string[]Every problem in the definition, in document order, as located strings. Needs no instance and no data.
Plan
interface Plan {
readonly report: CompiledReport | null
readonly problems: readonly Problem[]
readonly anchors: Readonly<Record<string, readonly string[]>>
readonly warnings: readonly Warning[]
}report is null while the document has problems. anchors maps a compiled
source’s schema path to the anchors and handles it reads. warnings is advisory, in
document order from the same descent.
Problem
interface Problem {
readonly path: string
readonly source?: string
readonly message: string
readonly diagnostic?: QuarioDiagnostic
}Frozen. message is exactly the string validate returns for this problem.
Warning
interface Warning {
readonly path: string
readonly message: string
}An advisory says the document declares something nothing will read. Not a
Problem at lower severity, and not its shape. It carries no source and no
diagnostic, because nothing raised, and the engine decides nothing will read
a declaration only after every compile has succeeded.
isDiagnostic(e)
function isDiagnostic(e: unknown): e is QuarioDiagnosticTrue for a located diagnostic raised by a delegated engine, authenticated by identity. False for quario’s own verdicts and for a registered function’s throw.
QuarioDiagnostic
interface QuarioDiagnostic extends Error {
readonly code?: QuarioErrorCode
readonly start?: number
readonly end?: number
readonly limit?: number
readonly actual?: number
readonly blocks?: readonly SjabloonBlock[]
}code is absent on option and target-definition faults. limit and actual
appear on a budget failure. Diagnostic codes sit outside the frozen authoring
surface and may change.
Writing a target
These exports exist for code consuming the event stream. An application
rendering through html(), pdf(), xlsx() or csv() needs none of them.
Custom targets covers what they’re for
and builds a complete target from them.
walk(events, handlers)
function walk(events: Iterable<ReportEvent>, handlers: WalkHandlers): Promise<void>Dispatches one render’s events to per-event handlers in stream order and once each, pulling lazily and handing the loop back between batches. Handlers are synchronous, and a promise one returns isn’t awaited.
breathe()
function breathe(): Promise<void>Hands the event loop back to the host, resolving once it has had its turn.
text(tokens) and display(value)
function text(tokens: readonly Token[]): string
function display(value: unknown): stringtext joins a token stream to display text. display is the scalar rule it
joins with, so a target stringifies exactly as the stream does. A valid Date
renders as ISO 8601 UTC, an invalid one stays "Invalid Date", and nullish
displays empty.
typed(tokens, decl?)
function typed(
tokens: readonly Token[],
decl?: ResolvedFormat | FormatKind,
): number | boolean | Date | undefinedThe typed-cell seam. Exactly one value token holding a finite number, a boolean
or a valid Date keeps its pre-stringify value. Anything else reports
undefined. Passing the resolved format opts into reviving a date string
under the date kind. One run of one value token is still a single-token
array. The second argument is that token's run's resolved format rather
than the cell's.
styledRuns(tokens)
interface TokenRun {
style: Record<string, unknown> | null
tokens: Token[]
}
function styledRuns(tokens: Token[]): TokenRun[]Groups a cell’s tokens into its runs, in order, consecutive tokens with equal
styles forming one. style is null where the cell’s own applies. Equality
goes one level deep, which is exhaustive rather than approximate, since
format is the only object-valued declaration and is itself flat. The built-in
targets consume it, so a custom target grouping through it can’t drift from
them.
format(value, style?, options?)
function format(
value: unknown,
style?: { format?: unknown; currency?: unknown } | null,
options?: { locale?: string; currency?: string; timeZone?: string } | null,
): string | undefinedPresents a token for a cell’s resolved style. Returns nothing when the kind
doesn’t apply, so the caller falls back to display().
currencyOf(style?, options?)
function currencyOf(
style?: { currency?: unknown } | null,
options?: { currency?: string } | null,
): string | nullWhich code a cell wears under format: "currency". Branch on this rather than
on style.currency ?? instanceCurrency, which gets an unusable code wrong.
fractionDigits(style?, options?)
function fractionDigits(
style?: { format?: unknown; currency?: unknown } | null,
options?: { currency?: string } | null,
): number | undefinedHow many fraction digits a cell presents. Returns nothing where the cell presents no count.
isReportBand(role)
function isReportBand(role: string | undefined): booleanWhether a band role names one of the report’s own bands rather than a group instance’s.
hostOptions(value, keys, at) and hostMeta(value, at)
interface QuarioMeta {
title?: string
author?: string
subject?: string
}
function hostOptions<T>(value: T, keys: readonly string[], at: string): T
function hostMeta<T extends QuarioMeta | null | undefined>(value: T, at: string): TThe checks every official target refuses its options with, exported so a target
of your own refuses them the same way. hostOptions closes a key set. It throws
a TypeError prefixed with at when the value carries a key outside keys. A
host’s typo then costs one stack trace rather than an option silently lost.
Nullish is absence, and own enumerable keys only, so an inherited property never
counts as an option the host wrote.
hostMeta validates the { title, author, subject } contract the document
targets share — each a string, and nothing else. It checks the three once here
because every document format carries the same three. What each format calls them
inside its own package stays that target’s business. Both return the value you
hand them, so a factory reads its options through them.
imageError(path, said, cause?)
function imageError(path: string | undefined, said: string, cause?: unknown): ErrorMints an image failure named on the item that asked for the bytes. The result
takes cause’s class. Not a diagnostic.
STYLE_NAMES, RUN_STYLE_NAMES and FORMAT_VOCABULARY
const STYLE_NAMES: readonly string[]
const RUN_STYLE_NAMES: readonly string[]
const FORMAT_VOCABULARY: {
readonly kinds: readonly FormatKind[]
readonly forms: readonly DateForm[]
readonly modifiers: Readonly<Record<FormatKind, 'digits' | 'form'>>
readonly defaultForm: DateForm
readonly maxDigits: number
}The closed vocabularies as data, for a tool that offers them rather than checks
them. RUN_STYLE_NAMES is the inline half a styled run may wear, in the
vocabulary's own order.