@quario/csv 0.7.0 → 0.8.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 +77 -26
- package/README.md +40 -25
- package/lib/index.d.ts +3 -0
- package/lib/index.js +11 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,65 +1,116 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @quario/csv
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## 0.8.0
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
|
+
### Minor Changes
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
- **Every target factory now refuses an option it does not understand.** An unknown key, a key with
|
|
8
|
+
a value of the wrong type, or an `options` that is not an object throws a `TypeError` at the
|
|
9
|
+
factory call, naming the option path — `options.meta.title`, `options.page.size`. `@quario/docx`
|
|
10
|
+
already behaved this way. `@quario/pdf`, `@quario/html`, `@quario/xlsx` and `@quario/layout` read
|
|
11
|
+
the keys they knew and ignored the rest, so a typo cost you the option you meant to set with no
|
|
12
|
+
signal at any point. `csv()` takes no options, and it refuses an argument rather than discarding
|
|
13
|
+
one.
|
|
9
14
|
|
|
10
|
-
|
|
15
|
+
The check itself is one thing, so the engine now exports it: `hostOptions` closes a key set and
|
|
16
|
+
`hostMeta` validates the `{ title, author, subject }` contract the document targets share. A
|
|
17
|
+
fourth document property is one edit rather than three.
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
**What this changes for you.** One options object spread across several targets stops working if
|
|
20
|
+
any target does not know one of its keys — `const o = { page, fonts, meta }` passed to `pdf(o)`,
|
|
21
|
+
`html(o)` and `xlsx(o)` is three different key sets. An object holding only what its consumers
|
|
22
|
+
share is unaffected, so `{ page, fonts }` into both `pdf()` and `layout()` still works.
|
|
23
|
+
TypeScript does not warn about this: excess-property checking fires on an object literal and not
|
|
24
|
+
on a variable, so a bag held in a `const` compiles clean and throws when you call the factory.
|
|
25
|
+
|
|
26
|
+
Nullish is absence everywhere, at both levels, so `{ meta: config.meta ?? null }` and
|
|
27
|
+
`{ meta: { title: config.title } }` over a config that carries neither are both fine.
|
|
28
|
+
`html({ paths })` now takes `true` or `false` rather than anything truthy, so `paths: "no"` throws
|
|
29
|
+
instead of turning path stamping on. A `fonts` mapping given as an array is refused by
|
|
30
|
+
`@quario/html` and `@quario/layout` rather than read as families named `0`, `1`, `2`.
|
|
31
|
+
|
|
32
|
+
Every host-option failure is now a `TypeError` rather than a plain `Error`. A `catch` that tests
|
|
33
|
+
`instanceof Error` is unaffected. One that compares the constructor is not.
|
|
34
|
+
|
|
35
|
+
`@quario/docx` is relaxed in three places, each of them now accepting what it refused: `meta: null`
|
|
36
|
+
and `page: null` are absence rather than errors, a property written as `meta: { title: undefined }`
|
|
37
|
+
is a property you did not write rather than one of the wrong type, and an inherited enumerable key
|
|
38
|
+
is no longer reported as an option you wrote.
|
|
39
|
+
|
|
40
|
+
`@quario/pdf`, `@quario/xlsx` and `@quario/docx` now copy `meta` at the factory call. Mutating the
|
|
41
|
+
object you passed no longer changes what a configured target writes.
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- Updated dependencies
|
|
46
|
+
- quario@0.9.0
|
|
47
|
+
|
|
48
|
+
## 0.7.1
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- **Every published README says where the documentation is.** Each package now
|
|
53
|
+
carries a Documentation section pointing at the reference, at the report schema
|
|
54
|
+
that normatively specifies what a report may declare, and at the package's own
|
|
55
|
+
API. The paragraphs that used to end on an unstated contract — the event
|
|
56
|
+
stream's field semantics, the style vocabulary, page columns, the Content
|
|
57
|
+
Security Policy a fragment with images needs, the formula mangling, and each
|
|
58
|
+
target's own contract — link the page that states it. Every link is an absolute
|
|
59
|
+
URL, so it resolves from the npm package page as readily as from an installed
|
|
60
|
+
copy.
|
|
61
|
+
- Updated dependencies
|
|
62
|
+
- quario@0.8.0
|
|
63
|
+
|
|
64
|
+
## 0.7.0
|
|
65
|
+
|
|
66
|
+
### Minor Changes
|
|
13
67
|
|
|
14
68
|
- **Styled runs flatten to their joined text.** A cell value written as a list of
|
|
15
69
|
styled runs writes the runs' text as one field. This target withdraws every
|
|
16
70
|
style, and a run's is no different.
|
|
17
71
|
|
|
18
|
-
##
|
|
72
|
+
## 0.6.0
|
|
19
73
|
|
|
20
|
-
###
|
|
74
|
+
### Minor Changes
|
|
21
75
|
|
|
22
|
-
-
|
|
76
|
+
- Updated dependencies
|
|
77
|
+
- quario@0.6.0
|
|
23
78
|
|
|
24
|
-
##
|
|
79
|
+
## 0.5.0
|
|
25
80
|
|
|
26
|
-
###
|
|
81
|
+
### Minor Changes
|
|
27
82
|
|
|
28
83
|
- **Spans keep the record rectangular.** A cell covering several columns writes
|
|
29
84
|
its value in the first field it covers and leaves the rest empty, so every
|
|
30
85
|
record is the same width. This target reads no geometry, so there is nothing
|
|
31
86
|
here for a merge to mean.
|
|
32
87
|
|
|
33
|
-
##
|
|
88
|
+
## 0.4.0
|
|
34
89
|
|
|
35
|
-
###
|
|
90
|
+
### Minor Changes
|
|
36
91
|
|
|
37
|
-
-
|
|
92
|
+
- Updated dependencies
|
|
93
|
+
- quario@0.4.0
|
|
38
94
|
|
|
39
|
-
##
|
|
95
|
+
## 0.3.0
|
|
40
96
|
|
|
41
|
-
###
|
|
97
|
+
### Minor Changes
|
|
42
98
|
|
|
43
99
|
- **A table total emits N records.** Each `total-row` is one record, as
|
|
44
100
|
each data row is.
|
|
45
|
-
|
|
46
101
|
- **`format` is unread.** Bare interpolations stay `1000` / ISO dates, as
|
|
47
102
|
every other style is unread here.
|
|
48
|
-
|
|
49
103
|
- **`page.margin` and report-header `height` are unread.** This target has
|
|
50
104
|
no page to inset or pin on.
|
|
51
105
|
|
|
52
|
-
##
|
|
106
|
+
## 0.2.0
|
|
53
107
|
|
|
54
|
-
###
|
|
108
|
+
### Minor Changes
|
|
55
109
|
|
|
56
110
|
- **A split is one record, its slots the fields.** Slots are values beside
|
|
57
111
|
each other, which is what a record is. Slot widths go unread, as every width
|
|
58
112
|
is here. Images stay unread too, but a slot holding one still writes an
|
|
59
113
|
empty field, so the fields either side keep their positions.
|
|
60
|
-
|
|
61
|
-
### Changed
|
|
62
|
-
|
|
63
114
|
- **Display-text `Date`s join as ISO 8601 UTC.** A `Date` inside a mixed
|
|
64
115
|
cell (literal text plus interpolation) joined through `String(date)`, so
|
|
65
116
|
the field carried the host's timezone and locale. It now joins through the
|
|
@@ -67,9 +118,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
67
118
|
typed single-`Date` field has always used, so every `Date` in a CSV now
|
|
68
119
|
reads the same way.
|
|
69
120
|
|
|
70
|
-
##
|
|
121
|
+
## 0.1.0
|
|
71
122
|
|
|
72
|
-
###
|
|
123
|
+
### Minor Changes
|
|
73
124
|
|
|
74
125
|
- **CSV records in render order.** A bare interpolation stays typed text (a
|
|
75
126
|
number's decimal, a Date as ISO 8601 UTC); everything else is display text,
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @quario/csv
|
|
2
2
|
|
|
3
3
|
**The CSV render target for [quario](https://www.npmjs.com/package/quario).** Renders a report
|
|
4
|
-
definition to CSV records with typed fields
|
|
5
|
-
stays ISO 8601 UTC
|
|
4
|
+
definition to CSV records with typed fields. A bare number stays a number's decimal, and a Date
|
|
5
|
+
stays ISO 8601 UTC. This target neutralizes text that would open as a spreadsheet formula.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ npm install quario @quario/csv
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
The engine is a peer dependency, installed beside the target. ESM-only, Node 22+, and
|
|
14
|
-
browser-ready through any standards-based ESM bundler. The renderer returns a string
|
|
14
|
+
browser-ready through any standards-based ESM bundler. The renderer returns a string. You
|
|
15
15
|
encode the file.
|
|
16
16
|
|
|
17
17
|
## Quick start
|
|
@@ -54,15 +54,16 @@ Chair,120
|
|
|
54
54
|
Lamp,40
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
Any schema the other targets render works here unchanged. A CSV file has no pages, so
|
|
58
|
-
|
|
59
|
-
`{{ @.amount }}` writes `1000
|
|
57
|
+
Any schema the other targets render works here unchanged. A CSV file has no pages, so this target
|
|
58
|
+
ignores page bands. Interpolate the bare value, not a formatter, when you want a typed field.
|
|
59
|
+
`{{ @.amount }}` writes `1000`, and `{{ currency(@.amount) }}` writes text.
|
|
60
60
|
|
|
61
61
|
## API
|
|
62
62
|
|
|
63
63
|
### `csv()`
|
|
64
64
|
|
|
65
|
-
The target factory takes no options and returns the target you pass to `render`.
|
|
65
|
+
The target factory takes no options and returns the target you pass to `render`. It refuses an argument rather than
|
|
66
|
+
discarding one. It throws a `TypeError` if you give it one.
|
|
66
67
|
`report()` compiles once and `report.render(csv(), data)` resolves the string. Compile at
|
|
67
68
|
startup, render per request. Definition problems throw at `report()`, at compile time.
|
|
68
69
|
|
|
@@ -75,7 +76,7 @@ The compiled report carries `stream` (the raw event generator), `names`, `functi
|
|
|
75
76
|
`paths`, like every quario report. Engine-level options (`query` budgets, the license key)
|
|
76
77
|
live on the instance, and `q.license` settles with the verification result.
|
|
77
78
|
|
|
78
|
-
Rendering is asynchronous and
|
|
79
|
+
Rendering is asynchronous and returns the loop between batches, so a large report never
|
|
79
80
|
blocks the host. Render-time failures reject with located errors.
|
|
80
81
|
|
|
81
82
|
## Mapping
|
|
@@ -83,12 +84,14 @@ blocks the host. Render-time failures reject with located errors.
|
|
|
83
84
|
The banded walk flattened as records in render order: report-header items, then per group
|
|
84
85
|
instance its header items, nested content, and footer items, then the table's header record,
|
|
85
86
|
data records, and total records, then report-footer items. Grouping exists as that order
|
|
86
|
-
alone. Group boundaries add no records of their own, and
|
|
87
|
-
|
|
87
|
+
alone. Group boundaries add no records of their own, and this target ignores `break: "page"`
|
|
88
|
+
and `reset: "page"`. This target paginates nothing, so it ignores `report-start.page` band
|
|
89
|
+
closures.
|
|
88
90
|
|
|
89
|
-
Each item takes one record with one field
|
|
90
|
-
spanning cell writes empty fields for the columns it covers so positions hold. A report that is
|
|
91
|
-
table and no other bands has its column headers as record 1
|
|
91
|
+
Each item takes one record with one field. A split takes one record with a field per slot, and a
|
|
92
|
+
spanning cell writes empty fields for the columns it covers so positions hold. A report that is
|
|
93
|
+
one table and no other bands has its column headers as record 1. Any other band makes the file
|
|
94
|
+
ragged.
|
|
92
95
|
|
|
93
96
|
### Typed fields
|
|
94
97
|
|
|
@@ -97,25 +100,26 @@ number as ECMAScript ToString, a boolean as `true`/`false`, a `Date` as ISO 8601
|
|
|
97
100
|
other cell joins to display text with `text()`, then the injection guard, then RFC 4180
|
|
98
101
|
quoting.
|
|
99
102
|
|
|
100
|
-
**
|
|
101
|
-
`+`, `-`, `@`, TAB, or CR gets an apostrophe. A consumer that parses the file back does not
|
|
103
|
+
**This target mangles display-text fields that would open as spreadsheet formulas.** A leading
|
|
104
|
+
`=`, `+`, `-`, `@`, TAB, or CR gets an apostrophe. A consumer that parses the file back does not
|
|
102
105
|
round-trip those fields. The XLSX target does the opposite: it writes an inert string and
|
|
103
|
-
does not mangle.
|
|
106
|
+
does not mangle. See
|
|
107
|
+
[The CSV target](https://getquario.com/docs/diving-deeper/csv-target/#design-decisions).
|
|
104
108
|
|
|
105
109
|
A hidden cell keeps its column slot as an empty field.
|
|
106
110
|
|
|
107
111
|
### Withdrawn, and the unread page bands
|
|
108
112
|
|
|
109
|
-
`style`, column `width`, slot `width`, page columns and images
|
|
110
|
-
presentation, no width and no page, so there is nothing here for any of them to
|
|
111
|
-
image emits no record, though an image in a slot still writes its empty
|
|
112
|
-
one unread declaration
|
|
113
|
-
never
|
|
113
|
+
This target withdraws `style`, column `width`, slot `width`, page columns and images. A record
|
|
114
|
+
carries no presentation, no width and no page, so there is nothing here for any of them to
|
|
115
|
+
resolve against. An image emits no record, though an image in a slot still writes its empty
|
|
116
|
+
field. Page bands are the one unread declaration. This target never calls their closures, so an
|
|
117
|
+
expression inside one never runs and never raises here.
|
|
114
118
|
|
|
115
119
|
### Text shape
|
|
116
120
|
|
|
117
121
|
No BOM. Records separated by LF, not CRLF. The string ends with a newline. Quoting follows
|
|
118
|
-
RFC 4180
|
|
122
|
+
RFC 4180. The line ending does not.
|
|
119
123
|
|
|
120
124
|
## Unlicensed marking
|
|
121
125
|
|
|
@@ -127,12 +131,23 @@ presence is normative. That a parser who stops before EOF will see it is best-ef
|
|
|
127
131
|
|
|
128
132
|
Same schema and data produce an identical string.
|
|
129
133
|
|
|
134
|
+
The full contract is [The CSV target](https://getquario.com/docs/diving-deeper/csv-target/),
|
|
135
|
+
with each declaration's fate in the
|
|
136
|
+
[support matrix](https://getquario.com/docs/reference/support-matrix/).
|
|
137
|
+
|
|
138
|
+
## Documentation
|
|
139
|
+
|
|
140
|
+
[The quario documentation](https://getquario.com/docs/) is the reference.
|
|
141
|
+
The [report schema](https://getquario.com/docs/reference/report-schema/) is the normative
|
|
142
|
+
specification of what a report may declare, and
|
|
143
|
+
[`@quario/csv`](https://getquario.com/docs/reference/csv/) is this package's own API.
|
|
144
|
+
|
|
130
145
|
## License
|
|
131
146
|
|
|
132
|
-
Commercial software with readable source.
|
|
133
|
-
licenses at [getquario.com](https://getquario.com). See the bundled LICENSE.
|
|
147
|
+
Commercial software with readable source. Evaluation is free, unlimited, and watermarked.
|
|
148
|
+
Per-developer licenses at [getquario.com](https://getquario.com). See the bundled LICENSE.
|
|
134
149
|
|
|
135
|
-
Pass your license key once, on the instance
|
|
150
|
+
Pass your license key once, on the instance. quario verifies it offline:
|
|
136
151
|
|
|
137
152
|
```js
|
|
138
153
|
const q = quario({ license: "quario_..." });
|
package/lib/index.d.ts
CHANGED
|
@@ -4,5 +4,8 @@ import type { Target } from "quario";
|
|
|
4
4
|
* The CSV render target:
|
|
5
5
|
* `quario().report(schema).render(csv(), data)` resolves the records
|
|
6
6
|
* described in SCHEMA.md ("The CSV target").
|
|
7
|
+
*
|
|
8
|
+
* It takes no options, and an argument is a `TypeError` at the call rather
|
|
9
|
+
* than an argument quietly discarded.
|
|
7
10
|
*/
|
|
8
11
|
export function csv(): Target<"csv", Promise<string>>;
|
package/lib/index.js
CHANGED
|
@@ -32,10 +32,20 @@ let field = (cell) => {
|
|
|
32
32
|
* string (the host encodes the file). Rendering runs the engine's `walk`
|
|
33
33
|
* driver over the handlers below, so large reports stay cooperative.
|
|
34
34
|
*
|
|
35
|
+
* This target reads no host options, and refuses an argument rather than
|
|
36
|
+
* discarding one: a host writing `csv({ delimiter: ";" })` believes something
|
|
37
|
+
* about the output that is not true, and nothing later would tell them
|
|
38
|
+
* (`docs/adr/0072`). The rule the other targets state over a key set, this
|
|
39
|
+
* one states over the whole call. Nullish is absence here as everywhere, so
|
|
40
|
+
* `csv(config.options)` over a config carrying none is not a mistake.
|
|
41
|
+
*
|
|
42
|
+
* @param {...never} rest Nothing: an option is a definition error.
|
|
35
43
|
* @returns {{name: "csv", compile: (stream: any) => (data?: any) => Promise<string>}}
|
|
36
44
|
* The target (see SCHEMA.md, "Instances and targets").
|
|
37
45
|
*/
|
|
38
|
-
export function csv() {
|
|
46
|
+
export function csv(...rest) {
|
|
47
|
+
if (rest.some((option) => option != null))
|
|
48
|
+
throw TypeError("options: this target takes no options");
|
|
39
49
|
return {
|
|
40
50
|
name: "csv",
|
|
41
51
|
compile: (stream) => async (data) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quario/csv",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "The CSV render target for quario — in the makings, not yet released",
|
|
5
5
|
"homepage": "https://getquario.com",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@arethetypeswrong/cli": "^0.18.3",
|
|
40
40
|
"@size-limit/preset-small-lib": "^13.0.3",
|
|
41
|
-
"quario": "^0.
|
|
41
|
+
"quario": "^0.9.0",
|
|
42
42
|
"size-limit": "^13.0.3",
|
|
43
43
|
"typescript": "^7.0.2"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"quario": "^0.
|
|
46
|
+
"quario": "^0.9.0"
|
|
47
47
|
},
|
|
48
48
|
"size-limit": [
|
|
49
49
|
{
|