quario 0.12.0 → 0.13.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 +135 -0
- package/README.md +29 -2
- package/lib/index.d.ts +206 -44
- package/lib/index.js +65 -17
- package/lib/license.js +12 -10
- package/lib/names.js +2 -0
- package/lib/plan.js +395 -64
- package/lib/schema.json +1279 -0
- package/package.json +8 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,140 @@
|
|
|
1
1
|
# quario
|
|
2
2
|
|
|
3
|
+
## 0.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- A band gains a `grid` item: splits that share one column geometry.
|
|
8
|
+
|
|
9
|
+
A statement is twenty lines of a label and an amount, on the same two widths. As splits, each line restated its widths:
|
|
10
|
+
|
|
11
|
+
```jsonc
|
|
12
|
+
{ "type": "split", "slots": [
|
|
13
|
+
{ "type": "text", "value": "Opening", "width": 70 },
|
|
14
|
+
{ "type": "text", "value": "{{ @.opening }}", "width": 30, "style": { "align": "right" } }
|
|
15
|
+
] }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
A grid states the widths, and each column's style, once:
|
|
19
|
+
|
|
20
|
+
```jsonc
|
|
21
|
+
{
|
|
22
|
+
"type": "grid",
|
|
23
|
+
"columns": [{ "width": 70 }, { "width": 30, "style": { "align": "right" } }],
|
|
24
|
+
"rows": [
|
|
25
|
+
{ "slots": [{ "type": "text", "value": "Opening" }, { "type": "text", "value": "{{ @.opening }}" }] },
|
|
26
|
+
{},
|
|
27
|
+
{ "slots": [{ "type": "text", "value": "Total" }, { "type": "text", "value": "{{ @.total }}" }], "style": { "bold": true } }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
A row is a split without `type`, and it keeps every rule a split has. A column's `style` is the layer under each of its slots, and a slot's own declarations win. A row that names fewer slots than there are columns leaves the rest empty, so `{}` is a spacer line and a one-slot row is a label-only line.
|
|
33
|
+
|
|
34
|
+
Each row reaches a target as the split it is, so the event stream does not change and no target needed an update. No existing report changes.
|
|
35
|
+
|
|
36
|
+
- The package now ships a JSON Schema of the report document.
|
|
37
|
+
|
|
38
|
+
The file is `lib/schema.json`, and the package exports it as `quario/schema.json`. Point `$schema` at the installed copy, and an editor checks the document and shows the documentation for each key:
|
|
39
|
+
|
|
40
|
+
```jsonc
|
|
41
|
+
{ "$schema": "./node_modules/quario/lib/schema.json", "data": "$.orders[*]" }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
A report document accepts one new top-level key, `$schema`. Its value must be a string. The engine checks the type and reads nothing else, so a document keeps its `$schema` through an upgrade. Anywhere below the top level, `$schema` stays an unknown key.
|
|
45
|
+
|
|
46
|
+
The JSON Schema proves the shape of each value, and `validate()` still proves the document. A document can pass the JSON Schema and fail `validate()`: a rule across two values, a reserved name, or an expression that does not compile. The strict structured-output modes of OpenAI and Anthropic do not accept the file, because a report document leaves most of its keys out.
|
|
47
|
+
|
|
48
|
+
The TypeScript declarations are stricter in one place. A parameter's value under `params` is now typed as any JSON value except a plain object. The engine always read a plain object there as a declaration, so a document that the new type refuses was never the document it looked like.
|
|
49
|
+
|
|
50
|
+
- **A license key has an end date and no start date.** A key covers every version released on or before its `to` date. Before, a key also named a `from` date, and a version released before that date stayed marked. The engine now ignores a `from` in a key. When a key ends before the release date of the installed version, the warning names both dates.
|
|
51
|
+
- A value the runtime has no text form for is now a located render error rather than `[object Object]` in the document.
|
|
52
|
+
|
|
53
|
+
A cell reaches its reader through `String(value)`. A plain object, a `Map` and a `Set` have no text form of their own, so that falls back to a tag: `[object Object]`, `[object Map]`, `[object Set]`. A tag lays out, paginates and lands in a worksheet cell, and the document is wrong. A few values have no text form at all, and `String()` throws on them — an object with no prototype, a boxed symbol. The engine now refuses both kinds and names the cell:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
detail[0].value [{{ @.address }}]: a value with no text form, which would print as [object Object]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The rule reads the value, not its source, so a registered function's result and a data field answer to it alike. A value that says what it is still prints it: a class with its own `toString`, an array (`[1, 2]` prints `1,2`), a `Date`. An absent read still prints nothing. A computed property is outside the rule, because a group's `by` is an identity rather than text — `by: "=@"` makes each row its own instance — and a `where` and a `visible` are read for truth.
|
|
60
|
+
|
|
61
|
+
Every entry in the function registry must be a function. `plan` reports one that is not at `functions.<name>`, where before it raised an unhandled `TypeError` out of `plan` itself at a caller who had only asked a question.
|
|
62
|
+
|
|
63
|
+
A report that printed `[object Object]` stops rendering. It was printing a value no reader could use.
|
|
64
|
+
|
|
65
|
+
- A document may now name its paper and turn it, and its margin may name each side.
|
|
66
|
+
|
|
67
|
+
```jsonc
|
|
68
|
+
{
|
|
69
|
+
"page": {
|
|
70
|
+
"size": "letter",
|
|
71
|
+
"orientation": "landscape",
|
|
72
|
+
"margin": { "top": 36, "right": 29, "bottom": 36, "left": 29 }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`page.size` takes `"A4"` or `"letter"`. A `[width, height]` pair stays a target option. `page.orientation` takes `"portrait"` or `"landscape"`, and it turns whichever paper is in force. `page.margin` still takes one number for all four sides.
|
|
78
|
+
|
|
79
|
+
The rule `page.margin` already followed now covers all three keys. The document's key wins where it declares one, a target option applies where it does not, and both declaring the same key is a render error. `orientation` in a document beside a target's `size` is not both.
|
|
80
|
+
|
|
81
|
+
Each target writes the paper: the PDF and the layout draw on it, HTML writes an `@page` size and per-side margin, and DOCX writes `pgSz` with `w:orient` and `pgMar` per side. XLSX writes the paper code, the orientation and each print margin. CSV withdraws all three.
|
|
82
|
+
|
|
83
|
+
The capability descriptors gain `page.size` and `page.orientation`, and both are names a document may mark `required`.
|
|
84
|
+
|
|
85
|
+
A target's margin error now reads `expected a non-negative number, or { top, right, bottom, left }, that leaves the page room`.
|
|
86
|
+
|
|
87
|
+
- `params` is now what the report declares it needs, and a render may supply one.
|
|
88
|
+
|
|
89
|
+
A bare value under `params` still **is** the parameter's value, so a document of constants reads the way it always did:
|
|
90
|
+
|
|
91
|
+
```jsonc
|
|
92
|
+
{ "params": { "year": 2025, "branded": true } }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
A plain object is a **declaration** instead, closed at `default` and `type`:
|
|
96
|
+
|
|
97
|
+
```jsonc
|
|
98
|
+
{
|
|
99
|
+
"params": {
|
|
100
|
+
"year": { "type": "number", "default": 2025 },
|
|
101
|
+
"region": { "type": "string" }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`type` names a JSON kind — `string`, `number`, `boolean`, `array`, `object` — because a parameter is a JSON value. There is no `date` and no `enum`.
|
|
107
|
+
|
|
108
|
+
**`default` absent makes the parameter required.** The engine rejects a render that supplies no value for it, before any expression runs. That is the main thing declaring buys: a report that states what it needs hears about it when a render does not bring it.
|
|
109
|
+
|
|
110
|
+
A host supplies values as the last argument to `render` and to `stream`:
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
await report.render(html(), data, { region: "EU" });
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Only a declared key may be supplied, a supplied value answers to the declared `type`, and values stay JSON and deep-frozen — now per render rather than once at compile.
|
|
117
|
+
|
|
118
|
+
**One kind of document changes meaning.** The engine reads an object-valued parameter as a declaration, so a document that wrote one for its value wraps it:
|
|
119
|
+
|
|
120
|
+
```jsonc
|
|
121
|
+
{ "params": { "config": { "default": { "retries": 3 } } } }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
An empty object is the sharpest case. `{ "config": {} }` now declares a parameter with no default, so every render of that document is refused until one supplies a value, or until the document wraps it.
|
|
125
|
+
|
|
126
|
+
Nothing else moves. A bare string, number, boolean or array is untouched.
|
|
127
|
+
|
|
128
|
+
A declaration may also carry a `label`, the text a person reads for the parameter. A labelled parameter is one a person supplies, so a host panel shows only those. The engine never renders a label.
|
|
129
|
+
|
|
130
|
+
A `null` default beside a `type` makes a typed parameter optional, and a render may then supply `null`:
|
|
131
|
+
|
|
132
|
+
```jsonc
|
|
133
|
+
{ "params": { "branch": { "type": "string", "default": null, "label": "Branch" } } }
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
A host reads what a document declares from `report.params` and from `plan(...).params`: one frozen `{ name, required, type?, default?, label? }` per parameter, in declaration order. A plan carries them whether or not the document compiled, so an editor can render a panel beside the problems.
|
|
137
|
+
|
|
3
138
|
## 0.12.0
|
|
4
139
|
|
|
5
140
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -70,8 +70,8 @@ key verification as `{ licensed, licensee?, id? }`.
|
|
|
70
70
|
|
|
71
71
|
### `report(schema, functions?)`
|
|
72
72
|
|
|
73
|
-
Compiles a report and returns the compiled report. `stream(data)` is the raw event generator.
|
|
74
|
-
`render(target, data)` takes a self-naming `{ name, compile }` object from a target factory
|
|
73
|
+
Compiles a report and returns the compiled report. `stream(data, params)` is the raw event generator, and `params` are the values this render supplies for what the document declares.
|
|
74
|
+
`render(target, data, params)` takes a self-naming `{ name, compile }` object from a target factory
|
|
75
75
|
(e.g. `html()` from `@quario/html`) or your own.
|
|
76
76
|
|
|
77
77
|
A render is async: quario awaits key verification before the target sees its first event. A
|
|
@@ -209,6 +209,33 @@ validate({ data: "$.o[*]", sort: [{ by: "=@.a", dir: "up" }] });
|
|
|
209
209
|
`report()` throws on the first problem instead. Validation and compilation share one traversal,
|
|
210
210
|
so `validate()` can never disagree with what `report()` accepts.
|
|
211
211
|
|
|
212
|
+
### JSON Schema
|
|
213
|
+
|
|
214
|
+
The package ships a JSON Schema of the report document. Point `$schema` at the installed copy,
|
|
215
|
+
and your editor checks the document and shows the documentation for each key:
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"$schema": "./node_modules/quario/lib/schema.json",
|
|
220
|
+
"data": "$.orders[*]",
|
|
221
|
+
"detail": [{ "type": "text", "value": "{{ @.product }}" }]
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The path is relative to the report file. The engine accepts the `$schema` key and does not read
|
|
226
|
+
it.
|
|
227
|
+
|
|
228
|
+
Code reads the same file through the package export:
|
|
229
|
+
|
|
230
|
+
```js
|
|
231
|
+
import schema from "quario/schema.json" with { type: "json" };
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The JSON Schema proves the shape of each value. It does not replace `validate()`. Rules that
|
|
235
|
+
join two or more values, and every expression and template, stay with `validate()`. Use the
|
|
236
|
+
JSON Schema to constrain what an editor or a model writes. Use `validate()` to accept a
|
|
237
|
+
document.
|
|
238
|
+
|
|
212
239
|
### `quario().plan(schema, functions?, { targets }?)`
|
|
213
240
|
|
|
214
241
|
The one traversal, whole — for hosts that validate and render in a loop, like an editor. Returns
|
package/lib/index.d.ts
CHANGED
|
@@ -12,7 +12,46 @@ import type {
|
|
|
12
12
|
export type { QueryPath } from "padvinder";
|
|
13
13
|
|
|
14
14
|
export type FunctionRegistry = Record<string, (...args: any[]) => any>;
|
|
15
|
-
|
|
15
|
+
// Named so its pattern reaches every field that takes an expression, which is
|
|
16
|
+
// how the generated JSON Schema tells an expression from a literal.
|
|
17
|
+
/**
|
|
18
|
+
* An `=` expression: xprsn source after the leading `=`.
|
|
19
|
+
*
|
|
20
|
+
* @pattern ^=
|
|
21
|
+
*/
|
|
22
|
+
export type Expression = `=${string}`;
|
|
23
|
+
export type ExpressionValue<T = unknown> = T | Expression;
|
|
24
|
+
|
|
25
|
+
// The literal shapes the traversal checks one value at a time, named so each
|
|
26
|
+
// carries its rule as a tag. TypeScript reads each as the plain type. The tags
|
|
27
|
+
// are for the JSON Schema generated from this file (`lib/schema.json`), which
|
|
28
|
+
// holds each one to the check it mirrors in `style.js` or `plan.js`.
|
|
29
|
+
|
|
30
|
+
/** `#rgb` or `#rrggbb`. @pattern ^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$ */
|
|
31
|
+
type Color = string;
|
|
32
|
+
/** A three-letter ISO 4217 code, by shape. @pattern ^[A-Z]{3}$ */
|
|
33
|
+
type CurrencyCode = string;
|
|
34
|
+
/** @minLength 1 */
|
|
35
|
+
type NonEmpty = string;
|
|
36
|
+
/** Points, zero or more. @minimum 0 */
|
|
37
|
+
type Points = number;
|
|
38
|
+
/** Points, more than zero. @exclusiveMinimum 0 */
|
|
39
|
+
type PositivePoints = number;
|
|
40
|
+
/** A share of the width, in percent. @exclusiveMinimum 0 @maximum 100 */
|
|
41
|
+
type WidthShare = number;
|
|
42
|
+
/** @asType integer @minimum 1 */
|
|
43
|
+
type Count = number;
|
|
44
|
+
/** @asType integer @minimum 2 */
|
|
45
|
+
type ColumnCount = number;
|
|
46
|
+
/** @asType integer @minimum 0 @maximum 20 */
|
|
47
|
+
type Digits = number;
|
|
48
|
+
/** @minItems 1 */
|
|
49
|
+
type StyledRuns = StyledRun[];
|
|
50
|
+
/**
|
|
51
|
+
* A parameter's value when it is not a declaration: any JSON value but a plain
|
|
52
|
+
* object, which `params` reads as a declaration.
|
|
53
|
+
*/
|
|
54
|
+
type ParamValue = null | boolean | number | string | JsonValue[];
|
|
16
55
|
export type ReducerSpec = string;
|
|
17
56
|
|
|
18
57
|
/**
|
|
@@ -50,16 +89,16 @@ export type LineStyle = "solid" | "dashed" | "dotted";
|
|
|
50
89
|
*/
|
|
51
90
|
export type BoxDeclarations = {
|
|
52
91
|
/** Inset on that side, in points (>= 0). */
|
|
53
|
-
[S in Side as `padding${S}`]?: ExpressionValue<
|
|
92
|
+
[S in Side as `padding${S}`]?: ExpressionValue<Points>;
|
|
54
93
|
} & {
|
|
55
94
|
/** Stroke width on that side, in points (>= 0). `0` is a complete side that draws nothing. */
|
|
56
|
-
[S in Side as `border${S}Width`]?: ExpressionValue<
|
|
95
|
+
[S in Side as `border${S}Width`]?: ExpressionValue<Points>;
|
|
57
96
|
} & {
|
|
58
97
|
/** Line style of that side. */
|
|
59
98
|
[S in Side as `border${S}Style`]?: ExpressionValue<LineStyle>;
|
|
60
99
|
} & {
|
|
61
100
|
/** Stroke color of that side, `#rgb`/`#rrggbb`. */
|
|
62
|
-
[S in Side as `border${S}Color`]?: ExpressionValue<
|
|
101
|
+
[S in Side as `border${S}Color`]?: ExpressionValue<Color>;
|
|
63
102
|
};
|
|
64
103
|
|
|
65
104
|
/**
|
|
@@ -72,9 +111,9 @@ export type BoxDeclarations = {
|
|
|
72
111
|
*/
|
|
73
112
|
export interface StyleDeclarations extends BoxDeclarations {
|
|
74
113
|
/** `'sans'` | `'serif'` | `'mono'`, or an embedded font family name. */
|
|
75
|
-
family?: ExpressionValue<
|
|
114
|
+
family?: ExpressionValue<NonEmpty>;
|
|
76
115
|
/** Font size in points. */
|
|
77
|
-
size?: ExpressionValue<
|
|
116
|
+
size?: ExpressionValue<PositivePoints>;
|
|
78
117
|
bold?: ExpressionValue<boolean>;
|
|
79
118
|
italic?: ExpressionValue<boolean>;
|
|
80
119
|
underline?: ExpressionValue<boolean>;
|
|
@@ -82,9 +121,9 @@ export interface StyleDeclarations extends BoxDeclarations {
|
|
|
82
121
|
/** Render the text in capitals. Capitals, not small caps. */
|
|
83
122
|
uppercase?: ExpressionValue<boolean>;
|
|
84
123
|
/** Text color, `#rgb`/`#rrggbb`. */
|
|
85
|
-
color?: ExpressionValue<
|
|
124
|
+
color?: ExpressionValue<Color>;
|
|
86
125
|
/** Background color, `#rgb`/`#rrggbb`. */
|
|
87
|
-
background?: ExpressionValue<
|
|
126
|
+
background?: ExpressionValue<Color>;
|
|
88
127
|
/** Horizontal alignment within the cell. */
|
|
89
128
|
align?: ExpressionValue<Align>;
|
|
90
129
|
/**
|
|
@@ -107,7 +146,7 @@ export interface StyleDeclarations extends BoxDeclarations {
|
|
|
107
146
|
* the cell's own answer still, so the cell presents as display text rather
|
|
108
147
|
* than falling back to the instance's currency. Unread without the kind.
|
|
109
148
|
*/
|
|
110
|
-
currency?: ExpressionValue<
|
|
149
|
+
currency?: ExpressionValue<CurrencyCode>;
|
|
111
150
|
/**
|
|
112
151
|
* Where this cell's text points: a URL, or `#` and a group's `label` for a
|
|
113
152
|
* destination inside the document. The one declaration the engine judges
|
|
@@ -115,15 +154,15 @@ export interface StyleDeclarations extends BoxDeclarations {
|
|
|
115
154
|
* allowlist before it crosses, and a refused value is omitted, so the text
|
|
116
155
|
* renders and the link does not. A table row refuses it.
|
|
117
156
|
*/
|
|
118
|
-
href?: ExpressionValue<
|
|
157
|
+
href?: ExpressionValue<NonEmpty>;
|
|
119
158
|
/** Blank space before this item, in points. */
|
|
120
|
-
spaceBefore?: ExpressionValue<
|
|
159
|
+
spaceBefore?: ExpressionValue<Points>;
|
|
121
160
|
/** Blank space after this item, in points. */
|
|
122
|
-
spaceAfter?: ExpressionValue<
|
|
161
|
+
spaceAfter?: ExpressionValue<Points>;
|
|
123
162
|
}
|
|
124
163
|
|
|
125
164
|
export interface SortKey {
|
|
126
|
-
by:
|
|
165
|
+
by: Expression;
|
|
127
166
|
dir?: "asc" | "desc";
|
|
128
167
|
}
|
|
129
168
|
|
|
@@ -135,7 +174,7 @@ export interface SortKey {
|
|
|
135
174
|
export const RUN_STYLE_NAMES: readonly string[];
|
|
136
175
|
|
|
137
176
|
/**
|
|
138
|
-
* The names a [report default](
|
|
177
|
+
* The names a [report default](https://getquario.com/docs/reference/style-declarations) may
|
|
139
178
|
* declare, in the vocabulary's own order. A tool that offers them — the
|
|
140
179
|
* editor's Document panel — reads this rather than keeping a copy.
|
|
141
180
|
*/
|
|
@@ -149,7 +188,7 @@ export const REPORT_STYLE_NAMES: readonly string[];
|
|
|
149
188
|
export const ZERO_DASH: string;
|
|
150
189
|
|
|
151
190
|
/**
|
|
152
|
-
* The declarations a document may mark [`required`](
|
|
191
|
+
* The declarations a document may mark [`required`](https://getquario.com/docs/diving-deeper/validating),
|
|
153
192
|
* in the order the support matrix states them. Every published target's
|
|
154
193
|
* `capabilities` descriptor answers for exactly these, which is what makes a
|
|
155
194
|
* marking checkable.
|
|
@@ -159,7 +198,7 @@ export const REQUIRABLE: readonly string[];
|
|
|
159
198
|
/**
|
|
160
199
|
* The same names as a type, so a marking no target could answer for is an
|
|
161
200
|
* error where an author writes it rather than a
|
|
162
|
-
* [`plan`](
|
|
201
|
+
* [`plan`](https://getquario.com/docs/diving-deeper/validating) problem after the fact. This
|
|
163
202
|
* package's suite holds the two to each other in both directions, so neither
|
|
164
203
|
* can gain a name the other lacks.
|
|
165
204
|
*/
|
|
@@ -169,6 +208,8 @@ export type RequirableName =
|
|
|
169
208
|
| "break"
|
|
170
209
|
| "reset"
|
|
171
210
|
| "page.margin"
|
|
211
|
+
| "page.size"
|
|
212
|
+
| "page.orientation"
|
|
172
213
|
| "header.height"
|
|
173
214
|
| "groups"
|
|
174
215
|
| "label"
|
|
@@ -225,7 +266,7 @@ export interface StyledRun {
|
|
|
225
266
|
* cell written as one template string is one run, so a one-run array says
|
|
226
267
|
* exactly what that string says.
|
|
227
268
|
*/
|
|
228
|
-
export type CellValue = string |
|
|
269
|
+
export type CellValue = string | StyledRuns;
|
|
229
270
|
|
|
230
271
|
export type Align = "left" | "center" | "right";
|
|
231
272
|
export type VAlign = "top" | "middle" | "bottom";
|
|
@@ -252,7 +293,7 @@ export type FormatDeclaration =
|
|
|
252
293
|
| FormatKind
|
|
253
294
|
| {
|
|
254
295
|
kind: "number" | "currency" | "percent";
|
|
255
|
-
digits?:
|
|
296
|
+
digits?: Digits;
|
|
256
297
|
negative?: NegativeReading;
|
|
257
298
|
zero?: ZeroReading;
|
|
258
299
|
}
|
|
@@ -315,7 +356,7 @@ export type ReportStyleDeclarations = Pick<StyleDeclarations, "family" | "size">
|
|
|
315
356
|
*/
|
|
316
357
|
export interface ImageItem {
|
|
317
358
|
type: "image";
|
|
318
|
-
source:
|
|
359
|
+
source: Expression;
|
|
319
360
|
/** Defaults to `"natural"`. */
|
|
320
361
|
fit?: ImageFit;
|
|
321
362
|
/**
|
|
@@ -381,7 +422,7 @@ export type SplitSlot = (
|
|
|
381
422
|
| (Omit<ImageItem, "style"> & { style?: SlotImageStyleDeclarations })
|
|
382
423
|
) & {
|
|
383
424
|
/** Slot width as a percentage of the content width (0 < width <= 100). */
|
|
384
|
-
width?:
|
|
425
|
+
width?: WidthShare;
|
|
385
426
|
};
|
|
386
427
|
|
|
387
428
|
/**
|
|
@@ -397,8 +438,50 @@ export interface SplitItem {
|
|
|
397
438
|
style?: StyleDeclarations;
|
|
398
439
|
}
|
|
399
440
|
|
|
400
|
-
/**
|
|
401
|
-
|
|
441
|
+
/**
|
|
442
|
+
* One slot of a grid row: a split slot less `width`, which the slot takes
|
|
443
|
+
* from its column.
|
|
444
|
+
*/
|
|
445
|
+
export type GridSlot =
|
|
446
|
+
| (Omit<TextItem, "style"> & { style?: SlotStyleDeclarations })
|
|
447
|
+
| (Omit<ImageItem, "style"> & { style?: SlotImageStyleDeclarations });
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* One column of a grid: the width share every row's slot in this position
|
|
451
|
+
* takes, and the declarations each of those slots layers its own over.
|
|
452
|
+
*/
|
|
453
|
+
export interface GridColumn {
|
|
454
|
+
/** Column width as a percentage of the content width (0 < width <= 100). */
|
|
455
|
+
width?: WidthShare;
|
|
456
|
+
style?: SlotStyleDeclarations;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* One line on a grid's geometry: a split without `type`. A row naming fewer
|
|
461
|
+
* slots than the grid has columns leaves the rest empty, so `{}` is a
|
|
462
|
+
* spacer line of the row's size.
|
|
463
|
+
*/
|
|
464
|
+
export interface GridRow {
|
|
465
|
+
slots?: GridSlot[];
|
|
466
|
+
visible?: ExpressionValue<boolean>;
|
|
467
|
+
style?: StyleDeclarations;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Splits that share one column geometry: the widths, and each column's
|
|
472
|
+
* style, are stated once and every row is laid on them. Every rule a split
|
|
473
|
+
* has, a row has — full content width, no nesting, never broken across a
|
|
474
|
+
* page — and each row crosses the event stream as the split bracket it is.
|
|
475
|
+
*/
|
|
476
|
+
export interface GridItem {
|
|
477
|
+
type: "grid";
|
|
478
|
+
columns: [GridColumn, GridColumn, ...GridColumn[]];
|
|
479
|
+
rows: [GridRow, ...GridRow[]];
|
|
480
|
+
visible?: ExpressionValue<boolean>;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/** One item in a band: text, an image, a split, or a grid. Future types may be additive. */
|
|
484
|
+
export type Item = TextItem | ImageItem | SplitItem | GridItem;
|
|
402
485
|
|
|
403
486
|
export interface TableHeader {
|
|
404
487
|
value: CellValue;
|
|
@@ -408,7 +491,7 @@ export interface TableHeader {
|
|
|
408
491
|
* How many columns this header covers — a literal integer >= 1, never an
|
|
409
492
|
* expression; absent is 1. The columns it covers omit their own `header`.
|
|
410
493
|
*/
|
|
411
|
-
span?:
|
|
494
|
+
span?: Count;
|
|
412
495
|
}
|
|
413
496
|
|
|
414
497
|
export interface TableColumn extends Omit<Cell, "style"> {
|
|
@@ -420,7 +503,7 @@ export interface TableColumn extends Omit<Cell, "style"> {
|
|
|
420
503
|
*/
|
|
421
504
|
header?: string | TableHeader;
|
|
422
505
|
/** Column width as a percentage of the table width (0 < width <= 100). */
|
|
423
|
-
width?:
|
|
506
|
+
width?: WidthShare;
|
|
424
507
|
}
|
|
425
508
|
|
|
426
509
|
export interface TableRow {
|
|
@@ -439,7 +522,7 @@ export type TotalCell = Omit<Cell, "style"> & {
|
|
|
439
522
|
* How many columns this cell covers — a literal integer >= 1, never an
|
|
440
523
|
* expression; absent is 1.
|
|
441
524
|
*/
|
|
442
|
-
span?:
|
|
525
|
+
span?: Count;
|
|
443
526
|
};
|
|
444
527
|
|
|
445
528
|
export interface TotalRow {
|
|
@@ -476,7 +559,7 @@ export interface TableDetail {
|
|
|
476
559
|
|
|
477
560
|
export interface Group {
|
|
478
561
|
name: string;
|
|
479
|
-
by:
|
|
562
|
+
by: Expression;
|
|
480
563
|
/**
|
|
481
564
|
* This instance's name for **navigation** rather than for the page: one
|
|
482
565
|
* template, resolved once per instance in group scope, where the handle and
|
|
@@ -490,7 +573,7 @@ export interface Group {
|
|
|
490
573
|
* and the content between them does not. A target with a way to hide a row
|
|
491
574
|
* and keep it -- the worksheet -- hides those rows, where a reader opens the
|
|
492
575
|
* group again. The rest drop them, and the
|
|
493
|
-
* [matrix](
|
|
576
|
+
* [matrix](https://getquario.com/docs/reference/support-matrix) says
|
|
494
577
|
* which does which.
|
|
495
578
|
*/
|
|
496
579
|
collapsed?: boolean;
|
|
@@ -509,13 +592,13 @@ export interface Group {
|
|
|
509
592
|
* Flow each instance's content in this many page columns (integer >= 2).
|
|
510
593
|
* Columned regions cannot nest.
|
|
511
594
|
*/
|
|
512
|
-
columns?:
|
|
595
|
+
columns?: ColumnCount;
|
|
513
596
|
sort?: SortKey[];
|
|
514
597
|
/**
|
|
515
598
|
* Keep this many rows after this group's `sort`. Integer >= 1. Rows past
|
|
516
599
|
* the count are dropped from aggregates and runners, unlike `visible`.
|
|
517
600
|
*/
|
|
518
|
-
take?:
|
|
601
|
+
take?: Count;
|
|
519
602
|
aggregates?: Record<string, ReducerSpec>;
|
|
520
603
|
/** Running accumulators, read as `run.<name>` on detail rows. */
|
|
521
604
|
run?: Record<string, ReducerSpec>;
|
|
@@ -531,15 +614,81 @@ export interface Group {
|
|
|
531
614
|
export interface PageBands {
|
|
532
615
|
header?: Item[];
|
|
533
616
|
footer?: Item[];
|
|
534
|
-
/**
|
|
535
|
-
|
|
617
|
+
/**
|
|
618
|
+
* The inset from the paper's edge, in points: one number for all four
|
|
619
|
+
* sides, or each side named. Required when the report header declares
|
|
620
|
+
* `height`. A target's own `margin` option applies where this is absent,
|
|
621
|
+
* and declaring both is a render error.
|
|
622
|
+
*/
|
|
623
|
+
margin?: Points | PageMargin;
|
|
624
|
+
/**
|
|
625
|
+
* The report's paper, by name. A `[width, height]` pair is a target option
|
|
626
|
+
* only. A target's own `size` option applies where this is absent, and
|
|
627
|
+
* declaring both is a render error.
|
|
628
|
+
*/
|
|
629
|
+
size?: PaperName;
|
|
630
|
+
/** Which way the paper is turned. */
|
|
631
|
+
orientation?: Orientation;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/** A margin that names each side, in points. All four are required. */
|
|
635
|
+
export interface PageMargin {
|
|
636
|
+
top: Points;
|
|
637
|
+
right: Points;
|
|
638
|
+
bottom: Points;
|
|
639
|
+
left: Points;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/** The named paper sizes a document may declare. */
|
|
643
|
+
export type PaperName = "A4" | "letter";
|
|
644
|
+
|
|
645
|
+
/** Which way the paper is turned. */
|
|
646
|
+
export type Orientation = "portrait" | "landscape";
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* What a report declares it needs. A bare value under `params` *is* the
|
|
650
|
+
* parameter's value; a plain object is a declaration. `default` absent means
|
|
651
|
+
* the parameter is required, and a render that supplies none is rejected
|
|
652
|
+
* before any expression runs. `type` names a JSON kind, because a parameter
|
|
653
|
+
* is a JSON value. A `null` default beside a `type` makes the parameter
|
|
654
|
+
* optional and lets a render supply `null`.
|
|
655
|
+
*/
|
|
656
|
+
export interface ParamDeclaration {
|
|
657
|
+
default?: JsonValue;
|
|
658
|
+
type?: ParamType;
|
|
659
|
+
/**
|
|
660
|
+
* The text a person reads for this parameter. A parameter with a label is
|
|
661
|
+
* one a person supplies; the engine never renders it.
|
|
662
|
+
*/
|
|
663
|
+
label?: string;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export type ParamType = "string" | "number" | "boolean" | "array" | "object";
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* One declared parameter, as a host reads it: the surface a parameter panel
|
|
670
|
+
* asks what to render. `type`, `default` and `label` are present only where
|
|
671
|
+
* the document wrote one, and `required` is the absence of a default.
|
|
672
|
+
*/
|
|
673
|
+
export interface DeclaredParam {
|
|
674
|
+
readonly name: string;
|
|
675
|
+
readonly required: boolean;
|
|
676
|
+
readonly type?: ParamType;
|
|
677
|
+
readonly default?: JsonValue;
|
|
678
|
+
/** Present where the document wrote one: a person supplies this parameter. */
|
|
679
|
+
readonly label?: string;
|
|
536
680
|
}
|
|
537
681
|
|
|
538
682
|
export interface ReportSchema {
|
|
539
|
-
|
|
683
|
+
/**
|
|
684
|
+
* Where an editor finds this document's JSON Schema. The engine checks that
|
|
685
|
+
* it is a string and reads nothing else.
|
|
686
|
+
*/
|
|
687
|
+
$schema?: string;
|
|
688
|
+
params?: Record<string, ParamValue | ParamDeclaration>;
|
|
540
689
|
/**
|
|
541
690
|
* The declarations this document cannot do without, each marked `true`.
|
|
542
|
-
* Only [`plan`](
|
|
691
|
+
* Only [`plan`](https://getquario.com/docs/diving-deeper/validating) reads it, against the target
|
|
543
692
|
* descriptors its caller names: every required declaration one of them
|
|
544
693
|
* withdraws or leaves unread becomes a problem of its own at
|
|
545
694
|
* `required.<name>`, which nulls the report as any other problem does. No
|
|
@@ -547,13 +696,13 @@ export interface ReportSchema {
|
|
|
547
696
|
*/
|
|
548
697
|
required?: Partial<Record<RequirableName, true>>;
|
|
549
698
|
data: string;
|
|
550
|
-
where?:
|
|
699
|
+
where?: Expression;
|
|
551
700
|
sort?: SortKey[];
|
|
552
701
|
/**
|
|
553
702
|
* Keep this many rows after the report `sort`. Integer >= 1. Rows past the
|
|
554
703
|
* count are dropped from aggregates and runners, unlike `visible`.
|
|
555
704
|
*/
|
|
556
|
-
take?:
|
|
705
|
+
take?: Count;
|
|
557
706
|
aggregates?: Record<string, ReducerSpec>;
|
|
558
707
|
/** Running accumulators, read as `run.<name>` on detail rows. */
|
|
559
708
|
run?: Record<string, ReducerSpec>;
|
|
@@ -567,13 +716,13 @@ export interface ReportSchema {
|
|
|
567
716
|
* Dual-shaped like `detail`: an item array, or `{ height, items }` when the
|
|
568
717
|
* header pins a flow box from the page top.
|
|
569
718
|
*/
|
|
570
|
-
header?: Item[] | { height:
|
|
719
|
+
header?: Item[] | { height: PositivePoints; items: Item[] };
|
|
571
720
|
empty?: Item[];
|
|
572
721
|
/**
|
|
573
722
|
* Flow the report body in this many page columns (integer >= 2). Columned
|
|
574
723
|
* regions cannot nest.
|
|
575
724
|
*/
|
|
576
|
-
columns?:
|
|
725
|
+
columns?: ColumnCount;
|
|
577
726
|
groups?: Group[];
|
|
578
727
|
detail?: Item[] | TableDetail;
|
|
579
728
|
footer?: Item[];
|
|
@@ -601,8 +750,8 @@ export interface QuarioOptions {
|
|
|
601
750
|
/**
|
|
602
751
|
* License key (LICENSE section 6). Verified offline once, when the instance
|
|
603
752
|
* is created; `license` settles with the result. Without a key, or with one
|
|
604
|
-
*
|
|
605
|
-
*
|
|
753
|
+
* that ends before this version's release date, every report this instance
|
|
754
|
+
* compiles marks its output as unlicensed.
|
|
606
755
|
*/
|
|
607
756
|
license?: string;
|
|
608
757
|
/** Locale for `format`. Defaults to `"en-US"` when a kind is presented. */
|
|
@@ -755,8 +904,12 @@ export interface ReportStartEvent {
|
|
|
755
904
|
* states it so no target has to know it.
|
|
756
905
|
*/
|
|
757
906
|
marking?: string;
|
|
758
|
-
/** The document's `page.margin`, when declared. */
|
|
759
|
-
margin?: number;
|
|
907
|
+
/** The document's `page.margin`, when declared, in the shape the author wrote it. */
|
|
908
|
+
margin?: number | PageMargin;
|
|
909
|
+
/** The document's `page.size`, when declared. */
|
|
910
|
+
size?: PaperName;
|
|
911
|
+
/** The document's `page.orientation`, when declared. */
|
|
912
|
+
orientation?: Orientation;
|
|
760
913
|
/** The report header's authored `height`, when the object form is used. */
|
|
761
914
|
headerHeight?: number;
|
|
762
915
|
/** Present when the instance was constructed with `locale`. */
|
|
@@ -953,7 +1106,7 @@ export type WalkEvent = ReportEvent | SplitEvent;
|
|
|
953
1106
|
export function splits(events: Iterable<ReportEvent>): Generator<WalkEvent, void>;
|
|
954
1107
|
|
|
955
1108
|
/**
|
|
956
|
-
* Each [collapsed](
|
|
1109
|
+
* Each [collapsed](https://getquario.com/docs/reference/report-schema#group) instance shut: its
|
|
957
1110
|
* brackets and its own header and footer items survive, and everything
|
|
958
1111
|
* between them is dropped, nested instances whole.
|
|
959
1112
|
*
|
|
@@ -1010,7 +1163,11 @@ export interface QuarioDiagnostic extends Error {
|
|
|
1010
1163
|
/** The compiled report: `stream` plus its metadata, rendered per target. */
|
|
1011
1164
|
export interface CompiledReport {
|
|
1012
1165
|
/** The raw event seam: one generator of report events per call. */
|
|
1013
|
-
stream(
|
|
1166
|
+
stream(
|
|
1167
|
+
data?: unknown,
|
|
1168
|
+
params?: Readonly<Record<string, JsonValue>>,
|
|
1169
|
+
): Generator<ReportEvent, void, undefined>;
|
|
1170
|
+
readonly params: readonly DeclaredParam[];
|
|
1014
1171
|
readonly names: readonly string[];
|
|
1015
1172
|
readonly functions: readonly FunctionSignature[];
|
|
1016
1173
|
readonly paths: readonly QueryPath[];
|
|
@@ -1019,7 +1176,11 @@ export interface CompiledReport {
|
|
|
1019
1176
|
* output, whether the target renders synchronously or not; target shape
|
|
1020
1177
|
* problems throw synchronously as definition errors.
|
|
1021
1178
|
*/
|
|
1022
|
-
render<Out>(
|
|
1179
|
+
render<Out>(
|
|
1180
|
+
target: Target<string, Out>,
|
|
1181
|
+
data?: unknown,
|
|
1182
|
+
params?: Readonly<Record<string, JsonValue>>,
|
|
1183
|
+
): Promise<Awaited<Out>>;
|
|
1023
1184
|
}
|
|
1024
1185
|
|
|
1025
1186
|
/**
|
|
@@ -1083,6 +1244,7 @@ export interface PlanOptions {
|
|
|
1083
1244
|
|
|
1084
1245
|
export interface Plan {
|
|
1085
1246
|
readonly report: CompiledReport | null;
|
|
1247
|
+
readonly params: readonly DeclaredParam[];
|
|
1086
1248
|
readonly problems: readonly Problem[];
|
|
1087
1249
|
readonly anchors: Readonly<Record<string, readonly string[]>>;
|
|
1088
1250
|
readonly warnings: readonly Warning[];
|