@ipld/car 4.1.5 → 5.0.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/LICENSE +4 -0
- package/README.md +12 -4
- package/dist/index.min.js +5 -0
- package/{types → dist/src}/api.d.ts +19 -19
- package/dist/src/api.d.ts.map +1 -0
- package/{types/lib → dist/src}/buffer-writer.d.ts +10 -10
- package/{types/lib → dist/src}/buffer-writer.d.ts.map +1 -1
- package/dist/src/coding.d.ts +41 -0
- package/dist/src/coding.d.ts.map +1 -0
- package/{types/lib → dist/src}/decoder.d.ts +3 -3
- package/{types/lib → dist/src}/decoder.d.ts.map +1 -1
- package/{types/lib → dist/src}/encoder.d.ts +2 -2
- package/{types/lib → dist/src}/encoder.d.ts.map +1 -1
- package/{types/lib → dist/src}/header-validator.d.ts +0 -0
- package/dist/src/header-validator.d.ts.map +1 -0
- package/dist/src/index-browser.d.ts +8 -0
- package/dist/src/index-browser.d.ts.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/{types/lib → dist/src}/indexed-reader-browser.d.ts +0 -0
- package/dist/src/indexed-reader-browser.d.ts.map +1 -0
- package/{types/lib → dist/src}/indexed-reader.d.ts +13 -13
- package/dist/src/indexed-reader.d.ts.map +1 -0
- package/{types/lib → dist/src}/indexer.d.ts +9 -9
- package/{types/lib → dist/src}/indexer.d.ts.map +1 -1
- package/{types/lib → dist/src}/iterator-channel.d.ts +0 -0
- package/{types/lib → dist/src}/iterator-channel.d.ts.map +1 -1
- package/{types/lib → dist/src}/iterator.d.ts +8 -8
- package/{types/lib → dist/src}/iterator.d.ts.map +1 -1
- package/{types/lib → dist/src}/reader-browser.d.ts +10 -10
- package/{types/lib → dist/src}/reader-browser.d.ts.map +1 -1
- package/{types/lib → dist/src}/reader.d.ts +5 -5
- package/{types/lib → dist/src}/reader.d.ts.map +1 -1
- package/{types/lib → dist/src}/writer-browser.d.ts +10 -10
- package/{types/lib → dist/src}/writer-browser.d.ts.map +1 -1
- package/{types/lib → dist/src}/writer.d.ts +4 -4
- package/{types/lib → dist/src}/writer.d.ts.map +1 -1
- package/package.json +102 -209
- package/{api.ts → src/api.ts} +14 -14
- package/{lib → src}/buffer-writer.js +5 -5
- package/src/coding.ts +56 -0
- package/{lib → src}/decoder.js +4 -4
- package/{lib → src}/encoder.js +1 -1
- package/src/header-validator.js +74 -0
- package/{lib → src}/header.ipldsch +0 -0
- package/src/index-browser.js +14 -0
- package/src/index.js +16 -0
- package/{lib → src}/indexed-reader-browser.js +0 -0
- package/{lib → src}/indexed-reader.js +9 -9
- package/{lib → src}/indexer.js +4 -4
- package/{lib → src}/iterator-channel.js +0 -0
- package/{lib → src}/iterator.js +4 -4
- package/{lib → src}/reader-browser.js +7 -7
- package/{lib → src}/reader.js +5 -5
- package/{lib → src}/writer-browser.js +7 -7
- package/{lib → src}/writer.js +3 -3
- package/LICENSE-APACHE +0 -13
- package/LICENSE-MIT +0 -7
- package/buffer-writer +0 -1
- package/car-browser.js +0 -14
- package/car.js +0 -16
- package/cjs/browser-test/common.js +0 -301
- package/cjs/browser-test/node-test-file-streams.js +0 -71
- package/cjs/browser-test/node-test-indexed-reader.js +0 -51
- package/cjs/browser-test/node-test-large.js +0 -135
- package/cjs/browser-test/node-test-raw.js +0 -68
- package/cjs/browser-test/node-test-updateroots.js +0 -78
- package/cjs/browser-test/test-buffer-writer.js +0 -330
- package/cjs/browser-test/test-errors.js +0 -90
- package/cjs/browser-test/test-indexer.js +0 -80
- package/cjs/browser-test/test-interface.js +0 -21
- package/cjs/browser-test/test-iterator.js +0 -83
- package/cjs/browser-test/test-reader.js +0 -278
- package/cjs/browser-test/test-writer.js +0 -286
- package/cjs/browser-test/verify-store-reader.js +0 -142
- package/cjs/car-browser.js +0 -18
- package/cjs/car.js +0 -20
- package/cjs/lib/buffer-writer.js +0 -164
- package/cjs/lib/decoder.js +0 -301
- package/cjs/lib/encoder.js +0 -44
- package/cjs/lib/header-validator.js +0 -29
- package/cjs/lib/indexed-reader-browser.js +0 -13
- package/cjs/lib/indexed-reader.js +0 -90
- package/cjs/lib/indexer.js +0 -41
- package/cjs/lib/iterator-channel.js +0 -77
- package/cjs/lib/iterator.js +0 -97
- package/cjs/lib/reader-browser.js +0 -62
- package/cjs/lib/reader.js +0 -38
- package/cjs/lib/writer-browser.js +0 -118
- package/cjs/lib/writer.js +0 -51
- package/cjs/node-test/common.js +0 -301
- package/cjs/node-test/node-test-file-streams.js +0 -71
- package/cjs/node-test/node-test-indexed-reader.js +0 -51
- package/cjs/node-test/node-test-large.js +0 -135
- package/cjs/node-test/node-test-raw.js +0 -68
- package/cjs/node-test/node-test-updateroots.js +0 -78
- package/cjs/node-test/test-buffer-writer.js +0 -330
- package/cjs/node-test/test-errors.js +0 -90
- package/cjs/node-test/test-indexer.js +0 -80
- package/cjs/node-test/test-interface.js +0 -21
- package/cjs/node-test/test-iterator.js +0 -83
- package/cjs/node-test/test-reader.js +0 -278
- package/cjs/node-test/test-writer.js +0 -286
- package/cjs/node-test/verify-store-reader.js +0 -142
- package/decoder +0 -1
- package/esm/browser-test/common.js +0 -274
- package/esm/browser-test/node-test-file-streams.js +0 -76
- package/esm/browser-test/node-test-indexed-reader.js +0 -53
- package/esm/browser-test/node-test-large.js +0 -109
- package/esm/browser-test/node-test-raw.js +0 -63
- package/esm/browser-test/node-test-updateroots.js +0 -76
- package/esm/browser-test/test-buffer-writer.js +0 -311
- package/esm/browser-test/test-errors.js +0 -91
- package/esm/browser-test/test-indexer.js +0 -85
- package/esm/browser-test/test-interface.js +0 -24
- package/esm/browser-test/test-iterator.js +0 -91
- package/esm/browser-test/test-reader.js +0 -270
- package/esm/browser-test/test-writer.js +0 -297
- package/esm/browser-test/verify-store-reader.js +0 -122
- package/esm/car-browser.js +0 -16
- package/esm/car.js +0 -18
- package/esm/lib/buffer-writer.js +0 -129
- package/esm/lib/decoder.js +0 -265
- package/esm/lib/encoder.js +0 -35
- package/esm/lib/header-validator.js +0 -23
- package/esm/lib/indexed-reader-browser.js +0 -6
- package/esm/lib/indexed-reader.js +0 -78
- package/esm/lib/indexer.js +0 -38
- package/esm/lib/iterator-channel.js +0 -71
- package/esm/lib/iterator.js +0 -92
- package/esm/lib/reader-browser.js +0 -57
- package/esm/lib/reader.js +0 -26
- package/esm/lib/writer-browser.js +0 -115
- package/esm/lib/writer.js +0 -42
- package/esm/node-test/common.js +0 -274
- package/esm/node-test/node-test-file-streams.js +0 -76
- package/esm/node-test/node-test-indexed-reader.js +0 -53
- package/esm/node-test/node-test-large.js +0 -109
- package/esm/node-test/node-test-raw.js +0 -63
- package/esm/node-test/node-test-updateroots.js +0 -76
- package/esm/node-test/test-buffer-writer.js +0 -311
- package/esm/node-test/test-errors.js +0 -91
- package/esm/node-test/test-indexer.js +0 -85
- package/esm/node-test/test-interface.js +0 -24
- package/esm/node-test/test-iterator.js +0 -91
- package/esm/node-test/test-reader.js +0 -270
- package/esm/node-test/test-writer.js +0 -297
- package/esm/node-test/verify-store-reader.js +0 -122
- package/esm/package.json +0 -9
- package/examples/car-to-fixture.js +0 -66
- package/examples/dump-car.js +0 -58
- package/examples/dump-index.js +0 -24
- package/examples/package.json +0 -27
- package/examples/round-trip.js +0 -45
- package/examples/test-examples.js +0 -115
- package/examples/verify-car.js +0 -87
- package/index.js +0 -1
- package/indexed-reader +0 -1
- package/indexer +0 -1
- package/iterator +0 -1
- package/lib/coding.ts +0 -56
- package/lib/header-validator.js +0 -33
- package/reader +0 -1
- package/test/_fixtures_to_js.mjs +0 -24
- package/test/common.js +0 -210
- package/test/go.car +0 -0
- package/test/go.carv2 +0 -0
- package/test/node-test-file-streams.js +0 -84
- package/test/node-test-indexed-reader.js +0 -45
- package/test/node-test-large.js +0 -112
- package/test/node-test-raw.js +0 -83
- package/test/node-test-updateroots.js +0 -89
- package/test/test-buffer-writer.js +0 -256
- package/test/test-errors.js +0 -98
- package/test/test-indexer.js +0 -87
- package/test/test-interface.js +0 -24
- package/test/test-iterator.js +0 -74
- package/test/test-reader.js +0 -245
- package/test/test-writer.js +0 -336
- package/test/verify-store-reader.js +0 -191
- package/tsconfig.json +0 -48
- package/types/api.d.ts.map +0 -1
- package/types/car-browser.d.ts +0 -8
- package/types/car-browser.d.ts.map +0 -1
- package/types/car.d.ts +0 -9
- package/types/car.d.ts.map +0 -1
- package/types/lib/coding.d.ts +0 -41
- package/types/lib/coding.d.ts.map +0 -1
- package/types/lib/header-validator.d.ts.map +0 -1
- package/types/lib/indexed-reader-browser.d.ts.map +0 -1
- package/types/lib/indexed-reader.d.ts.map +0 -1
- package/types/test/_fixtures_to_js.d.mts +0 -3
- package/types/test/_fixtures_to_js.d.mts.map +0 -1
- package/types/test/common.d.ts +0 -73
- package/types/test/common.d.ts.map +0 -1
- package/types/test/fixtures-expectations.d.ts +0 -63
- package/types/test/fixtures-expectations.d.ts.map +0 -1
- package/types/test/fixtures.d.ts +0 -3
- package/types/test/fixtures.d.ts.map +0 -1
- package/types/test/node-test-file-streams.d.ts +0 -3
- package/types/test/node-test-file-streams.d.ts.map +0 -1
- package/types/test/node-test-indexed-reader.d.ts +0 -2
- package/types/test/node-test-indexed-reader.d.ts.map +0 -1
- package/types/test/node-test-large.d.ts +0 -2
- package/types/test/node-test-large.d.ts.map +0 -1
- package/types/test/node-test-raw.d.ts +0 -2
- package/types/test/node-test-raw.d.ts.map +0 -1
- package/types/test/node-test-updateroots.d.ts +0 -2
- package/types/test/node-test-updateroots.d.ts.map +0 -1
- package/types/test/test-buffer-writer.d.ts +0 -2
- package/types/test/test-buffer-writer.d.ts.map +0 -1
- package/types/test/test-errors.d.ts +0 -2
- package/types/test/test-errors.d.ts.map +0 -1
- package/types/test/test-indexer.d.ts +0 -2
- package/types/test/test-indexer.d.ts.map +0 -1
- package/types/test/test-interface.d.ts +0 -2
- package/types/test/test-interface.d.ts.map +0 -1
- package/types/test/test-iterator.d.ts +0 -2
- package/types/test/test-iterator.d.ts.map +0 -1
- package/types/test/test-reader.d.ts +0 -2
- package/types/test/test-reader.d.ts.map +0 -1
- package/types/test/test-writer.d.ts +0 -2
- package/types/test/test-writer.d.ts.map +0 -1
- package/types/test/verify-store-reader.d.ts +0 -29
- package/types/test/verify-store-reader.d.ts.map +0 -1
- package/writer +0 -1
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
import { CarWriter } from '../lib/writer.js';
|
|
2
|
-
import { CarReader } from '../lib/reader.js';
|
|
3
|
-
import {
|
|
4
|
-
bytes,
|
|
5
|
-
CID
|
|
6
|
-
} from 'multiformats';
|
|
7
|
-
import {
|
|
8
|
-
carBytes,
|
|
9
|
-
makeData,
|
|
10
|
-
assert,
|
|
11
|
-
rndCid
|
|
12
|
-
} from './common.js';
|
|
13
|
-
import {
|
|
14
|
-
verifyRoots,
|
|
15
|
-
verifyHas,
|
|
16
|
-
verifyGet,
|
|
17
|
-
verifyBlocks,
|
|
18
|
-
verifyCids
|
|
19
|
-
} from './verify-store-reader.js';
|
|
20
|
-
const {toHex} = bytes;
|
|
21
|
-
function concatBytes(chunks) {
|
|
22
|
-
const length = chunks.reduce((p, c) => p + c.length, 0);
|
|
23
|
-
const bytes = new Uint8Array(length);
|
|
24
|
-
let off = 0;
|
|
25
|
-
for (const chunk of chunks) {
|
|
26
|
-
bytes.set(chunk, off);
|
|
27
|
-
off += chunk.length;
|
|
28
|
-
}
|
|
29
|
-
return bytes;
|
|
30
|
-
}
|
|
31
|
-
function collector(iterable) {
|
|
32
|
-
const chunks = [];
|
|
33
|
-
const cfn = (async () => {
|
|
34
|
-
for await (const chunk of iterable) {
|
|
35
|
-
chunks.push(chunk);
|
|
36
|
-
}
|
|
37
|
-
return concatBytes(chunks);
|
|
38
|
-
})();
|
|
39
|
-
return cfn;
|
|
40
|
-
}
|
|
41
|
-
const newRoots = [
|
|
42
|
-
CID.parse('bafkreidbxzk2ryxwwtqxem4l3xyyjvw35yu4tcct4cqeqxwo47zhxgxqwq'),
|
|
43
|
-
CID.parse('bafkreiebzrnroamgos2adnbpgw5apo3z4iishhbdx77gldnbk57d4zdio4')
|
|
44
|
-
];
|
|
45
|
-
async function verifyUpdateRoots(bytes) {
|
|
46
|
-
const reader = await CarReader.fromBytes(bytes);
|
|
47
|
-
await assert.isRejected(verifyRoots(reader));
|
|
48
|
-
assert.deepEqual(await reader.getRoots(), newRoots);
|
|
49
|
-
await verifyHas(reader);
|
|
50
|
-
await verifyGet(reader);
|
|
51
|
-
await verifyBlocks(reader.blocks(), true);
|
|
52
|
-
await verifyCids(reader.cids(), true);
|
|
53
|
-
}
|
|
54
|
-
describe('CarWriter', () => {
|
|
55
|
-
let cborBlocks;
|
|
56
|
-
let allBlocks;
|
|
57
|
-
let allBlocksFlattened;
|
|
58
|
-
let roots;
|
|
59
|
-
function assertCarData(actual) {
|
|
60
|
-
assert.strictEqual(toHex(actual), toHex(carBytes), 'got expected bytes');
|
|
61
|
-
}
|
|
62
|
-
before(async () => {
|
|
63
|
-
const data = await makeData();
|
|
64
|
-
cborBlocks = data.cborBlocks;
|
|
65
|
-
allBlocks = data.allBlocks;
|
|
66
|
-
allBlocksFlattened = data.allBlocksFlattened;
|
|
67
|
-
roots = [
|
|
68
|
-
cborBlocks[0].cid,
|
|
69
|
-
cborBlocks[1].cid
|
|
70
|
-
];
|
|
71
|
-
});
|
|
72
|
-
it('complete', async () => {
|
|
73
|
-
const {writer, out} = CarWriter.create(roots);
|
|
74
|
-
assert.strictEqual(typeof out[Symbol.asyncIterator], 'function');
|
|
75
|
-
const collection = collector(out);
|
|
76
|
-
const writeQueue = [];
|
|
77
|
-
for (const block of allBlocksFlattened) {
|
|
78
|
-
writeQueue.push(writer.put(block));
|
|
79
|
-
}
|
|
80
|
-
writeQueue.push(writer.close());
|
|
81
|
-
let collected = false;
|
|
82
|
-
collection.then(bytes => {
|
|
83
|
-
collected = true;
|
|
84
|
-
assertCarData(bytes);
|
|
85
|
-
});
|
|
86
|
-
await Promise.all(writeQueue);
|
|
87
|
-
assert.strictEqual(collected, true);
|
|
88
|
-
});
|
|
89
|
-
it('complete, deferred collection', async () => {
|
|
90
|
-
const {writer, out} = CarWriter.create(roots);
|
|
91
|
-
const writeQueue = [];
|
|
92
|
-
for (const block of allBlocksFlattened) {
|
|
93
|
-
writeQueue.push(writer.put(block));
|
|
94
|
-
}
|
|
95
|
-
writeQueue.push(writer.close());
|
|
96
|
-
let collected = false;
|
|
97
|
-
collector(out).then(bytes => {
|
|
98
|
-
collected = true;
|
|
99
|
-
assertCarData(bytes);
|
|
100
|
-
});
|
|
101
|
-
await Promise.all(writeQueue);
|
|
102
|
-
assert.strictEqual(collected, true);
|
|
103
|
-
});
|
|
104
|
-
it('complete, close after write', async () => {
|
|
105
|
-
const {writer, out} = CarWriter.create(roots);
|
|
106
|
-
assert.strictEqual(typeof out[Symbol.asyncIterator], 'function');
|
|
107
|
-
const collection = collector(out);
|
|
108
|
-
const writeQueue = [];
|
|
109
|
-
for (const block of allBlocksFlattened) {
|
|
110
|
-
writeQueue.push(writer.put(block));
|
|
111
|
-
}
|
|
112
|
-
writeQueue.push(writer.close());
|
|
113
|
-
let written = false;
|
|
114
|
-
Promise.all(writeQueue).then(() => {
|
|
115
|
-
written = true;
|
|
116
|
-
});
|
|
117
|
-
const bytes = await collection;
|
|
118
|
-
assert.strictEqual(written, false);
|
|
119
|
-
await Promise.resolve();
|
|
120
|
-
assertCarData(bytes);
|
|
121
|
-
});
|
|
122
|
-
it('complete, no queue', async () => {
|
|
123
|
-
const {writer, out} = CarWriter.create(roots);
|
|
124
|
-
const collection = collector(out);
|
|
125
|
-
for (const block of allBlocksFlattened) {
|
|
126
|
-
await writer.put(block);
|
|
127
|
-
}
|
|
128
|
-
await writer.close();
|
|
129
|
-
const bytes = await collection;
|
|
130
|
-
assertCarData(bytes);
|
|
131
|
-
});
|
|
132
|
-
it('complete, slow drip', async () => {
|
|
133
|
-
const {writer, out} = CarWriter.create(roots);
|
|
134
|
-
assert.strictEqual(typeof out[Symbol.asyncIterator], 'function');
|
|
135
|
-
const collection = collector(out);
|
|
136
|
-
for (const block of allBlocksFlattened) {
|
|
137
|
-
writer.put(block);
|
|
138
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
139
|
-
}
|
|
140
|
-
await writer.close();
|
|
141
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
142
|
-
const bytes = await collection;
|
|
143
|
-
assertCarData(bytes);
|
|
144
|
-
});
|
|
145
|
-
it('complete, no queue, deferred collection', async () => {
|
|
146
|
-
const {writer, out} = CarWriter.create(roots);
|
|
147
|
-
for (const block of allBlocksFlattened) {
|
|
148
|
-
writer.put(block);
|
|
149
|
-
}
|
|
150
|
-
writer.close();
|
|
151
|
-
const collection = collector(out);
|
|
152
|
-
const bytes = await collection;
|
|
153
|
-
assertCarData(bytes);
|
|
154
|
-
});
|
|
155
|
-
it('single root', async () => {
|
|
156
|
-
const {writer, out} = CarWriter.create(roots[0]);
|
|
157
|
-
const collection = collector(out);
|
|
158
|
-
for (const block of allBlocksFlattened) {
|
|
159
|
-
await writer.put(block);
|
|
160
|
-
}
|
|
161
|
-
await writer.close();
|
|
162
|
-
const bytes = await collection;
|
|
163
|
-
const expectedRootDef = 'a265726f6f747381d82a58250001711220f88bc853804cf294fe417e4fa83028689fcdb1b1592c5102e1474dbc200fab8b6776657273696f6e01';
|
|
164
|
-
const expectedStart = (expectedRootDef.length / 2).toString(16) + expectedRootDef + '28';
|
|
165
|
-
assert.strictEqual(toHex(bytes).substring(0, expectedStart.length), expectedStart);
|
|
166
|
-
});
|
|
167
|
-
it('no roots', async () => {
|
|
168
|
-
const {writer, out} = CarWriter.create();
|
|
169
|
-
const collection = collector(out);
|
|
170
|
-
for (const block of allBlocksFlattened) {
|
|
171
|
-
await writer.put(block);
|
|
172
|
-
}
|
|
173
|
-
await writer.close();
|
|
174
|
-
const bytes = await collection;
|
|
175
|
-
const expectedRootDef = 'a265726f6f7473806776657273696f6e01';
|
|
176
|
-
const expectedStart = (expectedRootDef.length / 2).toString(16) + expectedRootDef + '28';
|
|
177
|
-
assert.strictEqual(toHex(bytes).substring(0, expectedStart.length), expectedStart);
|
|
178
|
-
});
|
|
179
|
-
it('appender', async () => {
|
|
180
|
-
let writerOut = CarWriter.create(roots);
|
|
181
|
-
let collection = collector(writerOut.out);
|
|
182
|
-
await writerOut.writer.close();
|
|
183
|
-
const headerBytes = await collection;
|
|
184
|
-
const append = async index => {
|
|
185
|
-
writerOut = CarWriter.createAppender();
|
|
186
|
-
collection = collector(writerOut.out);
|
|
187
|
-
for (const block of allBlocks[index][1]) {
|
|
188
|
-
await writerOut.writer.put(block);
|
|
189
|
-
}
|
|
190
|
-
await writerOut.writer.close();
|
|
191
|
-
return collection;
|
|
192
|
-
};
|
|
193
|
-
const rawBytes = await append(0);
|
|
194
|
-
const pbBytes = await append(1);
|
|
195
|
-
const cborBytes = await append(2);
|
|
196
|
-
assert.ok(rawBytes.length > 0);
|
|
197
|
-
assert.ok(pbBytes.length > 0);
|
|
198
|
-
assert.ok(cborBytes.length > 0);
|
|
199
|
-
const reassembled = concatBytes([
|
|
200
|
-
headerBytes,
|
|
201
|
-
rawBytes,
|
|
202
|
-
pbBytes,
|
|
203
|
-
cborBytes
|
|
204
|
-
]);
|
|
205
|
-
assert.strictEqual(toHex(reassembled), toHex(carBytes));
|
|
206
|
-
});
|
|
207
|
-
it('bad argument for create()', () => {
|
|
208
|
-
for (const arg of [
|
|
209
|
-
new Uint8Array(0),
|
|
210
|
-
true,
|
|
211
|
-
false,
|
|
212
|
-
null,
|
|
213
|
-
'string',
|
|
214
|
-
100,
|
|
215
|
-
{ obj: 'nope' },
|
|
216
|
-
[false]
|
|
217
|
-
]) {
|
|
218
|
-
assert.throws(() => CarWriter.create(arg));
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
it('bad argument for put()', async () => {
|
|
222
|
-
const {writer} = CarWriter.create();
|
|
223
|
-
for (const arg of [
|
|
224
|
-
new Uint8Array(0),
|
|
225
|
-
true,
|
|
226
|
-
false,
|
|
227
|
-
null,
|
|
228
|
-
'string',
|
|
229
|
-
100,
|
|
230
|
-
{ obj: 'nope' },
|
|
231
|
-
[false]
|
|
232
|
-
]) {
|
|
233
|
-
await assert.isRejected(writer.put(arg));
|
|
234
|
-
}
|
|
235
|
-
for (const arg of [
|
|
236
|
-
true,
|
|
237
|
-
false,
|
|
238
|
-
null,
|
|
239
|
-
'string',
|
|
240
|
-
100,
|
|
241
|
-
{ obj: 'nope' },
|
|
242
|
-
[false]
|
|
243
|
-
]) {
|
|
244
|
-
await assert.isRejected(writer.put({
|
|
245
|
-
bytes: new Uint8Array(0),
|
|
246
|
-
cid: arg
|
|
247
|
-
}));
|
|
248
|
-
}
|
|
249
|
-
for (const arg of [
|
|
250
|
-
true,
|
|
251
|
-
false,
|
|
252
|
-
null,
|
|
253
|
-
'string',
|
|
254
|
-
100,
|
|
255
|
-
{ obj: 'nope' },
|
|
256
|
-
[false]
|
|
257
|
-
]) {
|
|
258
|
-
await assert.isRejected(writer.put({
|
|
259
|
-
cid: rndCid,
|
|
260
|
-
bytes: arg
|
|
261
|
-
}));
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
it('bad write after closed', async () => {
|
|
265
|
-
const {writer, out} = CarWriter.create();
|
|
266
|
-
const collection = collector(out);
|
|
267
|
-
await writer.put(allBlocksFlattened[0]);
|
|
268
|
-
await writer.close();
|
|
269
|
-
await assert.isRejected(writer.put(allBlocksFlattened[1]), /closed/);
|
|
270
|
-
await collection;
|
|
271
|
-
});
|
|
272
|
-
it('bad attempt to multiple iterate', async () => {
|
|
273
|
-
const {out} = CarWriter.create();
|
|
274
|
-
collector(out);
|
|
275
|
-
await assert.isRejected(collector(out), /multiple iterator/i);
|
|
276
|
-
});
|
|
277
|
-
it('bad attempt to multiple close', async () => {
|
|
278
|
-
const {writer, out} = CarWriter.create();
|
|
279
|
-
collector(out);
|
|
280
|
-
await writer.close();
|
|
281
|
-
await assert.isRejected(writer.close(), /closed/i);
|
|
282
|
-
});
|
|
283
|
-
it('update roots (fd)', async () => {
|
|
284
|
-
const bytes = carBytes.slice();
|
|
285
|
-
await CarWriter.updateRootsInBytes(bytes, newRoots);
|
|
286
|
-
await verifyUpdateRoots(bytes);
|
|
287
|
-
});
|
|
288
|
-
it('update roots error: wrong header size', async () => {
|
|
289
|
-
const bytes = carBytes.slice();
|
|
290
|
-
await assert.isRejected(CarWriter.updateRootsInBytes(bytes, [
|
|
291
|
-
...newRoots,
|
|
292
|
-
newRoots[0]
|
|
293
|
-
]), /can only overwrite a header of the same length/);
|
|
294
|
-
await assert.isRejected(CarWriter.updateRootsInBytes(bytes, [newRoots[0]]), /can only overwrite a header of the same length/);
|
|
295
|
-
await assert.isRejected(CarWriter.updateRootsInBytes(bytes, []), /can only overwrite a header of the same length/);
|
|
296
|
-
});
|
|
297
|
-
});
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { bytes } from 'multiformats';
|
|
2
|
-
import * as raw from 'multiformats/codecs/raw';
|
|
3
|
-
import {
|
|
4
|
-
toBlock,
|
|
5
|
-
assert,
|
|
6
|
-
makeData
|
|
7
|
-
} from './common.js';
|
|
8
|
-
function compareBlockData(actual, expected, id) {
|
|
9
|
-
assert.strictEqual(bytes.toHex(actual.bytes), bytes.toHex(expected.bytes), `comparing block as hex ${ id || '' }`);
|
|
10
|
-
}
|
|
11
|
-
function compareCids(actual, expected) {
|
|
12
|
-
assert.strictEqual(actual.toString(), expected.toString());
|
|
13
|
-
}
|
|
14
|
-
async function verifyRoots(reader) {
|
|
15
|
-
const {cborBlocks} = await makeData();
|
|
16
|
-
const expected = [
|
|
17
|
-
cborBlocks[0].cid.toString(),
|
|
18
|
-
cborBlocks[1].cid.toString()
|
|
19
|
-
];
|
|
20
|
-
assert.deepStrictEqual((await reader.getRoots()).map(c => c.toString()), expected);
|
|
21
|
-
}
|
|
22
|
-
async function verifyHas(reader) {
|
|
23
|
-
const {allBlocks} = await makeData();
|
|
24
|
-
const verifyHas = async (cid, name) => {
|
|
25
|
-
assert.ok(await reader.has(cid), `reader doesn't have expected key for ${ name }`);
|
|
26
|
-
};
|
|
27
|
-
const verifyHasnt = async (cid, name) => {
|
|
28
|
-
assert.ok(!await reader.has(cid), `reader has unexpected key for ${ name }`);
|
|
29
|
-
assert.strictEqual(await reader.get(cid), undefined);
|
|
30
|
-
};
|
|
31
|
-
for (const [type, blocks] of allBlocks) {
|
|
32
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
33
|
-
await verifyHas(blocks[i].cid, `block #${ i } (${ type } / ${ blocks[i].cid })`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
await verifyHasnt((await toBlock(new TextEncoder().encode('dddd'), raw)).cid, 'dddd');
|
|
37
|
-
}
|
|
38
|
-
async function verifyGet(reader) {
|
|
39
|
-
const {allBlocks} = await makeData();
|
|
40
|
-
const verifyBlock = async (expected, index, type) => {
|
|
41
|
-
let actual;
|
|
42
|
-
try {
|
|
43
|
-
actual = await reader.get(expected.cid);
|
|
44
|
-
assert.isDefined(actual);
|
|
45
|
-
if (actual) {
|
|
46
|
-
compareBlockData(actual, expected, `#${ index } (${ type })`);
|
|
47
|
-
}
|
|
48
|
-
} catch (err) {
|
|
49
|
-
assert.ifError(err, `get block length #${ index } (${ type })`);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
for (const [type, blocks] of allBlocks) {
|
|
53
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
54
|
-
await verifyBlock(blocks[i], i, type);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function verifyBlocks(iterator, unordered) {
|
|
59
|
-
const {allBlocksFlattened} = await makeData();
|
|
60
|
-
if (!unordered) {
|
|
61
|
-
const expected = allBlocksFlattened.slice();
|
|
62
|
-
for await (const actual of iterator) {
|
|
63
|
-
const next = expected.shift();
|
|
64
|
-
assert.isDefined(next);
|
|
65
|
-
if (next) {
|
|
66
|
-
compareBlockData(actual, next);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
const expected = {};
|
|
71
|
-
for (const block of allBlocksFlattened) {
|
|
72
|
-
expected[block.cid.toString()] = block;
|
|
73
|
-
}
|
|
74
|
-
for await (const actual of iterator) {
|
|
75
|
-
const {cid} = actual;
|
|
76
|
-
const exp = expected[cid.toString()];
|
|
77
|
-
if (!exp) {
|
|
78
|
-
throw new Error(`Unexpected block: ${ cid.toString() }`);
|
|
79
|
-
}
|
|
80
|
-
compareBlockData(actual, exp);
|
|
81
|
-
delete expected[cid.toString()];
|
|
82
|
-
}
|
|
83
|
-
if (Object.keys(expected).length) {
|
|
84
|
-
throw new Error('Did not find all expected blocks');
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
async function verifyCids(iterator, unordered) {
|
|
89
|
-
const {allBlocksFlattened} = await makeData();
|
|
90
|
-
if (!unordered) {
|
|
91
|
-
const expected = allBlocksFlattened.slice();
|
|
92
|
-
for await (const actual of iterator) {
|
|
93
|
-
const next = expected.shift();
|
|
94
|
-
assert.isDefined(next);
|
|
95
|
-
if (next) {
|
|
96
|
-
compareCids(actual, next.cid);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
const expected = {};
|
|
101
|
-
for (const block of allBlocksFlattened) {
|
|
102
|
-
expected[block.cid.toString()] = block;
|
|
103
|
-
}
|
|
104
|
-
for await (const cid of iterator) {
|
|
105
|
-
const exp = expected[cid.toString()];
|
|
106
|
-
if (!exp) {
|
|
107
|
-
throw new Error(`Unexpected cid: ${ cid.toString() }`);
|
|
108
|
-
}
|
|
109
|
-
delete expected[cid.toString()];
|
|
110
|
-
}
|
|
111
|
-
if (Object.keys(expected).length) {
|
|
112
|
-
throw new Error('Did not find all expected cids');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
export {
|
|
117
|
-
verifyRoots,
|
|
118
|
-
verifyHas,
|
|
119
|
-
verifyGet,
|
|
120
|
-
verifyBlocks,
|
|
121
|
-
verifyCids
|
|
122
|
-
};
|
package/esm/package.json
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Take a .car file and dump its contents to stdout as a single DAG-JSON format
|
|
4
|
-
// block. The format is standardised for describing CAR fixtures at
|
|
5
|
-
// https://ipld.io/specs/transport/car/fixture/
|
|
6
|
-
|
|
7
|
-
import fs from 'fs'
|
|
8
|
-
import { CarReader } from '@ipld/car/reader'
|
|
9
|
-
import { CarIndexer } from '@ipld/car/indexer'
|
|
10
|
-
import * as dagCbor from '@ipld/dag-cbor'
|
|
11
|
-
import * as dagPb from '@ipld/dag-pb'
|
|
12
|
-
import * as dagJson from '@ipld/dag-json'
|
|
13
|
-
import * as raw from 'multiformats/codecs/raw'
|
|
14
|
-
import * as json from 'multiformats/codecs/json'
|
|
15
|
-
|
|
16
|
-
if (!process.argv[2]) {
|
|
17
|
-
console.log('Usage: dump-car.js <path/to/car>')
|
|
18
|
-
process.exit(1)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const codecs = {
|
|
22
|
-
[dagCbor.code]: dagCbor,
|
|
23
|
-
[dagPb.code]: dagPb,
|
|
24
|
-
[dagJson.code]: dagJson,
|
|
25
|
-
[raw.code]: raw,
|
|
26
|
-
[json.code]: json
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function decode (cid, bytes) {
|
|
30
|
-
if (!codecs[cid.code]) {
|
|
31
|
-
throw new Error(`Unknown codec code: 0x${cid.code.toString(16)}`)
|
|
32
|
-
}
|
|
33
|
-
return codecs[cid.code].decode(bytes)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function run () {
|
|
37
|
-
const bytes = await fs.promises.readFile(process.argv[2])
|
|
38
|
-
// this is not the most optimal way to get both an index and a reader,
|
|
39
|
-
// nor is reading in the bytes into memory necessarily the best thing
|
|
40
|
-
// to be doing, but this is fine for small files and where efficiency
|
|
41
|
-
// isn't critical
|
|
42
|
-
const indexer = await CarIndexer.fromBytes(bytes)
|
|
43
|
-
const reader = await CarReader.fromBytes(bytes)
|
|
44
|
-
const fixture = {
|
|
45
|
-
header: reader._header, // a little naughty but we need gory details
|
|
46
|
-
blocks: []
|
|
47
|
-
}
|
|
48
|
-
let i = 0
|
|
49
|
-
for await (const blockIndex of indexer) {
|
|
50
|
-
fixture.blocks[i] = blockIndex
|
|
51
|
-
const block = await reader.get(blockIndex.cid)
|
|
52
|
-
fixture.blocks[i].content = decode(blockIndex.cid, block.bytes)
|
|
53
|
-
i++
|
|
54
|
-
}
|
|
55
|
-
const json = new TextDecoder().decode(dagJson.encode(fixture))
|
|
56
|
-
if (process.argv.includes('--pretty')) {
|
|
57
|
-
console.log(JSON.stringify(JSON.parse(json), null, 2))
|
|
58
|
-
} else {
|
|
59
|
-
console.log(json)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
run().catch((err) => {
|
|
64
|
-
console.error(err)
|
|
65
|
-
process.exit(1)
|
|
66
|
-
})
|
package/examples/dump-car.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Take a .car file and dump its contents into one file per block, with the
|
|
4
|
-
// filename being the CID of that block.
|
|
5
|
-
// Also prints a DAG-JSON form of the block and its CID to stdout.
|
|
6
|
-
// If `--inspect` is supplied, don't write the blocks, just print them to stdout.
|
|
7
|
-
|
|
8
|
-
import fs from 'fs'
|
|
9
|
-
import { CarBlockIterator } from '@ipld/car/iterator'
|
|
10
|
-
import * as dagCbor from '@ipld/dag-cbor'
|
|
11
|
-
import * as dagPb from '@ipld/dag-pb'
|
|
12
|
-
import * as dagJson from '@ipld/dag-json'
|
|
13
|
-
import * as raw from 'multiformats/codecs/raw'
|
|
14
|
-
import * as json from 'multiformats/codecs/json'
|
|
15
|
-
|
|
16
|
-
if (!process.argv[2]) {
|
|
17
|
-
console.log('Usage: dump-car.js [--inspect] <path/to/car>')
|
|
18
|
-
process.exit(1)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const codecs = {
|
|
22
|
-
[dagCbor.code]: dagCbor,
|
|
23
|
-
[dagPb.code]: dagPb,
|
|
24
|
-
[dagJson.code]: dagJson,
|
|
25
|
-
[raw.code]: raw,
|
|
26
|
-
[json.code]: json
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function decode (cid, bytes) {
|
|
30
|
-
if (!codecs[cid.code]) {
|
|
31
|
-
throw new Error(`Unknown codec code: 0x${cid.code.toString(16)}`)
|
|
32
|
-
}
|
|
33
|
-
return codecs[cid.code].decode(bytes)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function run () {
|
|
37
|
-
const inspect = process.argv.includes('--inspect')
|
|
38
|
-
const inStream = fs.createReadStream(process.argv.filter((a) => a !== '--inspect')[2])
|
|
39
|
-
const reader = await CarBlockIterator.fromIterable(inStream)
|
|
40
|
-
console.log(`Version: ${reader.version}`)
|
|
41
|
-
console.log(`Roots: [${(await reader.getRoots()).map((r) => r.toString()).join(', ')}]`)
|
|
42
|
-
console.log('Blocks:')
|
|
43
|
-
let i = 1
|
|
44
|
-
for await (const { cid, bytes } of reader) {
|
|
45
|
-
if (!inspect) {
|
|
46
|
-
await fs.promises.writeFile(cid.toString(), bytes)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const decoded = decode(cid, bytes)
|
|
50
|
-
console.log(`#${i++} ${cid} [${codecs[cid.code].name}]`)
|
|
51
|
-
console.dir(new TextDecoder().decode(dagJson.encode(decoded)))
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
run().catch((err) => {
|
|
56
|
-
console.error(err)
|
|
57
|
-
process.exit(1)
|
|
58
|
-
})
|
package/examples/dump-index.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Take a .car file and dump its index in DAG-JSON format, one line per block
|
|
4
|
-
|
|
5
|
-
import fs from 'fs'
|
|
6
|
-
import { CarIndexer } from '@ipld/car/indexer'
|
|
7
|
-
import * as dagJson from '@ipld/dag-json'
|
|
8
|
-
|
|
9
|
-
if (!process.argv[2]) {
|
|
10
|
-
console.log('Usage: dump-index.js <path/to/car>')
|
|
11
|
-
process.exit(1)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function run () {
|
|
15
|
-
const indexer = await CarIndexer.fromIterable(fs.createReadStream(process.argv[2]))
|
|
16
|
-
for await (const blockIndex of indexer) {
|
|
17
|
-
console.log(new TextDecoder().decode(dagJson.encode(blockIndex)))
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
run().catch((err) => {
|
|
22
|
-
console.error(err)
|
|
23
|
-
process.exit(1)
|
|
24
|
-
})
|
package/examples/package.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ipld/car-examples",
|
|
3
|
-
"version": "0.0.0-dev",
|
|
4
|
-
"description": "How to use the Content Addressable aRchive format reader and writer",
|
|
5
|
-
"main": "example.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"private": true,
|
|
8
|
-
"scripts": {
|
|
9
|
-
"start": "node round-trip.js",
|
|
10
|
-
"round-trip": "node round-trip.js",
|
|
11
|
-
"verify": "node verify-car.js",
|
|
12
|
-
"dump": "node dump-car.js",
|
|
13
|
-
"test": "npm install && node test-examples.js"
|
|
14
|
-
},
|
|
15
|
-
"author": "Rod <rod@vagg.org> (http://r.va.gg/)",
|
|
16
|
-
"license": "(Apache-2.0 AND MIT)",
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"@ipld/car": "file:..",
|
|
19
|
-
"@ipld/dag-cbor": "^7.0.0",
|
|
20
|
-
"@ipld/dag-json": "^8.0.0",
|
|
21
|
-
"@ipld/dag-pb": "^2.0.2",
|
|
22
|
-
"@multiformats/blake2": "^1.0.1",
|
|
23
|
-
"@types/varint": "^6.0.0",
|
|
24
|
-
"multiformats": "^9.0.4",
|
|
25
|
-
"varint": "^6.0.0"
|
|
26
|
-
}
|
|
27
|
-
}
|
package/examples/round-trip.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Create a simple .car file with a single block and that block's CID as the
|
|
4
|
-
// single root. Then read the .car and fetch the block again.
|
|
5
|
-
|
|
6
|
-
import fs from 'fs'
|
|
7
|
-
import { Readable } from 'stream'
|
|
8
|
-
import { CarReader, CarWriter } from '@ipld/car'
|
|
9
|
-
import * as raw from 'multiformats/codecs/raw'
|
|
10
|
-
import { CID } from 'multiformats/cid'
|
|
11
|
-
import { sha256 } from 'multiformats/hashes/sha2'
|
|
12
|
-
|
|
13
|
-
async function example () {
|
|
14
|
-
const bytes = new TextEncoder().encode('random meaningless bytes')
|
|
15
|
-
const hash = await sha256.digest(raw.encode(bytes))
|
|
16
|
-
const cid = CID.create(1, raw.code, hash)
|
|
17
|
-
|
|
18
|
-
// create the writer and set the header with a single root
|
|
19
|
-
const { writer, out } = await CarWriter.create([cid])
|
|
20
|
-
Readable.from(out).pipe(fs.createWriteStream('example.car'))
|
|
21
|
-
|
|
22
|
-
// store a new block, creates a new file entry in the CAR archive
|
|
23
|
-
await writer.put({ cid, bytes })
|
|
24
|
-
await writer.close()
|
|
25
|
-
|
|
26
|
-
const inStream = fs.createReadStream('example.car')
|
|
27
|
-
// read and parse the entire stream in one go, this will cache the contents of
|
|
28
|
-
// the car in memory so is not suitable for large files.
|
|
29
|
-
const reader = await CarReader.fromIterable(inStream)
|
|
30
|
-
|
|
31
|
-
// read the list of roots from the header
|
|
32
|
-
const roots = await reader.getRoots()
|
|
33
|
-
// retrieve a block, as a { cid:CID, bytes:UInt8Array } pair from the archive
|
|
34
|
-
const got = await reader.get(roots[0])
|
|
35
|
-
// also possible: for await (const { cid, bytes } of CarIterator.fromIterable(inStream)) { ... }
|
|
36
|
-
|
|
37
|
-
console.log('Retrieved [%s] from example.car with CID [%s]',
|
|
38
|
-
new TextDecoder().decode(got.bytes),
|
|
39
|
-
roots[0].toString())
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
example().catch((err) => {
|
|
43
|
-
console.error(err)
|
|
44
|
-
process.exit(1)
|
|
45
|
-
})
|