@cbortech/cbor 0.27.0 → 0.27.2
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/README.ja.md +100 -0
- package/README.md +103 -0
- package/dist/ast/CborAppSeqResult.d.ts +37 -4
- package/dist/ast/CborArray.d.ts +2 -2
- package/dist/ast/CborByteString.d.ts +2 -2
- package/dist/ast/CborEmbeddedCBOR.d.ts +1 -1
- package/dist/ast/CborFloat.d.ts +1 -1
- package/dist/ast/CborIndefiniteByteString.d.ts +1 -1
- package/dist/ast/CborIndefiniteTextString.d.ts +1 -1
- package/dist/ast/CborItem.d.ts +314 -9
- package/dist/ast/CborMap.d.ts +2 -2
- package/dist/ast/CborNint.d.ts +1 -1
- package/dist/ast/CborTag.d.ts +26 -4
- package/dist/ast/CborTextString.d.ts +2 -2
- package/dist/ast/CborUint.d.ts +1 -1
- package/dist/ast/CborUnresolvedAppExt.d.ts +9 -0
- package/dist/ast/index.cjs +1 -1
- package/dist/ast/index.js +2 -2
- package/dist/cbor/tagLabels.d.ts +26 -0
- package/dist/cddl/eRefScope.d.ts +241 -0
- package/dist/cddl/eref.d.ts +64 -0
- package/dist/cddl/implicitTags.d.ts +28 -0
- package/dist/cddl/index.cjs +2 -2
- package/dist/cddl/index.cjs.map +1 -1
- package/dist/cddl/index.d.ts +2 -0
- package/dist/cddl/index.js +26 -25
- package/dist/cddl/index.js.map +1 -1
- package/dist/cddl/validator.d.ts +98 -2
- package/dist/cdn/index.cjs +1 -1
- package/dist/cdn/index.js +1 -1
- package/dist/cdn/serialize-utils.d.ts +50 -15
- package/dist/extensions/cri.d.ts +2 -2
- package/dist/extensions/dt.d.ts +4 -4
- package/dist/extensions/eref.d.ts +135 -0
- package/dist/extensions/ip.d.ts +3 -3
- package/dist/extensions/types.d.ts +40 -1
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +190 -81
- package/dist/index.js.map +1 -1
- package/dist/js/fromJS.d.ts +23 -1
- package/dist/mapEntries-8zshEr-t.js +7085 -0
- package/dist/mapEntries-8zshEr-t.js.map +1 -0
- package/dist/mapEntries-DwHPAzCN.cjs +68 -0
- package/dist/mapEntries-DwHPAzCN.cjs.map +1 -0
- package/dist/schema-7r2xjpMK.js +345 -0
- package/dist/schema-7r2xjpMK.js.map +1 -0
- package/dist/schema-YiigSWjR.cjs +8 -0
- package/dist/schema-YiigSWjR.cjs.map +1 -0
- package/dist/{serialize-utils-BuIZPaUc.js → serialize-utils-BQtutOo6.js} +70 -52
- package/dist/serialize-utils-BQtutOo6.js.map +1 -0
- package/dist/{serialize-utils-CjTqQivB.cjs → serialize-utils-DQ8T3Mzw.cjs} +9 -9
- package/dist/serialize-utils-DQ8T3Mzw.cjs.map +1 -0
- package/dist/types.d.ts +426 -4
- package/dist/utils/hexfloat.d.ts +10 -2
- package/package.json +13 -14
- package/dist/mapEntries-C1f7G0AM.cjs +0 -13
- package/dist/mapEntries-C1f7G0AM.cjs.map +0 -1
- package/dist/mapEntries-CvLdiN0h.js +0 -3946
- package/dist/mapEntries-CvLdiN0h.js.map +0 -1
- package/dist/schema-CNfrVRYp.js +0 -1977
- package/dist/schema-CNfrVRYp.js.map +0 -1
- package/dist/schema-iXpYtKQl.cjs +0 -63
- package/dist/schema-iXpYtKQl.cjs.map +0 -1
- package/dist/serialize-utils-BuIZPaUc.js.map +0 -1
- package/dist/serialize-utils-CjTqQivB.cjs.map +0 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CborExtension } from './extensions/types';
|
|
2
|
+
import { CborItem } from './ast/CborItem';
|
|
2
3
|
import { CddlSchema } from './cddl/schema';
|
|
3
4
|
import { ValidateOptions as CddlValidateOptions } from './cddl/validator';
|
|
4
5
|
import { CddlValidationError, CddlValidationWarning } from './cddl/errors';
|
|
@@ -14,6 +15,114 @@ import { CddlValidationError, CddlValidationWarning } from './cddl/errors';
|
|
|
14
15
|
*/
|
|
15
16
|
export declare const CBOR_OMIT: unique symbol;
|
|
16
17
|
export type { CborExtension } from './extensions/types';
|
|
18
|
+
/**
|
|
19
|
+
* Context passed to an `itemOptions` callback (see `ToJSOptions.itemOptions`)
|
|
20
|
+
* describing where the node being visited sits in the tree.
|
|
21
|
+
*/
|
|
22
|
+
export interface ItemContext {
|
|
23
|
+
/**
|
|
24
|
+
* The direct parent AST node. `undefined` for the root value being
|
|
25
|
+
* converted. A tag or app-sequence wrapper is its content's `parent` —
|
|
26
|
+
* see `path` for how wrappers affect addressing.
|
|
27
|
+
*/
|
|
28
|
+
parent?: CborItem;
|
|
29
|
+
/**
|
|
30
|
+
* The path segment identifying this node: an array index (`number`), or a
|
|
31
|
+
* map key's JS value (any type — CBOR keys are not limited to strings).
|
|
32
|
+
* Always equal to the last element of `path`, except `undefined` for the
|
|
33
|
+
* root value and while converting a map key itself (`isMapKey: true`),
|
|
34
|
+
* since a key has no path of its own — it names its sibling value's
|
|
35
|
+
* segment instead. A tag or app-sequence wrapper's content inherits the
|
|
36
|
+
* wrapper's own `key` (and `path`) unchanged, since the wrapper adds no
|
|
37
|
+
* segment of its own — see `path`.
|
|
38
|
+
*/
|
|
39
|
+
key?: unknown;
|
|
40
|
+
/**
|
|
41
|
+
* The map key's own AST node, present when this node is a map entry's key
|
|
42
|
+
* or value — but *not* inherited into a tag/app-sequence wrapper's
|
|
43
|
+
* content the way `key`/`path` are, so it is only reliable at the map
|
|
44
|
+
* entry itself. Lets a callback inspect a non-scalar key structurally
|
|
45
|
+
* (e.g. via `keyNode._toCDN()`) instead of relying only on `key`'s
|
|
46
|
+
* computed JS value.
|
|
47
|
+
*/
|
|
48
|
+
keyNode?: CborItem;
|
|
49
|
+
/**
|
|
50
|
+
* `true` when this invocation is for converting a map key itself, rather
|
|
51
|
+
* than one of that key's sibling value's descendants.
|
|
52
|
+
*/
|
|
53
|
+
isMapKey?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Path from the root to this node, as a sequence of array indices and map
|
|
56
|
+
* key JS values. Empty for the root value. A tag or app-sequence wrapper
|
|
57
|
+
* does not add a segment of its own — its content shares the wrapper's own
|
|
58
|
+
* path.
|
|
59
|
+
*/
|
|
60
|
+
readonly path: readonly unknown[];
|
|
61
|
+
/**
|
|
62
|
+
* The options in effect for this node going into this call — i.e. the
|
|
63
|
+
* root options merged with whatever overrides its ancestors already
|
|
64
|
+
* returned, *before* this callback's own return value is merged on top.
|
|
65
|
+
* Read from this to build on the current value of an option (e.g. add an
|
|
66
|
+
* extension to whatever list is already in effect) instead of overriding
|
|
67
|
+
* it outright, or to make a decision based on an option's current value.
|
|
68
|
+
*
|
|
69
|
+
* A mutable-looking field here (currently just `extensions`) is a fresh
|
|
70
|
+
* copy, not the live array in effect elsewhere — mutating it in place
|
|
71
|
+
* (e.g. `ctx.options.extensions.push(ext)`) has no effect on this node,
|
|
72
|
+
* its siblings, or the caller's own options; return an override instead.
|
|
73
|
+
*
|
|
74
|
+
* Has no `reviver` — its type is `ReadonlyToJSNodeOptions`, not
|
|
75
|
+
* `ToJSOptions` — for the same reason this callback's own return value
|
|
76
|
+
* can't set one:
|
|
77
|
+
* since this callback may run more than once for the same node (see
|
|
78
|
+
* `ToJSOptions.itemOptions`), always reflecting only the reviver-
|
|
79
|
+
* independent options keeps what it reads consistent with what it can
|
|
80
|
+
* write, and keeps a callback that only inspects `options` pure across
|
|
81
|
+
* every one of those calls.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* // Add `dt_as_Date` to whatever extensions are already configured,
|
|
85
|
+
* // rather than replacing them.
|
|
86
|
+
* itemOptions: (_node, ctx) => ({
|
|
87
|
+
* extensions: [...(ctx.options.extensions ?? []), dt_as_Date],
|
|
88
|
+
* })
|
|
89
|
+
*/
|
|
90
|
+
readonly options: ReadonlyToJSNodeOptions;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* `ToJSOptions` with `reviver` removed. Used wherever an API only ever
|
|
94
|
+
* needs to see the reviver-*independent* part of the options in effect for
|
|
95
|
+
* a node — an `itemOptions` callback's return value, and the `options`
|
|
96
|
+
* parameter of `CborExtension.toJS()` — because reviving the value a node
|
|
97
|
+
* converts to always happens afterwards, exactly once per visit, in the
|
|
98
|
+
* container holding it (see `CborArray`/`CborMap`); it is never something
|
|
99
|
+
* the conversion of the node itself should (or, for `CborExtension.toJS()`,
|
|
100
|
+
* even can) branch on. Keeping `reviver` out of both signatures — rather
|
|
101
|
+
* than merely documenting that it should be ignored — means neither can
|
|
102
|
+
* observe whether one is present, which is what makes it safe for a
|
|
103
|
+
* `reviver`-driven `CborArray`/`CborMap` to convert a child more than once
|
|
104
|
+
* (see `ToJSOptions.itemOptions`) without either one's result depending on
|
|
105
|
+
* *which* of those conversions it was called for.
|
|
106
|
+
*/
|
|
107
|
+
export type ToJSNodeOptions = Omit<ToJSOptions, 'reviver'>;
|
|
108
|
+
/**
|
|
109
|
+
* `ToJSNodeOptions`, as handed to code that must not mutate it in place:
|
|
110
|
+
* `ItemContext.options` and the `options` parameter of
|
|
111
|
+
* `CborExtension.toJS()`. Both describe options actually in effect
|
|
112
|
+
* elsewhere in the tree, so mutating what's handed out here must not be
|
|
113
|
+
* able to reach that: reassigning a top-level property is a type error
|
|
114
|
+
* (`Readonly<...>`), and `extensions`, the one field on `ToJSOptions`
|
|
115
|
+
* that's an ordinary mutable array, is narrowed to a readonly array so an
|
|
116
|
+
* in-place mutation like `.push()` is one too. This only guards against
|
|
117
|
+
* *accidental* mutation via the type system — the implementation
|
|
118
|
+
* additionally hands out a fresh snapshot, with its own copy of
|
|
119
|
+
* `extensions`, on every call, so even a deliberate cast past this type
|
|
120
|
+
* can't corrupt what another node, sibling, hook, or pass sees (see
|
|
121
|
+
* `_toJSChild`'s `toReadonlyNodeOptions`).
|
|
122
|
+
*/
|
|
123
|
+
export type ReadonlyToJSNodeOptions = Readonly<Omit<ToJSNodeOptions, 'extensions'>> & {
|
|
124
|
+
readonly extensions?: readonly CborExtension[];
|
|
125
|
+
};
|
|
17
126
|
export interface ToHexDumpOptions {
|
|
18
127
|
/**
|
|
19
128
|
* Indentation per nesting level.
|
|
@@ -37,11 +146,19 @@ export interface ToJSOptions {
|
|
|
37
146
|
integerAs?: 'auto' | 'number' | 'bigint';
|
|
38
147
|
/**
|
|
39
148
|
* How to represent CBOR map values when converting to JavaScript.
|
|
40
|
-
* - `'auto'`:
|
|
41
|
-
*
|
|
42
|
-
*
|
|
149
|
+
* - `'auto'`: `Record<string, unknown>` when every key is a text string,
|
|
150
|
+
* or (with a CDDL `cddl` schema and `eRefKeys` not `false`) an e-ref
|
|
151
|
+
* annotated integer key that resolves to its name string — `Map<unknown,
|
|
152
|
+
* unknown>` for any other key type. Duplicate *text-string* keys are
|
|
153
|
+
* silently overwritten (last value wins), same as `'object'` below —
|
|
154
|
+
* but if a text-string key and an e-ref name key resolve to the same
|
|
155
|
+
* property string (e.g. `&(title: -1)` alongside a literal `"title"`
|
|
156
|
+
* key in the same map), `'auto'` falls back to `MapEntries` instead of
|
|
157
|
+
* silently dropping one of them.
|
|
43
158
|
* - `'object'`: always `Record<string, unknown>` — non-string keys are
|
|
44
|
-
* converted via `String()`. Duplicate keys
|
|
159
|
+
* converted via `String()`. Duplicate keys (including a text/e-ref
|
|
160
|
+
* collision as above) are overwritten (last wins) — unlike `'auto'`,
|
|
161
|
+
* `'object'` never falls back, since it was explicitly requested.
|
|
45
162
|
* - `'entries'`: always `MapEntries` (a typed `Array` subclass) — preserves all
|
|
46
163
|
* entries including duplicate keys (§2.4.2 of draft-ietf-cbor-edn-literals-27).
|
|
47
164
|
* `fromJS()` recognises `MapEntries` instances and converts them back to `CborMap`.
|
|
@@ -58,6 +175,30 @@ export interface ToJSOptions {
|
|
|
58
175
|
* @default false
|
|
59
176
|
*/
|
|
60
177
|
stripTags?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Whether a tag the CDDL schema itself implies is left off the JavaScript
|
|
180
|
+
* value — e.g. with `{ t: time }` (prelude `time = #6.1(number)`), the
|
|
181
|
+
* CBOR `{"t": 1(-14159024)}` (CDN `{"t": DT'1969-07-21T02:56:16Z'}`)
|
|
182
|
+
* converts to `{ t: -14159024 }` (a plain `number`) rather than a
|
|
183
|
+
* `Number` object carrying `Tag.symbol`.
|
|
184
|
+
*
|
|
185
|
+
* A tag counts as implied only where `FromJSOptions.implicitTags` would
|
|
186
|
+
* add it back when converting the result with the same schema, so
|
|
187
|
+
* `toJS()` → `fromJS()` still round-trips: it must be matched by a
|
|
188
|
+
* `#6.N(type)` with a literal tag number, and the untagged content must
|
|
189
|
+
* not be acceptable at that position on its own — under `time / number`
|
|
190
|
+
* a tagged `1(5)` keeps its tag, since plain `5` would stay untagged.
|
|
191
|
+
* Tags the schema doesn't require (`any`, `#6.<uint>(…)`, …) are always
|
|
192
|
+
* kept.
|
|
193
|
+
*
|
|
194
|
+
* Only takes effect for an item validated via `FromCBOROptions.cddl` /
|
|
195
|
+
* `FromCDNOptions.cddl` / `FromJSOptions.cddl`; without a schema, every
|
|
196
|
+
* tag is kept as before. Pass `false` to keep every tag even with one.
|
|
197
|
+
* `stripTags: true` removes all tags regardless.
|
|
198
|
+
*
|
|
199
|
+
* @default true
|
|
200
|
+
*/
|
|
201
|
+
implicitTags?: boolean;
|
|
61
202
|
/**
|
|
62
203
|
* Post-conversion reviver function, applied bottom-up after the CBOR value
|
|
63
204
|
* has been converted to JavaScript.
|
|
@@ -80,6 +221,110 @@ export interface ToJSOptions {
|
|
|
80
221
|
* @default false
|
|
81
222
|
*/
|
|
82
223
|
undefinedOmits?: boolean;
|
|
224
|
+
/**
|
|
225
|
+
* Extension plugins consulted during `toJS()`, tried in order for every
|
|
226
|
+
* node before its own default conversion. An extension takes part by
|
|
227
|
+
* implementing `CborExtension.toJS()`; the first one to return a result
|
|
228
|
+
* for a given node wins and that node's own `_toJS()` is not called.
|
|
229
|
+
*
|
|
230
|
+
* Unlike the `extensions` option on `FromCDNOptions`/`FromCBOROptions`,
|
|
231
|
+
* this does not affect parsing — it only lets `toJS()` reinterpret nodes
|
|
232
|
+
* that a *different* extension configuration already produced. For
|
|
233
|
+
* example, a tree parsed with the plain `dt` extension (`DT'...'` →
|
|
234
|
+
* `number`) can still be converted with `dt_as_Date` selected here
|
|
235
|
+
* (`DT'...'` → `Date`), and vice versa — see `itemOptions` below to apply
|
|
236
|
+
* this to only part of a tree.
|
|
237
|
+
*
|
|
238
|
+
* There is no `builtinExtensions` equivalent for `toJS()`: leaving this
|
|
239
|
+
* unset (the default) keeps every node's own built-in conversion
|
|
240
|
+
* behavior, so no bundled extension needs to be "re-added" here just to
|
|
241
|
+
* get default output.
|
|
242
|
+
*/
|
|
243
|
+
extensions?: CborExtension[];
|
|
244
|
+
/**
|
|
245
|
+
* Called for every node during `toJS()`, before that node is converted,
|
|
246
|
+
* to override the options used for its subtree. Return a partial options
|
|
247
|
+
* object to merge over the options in effect for this node (they apply to
|
|
248
|
+
* this node and are inherited by its descendants, who may override them
|
|
249
|
+
* again); return `undefined` to make no change.
|
|
250
|
+
*
|
|
251
|
+
* This is the mechanism for applying an option — including `extensions`,
|
|
252
|
+
* to select a different conversion for one node without affecting its
|
|
253
|
+
* siblings — to only part of a document, keyed off `ctx.path` or the
|
|
254
|
+
* node's own shape (`item instanceof ...`).
|
|
255
|
+
*
|
|
256
|
+
* **May be called more than once for the same AST node.** With a
|
|
257
|
+
* `reviver` present, `CborArray`/`CborMap` convert each child at least
|
|
258
|
+
* twice: once (with `reviver` itself withheld from the options this
|
|
259
|
+
* callback sees, though its own return value is honoured as normal) to
|
|
260
|
+
* build a holder a `reviver` call can inspect via `this[j]` for a
|
|
261
|
+
* not-yet-processed sibling `j`, and once more, for real, to compute the
|
|
262
|
+
* value the container actually keeps — and a node several levels down
|
|
263
|
+
* can in principle be offered to this callback more than twice, if a
|
|
264
|
+
* container at some intermediate level runs a pre-population pass of its
|
|
265
|
+
* own while itself sitting inside an *outer* container's. Each call is
|
|
266
|
+
* independent and reflects only the state relevant to *that* particular
|
|
267
|
+
* conversion (e.g. `ctx.path` for a value under a composite map key
|
|
268
|
+
* shows whatever that key currently converts to, which can differ
|
|
269
|
+
* between an earlier, not-yet-revived call and a later one after the
|
|
270
|
+
* key's own `reviver` has run). Write this callback as a pure function of
|
|
271
|
+
* `item`/`ctx` — it must not assume, or count, how many times it runs.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* // Convert only `date1` with `dt_as_Date`, leaving other DT values as
|
|
275
|
+
* // the epoch numbers the tree was originally parsed with.
|
|
276
|
+
* item.toJS({
|
|
277
|
+
* itemOptions: (node, ctx) =>
|
|
278
|
+
* ctx.path.length === 1 && ctx.path[0] === 'date1'
|
|
279
|
+
* ? { extensions: [dt_as_Date] }
|
|
280
|
+
* : undefined,
|
|
281
|
+
* });
|
|
282
|
+
*/
|
|
283
|
+
itemOptions?: (item: CborItem, ctx: ItemContext) => Partial<ToJSNodeOptions> | undefined;
|
|
284
|
+
/**
|
|
285
|
+
* Whether a map key annotated by CDDL `e'...'` external-reference
|
|
286
|
+
* resolution (draft-ietf-cbor-edn-e-ref) — an integer key the `cddl`
|
|
287
|
+
* schema names via a `&(name: value)` group entry at a map-member-key
|
|
288
|
+
* position, e.g. `? &(title: -1) => oltext` — converts to a plain-object
|
|
289
|
+
* key spelled as that name (`"title"`) instead of the integer itself. A
|
|
290
|
+
* general CDDL constant rule (`title = -1`) is not enough on its own to
|
|
291
|
+
* annotate a key this way — see `cddl/eref.ts`'s module doc — only
|
|
292
|
+
* `e'title'` written explicitly in CDN source resolves via a plain
|
|
293
|
+
* constant rule.
|
|
294
|
+
*
|
|
295
|
+
* Defaults to `true`: such a key exists at all only because some earlier
|
|
296
|
+
* `cddl`-validated decode/parse (or an `eRefKeys`-driven `fromJS()`, see
|
|
297
|
+
* `FromJSOptions.eRefKeys`) already named it, so leaving this option unset
|
|
298
|
+
* uses that name — pass `false` explicitly to fall back to the plain
|
|
299
|
+
* integer key instead (e.g. for code that reads `obj[-1]` and doesn't
|
|
300
|
+
* want it silently renamed to `obj.title`). A map with no CDDL-named keys
|
|
301
|
+
* at all is entirely unaffected either way — `mapAs: 'auto'`'s own choice
|
|
302
|
+
* between a plain object and `MapEntries` only ever treats a key as
|
|
303
|
+
* object-eligible via this option when the key is actually annotated;
|
|
304
|
+
* this is not a general "coerce integer keys to strings" switch.
|
|
305
|
+
*
|
|
306
|
+
* Only takes effect for a key CDDL validation has already annotated (see
|
|
307
|
+
* `FromCBOROptions.cddl` / `FromCDNOptions.cddl`); without a schema, or for
|
|
308
|
+
* a key the schema does not name this way, the key converts as usual.
|
|
309
|
+
* Annotation is unambiguous by construction (a name mapped to more than
|
|
310
|
+
* one value, or a value named more than once, in the same schema is
|
|
311
|
+
* excluded from annotation entirely — and a name ambiguous in either
|
|
312
|
+
* direction is excluded from *both*), so this never introduces a name
|
|
313
|
+
* collision on its own — though a name can still collide with an
|
|
314
|
+
* unrelated map's own genuine text-string key of the same spelling
|
|
315
|
+
* (e.g. `&(title: -1)` alongside a literal `"title"` key in the same
|
|
316
|
+
* map). `mapAs: 'auto'` treats that case differently from a plain
|
|
317
|
+
* duplicate text-string key: it detects the collision and falls back to
|
|
318
|
+
* `MapEntries` rather than silently dropping one side — see
|
|
319
|
+
* `ToJSOptions.mapAs`. An explicit `mapAs: 'object'` still overwrites
|
|
320
|
+
* (last value wins), the same as it does for any other non-injective key
|
|
321
|
+
* conversion. Only integer-valued names are annotated (see
|
|
322
|
+
* `cddl/eref.ts`'s Scope note) — a float, text, or byte-string map key is
|
|
323
|
+
* never affected.
|
|
324
|
+
*
|
|
325
|
+
* @default true
|
|
326
|
+
*/
|
|
327
|
+
eRefKeys?: boolean;
|
|
83
328
|
}
|
|
84
329
|
export interface ToCBOROptions {
|
|
85
330
|
}
|
|
@@ -525,7 +770,151 @@ export interface FromJSOptions {
|
|
|
525
770
|
* Mirrors `FromCBOROptions.cddlValidationOptions`.
|
|
526
771
|
*/
|
|
527
772
|
cddlValidationOptions?: CddlValidateOptions;
|
|
773
|
+
/**
|
|
774
|
+
* When not `false`, a plain object's property name that the `cddl` schema
|
|
775
|
+
* names — via a `&(name: value)` group entry at a map-member-key
|
|
776
|
+
* position (e.g. `? &(title: -1) => oltext`), or a bare reference to a
|
|
777
|
+
* constant rule at that same position — converts to that integer key
|
|
778
|
+
* instead of a text-string key, so `fromJS({ title: "oops" }, { cddl })`
|
|
779
|
+
* produces the same map `toJS()` on that map would read back as
|
|
780
|
+
* `{ title: "oops" }` (both options default to on, so neither needs
|
|
781
|
+
* spelling out explicitly to get a round-trip). The resulting key
|
|
782
|
+
* round-trips through `toCDN()` as `e'title'` the same way a
|
|
783
|
+
* schema-annotated key produced by `fromCBOR()`/`fromCDN()` does — only
|
|
784
|
+
* an unambiguous, integer-valued name is ever used this way (see
|
|
785
|
+
* `cddl/eref.ts`'s module doc).
|
|
786
|
+
*
|
|
787
|
+
* `ToJSOptions.eRefKeys` only ever renames an integer key some earlier
|
|
788
|
+
* step already labeled (`annotateERefKeys()`, run automatically after a
|
|
789
|
+
* successful `cddl`-validated decode/parse — or `e'name'` written
|
|
790
|
+
* explicitly in CDN source); this direction is different, since it
|
|
791
|
+
* *constructs* the key before any validation happens — so which names are
|
|
792
|
+
* even eligible is resolved **positionally**: only a name bound at a member-key position
|
|
793
|
+
* within the CDDL type actually governing *this* property's own position
|
|
794
|
+
* (starting from the schema's root rule, or `cddlValidationOptions.rule`
|
|
795
|
+
* when set, and descending through nested map types the same way this
|
|
796
|
+
* object's own nesting does) is used, never a name that merely exists
|
|
797
|
+
* *somewhere* in the schema. A property named `title` is therefore left
|
|
798
|
+
* as an ordinary text-string key unless the schema specifically names
|
|
799
|
+
* `title` at the exact position this object is being converted for —
|
|
800
|
+
* even if some unrelated, structurally unreachable rule elsewhere in the
|
|
801
|
+
* same schema happens to name `title` too (see `cddl/eRefScope.ts`'s own
|
|
802
|
+
* module doc, including its Scope note on what "governing type" this can
|
|
803
|
+
* and can't resolve).
|
|
804
|
+
*
|
|
805
|
+
* Only applies to a plain object's own properties (`Object.entries()`), not
|
|
806
|
+
* to a `MapEntries` key, which is preserved exactly as given (a native
|
|
807
|
+
* `Map` is not currently recognized by `fromJS()` at all — see its own
|
|
808
|
+
* doc — independent of `eRefKeys`) — a `MapEntries` entry's *value* still
|
|
809
|
+
* gets a nested scope when its own key is a string naming a known map
|
|
810
|
+
* property, the same way an ordinary property's value does, so a nested
|
|
811
|
+
* object reached this way still converts correctly; an array element
|
|
812
|
+
* never does, regardless. Without a schema, or for a property name the
|
|
813
|
+
* schema does not name this way at this exact position, the key converts as usual (a
|
|
814
|
+
* text-string key). Pass `false` explicitly to keep every property as a
|
|
815
|
+
* plain text-string key even when the schema would otherwise name one —
|
|
816
|
+
* e.g. for code that writes `{ title: "oops" }` and wants that spelled
|
|
817
|
+
* literally rather than resolved to `-1`. Requires `cddl` — has no effect
|
|
818
|
+
* on its own.
|
|
819
|
+
*
|
|
820
|
+
* @default true
|
|
821
|
+
*/
|
|
822
|
+
eRefKeys?: boolean;
|
|
823
|
+
/**
|
|
824
|
+
* Whether a tag the CDDL schema requires is added to a value that lacks
|
|
825
|
+
* it — e.g. with `{ t: time }` (prelude `time = #6.1(number)`),
|
|
826
|
+
* `{ t: -14159024 }` (a plain `number`, no `Tag.symbol`) converts to
|
|
827
|
+
* `{"t": 1(-14159024)}` (CDN `{"t": DT'1969-07-21T02:56:16Z'}`). The
|
|
828
|
+
* mirror image of `ToJSOptions.implicitTags`.
|
|
829
|
+
*
|
|
830
|
+
* Inference is a fallback, never a rewrite of valid data: nothing is
|
|
831
|
+
* added when the converted value already matches the schema, and at
|
|
832
|
+
* every choice an alternative the value matches as-is wins — with
|
|
833
|
+
* `time / number`, a plain `5` stays `5`. Only a `#6.N(type)` with a
|
|
834
|
+
* literal tag number is inferred (the tag is created the same way a
|
|
835
|
+
* `Tag.symbol`-annotated value would be, so tag 1 becomes a `DT'…'`
|
|
836
|
+
* node); a value already carrying `Tag.symbol` is used as given. When
|
|
837
|
+
* even inference cannot make the value match, it is left unchanged and
|
|
838
|
+
* the usual `CddlMismatchError` is thrown.
|
|
839
|
+
*
|
|
840
|
+
* Requires `cddl` — has no effect on its own. Pass `false` to require
|
|
841
|
+
* every tag to be spelled out via `Tag.symbol`, as without a schema.
|
|
842
|
+
*
|
|
843
|
+
* @default true
|
|
844
|
+
*/
|
|
845
|
+
implicitTags?: boolean;
|
|
528
846
|
}
|
|
847
|
+
/**
|
|
848
|
+
* Context passed to a `toCDN()` `itemOptions` callback (see
|
|
849
|
+
* `ToCDNOptions.itemOptions`) describing where the node being visited sits
|
|
850
|
+
* in the tree. Structurally the same shape as `ItemContext` (`toJS()`'s
|
|
851
|
+
* own per-item context — see there for the full rationale behind each
|
|
852
|
+
* field), but `path`'s map-key segments are derived the CDN way: a
|
|
853
|
+
* text-string key contributes its string value, any other key contributes
|
|
854
|
+
* its own `toCDN()` rendering — there is no "JS value" for a CDN key to
|
|
855
|
+
* contribute instead, since converting to JS is not what this call is
|
|
856
|
+
* doing.
|
|
857
|
+
*
|
|
858
|
+
* Unlike `ItemContext`, a node's `toCDN()` `itemOptions` callback can run
|
|
859
|
+
* more than once for reasons `toJS()`'s never does: `inlineLeafContainers`
|
|
860
|
+
* (and a tag/app-sequence value's own multi-word check) render an entry a
|
|
861
|
+
* second time, at the *same* depth and options, purely to answer a layout
|
|
862
|
+
* question (does it fit on one line? is it multi-word?) before the real
|
|
863
|
+
* render — an existing, deliberate characteristic of `toCDN()` itself (see
|
|
864
|
+
* `serializeContainer` in `cdn/serialize-utils.ts`), not something
|
|
865
|
+
* `itemOptions` introduces. Write this callback as a pure function of
|
|
866
|
+
* `item`/`ctx`, the same guidance as `ItemContext`'s own, for the same
|
|
867
|
+
* reason: it must not assume, or count, how many times it runs.
|
|
868
|
+
*/
|
|
869
|
+
export interface CdnItemContext {
|
|
870
|
+
/** The direct parent AST node. `undefined` for the root value being converted. */
|
|
871
|
+
parent?: CborItem;
|
|
872
|
+
/**
|
|
873
|
+
* The path segment identifying this node: an array index (`number`), or
|
|
874
|
+
* a map key's string value/`toCDN()` rendering (see `CdnItemContext`'s
|
|
875
|
+
* own note). Always equal to the last element of `path`, except
|
|
876
|
+
* `undefined` for the root value and while converting a map key itself
|
|
877
|
+
* (`isMapKey: true`). A tag or app-sequence wrapper's content inherits
|
|
878
|
+
* the wrapper's own `key` (and `path`) unchanged, since the wrapper adds
|
|
879
|
+
* no segment of its own.
|
|
880
|
+
*/
|
|
881
|
+
key?: unknown;
|
|
882
|
+
/** The map key's own AST node, present when this node is a map entry's key or value. */
|
|
883
|
+
keyNode?: CborItem;
|
|
884
|
+
/**
|
|
885
|
+
* `true` when this invocation is for converting a map key itself, rather
|
|
886
|
+
* than one of that key's sibling value's descendants.
|
|
887
|
+
*/
|
|
888
|
+
isMapKey?: boolean;
|
|
889
|
+
/**
|
|
890
|
+
* Path from the root to this node, as a sequence of array indices and
|
|
891
|
+
* map key identifiers (see `CdnItemContext`'s own note). Empty for the
|
|
892
|
+
* root value. A tag or app-sequence wrapper does not add a segment of
|
|
893
|
+
* its own — its content shares the wrapper's own path.
|
|
894
|
+
*/
|
|
895
|
+
readonly path: readonly unknown[];
|
|
896
|
+
/**
|
|
897
|
+
* The options in effect for this node going into this call — the root
|
|
898
|
+
* options merged with whatever overrides its ancestors already
|
|
899
|
+
* returned, *before* this callback's own return value is merged on top.
|
|
900
|
+
* A mutable-looking field here (currently just the deprecated
|
|
901
|
+
* `textStringFormat`) is a fresh copy, not the live array in effect
|
|
902
|
+
* elsewhere — mutating it in place has no effect on this node, its
|
|
903
|
+
* siblings, or the caller's own options; return an override instead.
|
|
904
|
+
*/
|
|
905
|
+
readonly options: ReadonlyToCDNOptions;
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* `ToCDNOptions`, as handed to code that must not mutate it in place —
|
|
909
|
+
* `CdnItemContext.options` — the `toCDN()` counterpart of
|
|
910
|
+
* `ReadonlyToJSNodeOptions`. `textStringFormat` (the one field on
|
|
911
|
+
* `ToCDNOptions` that's an ordinary mutable array, and already deprecated)
|
|
912
|
+
* is narrowed to a readonly array for the same reason `extensions` is
|
|
913
|
+
* there; see `ReadonlyToJSNodeOptions`'s own doc for the full rationale.
|
|
914
|
+
*/
|
|
915
|
+
export type ReadonlyToCDNOptions = Readonly<Omit<ToCDNOptions, 'textStringFormat'>> & {
|
|
916
|
+
readonly textStringFormat?: readonly TextStringFormat[];
|
|
917
|
+
};
|
|
529
918
|
export interface ToCDNOptions {
|
|
530
919
|
/**
|
|
531
920
|
* Indentation for pretty-printing.
|
|
@@ -1049,6 +1438,39 @@ export interface ToCDNOptions {
|
|
|
1049
1438
|
* @default 'auto'
|
|
1050
1439
|
*/
|
|
1051
1440
|
encodingIndicators?: 'always' | 'auto' | 'never';
|
|
1441
|
+
/**
|
|
1442
|
+
* Called for every node during `toCDN()`, before that node is rendered,
|
|
1443
|
+
* to override the options used for its subtree. Return a partial options
|
|
1444
|
+
* object to merge over the options in effect for this node (they apply to
|
|
1445
|
+
* this node and are inherited by its descendants, who may override them
|
|
1446
|
+
* again); return `undefined` to make no change.
|
|
1447
|
+
*
|
|
1448
|
+
* This is the mechanism for applying an option to only part of a
|
|
1449
|
+
* document — e.g. rendering one array element in hex while the rest stay
|
|
1450
|
+
* decimal — keyed off `ctx.path` or the node's own shape
|
|
1451
|
+
* (`item instanceof ...`).
|
|
1452
|
+
*
|
|
1453
|
+
* **May be called more than once for the same AST node** — see
|
|
1454
|
+
* `CdnItemContext`'s own note on why, and why this callback should be a
|
|
1455
|
+
* pure function of `item`/`ctx` rather than relying on how many times it
|
|
1456
|
+
* runs.
|
|
1457
|
+
*
|
|
1458
|
+
* Not called for keys of an indefinite-length string's chunks or a
|
|
1459
|
+
* `<<...>>` sequence's items, which have no key of their own to convert
|
|
1460
|
+
* (only array elements and map entries/keys have a `path` segment).
|
|
1461
|
+
*
|
|
1462
|
+
* @example
|
|
1463
|
+
* // Render only the value at key "raw" using hex integers, leaving the
|
|
1464
|
+
* // rest of the document in the default decimal format.
|
|
1465
|
+
* item.toCDN({
|
|
1466
|
+
* indent: 2,
|
|
1467
|
+
* itemOptions: (_node, ctx) =>
|
|
1468
|
+
* ctx.path.length === 1 && ctx.path[0] === 'raw'
|
|
1469
|
+
* ? { intFormat: 'hex' }
|
|
1470
|
+
* : undefined,
|
|
1471
|
+
* });
|
|
1472
|
+
*/
|
|
1473
|
+
itemOptions?: (item: CborItem, ctx: CdnItemContext) => Partial<ToCDNOptions> | undefined;
|
|
1052
1474
|
}
|
|
1053
1475
|
export type TextStringFormat = 'newline' | 'cdn' | DeprecatedTextStringFormat;
|
|
1054
1476
|
/** @deprecated Use `'cdn'` instead. */
|
package/dist/utils/hexfloat.d.ts
CHANGED
|
@@ -19,8 +19,16 @@ export declare function parseHexFloat(s: string): number;
|
|
|
19
19
|
* Convert a JS number to a normalized hex float string compatible with
|
|
20
20
|
* CDN diagnostic notation.
|
|
21
21
|
*
|
|
22
|
-
* -
|
|
23
|
-
*
|
|
22
|
+
* - Every nonzero finite value: `0x1.[hex fraction]p[+-][exp]` (e.g.
|
|
23
|
+
* `0x1.8p+0` for 1.5) — including a *subnormal* double, renormalized
|
|
24
|
+
* into this same leading-`1` form rather than spelled out anchored to
|
|
25
|
+
* its own stored field layout (`0x0.[hex fraction]p-1022`, still a
|
|
26
|
+
* correct spelling of the same value, but needlessly longer: e.g.
|
|
27
|
+
* `Number.MIN_VALUE` used to read `0x0.0000000000001p-1022`, equal to
|
|
28
|
+
* but far longer than the normalized `0x1p-1074`. A hex-float literal
|
|
29
|
+
* is just `significand * 2^exponent` — there's no reason its spelling
|
|
30
|
+
* should vary by whether the *double* happened to run out of exponent
|
|
31
|
+
* range, once it's just text.)
|
|
24
32
|
* - Zero: `0x0p+0` / `-0x0p+0`
|
|
25
33
|
* - Non-finite values (NaN, ±Infinity) are returned unchanged as EDN tokens.
|
|
26
34
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cbortech/cbor",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.2",
|
|
4
4
|
"description": "Convert between CBOR, CDN (CBOR-EDN), and JavaScript values with CDDL validation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cbor",
|
|
@@ -93,10 +93,10 @@
|
|
|
93
93
|
"start": "node dist/index.js",
|
|
94
94
|
"dev": "npm run build && npm start",
|
|
95
95
|
"clean": "node -e \"['dist','coverage'].forEach(d=>require('fs').rmSync(d,{recursive:true,force:true}))\"",
|
|
96
|
-
"test": "vitest run --exclude src/cdn/edn-test-vectors.test.ts --exclude src/cdn/edn-abnf-vectors.test.ts --exclude src/cddl/cddl-corpus.test.ts --exclude src/cddl/cddl-validation-vectors.test.ts --exclude site/src
|
|
96
|
+
"test": "vitest run --exclude src/cdn/edn-test-vectors.test.ts --exclude src/cdn/edn-abnf-vectors.test.ts --exclude src/cddl/cddl-corpus.test.ts --exclude src/cddl/cddl-validation-vectors.test.ts --exclude 'site/src/**/*.browser.test.ts'",
|
|
97
97
|
"test:exports": "npm run build && node scripts/check-package-exports.mjs",
|
|
98
98
|
"fetch-test-vectors": "node scripts/fetch-test-vectors.mjs",
|
|
99
|
-
"test:node": "vitest run --exclude src/cdn/edn-test-vectors.test.ts --exclude src/cdn/edn-abnf-vectors.test.ts --exclude src/cddl/cddl-corpus.test.ts --exclude src/cddl/cddl-validation-vectors.test.ts --exclude site/src
|
|
99
|
+
"test:node": "vitest run --exclude src/cdn/edn-test-vectors.test.ts --exclude src/cdn/edn-abnf-vectors.test.ts --exclude src/cddl/cddl-corpus.test.ts --exclude src/cddl/cddl-validation-vectors.test.ts --exclude 'site/src/**/*.browser.test.ts'",
|
|
100
100
|
"test:edn-vectors": "vitest run src/cdn/edn-test-vectors.test.ts",
|
|
101
101
|
"test:edn-abnf": "vitest run src/cdn/edn-abnf-vectors.test.ts",
|
|
102
102
|
"test:cddl-corpus": "vitest run src/cddl/cddl-corpus.test.ts",
|
|
@@ -118,19 +118,18 @@
|
|
|
118
118
|
"site:test": "npm run build && npm run --workspace site test"
|
|
119
119
|
},
|
|
120
120
|
"devDependencies": {
|
|
121
|
-
"@
|
|
122
|
-
"@types/node": "^24.13.3",
|
|
121
|
+
"@types/node": "^24.13.6",
|
|
123
122
|
"@typescript/typescript6": "^6.0.2",
|
|
124
|
-
"@vitest/browser": "^4.1.
|
|
125
|
-
"@vitest/browser-playwright": "^4.1.
|
|
126
|
-
"@vitest/coverage-v8": "^4.1.
|
|
127
|
-
"@vitest/ui": "^4.1.
|
|
123
|
+
"@vitest/browser": "^4.1.11",
|
|
124
|
+
"@vitest/browser-playwright": "^4.1.11",
|
|
125
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
126
|
+
"@vitest/ui": "^4.1.11",
|
|
128
127
|
"cross-env": "^10.1.0",
|
|
129
|
-
"playwright": "^1.
|
|
130
|
-
"prettier": "^3.9.
|
|
128
|
+
"playwright": "^1.63.0",
|
|
129
|
+
"prettier": "^3.9.8",
|
|
131
130
|
"typescript": "^7.0.2",
|
|
132
|
-
"vite": "^8.
|
|
133
|
-
"vite-plugin-dts": "^5.
|
|
134
|
-
"vitest": "^4.1.
|
|
131
|
+
"vite": "^8.3.0",
|
|
132
|
+
"vite-plugin-dts": "^5.1.1",
|
|
133
|
+
"vitest": "^4.1.11"
|
|
135
134
|
}
|
|
136
135
|
}
|