quario 0.1.0 → 0.2.0
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.
- package/CHANGELOG.md +138 -0
- package/README.md +19 -4
- package/lib/index.d.ts +154 -10
- package/lib/index.js +109 -67
- package/lib/license.js +1 -1
- package/lib/locate.js +43 -56
- package/lib/plan.js +328 -136
- package/lib/scope.js +4 -10
- package/lib/stream.js +6 -6
- package/lib/style.js +23 -8
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,144 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2026-09-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **A report default: one `style` block for the whole document.** A top-level
|
|
15
|
+
`style` beside `header`/`detail`/`footer` states the typeface a report is set
|
|
16
|
+
in, so a document with one face names it once instead of on every item, every
|
|
17
|
+
table column, every header and every total cell. It takes `family` and
|
|
18
|
+
`size`; any other declaration there is a located definition error, exactly as
|
|
19
|
+
a text declaration on an image item is. Values are literals or `=`
|
|
20
|
+
expressions like any other style block's, resolved once per render in report
|
|
21
|
+
scope.
|
|
22
|
+
|
|
23
|
+
- **`report-start` carries the resolved report default as `style`.** A
|
|
24
|
+
report-level fact, never merged into an item's own `style`: an event's
|
|
25
|
+
`style` stays what the author wrote on that node, and a consumer composes the
|
|
26
|
+
default itself, once — under its own band-role defaults and under every
|
|
27
|
+
event's own style. Absent when the report declares none, so a consumer
|
|
28
|
+
written before this field renders in its own baseline exactly as it did.
|
|
29
|
+
|
|
30
|
+
- **An `uppercase` style declaration.** A boolean beside `bold` and `italic`,
|
|
31
|
+
literal or an `=` expression, for the capitalised column labels business
|
|
32
|
+
forms are usually set with. It is capitals, not small caps — real small caps
|
|
33
|
+
need a font feature the PDF target's built-in faces cannot supply, so the
|
|
34
|
+
declaration promises only what every target can draw. Image items keep
|
|
35
|
+
refusing it, as they refuse every text declaration.
|
|
36
|
+
|
|
37
|
+
- **A `split` item places values across the line instead of down the band.**
|
|
38
|
+
The invoice header's "seller left, customer right", which a band could not
|
|
39
|
+
say before. `{ "type": "split", "slots": [...] }` takes two or more slots,
|
|
40
|
+
each an ordinary `text` or `image` item plus an optional `width` percentage
|
|
41
|
+
under the same rules a table column's obeys; width-less slots divide what
|
|
42
|
+
the sized ones leave, evenly. A split is always the full content width and
|
|
43
|
+
never nests — it says what sits beside what, never where anything is — and
|
|
44
|
+
a slot that renders nothing keeps its width, so a line's geometry never
|
|
45
|
+
moves with the data. Splits may appear in every item array except table and
|
|
46
|
+
total cells.
|
|
47
|
+
|
|
48
|
+
- **`split-start` / `split-end` bracket a split's slots on the event stream.**
|
|
49
|
+
`split-start` carries the slot geometry, then one ordinary `item` or `image`
|
|
50
|
+
event per slot in order, then `split-end`. Existing consumers need no
|
|
51
|
+
change: the walk driver's missing-handler rule means a target that ignores
|
|
52
|
+
the bracket still receives the slot items and renders them stacked.
|
|
53
|
+
|
|
54
|
+
- **`quario().plan(schema, funcs?)` hands the whole traversal over at once.**
|
|
55
|
+
Returns `{ report, problems, anchors }` from one descent: the compiled
|
|
56
|
+
report (`null` while the document has problems), every problem as
|
|
57
|
+
`{ path, source?, message, diagnostic? }`, and a map from each compiled
|
|
58
|
+
source's schema path to the anchors and group handles it reads. A host that
|
|
59
|
+
validates and renders per edit — an editor — pays one traversal instead of
|
|
60
|
+
two, can point at a problem in its own UI without parsing a message apart,
|
|
61
|
+
and can tell where a node may safely move. `validate()` is unchanged: its
|
|
62
|
+
strings are those problems' `message` fields.
|
|
63
|
+
- **Every problem keeps its own located diagnostic.** `validate()` retained
|
|
64
|
+
`start`/`end` offsets on at most one problem per document; the structured
|
|
65
|
+
list carries each problem's own, so a consumer can underline the offending
|
|
66
|
+
character in every faulty expression rather than only the first.
|
|
67
|
+
- **Events name the definition behind them.** `item`, `image` and
|
|
68
|
+
`group-start` events carry `path`, the schema path of the node that
|
|
69
|
+
produced them; `table-start` carries `detail` and its columns their own,
|
|
70
|
+
and every table cell carries its column definition's path (a total cell its
|
|
71
|
+
`detail.total[i]` entry). Rows carry no identity — a row is data, not
|
|
72
|
+
schema. Additive: a consumer that ignores the field is unaffected.
|
|
73
|
+
- **`display(value)` joins one value the way `text()` does.** The scalar
|
|
74
|
+
display rule behind the token join, re-exported beside `text()` so a stream
|
|
75
|
+
consumer that stringifies token values itself renders exactly what the
|
|
76
|
+
official targets render — Dates included.
|
|
77
|
+
|
|
78
|
+
- **`maxDepth: Infinity` opts a query budget out.** The data query's traversal
|
|
79
|
+
budgets accept an explicit `Infinity` per key for "this budget, unbounded".
|
|
80
|
+
The 500-deep default is unchanged — it is now padvinder's own, applied for
|
|
81
|
+
every consumer rather than added by quario at the seam.
|
|
82
|
+
|
|
83
|
+
- **Located data-query errors carry padvinder's code and span.** A `data`
|
|
84
|
+
query that does not parse now surfaces with padvinder's `code` and
|
|
85
|
+
`start`/`end` offsets into the query you wrote — filter faults included —
|
|
86
|
+
alongside the band/item path quario already attached. The code names the
|
|
87
|
+
category of mistake: `PADVINDER_MISSING_ROOT`, `PADVINDER_BAD_SELECTOR`,
|
|
88
|
+
`PADVINDER_UNCLOSED_BRACKET`, `PADVINDER_BAD_STRING`,
|
|
89
|
+
`PADVINDER_UNKNOWN_FUNCTION`, or `PADVINDER_SYNTAX` for a path character or
|
|
90
|
+
filter body that is open-endedly not a query. Traversal budgets exceeded at
|
|
91
|
+
render time keep `limit`/`actual` and carry no span.
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
|
|
95
|
+
- **Cells render straight over the engine scope chain.** A text cell no longer
|
|
96
|
+
allocates a wrapper scope and an anchor pair per cell per row — quario's
|
|
97
|
+
chain already binds `$` at the render base and `@` on the detail row, and
|
|
98
|
+
sjabloon now renders over it as-is. A 4-column stream over a million rows
|
|
99
|
+
went from 1.7s to 0.5s. No report changes what it renders. Requires
|
|
100
|
+
sjabloon 0.11.
|
|
101
|
+
|
|
102
|
+
- **A compiled report's `functions` carry signatures.** Each entry is now
|
|
103
|
+
`{ name, arity, doc? }` instead of a bare name — `arity` from the function's
|
|
104
|
+
declared parameter count (or its own numeric `arity` where rest parameters
|
|
105
|
+
mislead `length`), `doc` from an own `doc` string when it carries one — in
|
|
106
|
+
the same call-first-seen order. `names` is unchanged. Requires xprsn 0.11
|
|
107
|
+
and sjabloon 0.11.
|
|
108
|
+
|
|
109
|
+
- **A bare `Date` renders as ISO 8601 UTC, the same on every machine.**
|
|
110
|
+
Display text for a `Date` value was `String(date)`, which bakes the
|
|
111
|
+
rendering host's timezone and locale into the output — so one report
|
|
112
|
+
produced different bytes on different machines. Every target now renders a
|
|
113
|
+
valid `Date` as its `toISOString()` form through the one shared display
|
|
114
|
+
rule; an invalid `Date` keeps its deterministic `Invalid Date` text.
|
|
115
|
+
Reports that want a formatted date keep using a registered function,
|
|
116
|
+
exactly as before.
|
|
117
|
+
|
|
118
|
+
- **A bad literal pattern in the data query is a definition error.** A typo'd
|
|
119
|
+
I-Regexp written as a string literal in `match()`/`search()` used to
|
|
120
|
+
produce a plausible empty report with no signal; `report()` and
|
|
121
|
+
`validate()` now surface it at compile time as a located error, with
|
|
122
|
+
offsets at the pattern literal in the query. The class and `code` are
|
|
123
|
+
treffer's — a malformed pattern is a `SyntaxError` with `TREFFER_SYNTAX`,
|
|
124
|
+
one past treffer's limits a `RangeError` with a `TREFFER_MAX_*` code and
|
|
125
|
+
`limit`/`actual` — on the same rule that already gives xprsn's codes to a
|
|
126
|
+
fault in an expression: the engine that decided the fault names it. A
|
|
127
|
+
pattern that arrives from render data keeps RFC 9535 semantics and still
|
|
128
|
+
matches nothing at render time. Requires padvinder 0.8.
|
|
129
|
+
|
|
130
|
+
- **Each engine relocates its own diagnostic.** A located error is now a copy
|
|
131
|
+
made by the engine that raised it (xprsn, sjabloon, or padvinder), so it
|
|
132
|
+
carries every field that engine puts on a diagnostic — nothing is lost in
|
|
133
|
+
quario's re-throw, today or when an engine adds a field — and it still
|
|
134
|
+
passes that engine's own `isDiagnostic`. Host errors are wrapped as plain
|
|
135
|
+
errors with no diagnostic metadata, exactly as before. Requires xprsn 0.10,
|
|
136
|
+
sjabloon 0.9, and padvinder 0.5. No report changes what it renders.
|
|
137
|
+
|
|
138
|
+
### Fixed
|
|
139
|
+
|
|
140
|
+
- **A host error cannot pose as the report's diagnostic.** `report()` rethrows
|
|
141
|
+
the first definition problem's located engine error; it chose that error by
|
|
142
|
+
probing for a `code` property, so a host error class that stamps `code` on
|
|
143
|
+
itself in its constructor was rethrown as if the engines had raised it. The
|
|
144
|
+
choice now goes through the same identity-based authentication as
|
|
145
|
+
`isDiagnostic`; everything else falls back to a plain `SyntaxError` naming
|
|
146
|
+
the first problem, as before.
|
|
147
|
+
|
|
10
148
|
## [0.1.0] - 2026-08-27
|
|
11
149
|
|
|
12
150
|
### Added
|
package/README.md
CHANGED
|
@@ -84,11 +84,11 @@ row, an optional `total-row`, and `table-end`.
|
|
|
84
84
|
| Event | Carries |
|
|
85
85
|
| -------------- | ------------------------------------------------------------------------------------------- |
|
|
86
86
|
| `report-start` | `params`, resolved report `aggregates`, optional `page` band closures, `columns`, `marking` |
|
|
87
|
-
| `item` | `role`, `tokens`, optional `style`, `run`
|
|
88
|
-
| `image` | `role`, `bytes`, `format` (`png` \| `jpeg`), `fit`, optional `alt`, `style`, `run`
|
|
89
|
-
| `group-start` | `name`, `depth`, `key`, `aggregates`, optional `break`, `reset`, `columns`
|
|
87
|
+
| `item` | `role`, `path`, `tokens`, optional `style`, `run` |
|
|
88
|
+
| `image` | `role`, `path`, `bytes`, `format` (`png` \| `jpeg`), `fit`, optional `alt`, `style`, `run` |
|
|
89
|
+
| `group-start` | `name`, `depth`, `key`, `aggregates`, `path`, optional `break`, `reset`, `columns` |
|
|
90
90
|
| `group-end` | `name`, `depth` |
|
|
91
|
-
| `table-start` | `columns` (each `header`, optional `width`)
|
|
91
|
+
| `table-start` | `path`, `columns` (each `header`, `path`, optional `width`) |
|
|
92
92
|
| `row` | `cells`, optional `style`, `run` |
|
|
93
93
|
| `total-row` | `cells` |
|
|
94
94
|
| `table-end` | - |
|
|
@@ -145,6 +145,21 @@ validate({ data: "$.o[*]", sort: [{ by: "=@.a", dir: "up" }] });
|
|
|
145
145
|
`report()` throws on the first problem instead. Validation and compilation share one traversal,
|
|
146
146
|
so `validate()` can never disagree with what `report()` accepts.
|
|
147
147
|
|
|
148
|
+
### `quario().plan(schema, functions?)`
|
|
149
|
+
|
|
150
|
+
The one traversal, whole — for hosts that validate and render in a loop, like an editor. Returns
|
|
151
|
+
`{ report, problems, anchors }`: the compiled report (`null` while the document has problems),
|
|
152
|
+
every problem structurally as `{ path, source?, message, diagnostic? }` (the `message` is exactly
|
|
153
|
+
`validate()`'s string, and every problem keeps its own located diagnostic with `start`/`end`
|
|
154
|
+
offsets, not only the first), and `anchors`, mapping each compiled source's schema path to the
|
|
155
|
+
anchors and group handles it reads — the unfiltered complement of `names`.
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
const { report, problems, anchors } = quario().plan(schema);
|
|
159
|
+
if (report) await report.render(html(), data);
|
|
160
|
+
else console.error(problems[0].path, problems[0].message);
|
|
161
|
+
```
|
|
162
|
+
|
|
148
163
|
### `isDiagnostic(error)`
|
|
149
164
|
|
|
150
165
|
True when a caught value is one of the stack's located errors: quario's own, or one thrown
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { PadvinderErrorCode, QueryOptions, QueryPath } from "padvinder";
|
|
1
|
+
import type { PadvinderErrorCode, QueryOptions, QueryPath, TrefferErrorCode } from "padvinder";
|
|
2
|
+
import type { XprsnErrorCode, XprsnSignature } from "xprsn";
|
|
2
3
|
import type {
|
|
3
4
|
LiteralToken as SjabloonLiteralToken,
|
|
4
5
|
SjabloonBlock,
|
|
@@ -44,6 +45,8 @@ export interface StyleDeclarations {
|
|
|
44
45
|
italic?: ExpressionValue<boolean>;
|
|
45
46
|
underline?: ExpressionValue<boolean>;
|
|
46
47
|
strikethrough?: ExpressionValue<boolean>;
|
|
48
|
+
/** Render the text in capitals. Capitals, not small caps. */
|
|
49
|
+
uppercase?: ExpressionValue<boolean>;
|
|
47
50
|
/** Text color, `#rgb`/`#rrggbb`. */
|
|
48
51
|
color?: ExpressionValue<string>;
|
|
49
52
|
/** Background color, `#rgb`/`#rrggbb`. */
|
|
@@ -84,6 +87,12 @@ export type ImageFit = "natural" | "width";
|
|
|
84
87
|
*/
|
|
85
88
|
export type ImageStyleDeclarations = Pick<StyleDeclarations, "background" | "align">;
|
|
86
89
|
|
|
90
|
+
/**
|
|
91
|
+
* What a report default declares: the two declarations a typeface is made of.
|
|
92
|
+
* Anything else is a definition error, as on an image item.
|
|
93
|
+
*/
|
|
94
|
+
export type ReportStyleDeclarations = Pick<StyleDeclarations, "family" | "size">;
|
|
95
|
+
|
|
87
96
|
/**
|
|
88
97
|
* A host-supplied raster graphic in the band flow. `source` is an expression
|
|
89
98
|
* (never a literal — JSON has no way to write bytes) yielding the complete
|
|
@@ -101,8 +110,31 @@ export interface ImageItem {
|
|
|
101
110
|
style?: ImageStyleDeclarations;
|
|
102
111
|
}
|
|
103
112
|
|
|
104
|
-
/**
|
|
105
|
-
|
|
113
|
+
/**
|
|
114
|
+
* One slot of a split: an ordinary item, plus the width share that is a slot
|
|
115
|
+
* property rather than an item one. A split may not stand in a slot —
|
|
116
|
+
* placement inside placement is the coordinate system quario does not have.
|
|
117
|
+
*/
|
|
118
|
+
export type SplitSlot = (TextItem | ImageItem) & {
|
|
119
|
+
/** Slot width as a percentage of the content width (0 < width <= 100). */
|
|
120
|
+
width?: number;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Items placed across the content width rather than stacked down the band —
|
|
125
|
+
* the invoice header's "seller left, customer right". A split is always the
|
|
126
|
+
* full content width and never nests; a slot that renders nothing keeps its
|
|
127
|
+
* width, so the line's geometry does not move with the data.
|
|
128
|
+
*/
|
|
129
|
+
export interface SplitItem {
|
|
130
|
+
type: "split";
|
|
131
|
+
slots: [SplitSlot, SplitSlot, ...SplitSlot[]];
|
|
132
|
+
visible?: ExpressionValue<boolean>;
|
|
133
|
+
style?: StyleDeclarations;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** One item in a band: text, an image, or a split. Future types may be additive. */
|
|
137
|
+
export type Item = TextItem | ImageItem | SplitItem;
|
|
106
138
|
|
|
107
139
|
export interface TableHeader {
|
|
108
140
|
value: CellValue;
|
|
@@ -178,6 +210,12 @@ export interface ReportSchema {
|
|
|
178
210
|
aggregates?: Record<string, ReducerSpec>;
|
|
179
211
|
/** Running accumulators, read as `run.<name>` on detail rows. */
|
|
180
212
|
run?: Record<string, ReducerSpec>;
|
|
213
|
+
/**
|
|
214
|
+
* The report default: the typeface this document is set in. It sits under
|
|
215
|
+
* the targets' band-role defaults and under every item's own `style`, so a
|
|
216
|
+
* declared `size` does not change a report header's headline size.
|
|
217
|
+
*/
|
|
218
|
+
style?: ReportStyleDeclarations;
|
|
181
219
|
header?: Item[];
|
|
182
220
|
empty?: Item[];
|
|
183
221
|
/**
|
|
@@ -246,6 +284,12 @@ export type Token = LiteralToken | ValueToken;
|
|
|
246
284
|
export interface EventCell {
|
|
247
285
|
tokens: Token[];
|
|
248
286
|
style?: Record<string, unknown>;
|
|
287
|
+
/**
|
|
288
|
+
* The definition's schema path, on cells that belong to one: a `row` cell
|
|
289
|
+
* carries its column's (`detail.columns[i]`), a `total-row` cell its
|
|
290
|
+
* `detail.total[i]` entry. Absent on page-band cells reached by closure.
|
|
291
|
+
*/
|
|
292
|
+
path?: string;
|
|
249
293
|
}
|
|
250
294
|
|
|
251
295
|
/** The page anchor a paginated target passes to page band closures. */
|
|
@@ -273,6 +317,15 @@ export interface ReportStartEvent {
|
|
|
273
317
|
page?: PageBandRenderers;
|
|
274
318
|
/** The declared page column count, present when the root declares one. */
|
|
275
319
|
columns?: number;
|
|
320
|
+
/**
|
|
321
|
+
* The resolved report default, present when the report declares one. It is
|
|
322
|
+
* a report-level fact rather than something merged into each item's style,
|
|
323
|
+
* so a consumer composes it once — under its own band-role defaults, and
|
|
324
|
+
* under every event's own `style`. Ignoring it renders the report in the
|
|
325
|
+
* consumer's own baseline, which is what a consumer written before this
|
|
326
|
+
* field already does.
|
|
327
|
+
*/
|
|
328
|
+
style?: Record<string, unknown>;
|
|
276
329
|
/**
|
|
277
330
|
* The marking wording, present when this render is not covered by a valid
|
|
278
331
|
* license key — including while verification is still settling (await the
|
|
@@ -286,6 +339,8 @@ export interface ReportStartEvent {
|
|
|
286
339
|
export interface ItemEvent {
|
|
287
340
|
type: "item";
|
|
288
341
|
role: ItemRole;
|
|
342
|
+
/** The item definition's schema path, e.g. `detail[0]`. */
|
|
343
|
+
path: string;
|
|
289
344
|
tokens: Token[];
|
|
290
345
|
style?: Record<string, unknown>;
|
|
291
346
|
run?: Record<string, unknown>;
|
|
@@ -297,6 +352,8 @@ export type ImageFormat = "png" | "jpeg";
|
|
|
297
352
|
export interface ImageEvent {
|
|
298
353
|
type: "image";
|
|
299
354
|
role: ItemRole;
|
|
355
|
+
/** The image definition's schema path. */
|
|
356
|
+
path: string;
|
|
300
357
|
/** The bytes exactly as the `source` expression yielded them. */
|
|
301
358
|
bytes: Uint8Array;
|
|
302
359
|
/** Sniffed from the bytes' magic numbers, so no consumer repeats it. */
|
|
@@ -308,9 +365,28 @@ export interface ImageEvent {
|
|
|
308
365
|
run?: Record<string, unknown>;
|
|
309
366
|
}
|
|
310
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Opens a split: the slot geometry, then one ordinary `item` or `image` event
|
|
370
|
+
* per slot in order, then `split-end`. A consumer with no handler for the
|
|
371
|
+
* bracket still receives the slot items and renders them stacked.
|
|
372
|
+
*/
|
|
373
|
+
export interface SplitStartEvent {
|
|
374
|
+
type: "split-start";
|
|
375
|
+
role: ItemRole;
|
|
376
|
+
/** One entry per slot, in order; `width` is absent on a width-less slot. */
|
|
377
|
+
slots: { width?: number }[];
|
|
378
|
+
style?: Record<string, unknown>;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export interface SplitEndEvent {
|
|
382
|
+
type: "split-end";
|
|
383
|
+
}
|
|
384
|
+
|
|
311
385
|
export interface GroupStartEvent {
|
|
312
386
|
type: "group-start";
|
|
313
387
|
name: string;
|
|
388
|
+
/** The group definition's schema path, e.g. `groups[0]`. */
|
|
389
|
+
path: string;
|
|
314
390
|
depth: number;
|
|
315
391
|
key: unknown;
|
|
316
392
|
aggregates: Record<string, unknown>;
|
|
@@ -329,7 +405,9 @@ export interface GroupEndEvent {
|
|
|
329
405
|
|
|
330
406
|
export interface TableStartEvent {
|
|
331
407
|
type: "table-start";
|
|
332
|
-
|
|
408
|
+
/** Always `detail` — the table definition's schema path. */
|
|
409
|
+
path: string;
|
|
410
|
+
columns: { header: EventCell; path: string; width?: number }[];
|
|
333
411
|
}
|
|
334
412
|
|
|
335
413
|
export interface RowEvent {
|
|
@@ -356,6 +434,8 @@ export type ReportEvent =
|
|
|
356
434
|
| ReportStartEvent
|
|
357
435
|
| ItemEvent
|
|
358
436
|
| ImageEvent
|
|
437
|
+
| SplitStartEvent
|
|
438
|
+
| SplitEndEvent
|
|
359
439
|
| GroupStartEvent
|
|
360
440
|
| GroupEndEvent
|
|
361
441
|
| TableStartEvent
|
|
@@ -364,10 +444,19 @@ export type ReportEvent =
|
|
|
364
444
|
| TableEndEvent
|
|
365
445
|
| ReportEndEvent;
|
|
366
446
|
|
|
447
|
+
/**
|
|
448
|
+
* One registry function a compiled report calls: its arity (the function's
|
|
449
|
+
* declared parameter count, or its own numeric `arity` where `length`
|
|
450
|
+
* misleads) and its own `doc` string when it carries one — xprsn's
|
|
451
|
+
* `signatures()` convention, in call-first-seen order. Aliased so hosts type
|
|
452
|
+
* the metadata from 'quario' alone, without their own xprsn dependency.
|
|
453
|
+
*/
|
|
454
|
+
export type FunctionSignature = XprsnSignature;
|
|
455
|
+
|
|
367
456
|
export interface ReportEventStream {
|
|
368
457
|
(data?: unknown): Generator<ReportEvent, void, undefined>;
|
|
369
458
|
readonly names: readonly string[];
|
|
370
|
-
readonly functions: readonly
|
|
459
|
+
readonly functions: readonly FunctionSignature[];
|
|
371
460
|
readonly paths: readonly QueryPath[];
|
|
372
461
|
}
|
|
373
462
|
|
|
@@ -397,10 +486,23 @@ export function walk(events: Iterable<ReportEvent>, handlers: WalkHandlers): Pro
|
|
|
397
486
|
*/
|
|
398
487
|
export function breathe(): Promise<void>;
|
|
399
488
|
|
|
400
|
-
|
|
489
|
+
/**
|
|
490
|
+
* Every code a located diagnostic can carry, which is a code from whichever
|
|
491
|
+
* engine decided the fault: quario relocates xprsn's directly, sjabloon
|
|
492
|
+
* carries xprsn's on a fault inside an expression, and padvinder carries
|
|
493
|
+
* treffer's on a pattern literal rejected when the query compiles.
|
|
494
|
+
*
|
|
495
|
+
* `TrefferErrorCode` reaches this union through padvinder, which re-exports
|
|
496
|
+
* it, so quario needs no treffer dependency to name it here.
|
|
497
|
+
*/
|
|
498
|
+
export type QuarioErrorCode =
|
|
499
|
+
| SjabloonErrorCode
|
|
500
|
+
| XprsnErrorCode
|
|
501
|
+
| PadvinderErrorCode
|
|
502
|
+
| TrefferErrorCode;
|
|
401
503
|
|
|
402
504
|
export interface QuarioDiagnostic extends Error {
|
|
403
|
-
/** Absent on
|
|
505
|
+
/** Absent on option and target-definition faults; present on every other diagnostic. */
|
|
404
506
|
readonly code?: QuarioErrorCode;
|
|
405
507
|
readonly start?: number;
|
|
406
508
|
readonly end?: number;
|
|
@@ -414,7 +516,7 @@ export interface CompiledReport {
|
|
|
414
516
|
/** The raw event seam: one generator of report events per call. */
|
|
415
517
|
stream(data?: unknown): Generator<ReportEvent, void, undefined>;
|
|
416
518
|
readonly names: readonly string[];
|
|
417
|
-
readonly functions: readonly
|
|
519
|
+
readonly functions: readonly FunctionSignature[];
|
|
418
520
|
readonly paths: readonly QueryPath[];
|
|
419
521
|
/**
|
|
420
522
|
* Render this compiled report through one target. Resolves the target's
|
|
@@ -424,6 +526,33 @@ export interface CompiledReport {
|
|
|
424
526
|
render<Out>(target: Target<string, Out>, data?: unknown): Promise<Awaited<Out>>;
|
|
425
527
|
}
|
|
426
528
|
|
|
529
|
+
/**
|
|
530
|
+
* One definition problem, structurally: the schema path it sits at, the
|
|
531
|
+
* offending author source when the problem came from compiling one, the whole
|
|
532
|
+
* located message (`validate()`'s string is exactly this field), and the
|
|
533
|
+
* engine's located diagnostic when one authenticated the fault — every
|
|
534
|
+
* problem keeps its own, offsets included, not only the first.
|
|
535
|
+
*/
|
|
536
|
+
export interface Problem {
|
|
537
|
+
readonly path: string;
|
|
538
|
+
readonly source?: string;
|
|
539
|
+
readonly message: string;
|
|
540
|
+
readonly diagnostic?: QuarioDiagnostic;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* The plan: both readings of the one traversal, kept. `report` is the
|
|
545
|
+
* compiled report, or null while the document has problems; `problems` is the
|
|
546
|
+
* structured list `validate()` flattens to strings; `anchors` maps each
|
|
547
|
+
* compiled source's schema path to the anchors and group handles it reads —
|
|
548
|
+
* the unfiltered complement of `names`, which excludes them.
|
|
549
|
+
*/
|
|
550
|
+
export interface Plan {
|
|
551
|
+
readonly report: CompiledReport | null;
|
|
552
|
+
readonly problems: readonly Problem[];
|
|
553
|
+
readonly anchors: Readonly<Record<string, readonly string[]>>;
|
|
554
|
+
}
|
|
555
|
+
|
|
427
556
|
export interface Quario {
|
|
428
557
|
/**
|
|
429
558
|
* Settles when this instance's license key verification completes;
|
|
@@ -432,6 +561,12 @@ export interface Quario {
|
|
|
432
561
|
readonly license: Promise<LicenseInfo>;
|
|
433
562
|
/** Compile a definition once; every target renders from it. */
|
|
434
563
|
report(schema: ReportSchema, functions?: FunctionRegistry): CompiledReport;
|
|
564
|
+
/**
|
|
565
|
+
* The one traversal, whole: compiled report (null on problems), structured
|
|
566
|
+
* problems, and per-node anchor sets — one descent per edit for a host that
|
|
567
|
+
* validates and renders in a loop.
|
|
568
|
+
*/
|
|
569
|
+
plan(schema: unknown, functions?: FunctionRegistry): Plan;
|
|
435
570
|
}
|
|
436
571
|
|
|
437
572
|
/**
|
|
@@ -451,11 +586,20 @@ export function validate(schema: unknown, functions?: FunctionRegistry): string[
|
|
|
451
586
|
export function isDiagnostic(e: unknown): e is QuarioDiagnostic;
|
|
452
587
|
|
|
453
588
|
/**
|
|
454
|
-
* Join a token stream to display text: literals verbatim, values
|
|
455
|
-
* `
|
|
589
|
+
* Join a token stream to display text: literals verbatim, values through
|
|
590
|
+
* `display()`. Re-exported from sjabloon.
|
|
456
591
|
*/
|
|
457
592
|
export function text(tokens: readonly Token[]): string;
|
|
458
593
|
|
|
594
|
+
/**
|
|
595
|
+
* Display text for one token value — the scalar rule `text()` joins with,
|
|
596
|
+
* re-exported from sjabloon so targets stringify exactly as the stream does.
|
|
597
|
+
* A valid `Date` renders as ISO 8601 UTC (`toISOString()`), deterministically
|
|
598
|
+
* across machines; an invalid `Date` stays `"Invalid Date"`; nullish displays
|
|
599
|
+
* empty; everything else is `String(value)`.
|
|
600
|
+
*/
|
|
601
|
+
export function display(value: unknown): string;
|
|
602
|
+
|
|
459
603
|
/**
|
|
460
604
|
* The typed-cell seam: exactly one value token holding a finite number, a
|
|
461
605
|
* boolean, or a valid Date keeps its pre-stringify value; anything else —
|