cesr-ts 0.3.1 → 0.5.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/README.md +3 -3
- package/esm/src/adapters/async-iterable.js +8 -0
- package/esm/src/adapters/effection.js +6 -0
- package/esm/src/annotate/annotator.js +16 -7
- package/esm/src/annotate/cli.js +12 -0
- package/esm/src/annotate/comments.js +6 -2
- package/esm/src/annotate/denot.js +6 -0
- package/esm/src/annotate/render.js +76 -76
- package/esm/src/core/bytes.js +56 -0
- package/esm/src/core/cbor.js +122 -0
- package/esm/src/core/errors.js +16 -0
- package/esm/src/core/parser-attachment-collector.js +1 -2
- package/esm/src/core/parser-engine.js +8 -8
- package/esm/src/core/parser-frame-parser.js +32 -35
- package/esm/src/core/vocabulary.js +47 -0
- package/esm/src/index.js +64 -33
- package/esm/src/parser/attachment-parser.js +5 -1
- package/esm/src/parser/cold-start.js +6 -0
- package/esm/src/parser/group-dispatch.js +28 -42
- package/esm/src/primitives/aggor.js +423 -36
- package/esm/src/primitives/bexter.js +59 -16
- package/esm/src/primitives/blinder.js +33 -20
- package/esm/src/primitives/byte-like.js +19 -0
- package/esm/src/primitives/cigar.js +39 -15
- package/esm/src/primitives/cipher.js +103 -0
- package/esm/src/primitives/codex.js +107 -0
- package/esm/src/primitives/compactor.js +308 -10
- package/esm/src/primitives/counter.js +207 -13
- package/esm/src/primitives/dater.js +30 -16
- package/esm/src/primitives/decimer.js +61 -0
- package/esm/src/primitives/decrypter.js +134 -0
- package/esm/src/primitives/diger.js +78 -18
- package/esm/src/primitives/disclosure.js +300 -0
- package/esm/src/primitives/encrypter.js +142 -0
- package/esm/src/primitives/hydrate.js +49 -0
- package/esm/src/primitives/ilker.js +22 -11
- package/esm/src/primitives/indexer.js +217 -8
- package/esm/src/primitives/labeler.js +73 -24
- package/esm/src/primitives/mapper.js +624 -68
- package/esm/src/primitives/matter.js +290 -6
- package/esm/src/primitives/mediar.js +33 -18
- package/esm/src/primitives/noncer.js +31 -14
- package/esm/src/primitives/number.js +27 -27
- package/esm/src/primitives/pather.js +128 -19
- package/esm/src/primitives/prefixer.js +22 -20
- package/esm/src/primitives/primitive.js +23 -0
- package/esm/src/primitives/registry.js +5 -3
- package/esm/src/primitives/saider.js +102 -19
- package/esm/src/primitives/salter.js +116 -0
- package/esm/src/primitives/sealed-box.js +41 -0
- package/esm/src/primitives/sealer.js +27 -32
- package/esm/src/primitives/seqner.js +27 -19
- package/esm/src/primitives/siger.js +84 -0
- package/esm/src/primitives/signer.js +257 -0
- package/esm/src/primitives/streamer.js +28 -0
- package/esm/src/primitives/structing.js +727 -0
- package/esm/src/primitives/structor.js +124 -0
- package/esm/src/primitives/tagger.js +43 -0
- package/esm/src/primitives/texter.js +23 -15
- package/esm/src/primitives/tholder.js +567 -22
- package/esm/src/primitives/traitor.js +21 -15
- package/esm/src/primitives/unknown.js +89 -0
- package/esm/src/primitives/verfer.js +69 -25
- package/esm/src/primitives/verser.js +63 -22
- package/esm/src/router/router-stub.js +1 -0
- package/esm/src/serder/native.js +1326 -0
- package/esm/src/serder/serder.js +1699 -20
- package/esm/src/serder/serdery.js +94 -9
- package/esm/src/serder/smell.js +26 -1
- package/esm/src/tables/codex-utils.js +11 -0
- package/esm/src/tables/counter-codex.js +3 -1
- package/esm/src/tables/counter-groups.js +52 -0
- package/esm/src/tables/counter-version-registry.js +1 -1
- package/esm/src/tables/indexer.codex.generated.js +64 -0
- package/esm/src/tables/indexer.tables.generated.js +72 -0
- package/esm/src/tables/matter.codex.generated.js +399 -0
- package/esm/src/tables/matter.tables.generated.js +112 -0
- package/esm/src/tables/trait.codex.generated.js +10 -0
- package/esm/src/tables/versions.js +4 -0
- package/esm/src/version.js +5 -2
- package/package.json +5 -2
- package/types/src/adapters/async-iterable.d.ts +9 -1
- package/types/src/adapters/async-iterable.d.ts.map +1 -1
- package/types/src/adapters/effection.d.ts +8 -1
- package/types/src/adapters/effection.d.ts.map +1 -1
- package/types/src/annotate/annotator.d.ts +12 -0
- package/types/src/annotate/annotator.d.ts.map +1 -1
- package/types/src/annotate/cli.d.ts +13 -0
- package/types/src/annotate/cli.d.ts.map +1 -1
- package/types/src/annotate/comments.d.ts +4 -0
- package/types/src/annotate/comments.d.ts.map +1 -1
- package/types/src/annotate/denot.d.ts +6 -0
- package/types/src/annotate/denot.d.ts.map +1 -1
- package/types/src/annotate/render.d.ts.map +1 -1
- package/types/src/annotate/types.d.ts +2 -0
- package/types/src/annotate/types.d.ts.map +1 -1
- package/types/src/bench/parser-benchmark.d.ts +3 -0
- package/types/src/bench/parser-benchmark.d.ts.map +1 -1
- package/types/src/core/bytes.d.ts +31 -0
- package/types/src/core/bytes.d.ts.map +1 -1
- package/types/src/core/cbor.d.ts +30 -0
- package/types/src/core/cbor.d.ts.map +1 -0
- package/types/src/core/errors.d.ts +16 -0
- package/types/src/core/errors.d.ts.map +1 -1
- package/types/src/core/parser-attachment-collector.d.ts.map +1 -1
- package/types/src/core/parser-engine.d.ts +5 -1
- package/types/src/core/parser-engine.d.ts.map +1 -1
- package/types/src/core/parser-frame-parser.d.ts +1 -1
- package/types/src/core/parser-frame-parser.d.ts.map +1 -1
- package/types/src/core/types.d.ts +9 -36
- package/types/src/core/types.d.ts.map +1 -1
- package/types/src/core/vocabulary.d.ts +48 -0
- package/types/src/core/vocabulary.d.ts.map +1 -0
- package/types/src/index.d.ts +64 -33
- package/types/src/index.d.ts.map +1 -1
- package/types/src/parser/attachment-fallback-policy.d.ts.map +1 -1
- package/types/src/parser/attachment-parser.d.ts +4 -0
- package/types/src/parser/attachment-parser.d.ts.map +1 -1
- package/types/src/parser/cold-start.d.ts +6 -0
- package/types/src/parser/cold-start.d.ts.map +1 -1
- package/types/src/parser/group-dispatch.d.ts +2 -2
- package/types/src/parser/group-dispatch.d.ts.map +1 -1
- package/types/src/primitives/aggor.d.ts +122 -9
- package/types/src/primitives/aggor.d.ts.map +1 -1
- package/types/src/primitives/bexter.d.ts +28 -6
- package/types/src/primitives/bexter.d.ts.map +1 -1
- package/types/src/primitives/blinder.d.ts +22 -8
- package/types/src/primitives/blinder.d.ts.map +1 -1
- package/types/src/primitives/byte-like.d.ts +7 -0
- package/types/src/primitives/byte-like.d.ts.map +1 -0
- package/types/src/primitives/cigar.d.ts +22 -7
- package/types/src/primitives/cigar.d.ts.map +1 -1
- package/types/src/primitives/cipher.d.ts +82 -0
- package/types/src/primitives/cipher.d.ts.map +1 -0
- package/types/src/primitives/codex.d.ts +84 -0
- package/types/src/primitives/codex.d.ts.map +1 -0
- package/types/src/primitives/compactor.d.ts +94 -2
- package/types/src/primitives/compactor.d.ts.map +1 -1
- package/types/src/primitives/counter.d.ts +63 -2
- package/types/src/primitives/counter.d.ts.map +1 -1
- package/types/src/primitives/dater.d.ts +12 -7
- package/types/src/primitives/dater.d.ts.map +1 -1
- package/types/src/primitives/decimer.d.ts +23 -0
- package/types/src/primitives/decimer.d.ts.map +1 -0
- package/types/src/primitives/decrypter.d.ts +72 -0
- package/types/src/primitives/decrypter.d.ts.map +1 -0
- package/types/src/primitives/diger.d.ts +32 -7
- package/types/src/primitives/diger.d.ts.map +1 -1
- package/types/src/primitives/disclosure.d.ts +201 -0
- package/types/src/primitives/disclosure.d.ts.map +1 -0
- package/types/src/primitives/encrypter.d.ts +74 -0
- package/types/src/primitives/encrypter.d.ts.map +1 -0
- package/types/src/primitives/hydrate.d.ts +20 -0
- package/types/src/primitives/hydrate.d.ts.map +1 -0
- package/types/src/primitives/ilker.d.ts +13 -6
- package/types/src/primitives/ilker.d.ts.map +1 -1
- package/types/src/primitives/indexer.d.ts +52 -1
- package/types/src/primitives/indexer.d.ts.map +1 -1
- package/types/src/primitives/labeler.d.ts +28 -11
- package/types/src/primitives/labeler.d.ts.map +1 -1
- package/types/src/primitives/mapper.d.ts +136 -17
- package/types/src/primitives/mapper.d.ts.map +1 -1
- package/types/src/primitives/matter.d.ts +76 -1
- package/types/src/primitives/matter.d.ts.map +1 -1
- package/types/src/primitives/mediar.d.ts +22 -8
- package/types/src/primitives/mediar.d.ts.map +1 -1
- package/types/src/primitives/noncer.d.ts +20 -6
- package/types/src/primitives/noncer.d.ts.map +1 -1
- package/types/src/primitives/number.d.ts +12 -7
- package/types/src/primitives/number.d.ts.map +1 -1
- package/types/src/primitives/pather.d.ts +33 -6
- package/types/src/primitives/pather.d.ts.map +1 -1
- package/types/src/primitives/prefixer.d.ts +12 -6
- package/types/src/primitives/prefixer.d.ts.map +1 -1
- package/types/src/primitives/primitive.d.ts +51 -0
- package/types/src/primitives/primitive.d.ts.map +1 -0
- package/types/src/primitives/registry.d.ts +3 -0
- package/types/src/primitives/registry.d.ts.map +1 -1
- package/types/src/primitives/saider.d.ts +53 -7
- package/types/src/primitives/saider.d.ts.map +1 -1
- package/types/src/primitives/salter.d.ts +68 -0
- package/types/src/primitives/salter.d.ts.map +1 -0
- package/types/src/primitives/sealed-box.d.ts +29 -0
- package/types/src/primitives/sealed-box.d.ts.map +1 -0
- package/types/src/primitives/sealer.d.ts +16 -8
- package/types/src/primitives/sealer.d.ts.map +1 -1
- package/types/src/primitives/seqner.d.ts +12 -7
- package/types/src/primitives/seqner.d.ts.map +1 -1
- package/types/src/primitives/siger.d.ts +30 -0
- package/types/src/primitives/siger.d.ts.map +1 -0
- package/types/src/primitives/signer.d.ts +90 -0
- package/types/src/primitives/signer.d.ts.map +1 -0
- package/types/src/primitives/streamer.d.ts +31 -0
- package/types/src/primitives/streamer.d.ts.map +1 -0
- package/types/src/primitives/structing.d.ts +4114 -0
- package/types/src/primitives/structing.d.ts.map +1 -0
- package/types/src/primitives/structor.d.ts +50 -0
- package/types/src/primitives/structor.d.ts.map +1 -0
- package/types/src/primitives/tagger.d.ts +17 -0
- package/types/src/primitives/tagger.d.ts.map +1 -0
- package/types/src/primitives/texter.d.ts +11 -6
- package/types/src/primitives/texter.d.ts.map +1 -1
- package/types/src/primitives/tholder.d.ts +156 -6
- package/types/src/primitives/tholder.d.ts.map +1 -1
- package/types/src/primitives/traitor.d.ts +13 -6
- package/types/src/primitives/traitor.d.ts.map +1 -1
- package/types/src/primitives/unknown.d.ts +32 -0
- package/types/src/primitives/unknown.d.ts.map +1 -0
- package/types/src/primitives/verfer.d.ts +24 -7
- package/types/src/primitives/verfer.d.ts.map +1 -1
- package/types/src/primitives/verser.d.ts +29 -8
- package/types/src/primitives/verser.d.ts.map +1 -1
- package/types/src/router/router-stub.d.ts +3 -0
- package/types/src/router/router-stub.d.ts.map +1 -1
- package/types/src/serder/native.d.ts +115 -0
- package/types/src/serder/native.d.ts.map +1 -0
- package/types/src/serder/serder.d.ts +247 -3
- package/types/src/serder/serder.d.ts.map +1 -1
- package/types/src/serder/serdery.d.ts +42 -0
- package/types/src/serder/serdery.d.ts.map +1 -1
- package/types/src/serder/smell.d.ts +22 -0
- package/types/src/serder/smell.d.ts.map +1 -1
- package/types/src/tables/codex-utils.d.ts +7 -0
- package/types/src/tables/codex-utils.d.ts.map +1 -0
- package/types/src/tables/counter-codex.d.ts +4 -0
- package/types/src/tables/counter-codex.d.ts.map +1 -1
- package/types/src/tables/counter-groups.d.ts +14 -0
- package/types/src/tables/counter-groups.d.ts.map +1 -0
- package/types/src/tables/counter.tables.generated.d.ts.map +1 -1
- package/types/src/tables/indexer.codex.generated.d.ts +127 -0
- package/types/src/tables/indexer.codex.generated.d.ts.map +1 -0
- package/types/src/tables/indexer.tables.generated.d.ts +46 -0
- package/types/src/tables/indexer.tables.generated.d.ts.map +1 -0
- package/types/src/tables/matter.codex.generated.d.ts +797 -0
- package/types/src/tables/matter.codex.generated.d.ts.map +1 -0
- package/types/src/tables/matter.tables.generated.d.ts +112 -0
- package/types/src/tables/matter.tables.generated.d.ts.map +1 -1
- package/types/src/tables/table-types.d.ts +13 -0
- package/types/src/tables/table-types.d.ts.map +1 -1
- package/types/src/tables/trait.codex.generated.d.ts +19 -0
- package/types/src/tables/trait.codex.generated.d.ts.map +1 -0
- package/types/src/tables/versions.d.ts +6 -0
- package/types/src/tables/versions.d.ts.map +1 -1
- package/types/src/version.d.ts +5 -2
- package/types/src/version.d.ts.map +1 -1
- package/esm/src/tables/indexer.tables.js +0 -30
- package/types/src/tables/indexer.tables.d.ts +0 -12
- package/types/src/tables/indexer.tables.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ const parser = createParser();
|
|
|
18
18
|
const out = parser.feed(new TextEncoder().encode("...CESR..."));
|
|
19
19
|
const last = parser.flush();
|
|
20
20
|
|
|
21
|
-
const text =
|
|
21
|
+
const text = "{\"v\":\"KERI10JSON00002e_\",\"t\":\"rpy\",\"d\":\"Eabc\"}";
|
|
22
22
|
const annotated = annotate(text, { domainHint: "txt", pretty: true });
|
|
23
23
|
```
|
|
24
24
|
|
|
@@ -61,5 +61,5 @@ tufa annotate --in mystream.cesr --pretty
|
|
|
61
61
|
|
|
62
62
|
## License
|
|
63
63
|
|
|
64
|
-
Licensed under the Apache License, Version 2.0 (`Apache-2.0`). See the
|
|
65
|
-
|
|
64
|
+
Licensed under the Apache License, Version 2.0 (`Apache-2.0`). See the top-level
|
|
65
|
+
`LICENSE` file in this repository.
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { createParser } from "../core/parser-engine.js";
|
|
2
|
+
/**
|
|
3
|
+
* Adapt an async byte stream into parsed CESR frames.
|
|
4
|
+
*
|
|
5
|
+
* Boundary contract:
|
|
6
|
+
* - chunks are fed in arrival order into one parser instance
|
|
7
|
+
* - emitted parser error events are rethrown as stream errors
|
|
8
|
+
* - yielded values are the historical `CesrMessage` frame payloads only
|
|
9
|
+
*/
|
|
2
10
|
export async function* toAsyncFrames(source, options = {}) {
|
|
3
11
|
const parser = createParser(options);
|
|
4
12
|
for await (const chunk of source) {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { action } from "effection";
|
|
2
2
|
import { toAsyncFrames } from "./async-iterable.js";
|
|
3
|
+
/**
|
|
4
|
+
* Bridge the async-iterable parser adapter into an Effection operation.
|
|
5
|
+
*
|
|
6
|
+
* This stays intentionally thin so parser semantics continue to live in
|
|
7
|
+
* `toAsyncFrames()` rather than forking behavior in an Effection-only path.
|
|
8
|
+
*/
|
|
3
9
|
export function* toEffectionFrames(source, options = {}) {
|
|
4
10
|
const frames = yield* action((resolve) => {
|
|
5
11
|
resolve(toAsyncFrames(source, options));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { b } from "../core/bytes.js";
|
|
1
2
|
import { parseBytes } from "../core/parser-engine.js";
|
|
2
|
-
import { renderAnnotatedFrames, renderWrapperAnnotatedStream
|
|
3
|
+
import { renderAnnotatedFrames, renderWrapperAnnotatedStream } from "./render.js";
|
|
3
4
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
4
5
|
commentMode: "inline",
|
|
5
6
|
indent: 2,
|
|
@@ -24,19 +25,27 @@ function parsedFramesOrThrow(frames) {
|
|
|
24
25
|
}
|
|
25
26
|
return parsedFrames;
|
|
26
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse input and return one annotation structure per emitted frame.
|
|
30
|
+
*
|
|
31
|
+
* Use this when callers want to inspect annotation lines programmatically
|
|
32
|
+
* instead of flattening the whole stream to one rendered string.
|
|
33
|
+
*/
|
|
27
34
|
export function annotateFrames(input, options) {
|
|
28
35
|
const opts = resolveOptions(options);
|
|
29
|
-
const bytes = typeof input === "string"
|
|
30
|
-
? new TextEncoder().encode(input)
|
|
31
|
-
: input;
|
|
36
|
+
const bytes = typeof input === "string" ? b(input) : input;
|
|
32
37
|
const frames = parsedFramesOrThrow(parseBytes(bytes));
|
|
33
38
|
return renderAnnotatedFrames(frames, opts);
|
|
34
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Render one CESR stream into maintainer-oriented annotated text.
|
|
42
|
+
*
|
|
43
|
+
* Wrapper-aware rendering is attempted first so opaque wrapper payloads can be
|
|
44
|
+
* preserved faithfully before falling back to frame-by-frame annotation.
|
|
45
|
+
*/
|
|
35
46
|
export function annotate(input, options) {
|
|
36
47
|
const opts = resolveOptions(options);
|
|
37
|
-
const bytes = typeof input === "string"
|
|
38
|
-
? new TextEncoder().encode(input)
|
|
39
|
-
: input;
|
|
48
|
+
const bytes = typeof input === "string" ? b(input) : input;
|
|
40
49
|
const wrapperAnnotated = renderWrapperAnnotatedStream(bytes, opts);
|
|
41
50
|
if (wrapperAnnotated !== null) {
|
|
42
51
|
return wrapperAnnotated;
|
package/esm/src/annotate/cli.js
CHANGED
|
@@ -35,6 +35,12 @@ function parseArgs(args) {
|
|
|
35
35
|
}
|
|
36
36
|
return out;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Read a full `ReadableStream` into one contiguous byte buffer.
|
|
40
|
+
*
|
|
41
|
+
* This is the shared browser/runtime-neutral helper used by annotate CLI
|
|
42
|
+
* shims that expose stdin as a web stream instead of synchronous file APIs.
|
|
43
|
+
*/
|
|
38
44
|
export async function readAllReadable(stream) {
|
|
39
45
|
const reader = stream.getReader();
|
|
40
46
|
const chunks = [];
|
|
@@ -61,6 +67,12 @@ export async function readAllReadable(stream) {
|
|
|
61
67
|
}
|
|
62
68
|
return out;
|
|
63
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Execute the standalone annotate CLI against the provided IO boundary.
|
|
72
|
+
*
|
|
73
|
+
* Error reporting is intentionally normalized here so runtime-specific entry
|
|
74
|
+
* points can stay as thin bootstraps.
|
|
75
|
+
*/
|
|
64
76
|
export async function annotateCli(args, io) {
|
|
65
77
|
try {
|
|
66
78
|
const options = parseArgs(args);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { COUNTER_CODE_NAMES_V1, COUNTER_CODE_NAMES_V2, } from "../tables/counter.tables.generated.js";
|
|
2
|
-
import { MATTER_CODE_NAMES } from "../tables/matter.tables.generated.js";
|
|
3
1
|
import { resolveCounterCodeNameTable } from "../tables/counter-version-registry.js";
|
|
2
|
+
import { COUNTER_CODE_NAMES_V1, COUNTER_CODE_NAMES_V2 } from "../tables/counter.tables.generated.js";
|
|
3
|
+
import { MATTER_CODE_NAMES } from "../tables/matter.tables.generated.js";
|
|
4
4
|
const NATIVE_FIELD_LABELS = Object.freeze({
|
|
5
5
|
v: "version string",
|
|
6
6
|
t: "ilk",
|
|
@@ -17,6 +17,7 @@ const NATIVE_FIELD_LABELS = Object.freeze({
|
|
|
17
17
|
c: "traits/config",
|
|
18
18
|
a: "anchors/data",
|
|
19
19
|
});
|
|
20
|
+
/** Resolve a human-readable counter name against either known counter table. */
|
|
20
21
|
export function counterCodeName(code) {
|
|
21
22
|
const v2 = COUNTER_CODE_NAMES_V2[code];
|
|
22
23
|
if (v2)
|
|
@@ -26,13 +27,16 @@ export function counterCodeName(code) {
|
|
|
26
27
|
return v1;
|
|
27
28
|
return "Counter";
|
|
28
29
|
}
|
|
30
|
+
/** Resolve a counter name against the registry selected for one protocol version. */
|
|
29
31
|
export function counterCodeNameForVersion(code, version) {
|
|
30
32
|
const table = resolveCounterCodeNameTable(version);
|
|
31
33
|
return table[code] ?? "Counter";
|
|
32
34
|
}
|
|
35
|
+
/** Resolve a human-readable matter name from the generated matter code table. */
|
|
33
36
|
export function matterCodeName(code) {
|
|
34
37
|
return MATTER_CODE_NAMES[code] ?? "Matter";
|
|
35
38
|
}
|
|
39
|
+
/** Expand well-known native field labels for annotation comments when available. */
|
|
36
40
|
export function nativeLabelName(label) {
|
|
37
41
|
if (!label)
|
|
38
42
|
return null;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
const TEXT_ENCODER = new TextEncoder();
|
|
2
|
+
/**
|
|
3
|
+
* Strip annotation comments/whitespace and rebuild the raw CESR text stream.
|
|
4
|
+
*
|
|
5
|
+
* This is the inverse of maintainer-facing annotation output, not a general
|
|
6
|
+
* parser: comment lines and inline `# ...` commentary are discarded.
|
|
7
|
+
*/
|
|
2
8
|
export function denot(annotated) {
|
|
3
9
|
const tokens = [];
|
|
4
10
|
for (const line of annotated.split(/\r?\n/)) {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { b64ToInt, intToB64 } from "../core/bytes.js";
|
|
2
|
+
import { DeserializeError, GroupSizeError, ShortageError, UnknownCodeError } from "../core/errors.js";
|
|
1
3
|
import { parseBytes } from "../core/parser-engine.js";
|
|
2
|
-
import { DeserializeError, GroupSizeError, ShortageError, UnknownCodeError, } from "../core/errors.js";
|
|
3
4
|
import { sniff } from "../parser/cold-start.js";
|
|
4
|
-
import { parseCounter } from "../primitives/counter.js";
|
|
5
|
-
import { parseMatter } from "../primitives/matter.js";
|
|
6
|
-
import { parseIndexer } from "../primitives/indexer.js";
|
|
7
5
|
import { parseAttachmentDispatchCompat } from "../parser/group-dispatch.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { Counter, parseCounter } from "../primitives/counter.js";
|
|
7
|
+
import { Indexer } from "../primitives/indexer.js";
|
|
8
|
+
import { Matter, parseMatter } from "../primitives/matter.js";
|
|
9
|
+
import { isCounterGroupLike, isPrimitiveTuple } from "../primitives/primitive.js";
|
|
10
|
+
import { UnknownPrimitive } from "../primitives/unknown.js";
|
|
11
|
+
import { counterCodeName, counterCodeNameForVersion, matterCodeName, nativeLabelName } from "./comments.js";
|
|
10
12
|
const TEXT_DECODER = new TextDecoder();
|
|
11
|
-
const TEXT_ENCODER = new TextEncoder();
|
|
12
13
|
const OPAQUE_TOKEN_COMMENT = "opaque token";
|
|
13
14
|
const OPAQUE_WRAPPER_PAYLOAD_COMMENT = "opaque wrapper payload";
|
|
14
15
|
const WRAPPER_GROUP_NAMES = new Set([
|
|
@@ -27,10 +28,10 @@ function toHex(bytes) {
|
|
|
27
28
|
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
28
29
|
}
|
|
29
30
|
function isRecoverableParseError(error) {
|
|
30
|
-
return error instanceof UnknownCodeError
|
|
31
|
-
error instanceof DeserializeError
|
|
32
|
-
error instanceof ShortageError
|
|
33
|
-
error instanceof GroupSizeError;
|
|
31
|
+
return error instanceof UnknownCodeError
|
|
32
|
+
|| error instanceof DeserializeError
|
|
33
|
+
|| error instanceof ShortageError
|
|
34
|
+
|| error instanceof GroupSizeError;
|
|
34
35
|
}
|
|
35
36
|
function spaces(count) {
|
|
36
37
|
return " ".repeat(Math.max(0, count));
|
|
@@ -58,51 +59,7 @@ function emitLine(lines, value, comment, indent, options) {
|
|
|
58
59
|
}
|
|
59
60
|
lines.push(`${pad}${value} # ${comment}`);
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
const input = TEXT_ENCODER.encode(token);
|
|
63
|
-
try {
|
|
64
|
-
const counter = parseCounter(input, version, domain);
|
|
65
|
-
return {
|
|
66
|
-
comment: `${counterCodeNameForVersion(counter.code, version)} counter`,
|
|
67
|
-
size: domain === "bny" ? counter.fullSizeB2 : counter.fullSize,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
if (!isRecoverableParseError(error)) {
|
|
72
|
-
throw error;
|
|
73
|
-
}
|
|
74
|
-
// Try indexer/matter below.
|
|
75
|
-
}
|
|
76
|
-
try {
|
|
77
|
-
const indexer = parseIndexer(input, domain);
|
|
78
|
-
return {
|
|
79
|
-
comment: `Indexer ${indexer.code}`,
|
|
80
|
-
size: domain === "bny" ? indexer.fullSizeB2 : indexer.fullSize,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
if (!isRecoverableParseError(error)) {
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
// Try matter below.
|
|
88
|
-
}
|
|
89
|
-
try {
|
|
90
|
-
const matter = parseMatter(input, domain);
|
|
91
|
-
return {
|
|
92
|
-
comment: matterCodeName(matter.code),
|
|
93
|
-
size: domain === "bny" ? matter.fullSizeB2 : matter.fullSize,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
if (!isRecoverableParseError(error)) {
|
|
98
|
-
throw error;
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
comment: OPAQUE_TOKEN_COMMENT,
|
|
102
|
-
size: token.length,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
}
|
|
62
|
+
/** Parse counters with a bounded v1/v2 fallback for annotation-only rendering paths. */
|
|
106
63
|
function parseCounterCompat(input, version, domain) {
|
|
107
64
|
try {
|
|
108
65
|
return parseCounter(input, version, domain);
|
|
@@ -117,6 +74,7 @@ function parseCounterCompat(input, version, domain) {
|
|
|
117
74
|
return parseCounter(input, alternate, domain);
|
|
118
75
|
}
|
|
119
76
|
}
|
|
77
|
+
/** Decode a wrapped genus-version selector into the active protocol version context. */
|
|
120
78
|
function decodeVersionCounter(counter) {
|
|
121
79
|
const triplet = counter.qb64.length >= 3
|
|
122
80
|
? counter.qb64.slice(-3)
|
|
@@ -128,29 +86,41 @@ function decodeVersionCounter(counter) {
|
|
|
128
86
|
minor: minorRaw,
|
|
129
87
|
};
|
|
130
88
|
}
|
|
89
|
+
/** Render hydrated group entries recursively using semantic primitive comments. */
|
|
131
90
|
function renderGroupItems(lines, items, version, indent, options) {
|
|
132
91
|
for (const item of items) {
|
|
133
|
-
if (item
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
emitLine(lines, item.qb64,
|
|
92
|
+
if (isPrimitiveTuple(item)) {
|
|
93
|
+
renderGroupItems(lines, item, version, indent + options.indent, options);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (isCounterGroupLike(item)) {
|
|
97
|
+
emitLine(lines, item.qb64, `${item.name} nested group`, indent, options);
|
|
98
|
+
renderGroupItems(lines, [...item.items], version, indent + options.indent, options);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (item instanceof UnknownPrimitive) {
|
|
102
|
+
const value = item.sourceDomain === "bny"
|
|
103
|
+
? `0x${toHex(item.qb2)}`
|
|
104
|
+
: item.qb64;
|
|
105
|
+
emitLine(lines, value, OPAQUE_WRAPPER_PAYLOAD_COMMENT, indent, options);
|
|
139
106
|
continue;
|
|
140
107
|
}
|
|
141
|
-
if (item
|
|
142
|
-
emitLine(lines,
|
|
108
|
+
if (item instanceof Counter) {
|
|
109
|
+
emitLine(lines, item.qb64, `${counterCodeNameForVersion(item.code, version)} counter`, indent, options);
|
|
143
110
|
continue;
|
|
144
111
|
}
|
|
145
|
-
if (item
|
|
146
|
-
|
|
112
|
+
if (item instanceof Indexer) {
|
|
113
|
+
emitLine(lines, item.qb64, `Indexer ${item.code}`, indent, options);
|
|
147
114
|
continue;
|
|
148
115
|
}
|
|
149
|
-
if (item
|
|
150
|
-
emitLine(lines,
|
|
116
|
+
if (item instanceof Matter) {
|
|
117
|
+
emitLine(lines, item.qb64, matterCodeName(item.code), indent, options);
|
|
118
|
+
continue;
|
|
151
119
|
}
|
|
120
|
+
emitLine(lines, String(item), OPAQUE_TOKEN_COMMENT, indent, options);
|
|
152
121
|
}
|
|
153
122
|
}
|
|
123
|
+
/** Render one raw attachment-group span, including nested wrapper groups when present. */
|
|
154
124
|
function renderAttachmentGroupRaw(lines, raw, version, indent, options) {
|
|
155
125
|
const domain = asDomain(raw);
|
|
156
126
|
if (domain !== "txt" && domain !== "bny") {
|
|
@@ -204,6 +174,7 @@ function renderAttachmentGroupRaw(lines, raw, version, indent, options) {
|
|
|
204
174
|
renderGroupItems(lines, parsed.group.items, version, indent + options.indent, options);
|
|
205
175
|
return parsed.consumed;
|
|
206
176
|
}
|
|
177
|
+
/** Render a native CESR body-group payload using hydrated native field projections when available. */
|
|
207
178
|
function renderNativeBody(lines, frame, options, version) {
|
|
208
179
|
const raw = frame.body.raw;
|
|
209
180
|
const domain = asDomain(raw);
|
|
@@ -212,18 +183,44 @@ function renderNativeBody(lines, frame, options, version) {
|
|
|
212
183
|
}
|
|
213
184
|
const counter = parseCounterCompat(raw, version, domain);
|
|
214
185
|
emitLine(lines, counter.qb64, `${counterCodeNameForVersion(counter.code, version)} count=${counter.count}`, 0, options);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
186
|
+
const unit = domain === "bny" ? 3 : 4;
|
|
187
|
+
const headerSize = domain === "bny" ? counter.fullSizeB2 : counter.fullSize;
|
|
188
|
+
const payloadSize = counter.count * unit;
|
|
189
|
+
const end = Math.min(raw.length, headerSize + payloadSize);
|
|
190
|
+
let offset = headerSize;
|
|
191
|
+
while (offset < end) {
|
|
192
|
+
const slice = raw.slice(offset, end);
|
|
193
|
+
try {
|
|
194
|
+
const nestedCounter = parseCounterCompat(slice, version, domain);
|
|
195
|
+
const nestedCounterSize = domain === "bny"
|
|
196
|
+
? nestedCounter.fullSizeB2
|
|
197
|
+
: nestedCounter.fullSize;
|
|
198
|
+
emitLine(lines, nestedCounter.qb64, `${counterCodeNameForVersion(nestedCounter.code, version)} counter`, options.indent, options);
|
|
199
|
+
offset += nestedCounterSize;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
if (!isRecoverableParseError(error)) {
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const matter = parseMatter(slice, domain);
|
|
208
|
+
const matterSize = domain === "bny" ? matter.fullSizeB2 : matter.fullSize;
|
|
209
|
+
const field = frame.body.native?.fields.find((candidate) => candidate.primitive.qb64 === matter.qb64);
|
|
210
|
+
const label = field ? nativeLabelName(field.label) : null;
|
|
211
|
+
const primitiveComment = matter instanceof Indexer
|
|
212
|
+
? `Indexer ${matter.code}`
|
|
213
|
+
: matterCodeName(matter.code);
|
|
214
|
+
const comment = label ? `${label} (${primitiveComment})` : primitiveComment;
|
|
215
|
+
emitLine(lines, matter.qb64, comment, options.indent, options);
|
|
216
|
+
offset += matterSize;
|
|
221
217
|
}
|
|
222
218
|
}
|
|
219
|
+
/** Render non-native or opaque message bodies as one annotated body line. */
|
|
223
220
|
function renderMessageBody(lines, frame, options) {
|
|
224
221
|
const rawBody = TEXT_DECODER.decode(frame.body.raw);
|
|
225
|
-
const isOpaqueCesrBody = frame.body.kind === "CESR"
|
|
226
|
-
frame.body.ked === null;
|
|
222
|
+
const isOpaqueCesrBody = frame.body.kind === "CESR"
|
|
223
|
+
&& frame.body.ked === null;
|
|
227
224
|
if (isOpaqueCesrBody) {
|
|
228
225
|
emitLine(lines, rawBody, `OPAQUE CESR body (non-serder fallback, hex=${toHex(frame.body.raw)})`, 0, options);
|
|
229
226
|
return;
|
|
@@ -249,6 +246,7 @@ function renderMessageBody(lines, frame, options) {
|
|
|
249
246
|
].filter(Boolean).join(" ");
|
|
250
247
|
emitLine(lines, body, info, 0, options);
|
|
251
248
|
}
|
|
249
|
+
/** Render one parsed frame and all of its attachment groups into annotation lines. */
|
|
252
250
|
function renderFrame(frame, index, options) {
|
|
253
251
|
const lines = [];
|
|
254
252
|
const version = frame.body.gvrsn ?? frame.body.pvrsn;
|
|
@@ -264,6 +262,7 @@ function renderFrame(frame, index, options) {
|
|
|
264
262
|
}
|
|
265
263
|
return { index, frame, lines };
|
|
266
264
|
}
|
|
265
|
+
/** Parse and render a nested frame chunk inside wrapper-aware annotation flows. */
|
|
267
266
|
function renderFrameChunk(lines, input, indent, options) {
|
|
268
267
|
const parsed = parseBytes(input);
|
|
269
268
|
const frames = [];
|
|
@@ -280,6 +279,7 @@ function renderFrameChunk(lines, input, indent, options) {
|
|
|
280
279
|
}
|
|
281
280
|
}
|
|
282
281
|
}
|
|
282
|
+
/** Walk a stream that may begin with wrapper/version selectors before ordinary frames. */
|
|
283
283
|
function renderWrapperAwareStream(lines, input, inheritedVersion, indent, options) {
|
|
284
284
|
let offset = 0;
|
|
285
285
|
let activeVersion = inheritedVersion;
|
package/esm/src/core/bytes.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
/** Shared UTF-8 encoder used by CESR and DB byte helpers. */
|
|
1
2
|
export const encoder = new TextEncoder();
|
|
3
|
+
/** Shared UTF-8 decoder used by CESR and DB byte helpers. */
|
|
2
4
|
export const decoder = new TextDecoder();
|
|
3
5
|
const B64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4
6
|
/**
|
|
@@ -17,6 +19,7 @@ export function concatBytes(...chunks) {
|
|
|
17
19
|
}
|
|
18
20
|
return out;
|
|
19
21
|
}
|
|
22
|
+
/** Encode a non-negative integer into CESR's URL-safe base64 sextet text. */
|
|
20
23
|
export function intToB64(value, length = 1) {
|
|
21
24
|
if (value < 0) {
|
|
22
25
|
throw new Error(`value must be >= 0, got ${value}`);
|
|
@@ -32,6 +35,7 @@ export function intToB64(value, length = 1) {
|
|
|
32
35
|
}
|
|
33
36
|
return out.padStart(length, "A");
|
|
34
37
|
}
|
|
38
|
+
/** Decode CESR URL-safe base64 sextet text into a non-negative integer. */
|
|
35
39
|
export function b64ToInt(text) {
|
|
36
40
|
let out = 0;
|
|
37
41
|
for (const ch of text) {
|
|
@@ -43,10 +47,12 @@ export function b64ToInt(text) {
|
|
|
43
47
|
}
|
|
44
48
|
return out;
|
|
45
49
|
}
|
|
50
|
+
/** Encode raw bytes to unpadded URL-safe base64 text. */
|
|
46
51
|
export function encodeB64(data) {
|
|
47
52
|
const str = btoa(String.fromCharCode(...data));
|
|
48
53
|
return str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
49
54
|
}
|
|
55
|
+
/** Decode unpadded URL-safe base64 text into raw bytes. */
|
|
50
56
|
export function decodeB64(text) {
|
|
51
57
|
const padded = text + "===".slice((text.length + 3) % 4);
|
|
52
58
|
const raw = atob(padded.replace(/-/g, "+").replace(/_/g, "/"));
|
|
@@ -56,14 +62,20 @@ export function decodeB64(text) {
|
|
|
56
62
|
}
|
|
57
63
|
return out;
|
|
58
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Symmetric ceiling function
|
|
67
|
+
* @param value
|
|
68
|
+
*/
|
|
59
69
|
export function sceil(value) {
|
|
60
70
|
return Math.ceil(value);
|
|
61
71
|
}
|
|
72
|
+
/** Convert a CESR code string to the exact leading qb2 bytes that carry it. */
|
|
62
73
|
export function codeB64ToB2(text) {
|
|
63
74
|
const n = sceil((text.length * 3) / 4);
|
|
64
75
|
const full = text + "A".repeat((4 - (text.length % 4)) % 4);
|
|
65
76
|
return decodeB64(full).slice(0, n);
|
|
66
77
|
}
|
|
78
|
+
/** Convert leading qb2 bytes into the requested number of CESR sextets. */
|
|
67
79
|
export function codeB2ToB64(bytes, sextets) {
|
|
68
80
|
const n = sceil((sextets * 3) / 4);
|
|
69
81
|
if (n > bytes.length) {
|
|
@@ -71,6 +83,50 @@ export function codeB2ToB64(bytes, sextets) {
|
|
|
71
83
|
}
|
|
72
84
|
return encodeB64(bytes.slice(0, n)).slice(0, sextets);
|
|
73
85
|
}
|
|
86
|
+
/** Re-slice the first `sextets` worth of qb2 bytes for parser/code probing. */
|
|
74
87
|
export function nabSextets(bytes, sextets) {
|
|
75
88
|
return codeB64ToB2(codeB2ToB64(bytes, sextets));
|
|
76
89
|
}
|
|
90
|
+
/** UTF-8 string -> bytes helper. */
|
|
91
|
+
export const b = (t) => encoder.encode(t);
|
|
92
|
+
/** UTF-8 bytes -> string helper. */
|
|
93
|
+
export const t = (b) => decoder.decode(b);
|
|
94
|
+
/**
|
|
95
|
+
* Normalize lmdb-js key/value payloads to `Uint8Array`.
|
|
96
|
+
* Example: converts Node `Buffer`-like values from `getRange()`.
|
|
97
|
+
*/
|
|
98
|
+
export function toBytes(value) {
|
|
99
|
+
if (value instanceof Uint8Array) {
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
return new Uint8Array(value);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Format number as 32-char hex string, zero padded.
|
|
106
|
+
* @param num
|
|
107
|
+
*/
|
|
108
|
+
export const to32CharHex = (num) => {
|
|
109
|
+
return num
|
|
110
|
+
.toString(16)
|
|
111
|
+
.padStart(32, "0");
|
|
112
|
+
};
|
|
113
|
+
/** Constant-time-ish byte equality for small DB keys/values. */
|
|
114
|
+
export function bytesEqual(left, right) {
|
|
115
|
+
if (left.length !== right.length) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
for (let i = 0; i < left.length; i++) {
|
|
119
|
+
if (left[i] !== right[i]) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
/** Stable hex fingerprint used for set-membership dedupe of binary values. */
|
|
126
|
+
export function bytesHex(value) {
|
|
127
|
+
// deno-fmt-ignore
|
|
128
|
+
return Array.from(value)
|
|
129
|
+
.map((byte) => byte.toString(16)
|
|
130
|
+
.padStart(2, "0"))
|
|
131
|
+
.join("");
|
|
132
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Decoder } from "cbor-x/decode";
|
|
2
|
+
import { Encoder } from "cbor-x/encode";
|
|
3
|
+
/**
|
|
4
|
+
* Normalize encoder output to a plain `Uint8Array`.
|
|
5
|
+
*
|
|
6
|
+
* `cbor-x` may return subclasses or reused backing buffers depending on the
|
|
7
|
+
* runtime and code path. The shared KERI codec deliberately copies the result
|
|
8
|
+
* so callers see a stable, plain `Uint8Array` contract that is safe to compare,
|
|
9
|
+
* persist, and hand across package boundaries without inheriting library
|
|
10
|
+
* implementation details.
|
|
11
|
+
*/
|
|
12
|
+
function normalizeEncodedBytes(bytes) {
|
|
13
|
+
return new Uint8Array(bytes);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Reject JavaScript `Map` values anywhere in the payload graph.
|
|
17
|
+
*
|
|
18
|
+
* This is not a statement about CBOR in general. CBOR absolutely supports map
|
|
19
|
+
* values. The narrower rule here is about KERI/ACDC parity: KERIpy serializes
|
|
20
|
+
* the same semantic payloads through JSON, MGPK, and CBOR, and the CBOR paths
|
|
21
|
+
* we are mirroring are dict/list shaped rather than "generic CBOR" shaped.
|
|
22
|
+
*
|
|
23
|
+
* In TypeScript, allowing `Map` values would silently widen the contract past
|
|
24
|
+
* what the JSON and MGPK paths can represent and past what KERIpy currently
|
|
25
|
+
* exercises in the mirrored protocol/storage serializers. This guard fails
|
|
26
|
+
* early so parity drift becomes an explicit decision instead of an accidental
|
|
27
|
+
* convenience.
|
|
28
|
+
*
|
|
29
|
+
* The walk is cycle-safe because this function is defensive validation, not a
|
|
30
|
+
* serializer in its own right. Cycles would fail later in the encoder anyway,
|
|
31
|
+
* but we avoid infinite recursion here while still checking the reachable graph
|
|
32
|
+
* for `Map` instances.
|
|
33
|
+
*/
|
|
34
|
+
function assertNoMapValues(value, seen = new Set()) {
|
|
35
|
+
if (value === null || typeof value !== "object") {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (value instanceof Map) {
|
|
39
|
+
throw new TypeError("KERI/ACDC CBOR payloads must use JSON-compatible plain objects/arrays, not JavaScript Map.");
|
|
40
|
+
}
|
|
41
|
+
if (seen.has(value)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
seen.add(value);
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
for (const item of value) {
|
|
47
|
+
assertNoMapValues(item, seen);
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
for (const item of Object.values(value)) {
|
|
52
|
+
assertNoMapValues(item, seen);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Canonical KERI/ACDC CBOR encoder configuration.
|
|
57
|
+
*
|
|
58
|
+
* Two choices matter for parity:
|
|
59
|
+
* - `useRecords: false` disables `cbor-x` record extensions so plain objects
|
|
60
|
+
* stay plain maps on the wire, matching KERIpy's `cbor2` behavior.
|
|
61
|
+
* - `variableMapSize: true` forces preferred-size map headers, avoiding the
|
|
62
|
+
* default `map16` preallocation strategy that broke exact byte parity.
|
|
63
|
+
*
|
|
64
|
+
* We import `Encoder` from `cbor-x/encode` rather than the package root because
|
|
65
|
+
* the root Node entrypoint probes `process.env` during module evaluation. That
|
|
66
|
+
* widened Deno test permissions for no KERI value, so the shared codec avoids
|
|
67
|
+
* that entrypoint on purpose.
|
|
68
|
+
*/
|
|
69
|
+
const keriCborEncoder = new Encoder({
|
|
70
|
+
useRecords: false,
|
|
71
|
+
variableMapSize: true,
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* Canonical KERI/ACDC CBOR decoder configuration.
|
|
75
|
+
*
|
|
76
|
+
* `mapsAsObjects: true` keeps decoded values aligned with the JSON-compatible
|
|
77
|
+
* object/list contract enforced by `encodeKeriCbor()`. This prevents the decode
|
|
78
|
+
* side from reintroducing `Map`-typed semantics that the encode side forbids
|
|
79
|
+
* and keeps protocol/storage callers working with the same value shapes they
|
|
80
|
+
* would see from JSON or MGPK decoding.
|
|
81
|
+
*
|
|
82
|
+
* Like the encoder, this uses the `cbor-x/decode` subpath to avoid the package
|
|
83
|
+
* root's Node-oriented environment probe.
|
|
84
|
+
*/
|
|
85
|
+
const keriCborDecoder = new Decoder({
|
|
86
|
+
useRecords: false,
|
|
87
|
+
mapsAsObjects: true,
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* Encode KERI/ACDC CBOR with the same preferred map-size choices as KERIpy's
|
|
91
|
+
* `cbor2.dumps`.
|
|
92
|
+
*
|
|
93
|
+
* This is a protocol/storage codec for KERI/ACDC payloads, not a generic CBOR
|
|
94
|
+
* helper. KERIpy's corresponding emitters serialize dict/list-shaped data
|
|
95
|
+
* through `cbor2.dumps`, for example:
|
|
96
|
+
* - `keri.core.coring.dumps`
|
|
97
|
+
* - `keri.core.serdering.Serder.dumps`
|
|
98
|
+
* - `keri.db.koming.Komer.__serializeCBOR`
|
|
99
|
+
*
|
|
100
|
+
* The same semantic payloads also serialize as JSON and MGPK in KERIpy, so the
|
|
101
|
+
* intended cross-format contract is JSON-compatible plain objects and arrays.
|
|
102
|
+
* The default `cbor-x` encoder intentionally uses fixed-width `map16` headers
|
|
103
|
+
* for plain JS objects so it can preallocate and patch in the size later. That
|
|
104
|
+
* is valid CBOR but not byte-identical to KERIpy. This helper enables
|
|
105
|
+
* `variableMapSize` so small maps use the same compact headers that `cbor2`
|
|
106
|
+
* emits and rejects `Map` values so we do not silently drift into a broader
|
|
107
|
+
* CBOR type contract than KERIpy currently uses.
|
|
108
|
+
*/
|
|
109
|
+
export function encodeKeriCbor(value) {
|
|
110
|
+
assertNoMapValues(value);
|
|
111
|
+
return normalizeEncodedBytes(keriCborEncoder.encode(value));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Decode KERI/ACDC CBOR into plain JS objects/arrays.
|
|
115
|
+
*
|
|
116
|
+
* This keeps the decoder aligned with the encoder policy surface and avoids
|
|
117
|
+
* record-extension or `Map`-typed decode behavior on KERI/ACDC protocol and
|
|
118
|
+
* storage paths.
|
|
119
|
+
*/
|
|
120
|
+
export function decodeKeriCbor(raw) {
|
|
121
|
+
return keriCborDecoder.decode(raw);
|
|
122
|
+
}
|
package/esm/src/core/errors.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base parser failure carrying optional offset/context for maintainer
|
|
3
|
+
* diagnostics.
|
|
4
|
+
*
|
|
5
|
+
* Subclasses identify which parser phase rejected the input so callers can
|
|
6
|
+
* decide whether to recover, retry, or fail hard.
|
|
7
|
+
*/
|
|
1
8
|
export class ParserError extends Error {
|
|
2
9
|
constructor(message, offset, context) {
|
|
3
10
|
super(message);
|
|
@@ -16,6 +23,7 @@ export class ParserError extends Error {
|
|
|
16
23
|
this.name = globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).name;
|
|
17
24
|
}
|
|
18
25
|
}
|
|
26
|
+
/** Input ended before the parser had enough bytes to complete the current unit. */
|
|
19
27
|
export class ShortageError extends ParserError {
|
|
20
28
|
constructor(needed, available, offset) {
|
|
21
29
|
super(`Need ${needed} bytes but only ${available} available`, offset);
|
|
@@ -33,16 +41,24 @@ export class ShortageError extends ParserError {
|
|
|
33
41
|
});
|
|
34
42
|
}
|
|
35
43
|
}
|
|
44
|
+
/** Parser encountered an invalid cold-start selector. */
|
|
36
45
|
export class ColdStartError extends ParserError {
|
|
37
46
|
}
|
|
47
|
+
/** Version framing or version-table selection failed. */
|
|
38
48
|
export class VersionError extends ParserError {
|
|
39
49
|
}
|
|
50
|
+
/** A CESR code selector was not recognized in the active codex. */
|
|
40
51
|
export class UnknownCodeError extends ParserError {
|
|
41
52
|
}
|
|
53
|
+
/** Group/count metadata could not describe a valid parse shape. */
|
|
42
54
|
export class GroupSizeError extends ParserError {
|
|
43
55
|
}
|
|
56
|
+
/** Qualified input could not be deserialized into a valid CESR payload. */
|
|
44
57
|
export class DeserializeError extends ParserError {
|
|
45
58
|
}
|
|
59
|
+
/** A CESR payload could not be serialized into a valid protocol representation. */
|
|
60
|
+
export class SerializeError extends ParserError {
|
|
61
|
+
}
|
|
46
62
|
/** Failure while constructing syntax artifacts from token bytes. */
|
|
47
63
|
export class SyntaxParseError extends ParserError {
|
|
48
64
|
constructor(message, cause, offset, context) {
|