@hatk/hatk 0.0.1-alpha.4 → 0.0.1-alpha.41
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/dist/adapter.d.ts +19 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +107 -0
- package/dist/backfill.d.ts +60 -1
- package/dist/backfill.d.ts.map +1 -1
- package/dist/backfill.js +167 -33
- package/dist/car.d.ts +59 -1
- package/dist/car.d.ts.map +1 -1
- package/dist/car.js +179 -7
- package/dist/cbor.d.ts +37 -0
- package/dist/cbor.d.ts.map +1 -1
- package/dist/cbor.js +36 -3
- package/dist/cid.d.ts +37 -0
- package/dist/cid.d.ts.map +1 -1
- package/dist/cid.js +38 -3
- package/dist/cli.js +417 -133
- package/dist/cloudflare/container.d.ts +73 -0
- package/dist/cloudflare/container.d.ts.map +1 -0
- package/dist/cloudflare/container.js +232 -0
- package/dist/cloudflare/hooks.d.ts +33 -0
- package/dist/cloudflare/hooks.d.ts.map +1 -0
- package/dist/cloudflare/hooks.js +40 -0
- package/dist/cloudflare/init.d.ts +27 -0
- package/dist/cloudflare/init.d.ts.map +1 -0
- package/dist/cloudflare/init.js +103 -0
- package/dist/cloudflare/worker.d.ts +27 -0
- package/dist/cloudflare/worker.d.ts.map +1 -0
- package/dist/cloudflare/worker.js +54 -0
- package/dist/config.d.ts +12 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +36 -9
- package/dist/database/adapter-factory.d.ts +6 -0
- package/dist/database/adapter-factory.d.ts.map +1 -0
- package/dist/database/adapter-factory.js +20 -0
- package/dist/database/adapters/d1.d.ts +56 -0
- package/dist/database/adapters/d1.d.ts.map +1 -0
- package/dist/database/adapters/d1.js +108 -0
- package/dist/database/adapters/duckdb-search.d.ts +12 -0
- package/dist/database/adapters/duckdb-search.d.ts.map +1 -0
- package/dist/database/adapters/duckdb-search.js +27 -0
- package/dist/database/adapters/duckdb.d.ts +25 -0
- package/dist/database/adapters/duckdb.d.ts.map +1 -0
- package/dist/database/adapters/duckdb.js +161 -0
- package/dist/database/adapters/sqlite-search.d.ts +23 -0
- package/dist/database/adapters/sqlite-search.d.ts.map +1 -0
- package/dist/database/adapters/sqlite-search.js +74 -0
- package/dist/database/adapters/sqlite.d.ts +18 -0
- package/dist/database/adapters/sqlite.d.ts.map +1 -0
- package/dist/database/adapters/sqlite.js +87 -0
- package/dist/database/db.d.ts +159 -0
- package/dist/database/db.d.ts.map +1 -0
- package/dist/database/db.js +1445 -0
- package/dist/database/dialect.d.ts +45 -0
- package/dist/database/dialect.d.ts.map +1 -0
- package/dist/database/dialect.js +72 -0
- package/dist/database/fts.d.ts +27 -0
- package/dist/database/fts.d.ts.map +1 -0
- package/dist/database/fts.js +846 -0
- package/dist/database/index.d.ts +7 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +6 -0
- package/dist/database/ports.d.ts +50 -0
- package/dist/database/ports.d.ts.map +1 -0
- package/dist/database/ports.js +1 -0
- package/dist/database/schema.d.ts +61 -0
- package/dist/database/schema.d.ts.map +1 -0
- package/dist/database/schema.js +394 -0
- package/dist/db.d.ts +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +4 -38
- package/dist/dev-entry.d.ts +8 -0
- package/dist/dev-entry.d.ts.map +1 -0
- package/dist/dev-entry.js +111 -0
- package/dist/feeds.d.ts +12 -8
- package/dist/feeds.d.ts.map +1 -1
- package/dist/feeds.js +45 -6
- package/dist/fts.d.ts.map +1 -1
- package/dist/fts.js +5 -0
- package/dist/hooks.d.ts +43 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +102 -0
- package/dist/hydrate.d.ts +6 -5
- package/dist/hydrate.d.ts.map +1 -1
- package/dist/hydrate.js +4 -16
- package/dist/indexer.d.ts +22 -0
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +70 -7
- package/dist/labels.d.ts +34 -0
- package/dist/labels.d.ts.map +1 -1
- package/dist/labels.js +66 -6
- package/dist/logger.d.ts +29 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +29 -0
- package/dist/main.js +135 -67
- package/dist/mst.d.ts +18 -1
- package/dist/mst.d.ts.map +1 -1
- package/dist/mst.js +19 -8
- package/dist/oauth/db.d.ts.map +1 -1
- package/dist/oauth/db.js +43 -17
- package/dist/oauth/server.d.ts +2 -0
- package/dist/oauth/server.d.ts.map +1 -1
- package/dist/oauth/server.js +103 -8
- package/dist/oauth/session.d.ts +11 -0
- package/dist/oauth/session.d.ts.map +1 -0
- package/dist/oauth/session.js +65 -0
- package/dist/opengraph.d.ts +10 -0
- package/dist/opengraph.d.ts.map +1 -1
- package/dist/opengraph.js +73 -39
- package/dist/pds-proxy.d.ts +42 -0
- package/dist/pds-proxy.d.ts.map +1 -0
- package/dist/pds-proxy.js +189 -0
- package/dist/renderer.d.ts +27 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +46 -0
- package/dist/resolve-hatk.d.ts +6 -0
- package/dist/resolve-hatk.d.ts.map +1 -0
- package/dist/resolve-hatk.js +20 -0
- package/dist/response.d.ts +16 -0
- package/dist/response.d.ts.map +1 -0
- package/dist/response.js +69 -0
- package/dist/scanner.d.ts +21 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +88 -0
- package/dist/schema.d.ts +8 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +29 -0
- package/dist/seed.d.ts +19 -0
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +43 -4
- package/dist/server-init.d.ts +8 -0
- package/dist/server-init.d.ts.map +1 -0
- package/dist/server-init.js +61 -0
- package/dist/server.d.ts +26 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +528 -635
- package/dist/setup.d.ts +28 -1
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +50 -3
- package/dist/test.d.ts +1 -1
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +38 -32
- package/dist/views.js +1 -1
- package/dist/vite-plugin.d.ts +1 -1
- package/dist/vite-plugin.d.ts.map +1 -1
- package/dist/vite-plugin.js +254 -66
- package/dist/xrpc.d.ts +60 -10
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +155 -39
- package/package.json +13 -6
- package/public/admin.html +0 -54
package/dist/car.js
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* CAR (Content Addressable aRchive) parser.
|
|
3
|
+
*
|
|
4
|
+
* CAR files bundle content-addressed blocks into a single binary container.
|
|
5
|
+
* They're used by the AT Protocol firehose (`com.atproto.sync.getRepo`) to
|
|
6
|
+
* deliver entire repos and by commit events to deliver individual changes.
|
|
7
|
+
*
|
|
8
|
+
* Format: `varint(headerLen) | CBOR(header) | block*`
|
|
9
|
+
* Each block: `varint(blockLen) | CID | data`
|
|
10
|
+
*
|
|
11
|
+
* @see https://ipld.io/specs/transport/car/carv1/
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
3
14
|
import { cborDecode } from "./cbor.js";
|
|
4
15
|
import { cidToString, readVarint } from "./cid.js";
|
|
16
|
+
/**
|
|
17
|
+
* Parses a CID (Content Identifier) from raw bytes at the given offset.
|
|
18
|
+
*
|
|
19
|
+
* Handles both CIDv0 (bare SHA-256 multihash, starts with `0x12`) and
|
|
20
|
+
* CIDv1 (version + codec + multihash with varint-encoded lengths).
|
|
21
|
+
*
|
|
22
|
+
* @returns A tuple of `[cidBytes, nextOffset]`
|
|
23
|
+
*/
|
|
5
24
|
function parseCidFromBytes(bytes, offset) {
|
|
6
25
|
const firstByte = bytes[offset];
|
|
7
26
|
if (firstByte === 0x12) {
|
|
@@ -22,6 +41,160 @@ function parseCidFromBytes(bytes, offset) {
|
|
|
22
41
|
pos = afterDigestLen + digestLen;
|
|
23
42
|
return [bytes.slice(offset, pos), pos];
|
|
24
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* A memory-efficient block map that stores byte offsets into the original CAR
|
|
46
|
+
* buffer instead of copying block data. Implements the same `get`/`delete`/`size`
|
|
47
|
+
* interface as `Map<string, Uint8Array>` so it can be used as a drop-in replacement.
|
|
48
|
+
*/
|
|
49
|
+
export class LazyBlockMap {
|
|
50
|
+
offsets;
|
|
51
|
+
carBytes;
|
|
52
|
+
constructor(carBytes, offsets) {
|
|
53
|
+
this.carBytes = carBytes;
|
|
54
|
+
this.offsets = offsets;
|
|
55
|
+
}
|
|
56
|
+
get(cid) {
|
|
57
|
+
const range = this.offsets.get(cid);
|
|
58
|
+
if (!range || !this.carBytes)
|
|
59
|
+
return undefined;
|
|
60
|
+
return this.carBytes.subarray(range[0], range[1]);
|
|
61
|
+
}
|
|
62
|
+
delete(cid) {
|
|
63
|
+
return this.offsets.delete(cid);
|
|
64
|
+
}
|
|
65
|
+
get size() {
|
|
66
|
+
return this.offsets.size;
|
|
67
|
+
}
|
|
68
|
+
*[Symbol.iterator]() {
|
|
69
|
+
for (const [cid, range] of this.offsets) {
|
|
70
|
+
if (!this.carBytes)
|
|
71
|
+
return;
|
|
72
|
+
yield [cid, this.carBytes.subarray(range[0], range[1])];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Release the underlying CAR buffer */
|
|
76
|
+
free() {
|
|
77
|
+
this.carBytes = null;
|
|
78
|
+
this.offsets.clear();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Parses a CARv1 stream incrementally from a `ReadableStream`.
|
|
83
|
+
*
|
|
84
|
+
* Instead of buffering the entire CAR into a single ArrayBuffer, this reads
|
|
85
|
+
* chunks from the stream and parses blocks as they arrive. Each block's data
|
|
86
|
+
* is `.slice()`d into its own small `Uint8Array`, allowing V8 to GC individual
|
|
87
|
+
* blocks as they're consumed during the MST walk.
|
|
88
|
+
*
|
|
89
|
+
* This is critical for backfill where multiple workers download 30-90MB CARs
|
|
90
|
+
* concurrently — buffered downloads cause OOMs because `ArrayBuffer` memory
|
|
91
|
+
* is "external" to V8's heap and not controlled by `--max-old-space-size`.
|
|
92
|
+
*
|
|
93
|
+
* @param body - The response body stream (e.g. `res.body` from `fetch()`)
|
|
94
|
+
* @returns `roots` — root CID strings; `blocks` — map of CID → block data; `byteLength` — total bytes read
|
|
95
|
+
*/
|
|
96
|
+
export async function parseCarStream(body) {
|
|
97
|
+
const reader = body.getReader();
|
|
98
|
+
// Growable buffer with position tracking. We reuse a single allocation and
|
|
99
|
+
// compact (shift data to front) when the read position passes the midpoint,
|
|
100
|
+
// avoiding per-chunk allocations and subarray references that pin old memory.
|
|
101
|
+
let buf = new Uint8Array(64 * 1024);
|
|
102
|
+
let pos = 0; // read cursor
|
|
103
|
+
let len = 0; // bytes of valid data in buf
|
|
104
|
+
let byteLength = 0;
|
|
105
|
+
// Ensure at least `need` bytes are available at buf[pos..pos+need)
|
|
106
|
+
async function fill(need) {
|
|
107
|
+
while (len - pos < need) {
|
|
108
|
+
const { done, value } = await reader.read();
|
|
109
|
+
if (done)
|
|
110
|
+
return len - pos >= need;
|
|
111
|
+
byteLength += value.length;
|
|
112
|
+
// Compact: shift remaining data to front when read cursor passes midpoint
|
|
113
|
+
if (pos > 0 && pos > buf.length >>> 1) {
|
|
114
|
+
buf.copyWithin(0, pos, len);
|
|
115
|
+
len -= pos;
|
|
116
|
+
pos = 0;
|
|
117
|
+
}
|
|
118
|
+
// Grow if needed
|
|
119
|
+
const required = len + value.length;
|
|
120
|
+
if (required > buf.length) {
|
|
121
|
+
const newBuf = new Uint8Array(Math.max(required, buf.length * 2));
|
|
122
|
+
newBuf.set(buf.subarray(0, len));
|
|
123
|
+
buf = newBuf;
|
|
124
|
+
}
|
|
125
|
+
buf.set(value, len);
|
|
126
|
+
len += value.length;
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
function consume(n) {
|
|
131
|
+
pos += n;
|
|
132
|
+
}
|
|
133
|
+
// Read a varint starting at buf[pos]
|
|
134
|
+
function readVarintFromBuf() {
|
|
135
|
+
let value = 0;
|
|
136
|
+
let shift = 0;
|
|
137
|
+
let p = pos;
|
|
138
|
+
while (p < len) {
|
|
139
|
+
const byte = buf[p++];
|
|
140
|
+
value |= (byte & 0x7f) << shift;
|
|
141
|
+
if ((byte & 0x80) === 0)
|
|
142
|
+
return [value, p - pos];
|
|
143
|
+
shift += 7;
|
|
144
|
+
if (shift > 35)
|
|
145
|
+
throw new Error('Varint too long');
|
|
146
|
+
}
|
|
147
|
+
throw new Error('Unexpected end of varint');
|
|
148
|
+
}
|
|
149
|
+
// Parse header: varint(headerLen) + CBOR(header)
|
|
150
|
+
if (!(await fill(1)))
|
|
151
|
+
throw new Error('Empty CAR stream');
|
|
152
|
+
// Prefetch up to 10 bytes for the varint; readVarintFromBuf bounds to `len`
|
|
153
|
+
await fill(10);
|
|
154
|
+
const [headerLen, headerVarintSize] = readVarintFromBuf();
|
|
155
|
+
consume(headerVarintSize);
|
|
156
|
+
if (!(await fill(headerLen)))
|
|
157
|
+
throw new Error('Truncated CAR header');
|
|
158
|
+
// .slice() copies out of the reusable buffer
|
|
159
|
+
const headerSlice = buf.slice(pos, pos + headerLen);
|
|
160
|
+
const { value: header } = cborDecode(headerSlice);
|
|
161
|
+
consume(headerLen);
|
|
162
|
+
const roots = (header.roots || []).map((root) => root?.$link ?? cidToString(root));
|
|
163
|
+
// Parse blocks
|
|
164
|
+
const blocks = new Map();
|
|
165
|
+
while (true) {
|
|
166
|
+
if (!(await fill(1)))
|
|
167
|
+
break;
|
|
168
|
+
// Prefetch up to 10 bytes for the varint; readVarintFromBuf bounds to `len`
|
|
169
|
+
await fill(10);
|
|
170
|
+
const [blockLen, blockVarintSize] = readVarintFromBuf();
|
|
171
|
+
consume(blockVarintSize);
|
|
172
|
+
if (blockLen === 0)
|
|
173
|
+
break;
|
|
174
|
+
if (!(await fill(blockLen)))
|
|
175
|
+
throw new Error('Truncated CAR block');
|
|
176
|
+
const [cidBytes, afterCid] = parseCidFromBytes(buf, pos);
|
|
177
|
+
const cid = cidToString(cidBytes);
|
|
178
|
+
const cidLen = afterCid - pos;
|
|
179
|
+
// .slice() creates an independent copy — the buffer can be reused
|
|
180
|
+
const data = buf.slice(afterCid, afterCid + blockLen - cidLen);
|
|
181
|
+
blocks.set(cid, data);
|
|
182
|
+
consume(blockLen);
|
|
183
|
+
}
|
|
184
|
+
reader.releaseLock();
|
|
185
|
+
// Release the internal buffer
|
|
186
|
+
buf = null;
|
|
187
|
+
return { roots, blocks, byteLength };
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Parses a CARv1 binary frame into its root CIDs and a lazy block map.
|
|
191
|
+
*
|
|
192
|
+
* The block map stores byte offsets into `carBytes` rather than copying data,
|
|
193
|
+
* reducing heap usage from O(total block bytes) to O(number of blocks * 16 bytes).
|
|
194
|
+
*
|
|
195
|
+
* @param carBytes - Raw CAR file bytes (e.g. from `getRepo` or a firehose commit)
|
|
196
|
+
* @returns `roots` — ordered list of root CID strings; `blocks` — lazy block map
|
|
197
|
+
*/
|
|
25
198
|
export function parseCarFrame(carBytes) {
|
|
26
199
|
let offset = 0;
|
|
27
200
|
// Read header length (varint-prefixed CBOR)
|
|
@@ -34,8 +207,8 @@ export function parseCarFrame(carBytes) {
|
|
|
34
207
|
// Our CBOR decoder converts tag-42 CIDs to { $link: "b..." } objects,
|
|
35
208
|
// so roots may already be decoded strings
|
|
36
209
|
const roots = (header.roots || []).map((root) => root?.$link ?? cidToString(root));
|
|
37
|
-
//
|
|
38
|
-
const
|
|
210
|
+
// Build offset index: CID → [start, end] into carBytes
|
|
211
|
+
const offsets = new Map();
|
|
39
212
|
while (offset < carBytes.length) {
|
|
40
213
|
const [blockLen, afterBlockLen] = readVarint(carBytes, offset);
|
|
41
214
|
offset = afterBlockLen;
|
|
@@ -44,9 +217,8 @@ export function parseCarFrame(carBytes) {
|
|
|
44
217
|
const [cidBytes, afterCid] = parseCidFromBytes(carBytes, offset);
|
|
45
218
|
const cid = cidToString(cidBytes);
|
|
46
219
|
const dataLen = blockLen - (afterCid - offset);
|
|
47
|
-
|
|
48
|
-
blocks.set(cid, data);
|
|
220
|
+
offsets.set(cid, [afterCid, afterCid + dataLen]);
|
|
49
221
|
offset = afterCid + dataLen;
|
|
50
222
|
}
|
|
51
|
-
return { roots, blocks };
|
|
223
|
+
return { roots, blocks: new LazyBlockMap(carBytes, offsets) };
|
|
52
224
|
}
|
package/dist/cbor.d.ts
CHANGED
|
@@ -1,7 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal CBOR (RFC 8949) decoder with DAG-CBOR CID support.
|
|
3
|
+
*
|
|
4
|
+
* Returns `{ value, offset }` so callers can decode concatenated CBOR values —
|
|
5
|
+
* the AT Protocol firehose sends frames as two back-to-back CBOR items
|
|
6
|
+
* (header + body).
|
|
7
|
+
*
|
|
8
|
+
* DAG-CBOR tag 42 (CID links) are decoded as `{ $link: "bafy..." }` objects,
|
|
9
|
+
* matching the convention used by the AT Protocol.
|
|
10
|
+
*
|
|
11
|
+
* @see https://www.rfc-editor.org/rfc/rfc8949 — CBOR spec
|
|
12
|
+
* @see https://ipld.io/specs/codecs/dag-cbor/spec/ — DAG-CBOR spec
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
1
15
|
interface DecodeResult {
|
|
16
|
+
/** The decoded JavaScript value. */
|
|
2
17
|
value: any;
|
|
18
|
+
/** Byte offset immediately after the decoded value — use as `startOffset` to decode the next item. */
|
|
3
19
|
offset: number;
|
|
4
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Decodes a single CBOR value from a byte array.
|
|
23
|
+
*
|
|
24
|
+
* Supports all major types: unsigned/negative integers, byte/text strings,
|
|
25
|
+
* arrays, maps, tags (with special handling for CID tag 42), and simple
|
|
26
|
+
* values (true, false, null).
|
|
27
|
+
*
|
|
28
|
+
* @param bytes - Raw CBOR bytes
|
|
29
|
+
* @param startOffset - Byte position to start decoding from (default `0`)
|
|
30
|
+
* @returns The decoded value and the offset of the next byte after it
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* // Decode a single value
|
|
35
|
+
* const { value } = cborDecode(bytes)
|
|
36
|
+
*
|
|
37
|
+
* // Decode two concatenated values (firehose frame)
|
|
38
|
+
* const { value: header, offset } = cborDecode(frameBytes)
|
|
39
|
+
* const { value: body } = cborDecode(frameBytes, offset)
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
5
42
|
export declare function cborDecode(bytes: Uint8Array, startOffset?: number): DecodeResult;
|
|
6
43
|
export {};
|
|
7
44
|
//# sourceMappingURL=cbor.d.ts.map
|
package/dist/cbor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cbor.d.ts","sourceRoot":"","sources":["../src/cbor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cbor.d.ts","sourceRoot":"","sources":["../src/cbor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,UAAU,YAAY;IACpB,oCAAoC;IACpC,KAAK,EAAE,GAAG,CAAA;IACV,sGAAsG;IACtG,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,SAAI,GAAG,YAAY,CAgF3E"}
|
package/dist/cbor.js
CHANGED
|
@@ -1,8 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Minimal CBOR (RFC 8949) decoder with DAG-CBOR CID support.
|
|
3
|
+
*
|
|
4
|
+
* Returns `{ value, offset }` so callers can decode concatenated CBOR values —
|
|
5
|
+
* the AT Protocol firehose sends frames as two back-to-back CBOR items
|
|
6
|
+
* (header + body).
|
|
7
|
+
*
|
|
8
|
+
* DAG-CBOR tag 42 (CID links) are decoded as `{ $link: "bafy..." }` objects,
|
|
9
|
+
* matching the convention used by the AT Protocol.
|
|
10
|
+
*
|
|
11
|
+
* @see https://www.rfc-editor.org/rfc/rfc8949 — CBOR spec
|
|
12
|
+
* @see https://ipld.io/specs/codecs/dag-cbor/spec/ — DAG-CBOR spec
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
4
15
|
import { cidToString } from "./cid.js";
|
|
16
|
+
/** CBOR tag number for DAG-CBOR CID links. */
|
|
5
17
|
const CBOR_TAG_CID = 42;
|
|
18
|
+
/**
|
|
19
|
+
* Decodes a single CBOR value from a byte array.
|
|
20
|
+
*
|
|
21
|
+
* Supports all major types: unsigned/negative integers, byte/text strings,
|
|
22
|
+
* arrays, maps, tags (with special handling for CID tag 42), and simple
|
|
23
|
+
* values (true, false, null).
|
|
24
|
+
*
|
|
25
|
+
* @param bytes - Raw CBOR bytes
|
|
26
|
+
* @param startOffset - Byte position to start decoding from (default `0`)
|
|
27
|
+
* @returns The decoded value and the offset of the next byte after it
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* // Decode a single value
|
|
32
|
+
* const { value } = cborDecode(bytes)
|
|
33
|
+
*
|
|
34
|
+
* // Decode two concatenated values (firehose frame)
|
|
35
|
+
* const { value: header, offset } = cborDecode(frameBytes)
|
|
36
|
+
* const { value: body } = cborDecode(frameBytes, offset)
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
6
39
|
export function cborDecode(bytes, startOffset = 0) {
|
|
7
40
|
let offset = startOffset;
|
|
8
41
|
function read() {
|
package/dist/cid.d.ts
CHANGED
|
@@ -1,4 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CID (Content Identifier), base32, and varint primitives.
|
|
3
|
+
*
|
|
4
|
+
* CIDs are self-describing content hashes used throughout the AT Protocol
|
|
5
|
+
* to reference blocks in repos and CAR files. This module provides the
|
|
6
|
+
* low-level encoding needed to convert raw CID bytes into their string
|
|
7
|
+
* representation (base32lower with `b` multibase prefix).
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/multiformats/cid
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Encodes raw bytes as a base32 lowercase string (RFC 4648, no padding).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* base32Encode(new Uint8Array([0x01, 0x71])) // "afyq"
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
1
20
|
export declare function base32Encode(bytes: Uint8Array): string;
|
|
21
|
+
/**
|
|
22
|
+
* Converts raw CID bytes to their multibase-encoded string form (`b` prefix + base32lower).
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* cidToString(cidBytes) // "bafyreig..."
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
2
29
|
export declare function cidToString(cidBytes: Uint8Array): string;
|
|
30
|
+
/**
|
|
31
|
+
* Reads an unsigned LEB128 varint from a byte array.
|
|
32
|
+
*
|
|
33
|
+
* Varints are used extensively in CID encoding and CAR framing to represent
|
|
34
|
+
* variable-length integers in a compact form.
|
|
35
|
+
*
|
|
36
|
+
* @param bytes - Source byte array
|
|
37
|
+
* @param offset - Position to start reading from
|
|
38
|
+
* @returns A tuple of `[value, nextOffset]`
|
|
39
|
+
*/
|
|
3
40
|
export declare function readVarint(bytes: Uint8Array, offset: number): [number, number];
|
|
4
41
|
//# sourceMappingURL=cid.d.ts.map
|
package/dist/cid.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cid.d.ts","sourceRoot":"","sources":["../src/cid.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cid.d.ts","sourceRoot":"","sources":["../src/cid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAmBtD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAExD;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAc9E"}
|
package/dist/cid.js
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* CID (Content Identifier), base32, and varint primitives.
|
|
3
|
+
*
|
|
4
|
+
* CIDs are self-describing content hashes used throughout the AT Protocol
|
|
5
|
+
* to reference blocks in repos and CAR files. This module provides the
|
|
6
|
+
* low-level encoding needed to convert raw CID bytes into their string
|
|
7
|
+
* representation (base32lower with `b` multibase prefix).
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/multiformats/cid
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/** RFC 4648 base32 lowercase alphabet (no padding). */
|
|
3
13
|
const BASE32_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
|
|
14
|
+
/**
|
|
15
|
+
* Encodes raw bytes as a base32 lowercase string (RFC 4648, no padding).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* base32Encode(new Uint8Array([0x01, 0x71])) // "afyq"
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
4
22
|
export function base32Encode(bytes) {
|
|
5
23
|
let result = '';
|
|
6
24
|
let bits = 0;
|
|
@@ -18,10 +36,27 @@ export function base32Encode(bytes) {
|
|
|
18
36
|
}
|
|
19
37
|
return result;
|
|
20
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Converts raw CID bytes to their multibase-encoded string form (`b` prefix + base32lower).
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* cidToString(cidBytes) // "bafyreig..."
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
21
47
|
export function cidToString(cidBytes) {
|
|
22
|
-
// base32lower with 'b' multibase prefix
|
|
23
48
|
return `b${base32Encode(cidBytes)}`;
|
|
24
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Reads an unsigned LEB128 varint from a byte array.
|
|
52
|
+
*
|
|
53
|
+
* Varints are used extensively in CID encoding and CAR framing to represent
|
|
54
|
+
* variable-length integers in a compact form.
|
|
55
|
+
*
|
|
56
|
+
* @param bytes - Source byte array
|
|
57
|
+
* @param offset - Position to start reading from
|
|
58
|
+
* @returns A tuple of `[value, nextOffset]`
|
|
59
|
+
*/
|
|
25
60
|
export function readVarint(bytes, offset) {
|
|
26
61
|
let value = 0;
|
|
27
62
|
let shift = 0;
|