@atproto/repo 0.8.12 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/LICENSE.txt +1 -1
- package/dist/block-map.d.ts +15 -16
- package/dist/block-map.d.ts.map +1 -1
- package/dist/block-map.js +9 -44
- package/dist/block-map.js.map +1 -1
- package/dist/car.d.ts +8 -8
- package/dist/car.d.ts.map +1 -1
- package/dist/car.js +107 -37
- package/dist/car.js.map +1 -1
- package/dist/cid-set.d.ts +8 -7
- package/dist/cid-set.d.ts.map +1 -1
- package/dist/cid-set.js +11 -4
- package/dist/cid-set.js.map +1 -1
- package/dist/data-diff.d.ts +10 -10
- package/dist/data-diff.d.ts.map +1 -1
- package/dist/data-diff.js.map +1 -1
- package/dist/error.d.ts +10 -10
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +1 -0
- package/dist/logger.js.map +1 -1
- package/dist/mst/mst.d.ts +29 -29
- package/dist/mst/mst.d.ts.map +1 -1
- package/dist/mst/mst.js +12 -13
- package/dist/mst/mst.js.map +1 -1
- package/dist/mst/util.d.ts +2 -2
- package/dist/mst/util.d.ts.map +1 -1
- package/dist/mst/util.js +19 -40
- package/dist/mst/util.js.map +1 -1
- package/dist/parse.d.ts +6 -7
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +2 -3
- package/dist/parse.js.map +1 -1
- package/dist/readable-repo.d.ts +6 -7
- package/dist/readable-repo.d.ts.map +1 -1
- package/dist/readable-repo.js +0 -1
- package/dist/readable-repo.js.map +1 -1
- package/dist/repo.d.ts +4 -4
- package/dist/repo.d.ts.map +1 -1
- package/dist/repo.js +11 -10
- package/dist/repo.js.map +1 -1
- package/dist/storage/memory-blockstore.d.ts +9 -9
- package/dist/storage/memory-blockstore.d.ts.map +1 -1
- package/dist/storage/memory-blockstore.js.map +1 -1
- package/dist/storage/readable-blockstore.d.ts +11 -12
- package/dist/storage/readable-blockstore.d.ts.map +1 -1
- package/dist/storage/readable-blockstore.js +2 -36
- package/dist/storage/readable-blockstore.js.map +1 -1
- package/dist/storage/sync-storage.d.ts +5 -5
- package/dist/storage/sync-storage.d.ts.map +1 -1
- package/dist/storage/sync-storage.js.map +1 -1
- package/dist/storage/types.d.ts +25 -26
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/types.js +0 -1
- package/dist/storage/types.js.map +1 -1
- package/dist/sync/consumer.d.ts +3 -3
- package/dist/sync/consumer.d.ts.map +1 -1
- package/dist/sync/consumer.js +1 -1
- package/dist/sync/consumer.js.map +1 -1
- package/dist/sync/provider.d.ts +3 -3
- package/dist/sync/provider.d.ts.map +1 -1
- package/dist/sync/provider.js.map +1 -1
- package/dist/types.d.ts +127 -100
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +53 -13
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +8 -3
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +33 -17
- package/dist/util.js.map +1 -1
- package/package.json +6 -7
- package/src/block-map.ts +31 -28
- package/src/car.ts +124 -46
- package/src/cid-set.ts +16 -10
- package/src/data-diff.ts +10 -10
- package/src/error.ts +6 -6
- package/src/logger.ts +1 -0
- package/src/mst/mst.ts +24 -28
- package/src/mst/util.ts +24 -11
- package/src/parse.ts +8 -10
- package/src/readable-repo.ts +6 -9
- package/src/repo.ts +13 -12
- package/src/storage/memory-blockstore.ts +8 -8
- package/src/storage/readable-blockstore.ts +12 -15
- package/src/storage/sync-storage.ts +4 -4
- package/src/storage/types.ts +25 -27
- package/src/sync/consumer.ts +5 -5
- package/src/sync/provider.ts +10 -7
- package/src/types.ts +82 -43
- package/src/util.ts +31 -16
- package/tests/_keys.ts +156 -156
- package/tests/_util.ts +28 -14
- package/tests/car.test.ts +31 -13
- package/tests/commit-proof-fixtures.json +79 -57
- package/tests/commit-proofs.test.ts +3 -3
- package/tests/covering-proofs.test.ts +6 -6
- package/tests/mst.test.ts +18 -19
- package/tests/proofs.test.ts +8 -8
- package/tests/repo.test.ts +1 -1
- package/tests/sync.test.ts +3 -6
- package/bench/mst.bench.ts +0 -165
- package/bench/repo.bench.ts +0 -48
- package/tsconfig.tests.tsbuildinfo +0 -1
package/dist/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEzC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAiB,MAAM,mBAAmB,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EACL,MAAM,EACN,cAAc,EACd,oBAAoB,EAEpB,UAAU,EAEV,mBAAmB,EACnB,cAAc,EAEf,MAAM,SAAS,CAAA;AAEhB,eAAO,MAAM,oBAAoB,GAC/B,MAAM,QAAQ,KACb,OAAO,CAAC,mBAAmB,EAAE,CA+B/B,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,WAAW,mBAAmB,EAAE,KAC/B,oBAAoB,EAUtB,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,UAI1C,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,YAAY,MAAM,EAAE,MAAM,MAAM,KAAG,MAEhE,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,OAEhD,CAAA;AAED,eAAO,MAAM,UAAU,GACrB,UAAU,cAAc,EACxB,SAAS,OAAO,KACf,OAAO,CAAC,MAAM,CAOhB,CAAA;AAED,eAAO,MAAM,eAAe,GAC1B,QAAQ,MAAM,EACd,QAAQ,MAAM,KACb,OAAO,CAAC,OAAO,CAIjB,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,QAAsB,CAAA;AAEnE,eAAO,MAAM,eAAe,GAAI,KAAK,UAAU,KAAG,MAMjD,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,GAAG,CAAkB,CAAA;AAE3E,eAAO,MAAM,cAAc,GAAI,QAAQ,cAAc,GAAG,MAAM,KAAG,MAUhE,CAAA;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,wCAIzE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,CAUrE"}
|
package/dist/util.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable import/no-deprecated */
|
|
3
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
3
|
if (k2 === undefined) k2 = k;
|
|
5
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -35,10 +34,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
34
|
})();
|
|
36
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
36
|
exports.ensureV3Commit = exports.cidForRecord = exports.cborToLexRecord = exports.cborToLex = exports.verifyCommitSig = exports.signCommit = exports.metaEqual = exports.formatDataKey = exports.parseDataKey = exports.ensureCreates = exports.diffToWriteDescripts = void 0;
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
exports.concatBytesAsync = concatBytesAsync;
|
|
38
|
+
exports.concatBytes = concatBytes;
|
|
39
|
+
const common_web_1 = require("@atproto/common-web");
|
|
40
40
|
const crypto = __importStar(require("@atproto/crypto"));
|
|
41
|
-
const
|
|
41
|
+
const cbor = __importStar(require("@atproto/lex-cbor"));
|
|
42
|
+
const lex_data_1 = require("@atproto/lex-data");
|
|
42
43
|
const types_1 = require("./types");
|
|
43
44
|
const diffToWriteDescripts = (diff) => {
|
|
44
45
|
return Promise.all([
|
|
@@ -87,10 +88,10 @@ const ensureCreates = (descripts) => {
|
|
|
87
88
|
};
|
|
88
89
|
exports.ensureCreates = ensureCreates;
|
|
89
90
|
const parseDataKey = (key) => {
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
91
|
+
const { length, 0: collection, 1: rkey } = key.split('/');
|
|
92
|
+
if (length !== 2)
|
|
92
93
|
throw new Error(`Invalid record key: ${key}`);
|
|
93
|
-
return { collection
|
|
94
|
+
return { collection, rkey };
|
|
94
95
|
};
|
|
95
96
|
exports.parseDataKey = parseDataKey;
|
|
96
97
|
const formatDataKey = (collection, rkey) => {
|
|
@@ -116,22 +117,16 @@ const verifyCommitSig = async (commit, didKey) => {
|
|
|
116
117
|
return crypto.verifySignature(didKey, encoded, sig);
|
|
117
118
|
};
|
|
118
119
|
exports.verifyCommitSig = verifyCommitSig;
|
|
119
|
-
|
|
120
|
-
return (0, lexicon_1.ipldToLex)((0, common_1.cborDecode)(val));
|
|
121
|
-
};
|
|
122
|
-
exports.cborToLex = cborToLex;
|
|
120
|
+
exports.cborToLex = cbor.decode;
|
|
123
121
|
const cborToLexRecord = (val) => {
|
|
124
122
|
const parsed = (0, exports.cborToLex)(val);
|
|
125
|
-
if (!
|
|
123
|
+
if (!(0, lex_data_1.isPlainObject)(parsed)) {
|
|
126
124
|
throw new Error('lexicon records be a json object');
|
|
127
125
|
}
|
|
128
126
|
return parsed;
|
|
129
127
|
};
|
|
130
128
|
exports.cborToLexRecord = cborToLexRecord;
|
|
131
|
-
|
|
132
|
-
return (0, common_1.cidForCbor)((0, lexicon_1.lexToIpld)(val));
|
|
133
|
-
};
|
|
134
|
-
exports.cidForRecord = cidForRecord;
|
|
129
|
+
exports.cidForRecord = cbor.cidForLex;
|
|
135
130
|
const ensureV3Commit = (commit) => {
|
|
136
131
|
if (commit.version === 3) {
|
|
137
132
|
return commit;
|
|
@@ -140,9 +135,30 @@ const ensureV3Commit = (commit) => {
|
|
|
140
135
|
return {
|
|
141
136
|
...commit,
|
|
142
137
|
version: 3,
|
|
143
|
-
rev: commit.rev ??
|
|
138
|
+
rev: commit.rev ?? common_web_1.TID.nextStr(),
|
|
144
139
|
};
|
|
145
140
|
}
|
|
146
141
|
};
|
|
147
142
|
exports.ensureV3Commit = ensureV3Commit;
|
|
143
|
+
async function concatBytesAsync(iterable) {
|
|
144
|
+
const chunks = [];
|
|
145
|
+
for await (const chunk of iterable)
|
|
146
|
+
chunks.push(chunk);
|
|
147
|
+
return concatBytes(chunks);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* This is the same as {@link Buffer.concat}, without the `totalLength` argument.
|
|
151
|
+
*/
|
|
152
|
+
function concatBytes(chunks) {
|
|
153
|
+
let totalLength = 0;
|
|
154
|
+
for (const chunk of chunks)
|
|
155
|
+
totalLength += chunk.byteLength;
|
|
156
|
+
const result = new Uint8Array(totalLength);
|
|
157
|
+
let offset = 0;
|
|
158
|
+
for (const chunk of chunks) {
|
|
159
|
+
result.set(chunk, offset);
|
|
160
|
+
offset += chunk.byteLength;
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
148
164
|
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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","sourcesContent":["import { TID } from '@atproto/common-web'\nimport * as crypto from '@atproto/crypto'\nimport { Keypair } from '@atproto/crypto'\nimport * as cbor from '@atproto/lex-cbor'\nimport { Cid, LexMap, LexValue, isPlainObject } from '@atproto/lex-data'\nimport { DataDiff } from './data-diff'\nimport {\n Commit,\n LegacyV2Commit,\n RecordCreateDescript,\n RecordDeleteDescript,\n RecordPath,\n RecordUpdateDescript,\n RecordWriteDescript,\n UnsignedCommit,\n WriteOpAction,\n} from './types'\n\nexport const diffToWriteDescripts = (\n diff: DataDiff,\n): Promise<RecordWriteDescript[]> => {\n return Promise.all([\n ...diff.addList().map(async (add) => {\n const { collection, rkey } = parseDataKey(add.key)\n return {\n action: WriteOpAction.Create,\n collection,\n rkey,\n cid: add.cid,\n } as RecordCreateDescript\n }),\n ...diff.updateList().map(async (upd) => {\n const { collection, rkey } = parseDataKey(upd.key)\n return {\n action: WriteOpAction.Update,\n collection,\n rkey,\n cid: upd.cid,\n prev: upd.prev,\n } as RecordUpdateDescript\n }),\n ...diff.deleteList().map((del) => {\n const { collection, rkey } = parseDataKey(del.key)\n return {\n action: WriteOpAction.Delete,\n collection,\n rkey,\n cid: del.cid,\n } as RecordDeleteDescript\n }),\n ])\n}\n\nexport const ensureCreates = (\n descripts: RecordWriteDescript[],\n): RecordCreateDescript[] => {\n const creates: RecordCreateDescript[] = []\n for (const descript of descripts) {\n if (descript.action !== WriteOpAction.Create) {\n throw new Error(`Unexpected action: ${descript.action}`)\n } else {\n creates.push(descript)\n }\n }\n return creates\n}\n\nexport const parseDataKey = (key: string): RecordPath => {\n const { length, 0: collection, 1: rkey } = key.split('/')\n if (length !== 2) throw new Error(`Invalid record key: ${key}`)\n return { collection, rkey }\n}\n\nexport const formatDataKey = (collection: string, rkey: string): string => {\n return collection + '/' + rkey\n}\n\nexport const metaEqual = (a: Commit, b: Commit): boolean => {\n return a.did === b.did && a.version === b.version\n}\n\nexport const signCommit = async (\n unsigned: UnsignedCommit,\n keypair: Keypair,\n): Promise<Commit> => {\n const encoded = cbor.encode(unsigned)\n const sig = await keypair.sign(encoded)\n return {\n ...unsigned,\n sig,\n }\n}\n\nexport const verifyCommitSig = async (\n commit: Commit,\n didKey: string,\n): Promise<boolean> => {\n const { sig, ...rest } = commit\n const encoded = cbor.encode(rest)\n return crypto.verifySignature(didKey, encoded, sig)\n}\n\nexport const cborToLex: (val: Uint8Array) => LexValue = cbor.decode\n\nexport const cborToLexRecord = (val: Uint8Array): LexMap => {\n const parsed = cborToLex(val)\n if (!isPlainObject(parsed)) {\n throw new Error('lexicon records be a json object')\n }\n return parsed\n}\n\nexport const cidForRecord: (val: LexValue) => Promise<Cid> = cbor.cidForLex\n\nexport const ensureV3Commit = (commit: LegacyV2Commit | Commit): Commit => {\n if (commit.version === 3) {\n return commit\n } else {\n return {\n ...commit,\n version: 3,\n rev: commit.rev ?? TID.nextStr(),\n }\n }\n}\n\nexport async function concatBytesAsync(iterable: AsyncIterable<Uint8Array>) {\n const chunks: Uint8Array[] = []\n for await (const chunk of iterable) chunks.push(chunk)\n return concatBytes(chunks)\n}\n\n/**\n * This is the same as {@link Buffer.concat}, without the `totalLength` argument.\n */\nexport function concatBytes(chunks: readonly Uint8Array[]): Uint8Array {\n let totalLength = 0\n for (const chunk of chunks) totalLength += chunk.byteLength\n const result = new Uint8Array(totalLength)\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.byteLength\n }\n return result\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/repo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "atproto repo and MST implementation",
|
|
6
6
|
"keywords": [
|
|
@@ -19,15 +19,14 @@
|
|
|
19
19
|
"main": "dist/index.js",
|
|
20
20
|
"types": "dist/index.d.ts",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@ipld/dag-cbor": "^7.0.0",
|
|
23
|
-
"multiformats": "^9.9.0",
|
|
24
|
-
"uint8arrays": "3.0.0",
|
|
25
22
|
"varint": "^6.0.0",
|
|
26
23
|
"zod": "^3.23.8",
|
|
27
|
-
"@atproto/common": "^0.5.
|
|
28
|
-
"@atproto/common-web": "^0.4.
|
|
24
|
+
"@atproto/common": "^0.5.15",
|
|
25
|
+
"@atproto/common-web": "^0.4.19",
|
|
29
26
|
"@atproto/crypto": "^0.4.5",
|
|
30
|
-
"@atproto/
|
|
27
|
+
"@atproto/lex-cbor": "^0.0.15",
|
|
28
|
+
"@atproto/lex-data": "^0.0.14",
|
|
29
|
+
"@atproto/syntax": "^0.5.2"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
32
|
"jest": "^28.1.2",
|
package/src/block-map.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { encode } from '@atproto/lex-cbor'
|
|
2
|
+
import {
|
|
3
|
+
Cid,
|
|
4
|
+
LexValue,
|
|
5
|
+
cidForCbor,
|
|
6
|
+
parseCid,
|
|
7
|
+
ui8Equals,
|
|
8
|
+
} from '@atproto/lex-data'
|
|
9
|
+
|
|
10
|
+
export class BlockMap implements Iterable<[cid: Cid, bytes: Uint8Array]> {
|
|
9
11
|
private map: Map<string, Uint8Array> = new Map()
|
|
10
12
|
|
|
11
|
-
constructor(entries?: Iterable<readonly [cid:
|
|
13
|
+
constructor(entries?: Iterable<readonly [cid: Cid, bytes: Uint8Array]>) {
|
|
12
14
|
if (entries) {
|
|
13
15
|
for (const [cid, bytes] of entries) {
|
|
14
16
|
this.set(cid, bytes)
|
|
@@ -16,28 +18,29 @@ export class BlockMap implements Iterable<[cid: CID, bytes: Uint8Array]> {
|
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
async add(value: LexValue): Promise<
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
async add(value: LexValue): Promise<Cid> {
|
|
22
|
+
const bytes = encode(value)
|
|
23
|
+
const cid = await cidForCbor(bytes)
|
|
24
|
+
this.set(cid, bytes)
|
|
25
|
+
return cid
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
set(cid:
|
|
28
|
+
set(cid: Cid, bytes: Uint8Array): BlockMap {
|
|
26
29
|
this.map.set(cid.toString(), bytes)
|
|
27
30
|
return this
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
get(cid:
|
|
33
|
+
get(cid: Cid): Uint8Array | undefined {
|
|
31
34
|
return this.map.get(cid.toString())
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
delete(cid:
|
|
37
|
+
delete(cid: Cid): BlockMap {
|
|
35
38
|
this.map.delete(cid.toString())
|
|
36
39
|
return this
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
getMany(cids:
|
|
40
|
-
const missing:
|
|
42
|
+
getMany(cids: Cid[]): { blocks: BlockMap; missing: Cid[] } {
|
|
43
|
+
const missing: Cid[] = []
|
|
41
44
|
const blocks = new BlockMap()
|
|
42
45
|
for (const cid of cids) {
|
|
43
46
|
const got = this.map.get(cid.toString())
|
|
@@ -50,7 +53,7 @@ export class BlockMap implements Iterable<[cid: CID, bytes: Uint8Array]> {
|
|
|
50
53
|
return { blocks, missing }
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
has(cid:
|
|
56
|
+
has(cid: Cid): boolean {
|
|
54
57
|
return this.map.has(cid.toString())
|
|
55
58
|
}
|
|
56
59
|
|
|
@@ -58,7 +61,7 @@ export class BlockMap implements Iterable<[cid: CID, bytes: Uint8Array]> {
|
|
|
58
61
|
this.map.clear()
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
forEach(cb: (bytes: Uint8Array, cid:
|
|
64
|
+
forEach(cb: (bytes: Uint8Array, cid: Cid) => void): void {
|
|
62
65
|
for (const [cid, bytes] of this) cb(bytes, cid)
|
|
63
66
|
}
|
|
64
67
|
|
|
@@ -66,7 +69,7 @@ export class BlockMap implements Iterable<[cid: CID, bytes: Uint8Array]> {
|
|
|
66
69
|
return Array.from(this, toEntry)
|
|
67
70
|
}
|
|
68
71
|
|
|
69
|
-
cids():
|
|
72
|
+
cids(): Cid[] {
|
|
70
73
|
return Array.from(this.keys())
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -92,16 +95,16 @@ export class BlockMap implements Iterable<[cid: CID, bytes: Uint8Array]> {
|
|
|
92
95
|
for (const [cid, bytes] of this) {
|
|
93
96
|
const otherBytes = other.get(cid)
|
|
94
97
|
if (!otherBytes) return false
|
|
95
|
-
if (!
|
|
98
|
+
if (!ui8Equals(bytes, otherBytes)) {
|
|
96
99
|
return false
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
102
|
return true
|
|
100
103
|
}
|
|
101
104
|
|
|
102
|
-
*keys(): Generator<
|
|
105
|
+
*keys(): Generator<Cid, void, unknown> {
|
|
103
106
|
for (const key of this.map.keys()) {
|
|
104
|
-
yield
|
|
107
|
+
yield parseCid(key)
|
|
105
108
|
}
|
|
106
109
|
}
|
|
107
110
|
|
|
@@ -109,19 +112,19 @@ export class BlockMap implements Iterable<[cid: CID, bytes: Uint8Array]> {
|
|
|
109
112
|
yield* this.map.values()
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
*[Symbol.iterator](): Generator<[
|
|
115
|
+
*[Symbol.iterator](): Generator<[Cid, Uint8Array], void, unknown> {
|
|
113
116
|
for (const [key, value] of this.map) {
|
|
114
|
-
yield [
|
|
117
|
+
yield [parseCid(key), value]
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
|
|
119
|
-
function toEntry([cid, bytes]: readonly [
|
|
122
|
+
function toEntry([cid, bytes]: readonly [Cid, Uint8Array]): Entry {
|
|
120
123
|
return { cid, bytes }
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
type Entry = {
|
|
124
|
-
cid:
|
|
127
|
+
cid: Cid
|
|
125
128
|
bytes: Uint8Array
|
|
126
129
|
}
|
|
127
130
|
|
package/src/car.ts
CHANGED
|
@@ -1,22 +1,13 @@
|
|
|
1
|
-
/* eslint-disable import/no-deprecated */
|
|
2
|
-
|
|
3
1
|
import { setImmediate } from 'node:timers/promises'
|
|
4
|
-
import * as cbor from '@ipld/dag-cbor'
|
|
5
|
-
import { CID } from 'multiformats/cid'
|
|
6
|
-
import * as ui8 from 'uint8arrays'
|
|
7
2
|
import * as varint from 'varint'
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
parseCidFromBytes,
|
|
11
|
-
schema,
|
|
12
|
-
streamToBuffer,
|
|
13
|
-
verifyCidForBytes,
|
|
14
|
-
} from '@atproto/common'
|
|
3
|
+
import * as cbor from '@atproto/lex-cbor'
|
|
4
|
+
import { Cid, decodeCid, isCidForBytes } from '@atproto/lex-data'
|
|
15
5
|
import { BlockMap } from './block-map'
|
|
16
|
-
import { CarBlock } from './types'
|
|
6
|
+
import { CarBlock, schema } from './types'
|
|
7
|
+
import { concatBytesAsync } from './util'
|
|
17
8
|
|
|
18
9
|
export async function* writeCarStream(
|
|
19
|
-
root:
|
|
10
|
+
root: Cid | null,
|
|
20
11
|
blocks: AsyncIterable<CarBlock>,
|
|
21
12
|
): AsyncIterable<Uint8Array> {
|
|
22
13
|
const header = new Uint8Array(
|
|
@@ -36,16 +27,15 @@ export async function* writeCarStream(
|
|
|
36
27
|
}
|
|
37
28
|
}
|
|
38
29
|
|
|
39
|
-
export
|
|
40
|
-
root:
|
|
30
|
+
export async function blocksToCarFile(
|
|
31
|
+
root: Cid | null,
|
|
41
32
|
blocks: BlockMap,
|
|
42
|
-
): Promise<Uint8Array>
|
|
43
|
-
|
|
44
|
-
return streamToBuffer(carStream)
|
|
33
|
+
): Promise<Uint8Array> {
|
|
34
|
+
return concatBytesAsync(blocksToCarStream(root, blocks))
|
|
45
35
|
}
|
|
46
36
|
|
|
47
37
|
export const blocksToCarStream = (
|
|
48
|
-
root:
|
|
38
|
+
root: Cid | null,
|
|
49
39
|
blocks: BlockMap,
|
|
50
40
|
): AsyncIterable<Uint8Array> => {
|
|
51
41
|
return writeCarStream(root, iterateBlocks(blocks))
|
|
@@ -67,7 +57,7 @@ export type ReadCarOptions = {
|
|
|
67
57
|
export const readCar = async (
|
|
68
58
|
bytes: Uint8Array,
|
|
69
59
|
opts?: ReadCarOptions,
|
|
70
|
-
): Promise<{ roots:
|
|
60
|
+
): Promise<{ roots: Cid[]; blocks: BlockMap }> => {
|
|
71
61
|
const { roots, blocks } = await readCarReader(new Ui8Reader(bytes), opts)
|
|
72
62
|
const blockMap = new BlockMap()
|
|
73
63
|
for await (const block of blocks) {
|
|
@@ -79,7 +69,7 @@ export const readCar = async (
|
|
|
79
69
|
export const readCarWithRoot = async (
|
|
80
70
|
bytes: Uint8Array,
|
|
81
71
|
opts?: ReadCarOptions,
|
|
82
|
-
): Promise<{ root:
|
|
72
|
+
): Promise<{ root: Cid; blocks: BlockMap }> => {
|
|
83
73
|
const { roots, blocks } = await readCar(bytes, opts)
|
|
84
74
|
if (roots.length !== 1) {
|
|
85
75
|
throw new Error(`Expected one root, got ${roots.length}`)
|
|
@@ -98,7 +88,7 @@ export const readCarStream = async (
|
|
|
98
88
|
car: Iterable<Uint8Array> | AsyncIterable<Uint8Array>,
|
|
99
89
|
opts?: ReadCarOptions,
|
|
100
90
|
): Promise<{
|
|
101
|
-
roots:
|
|
91
|
+
roots: Cid[]
|
|
102
92
|
blocks: CarBlockIterable
|
|
103
93
|
}> => {
|
|
104
94
|
return readCarReader(new BufferedReader(car), opts)
|
|
@@ -108,7 +98,7 @@ export const readCarReader = async (
|
|
|
108
98
|
reader: BytesReader,
|
|
109
99
|
opts?: ReadCarOptions,
|
|
110
100
|
): Promise<{
|
|
111
|
-
roots:
|
|
101
|
+
roots: Cid[]
|
|
112
102
|
blocks: CarBlockIterable
|
|
113
103
|
}> => {
|
|
114
104
|
try {
|
|
@@ -118,11 +108,12 @@ export const readCarReader = async (
|
|
|
118
108
|
}
|
|
119
109
|
const headerBytes = await reader.read(headerSize)
|
|
120
110
|
const header = cbor.decode(headerBytes)
|
|
121
|
-
|
|
122
|
-
|
|
111
|
+
const result = schema.carHeader.safeParse(header)
|
|
112
|
+
if (!result.success) {
|
|
113
|
+
throw new Error('Could not parse CAR header', { cause: result.error })
|
|
123
114
|
}
|
|
124
115
|
return {
|
|
125
|
-
roots:
|
|
116
|
+
roots: result.data.roots,
|
|
126
117
|
blocks: readCarBlocksIter(reader, opts),
|
|
127
118
|
}
|
|
128
119
|
} catch (err) {
|
|
@@ -165,7 +156,7 @@ async function* readCarBlocksIterGenerator(
|
|
|
165
156
|
break
|
|
166
157
|
}
|
|
167
158
|
const blockBytes = await reader.read(blockSize)
|
|
168
|
-
const cid =
|
|
159
|
+
const cid = decodeCid(blockBytes.subarray(0, 36))
|
|
169
160
|
const bytes = blockBytes.subarray(36)
|
|
170
161
|
yield { cid, bytes }
|
|
171
162
|
|
|
@@ -185,7 +176,9 @@ export async function* verifyIncomingCarBlocks(
|
|
|
185
176
|
car: AsyncIterable<CarBlock>,
|
|
186
177
|
): AsyncGenerator<CarBlock, void, unknown> {
|
|
187
178
|
for await (const block of car) {
|
|
188
|
-
await
|
|
179
|
+
if (!(await isCidForBytes(block.cid, block.bytes))) {
|
|
180
|
+
throw new Error(`Not a valid CID for bytes (${block.cid.toString()})`)
|
|
181
|
+
}
|
|
189
182
|
yield block
|
|
190
183
|
}
|
|
191
184
|
}
|
|
@@ -207,7 +200,7 @@ const readVarint = async (reader: BytesReader): Promise<number | null> => {
|
|
|
207
200
|
done = true
|
|
208
201
|
}
|
|
209
202
|
}
|
|
210
|
-
const concatted =
|
|
203
|
+
const concatted = Buffer.concat(bytes)
|
|
211
204
|
return varint.decode(concatted)
|
|
212
205
|
}
|
|
213
206
|
|
|
@@ -235,11 +228,18 @@ class Ui8Reader implements BytesReader {
|
|
|
235
228
|
async close(): Promise<void> {}
|
|
236
229
|
}
|
|
237
230
|
|
|
231
|
+
/**
|
|
232
|
+
* This code was optimized for performance. See
|
|
233
|
+
* {@link https://github.com/bluesky-social/atproto/pull/4729 #4729} for more details
|
|
234
|
+
* and benchmarks.
|
|
235
|
+
*/
|
|
238
236
|
class BufferedReader implements BytesReader {
|
|
239
|
-
buffer: Uint8Array = new Uint8Array()
|
|
240
237
|
iterator: Iterator<Uint8Array> | AsyncIterator<Uint8Array>
|
|
241
238
|
isDone = false
|
|
242
239
|
|
|
240
|
+
/** fifo list of chunks to consume */
|
|
241
|
+
private chunks: Uint8Array[] = []
|
|
242
|
+
|
|
243
243
|
constructor(stream: Iterable<Uint8Array> | AsyncIterable<Uint8Array>) {
|
|
244
244
|
this.iterator =
|
|
245
245
|
Symbol.asyncIterator in stream
|
|
@@ -247,32 +247,110 @@ class BufferedReader implements BytesReader {
|
|
|
247
247
|
: stream[Symbol.iterator]()
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
250
|
+
/** Number of bytes currently buffered and available for reading */
|
|
251
|
+
get bufferedByteLength() {
|
|
252
|
+
let total = 0
|
|
253
|
+
for (let i = 0; i < this.chunks.length; i++) {
|
|
254
|
+
total += this.chunks[i].byteLength
|
|
255
|
+
}
|
|
256
|
+
return total
|
|
255
257
|
}
|
|
256
258
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
/**
|
|
260
|
+
* @note concurrent reads are **NOT** supported by the current implementation
|
|
261
|
+
* and would require call to readUntilBuffered to be using a fifo lock for
|
|
262
|
+
* read()s to be processed in fifo order.
|
|
263
|
+
*/
|
|
264
|
+
async read(bytesToRead: number): Promise<Uint8Array> {
|
|
265
|
+
const bytesNeeded = bytesToRead - this.bufferedByteLength
|
|
266
|
+
if (bytesNeeded > 0 && !this.isDone) {
|
|
267
|
+
await this.readUntilBuffered(bytesNeeded)
|
|
260
268
|
}
|
|
261
|
-
|
|
269
|
+
|
|
270
|
+
const resultLength = Math.min(bytesToRead, this.bufferedByteLength)
|
|
271
|
+
if (resultLength <= 0) return new Uint8Array()
|
|
272
|
+
|
|
273
|
+
const firstChunk = this.consumeChunk(resultLength)
|
|
274
|
+
if (firstChunk.byteLength === resultLength) {
|
|
275
|
+
// If the data consumed from the first chunk contains all we need, return
|
|
276
|
+
// it as-is. This allows to avoid any copy operation.
|
|
277
|
+
return firstChunk
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// The first chunk does not have all the data we need. We have to copy
|
|
281
|
+
// multiple chunks into a larger buffer
|
|
282
|
+
const result = new Uint8Array(resultLength)
|
|
283
|
+
let resultWriteIndex = 0
|
|
284
|
+
|
|
285
|
+
// Copy the first chunk into the result buffer
|
|
286
|
+
result.set(firstChunk, resultWriteIndex)
|
|
287
|
+
resultWriteIndex += firstChunk.byteLength
|
|
288
|
+
|
|
289
|
+
// Copy more chunks as needed (we use do-while because we *know* we need
|
|
290
|
+
// more than one chunk)
|
|
291
|
+
do {
|
|
292
|
+
const missingLength = resultLength - resultWriteIndex
|
|
293
|
+
const currentChunk = this.consumeChunk(missingLength)
|
|
294
|
+
|
|
295
|
+
result.set(currentChunk, resultWriteIndex)
|
|
296
|
+
resultWriteIndex += currentChunk.byteLength
|
|
297
|
+
} while (resultWriteIndex < resultLength)
|
|
298
|
+
|
|
299
|
+
return result
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private async readUntilBuffered(bytesNeeded: number) {
|
|
303
|
+
let bytesRead = 0
|
|
304
|
+
while (bytesRead < bytesNeeded) {
|
|
262
305
|
const next = await this.iterator.next()
|
|
263
306
|
if (next.done) {
|
|
264
307
|
this.isDone = true
|
|
265
|
-
|
|
308
|
+
break
|
|
309
|
+
} else {
|
|
310
|
+
this.chunks.push(next.value)
|
|
311
|
+
bytesRead += next.value.byteLength
|
|
266
312
|
}
|
|
267
|
-
|
|
313
|
+
}
|
|
314
|
+
return bytesRead
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
private consumeChunk(bytesToConsume: number) {
|
|
318
|
+
const firstChunk = this.chunks[0]!
|
|
319
|
+
if (bytesToConsume < firstChunk.byteLength) {
|
|
320
|
+
// return a sub-view of the data being read and replace the first chunk
|
|
321
|
+
// with a sub-view that does not contain that data.
|
|
322
|
+
|
|
323
|
+
// @NOTE for some reason, subarray() revealed to be 7-8% slower in NodeJS
|
|
324
|
+
// benchmarks.
|
|
325
|
+
|
|
326
|
+
// this.chunks[0] = firstChunk.subarray(bytesToConsume)
|
|
327
|
+
// return firstChunk.subarray(0, bytesToConsume)
|
|
328
|
+
|
|
329
|
+
this.chunks[0] = new Uint8Array(
|
|
330
|
+
firstChunk.buffer,
|
|
331
|
+
firstChunk.byteOffset + bytesToConsume,
|
|
332
|
+
firstChunk.byteLength - bytesToConsume,
|
|
333
|
+
)
|
|
334
|
+
return new Uint8Array(
|
|
335
|
+
firstChunk.buffer,
|
|
336
|
+
firstChunk.byteOffset,
|
|
337
|
+
bytesToConsume,
|
|
338
|
+
)
|
|
339
|
+
} else {
|
|
340
|
+
// First chunk is being read in full, discard it
|
|
341
|
+
this.chunks.shift()
|
|
342
|
+
return firstChunk
|
|
268
343
|
}
|
|
269
344
|
}
|
|
270
345
|
|
|
271
346
|
async close(): Promise<void> {
|
|
272
|
-
|
|
273
|
-
|
|
347
|
+
try {
|
|
348
|
+
if (!this.isDone && this.iterator.return) {
|
|
349
|
+
await this.iterator.return()
|
|
350
|
+
}
|
|
351
|
+
} finally {
|
|
352
|
+
this.isDone = true
|
|
353
|
+
this.chunks.length = 0
|
|
274
354
|
}
|
|
275
|
-
this.isDone = true
|
|
276
|
-
this.buffer = new Uint8Array()
|
|
277
355
|
}
|
|
278
356
|
}
|
package/src/cid-set.ts
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Cid, parseCid } from '@atproto/lex-data'
|
|
2
2
|
|
|
3
|
-
export class CidSet {
|
|
3
|
+
export class CidSet implements Iterable<Cid> {
|
|
4
4
|
private set: Set<string>
|
|
5
5
|
|
|
6
|
-
constructor(arr:
|
|
6
|
+
constructor(arr: Cid[] = []) {
|
|
7
7
|
const strArr = arr.map((c) => c.toString())
|
|
8
8
|
this.set = new Set(strArr)
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
add(cid:
|
|
11
|
+
add(cid: Cid): CidSet {
|
|
12
12
|
this.set.add(cid.toString())
|
|
13
13
|
return this
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
addSet(toMerge: CidSet): CidSet {
|
|
17
|
-
toMerge.
|
|
17
|
+
for (const c of toMerge.set) this.set.add(c)
|
|
18
18
|
return this
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
subtractSet(toSubtract: CidSet): CidSet {
|
|
22
|
-
toSubtract.
|
|
22
|
+
for (const c of toSubtract.set) this.set.delete(c)
|
|
23
23
|
return this
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
delete(cid:
|
|
26
|
+
delete(cid: Cid) {
|
|
27
27
|
this.set.delete(cid.toString())
|
|
28
28
|
return this
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
has(cid:
|
|
31
|
+
has(cid: Cid): boolean {
|
|
32
32
|
return this.set.has(cid.toString())
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -41,8 +41,14 @@ export class CidSet {
|
|
|
41
41
|
return this
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
toList():
|
|
45
|
-
return
|
|
44
|
+
toList(): Cid[] {
|
|
45
|
+
return Array.from(this)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
*[Symbol.iterator](): Generator<Cid, void, unknown> {
|
|
49
|
+
for (const c of this.set) {
|
|
50
|
+
yield parseCid(c)
|
|
51
|
+
}
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
54
|
|