@web3-storage/pail 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +208 -0
- package/dist/scripts/randomcid.d.ts +2 -0
- package/dist/scripts/randomcid.d.ts.map +1 -0
- package/dist/scripts/randomcid.js +10 -0
- package/dist/scripts/words/gen.d.ts +2 -0
- package/dist/scripts/words/gen.d.ts.map +1 -0
- package/dist/scripts/words/gen.js +51 -0
- package/dist/src/api.d.ts +4 -2
- package/dist/src/api.d.ts.map +1 -1
- package/dist/src/api.js +1 -0
- package/dist/src/batch/api.d.ts +2 -2
- package/dist/src/batch/api.d.ts.map +1 -1
- package/dist/src/batch/api.js +1 -0
- package/dist/src/batch/index.d.ts +1 -53
- package/dist/src/batch/index.d.ts.map +1 -1
- package/dist/src/batch/index.js +241 -0
- package/dist/src/batch/shard.d.ts +1 -1
- package/dist/src/batch/shard.d.ts.map +1 -1
- package/dist/src/batch/shard.js +12 -0
- package/dist/src/block.d.ts +2 -2
- package/dist/src/block.d.ts.map +1 -1
- package/dist/src/block.js +66 -0
- package/dist/src/clock/api.d.ts +1 -1
- package/dist/src/clock/api.d.ts.map +1 -1
- package/dist/src/clock/api.js +1 -0
- package/dist/src/clock/index.d.ts +2 -2
- package/dist/src/clock/index.d.ts.map +1 -1
- package/dist/src/clock/index.js +199 -0
- package/dist/src/crdt/api.d.ts +1 -1
- package/dist/src/crdt/api.d.ts.map +1 -1
- package/dist/src/crdt/api.js +1 -0
- package/dist/src/crdt/batch/api.d.ts +1 -1
- package/dist/src/crdt/batch/api.d.ts.map +1 -1
- package/dist/src/crdt/batch/api.js +1 -0
- package/dist/src/crdt/batch/index.d.ts.map +1 -1
- package/dist/src/crdt/batch/index.js +140 -0
- package/dist/src/crdt/index.d.ts +2 -2
- package/dist/src/crdt/index.d.ts.map +1 -1
- package/dist/src/crdt/index.js +344 -0
- package/dist/src/diff.d.ts +3 -3
- package/dist/src/diff.d.ts.map +1 -1
- package/dist/src/diff.js +151 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +356 -0
- package/dist/src/merge.d.ts.map +1 -1
- package/dist/src/merge.js +42 -0
- package/dist/src/shard.d.ts +4 -4
- package/dist/src/shard.d.ts.map +1 -1
- package/dist/src/shard.js +166 -0
- package/dist/test/batch.test.d.ts +2 -0
- package/dist/test/batch.test.d.ts.map +1 -0
- package/dist/test/batch.test.js +126 -0
- package/dist/test/clock.test.d.ts +2 -0
- package/dist/test/clock.test.d.ts.map +1 -0
- package/dist/test/clock.test.js +244 -0
- package/dist/test/crdt.test.d.ts +2 -0
- package/dist/test/crdt.test.d.ts.map +1 -0
- package/dist/test/crdt.test.js +271 -0
- package/dist/test/del.test.d.ts +2 -0
- package/dist/test/del.test.d.ts.map +1 -0
- package/dist/test/del.test.js +21 -0
- package/dist/test/diff.test.d.ts +2 -0
- package/dist/test/diff.test.d.ts.map +1 -0
- package/dist/test/diff.test.js +38 -0
- package/dist/test/entries.test.d.ts +2 -0
- package/dist/test/entries.test.d.ts.map +1 -0
- package/dist/test/entries.test.js +210 -0
- package/dist/test/get.test.d.ts +2 -0
- package/dist/test/get.test.d.ts.map +1 -0
- package/dist/test/get.test.js +26 -0
- package/dist/test/helpers.d.ts +35 -0
- package/dist/test/helpers.d.ts.map +1 -0
- package/dist/test/helpers.js +168 -0
- package/dist/test/put.test.d.ts +2 -0
- package/dist/test/put.test.d.ts.map +1 -0
- package/dist/test/put.test.js +165 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +13 -0
- package/package.json +49 -94
- package/scripts/propernames/gen.sh +3 -0
- package/cli.js +0 -218
- package/src/api.js +0 -1
- package/src/api.ts +0 -90
- package/src/batch/api.js +0 -1
- package/src/batch/api.ts +0 -59
- package/src/batch/index.js +0 -258
- package/src/batch/shard.js +0 -13
- package/src/block.js +0 -75
- package/src/clock/api.js +0 -1
- package/src/clock/api.ts +0 -12
- package/src/clock/index.js +0 -182
- package/src/crdt/api.js +0 -1
- package/src/crdt/api.ts +0 -33
- package/src/crdt/batch/api.js +0 -1
- package/src/crdt/batch/api.ts +0 -30
- package/src/crdt/batch/index.js +0 -155
- package/src/crdt/index.js +0 -354
- package/src/diff.js +0 -151
- package/src/index.js +0 -406
- package/src/merge.js +0 -43
- package/src/shard.js +0 -180
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { put, get, del } from '../src/index.js';
|
|
2
|
+
import { ShardBlock } from '../src/shard.js';
|
|
3
|
+
import { Blockstore, randomCID } from './helpers.js';
|
|
4
|
+
describe('del', () => {
|
|
5
|
+
it('deletes a value', async () => {
|
|
6
|
+
const empty = await ShardBlock.create();
|
|
7
|
+
const blocks = new Blockstore();
|
|
8
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
9
|
+
const dataCID = await randomCID(32);
|
|
10
|
+
const { root: root0, additions: additions0 } = await put(blocks, empty.cid, 'test', dataCID);
|
|
11
|
+
for (const b of additions0) {
|
|
12
|
+
await blocks.put(b.cid, b.bytes);
|
|
13
|
+
}
|
|
14
|
+
const { root: root1, additions: additions1 } = await del(blocks, root0, 'test');
|
|
15
|
+
for (const b of additions1) {
|
|
16
|
+
await blocks.put(b.cid, b.bytes);
|
|
17
|
+
}
|
|
18
|
+
const res = await get(blocks, root1, 'test');
|
|
19
|
+
assert.strictEqual(res, undefined);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.test.d.ts","sourceRoot":"","sources":["../../test/diff.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// eslint-disable-next-line no-unused-vars
|
|
2
|
+
import * as API from '../src/api.js';
|
|
3
|
+
import { put } from '../src/index.js';
|
|
4
|
+
import { ShardBlock } from '../src/shard.js';
|
|
5
|
+
import { difference } from '../src/diff.js';
|
|
6
|
+
import { Blockstore, randomCID } from './helpers.js';
|
|
7
|
+
describe('diff', () => {
|
|
8
|
+
it('diffs a non-sharded addition', async () => {
|
|
9
|
+
const empty = await ShardBlock.create();
|
|
10
|
+
const blocks = new Blockstore();
|
|
11
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
12
|
+
/** @type {Array<[string, API.UnknownLink]>} */
|
|
13
|
+
const testdata = [
|
|
14
|
+
['a', await randomCID(32)]
|
|
15
|
+
];
|
|
16
|
+
/** @type {API.ShardLink} */
|
|
17
|
+
let root = empty.cid;
|
|
18
|
+
for (const [k, v] of testdata) {
|
|
19
|
+
const res = await put(blocks, root, k, v);
|
|
20
|
+
for (const b of res.additions) {
|
|
21
|
+
await blocks.put(b.cid, b.bytes);
|
|
22
|
+
}
|
|
23
|
+
root = res.root;
|
|
24
|
+
}
|
|
25
|
+
const diff = await difference(blocks, empty.cid, root);
|
|
26
|
+
assert.equal(diff.shards.removals.length, 1);
|
|
27
|
+
assert.equal(diff.shards.removals[0].cid.toString(), empty.cid.toString());
|
|
28
|
+
assert.equal(diff.shards.additions.length, 1);
|
|
29
|
+
assert.equal(diff.shards.additions[0].cid.toString(), root.toString());
|
|
30
|
+
assert.equal(diff.keys.length, testdata.length);
|
|
31
|
+
for (const [k, v] of testdata) {
|
|
32
|
+
const d = diff.keys.find(p => p[0] === k);
|
|
33
|
+
assert(d);
|
|
34
|
+
assert.equal(d[1][0], null);
|
|
35
|
+
assert.equal(d[1][1]?.toString(), v.toString());
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entries.test.d.ts","sourceRoot":"","sources":["../../test/entries.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// eslint-disable-next-line no-unused-vars
|
|
2
|
+
import * as API from '../src/api.js';
|
|
3
|
+
import { put, entries } from '../src/index.js';
|
|
4
|
+
import { ShardBlock } from '../src/shard.js';
|
|
5
|
+
import { Blockstore, randomCID } from './helpers.js';
|
|
6
|
+
describe('entries', () => {
|
|
7
|
+
it('lists entries in lexicographical order', async () => {
|
|
8
|
+
const empty = await ShardBlock.create();
|
|
9
|
+
const blocks = new Blockstore();
|
|
10
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
11
|
+
/** @type {Array<[string, API.UnknownLink]>} */
|
|
12
|
+
const testdata = [
|
|
13
|
+
['c', await randomCID(32)],
|
|
14
|
+
['d', await randomCID(32)],
|
|
15
|
+
['a', await randomCID(32)],
|
|
16
|
+
['b', await randomCID(32)]
|
|
17
|
+
];
|
|
18
|
+
/** @type {API.ShardLink} */
|
|
19
|
+
let root = empty.cid;
|
|
20
|
+
for (const [k, v] of testdata) {
|
|
21
|
+
const res = await put(blocks, root, k, v);
|
|
22
|
+
for (const b of res.additions) {
|
|
23
|
+
await blocks.put(b.cid, b.bytes);
|
|
24
|
+
}
|
|
25
|
+
root = res.root;
|
|
26
|
+
}
|
|
27
|
+
const results = [];
|
|
28
|
+
for await (const entry of entries(blocks, root)) {
|
|
29
|
+
results.push(entry);
|
|
30
|
+
}
|
|
31
|
+
for (const [i, key] of testdata.map(d => d[0]).sort().entries()) {
|
|
32
|
+
assert.equal(results[i][0], key);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
it('lists entries by prefix', async () => {
|
|
36
|
+
const empty = await ShardBlock.create();
|
|
37
|
+
const blocks = new Blockstore();
|
|
38
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
39
|
+
/** @type {Array<[string, API.UnknownLink]>} */
|
|
40
|
+
const testdata = [
|
|
41
|
+
['cccc', await randomCID(32)],
|
|
42
|
+
['deee', await randomCID(32)],
|
|
43
|
+
['dooo', await randomCID(32)],
|
|
44
|
+
['beee', await randomCID(32)]
|
|
45
|
+
];
|
|
46
|
+
/** @type {API.ShardLink} */
|
|
47
|
+
let root = empty.cid;
|
|
48
|
+
for (const [k, v] of testdata) {
|
|
49
|
+
const res = await put(blocks, root, k, v);
|
|
50
|
+
for (const b of res.additions) {
|
|
51
|
+
await blocks.put(b.cid, b.bytes);
|
|
52
|
+
}
|
|
53
|
+
root = res.root;
|
|
54
|
+
}
|
|
55
|
+
const prefix = 'd';
|
|
56
|
+
const results = [];
|
|
57
|
+
for await (const entry of entries(blocks, root, { prefix })) {
|
|
58
|
+
results.push(entry);
|
|
59
|
+
}
|
|
60
|
+
for (const [i, key] of testdata.map(d => d[0]).filter(k => k.startsWith(prefix)).sort().entries()) {
|
|
61
|
+
assert.equal(results[i][0], key);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
it('lists entries by key greater than string', async () => {
|
|
65
|
+
const empty = await ShardBlock.create();
|
|
66
|
+
const blocks = new Blockstore();
|
|
67
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
68
|
+
/** @type {Array<[string, API.UnknownLink]>} */
|
|
69
|
+
const testdata = [
|
|
70
|
+
['cccc', await randomCID(32)],
|
|
71
|
+
['deee', await randomCID(32)],
|
|
72
|
+
['dooo', await randomCID(32)],
|
|
73
|
+
['beee', await randomCID(32)]
|
|
74
|
+
];
|
|
75
|
+
/** @type {API.ShardLink} */
|
|
76
|
+
let root = empty.cid;
|
|
77
|
+
for (const [k, v] of testdata) {
|
|
78
|
+
const res = await put(blocks, root, k, v);
|
|
79
|
+
for (const b of res.additions) {
|
|
80
|
+
await blocks.put(b.cid, b.bytes);
|
|
81
|
+
}
|
|
82
|
+
root = res.root;
|
|
83
|
+
}
|
|
84
|
+
const gt = 'beee';
|
|
85
|
+
const results = [];
|
|
86
|
+
for await (const entry of entries(blocks, root, { gt })) {
|
|
87
|
+
results.push(entry);
|
|
88
|
+
}
|
|
89
|
+
for (const [i, key] of testdata.map(d => d[0]).filter(k => k > gt).sort().entries()) {
|
|
90
|
+
assert.equal(results[i][0], key);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
it('lists entries by key greater than or equal to string', async () => {
|
|
94
|
+
const empty = await ShardBlock.create();
|
|
95
|
+
const blocks = new Blockstore();
|
|
96
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
97
|
+
/** @type {Array<[string, API.UnknownLink]>} */
|
|
98
|
+
const testdata = [
|
|
99
|
+
['cccc', await randomCID(32)],
|
|
100
|
+
['deee', await randomCID(32)],
|
|
101
|
+
['dooo', await randomCID(32)],
|
|
102
|
+
['beee', await randomCID(32)]
|
|
103
|
+
];
|
|
104
|
+
/** @type {API.ShardLink} */
|
|
105
|
+
let root = empty.cid;
|
|
106
|
+
for (const [k, v] of testdata) {
|
|
107
|
+
const res = await put(blocks, root, k, v);
|
|
108
|
+
for (const b of res.additions) {
|
|
109
|
+
await blocks.put(b.cid, b.bytes);
|
|
110
|
+
}
|
|
111
|
+
root = res.root;
|
|
112
|
+
}
|
|
113
|
+
const gte = 'beee';
|
|
114
|
+
const results = [];
|
|
115
|
+
for await (const entry of entries(blocks, root, { gte })) {
|
|
116
|
+
results.push(entry);
|
|
117
|
+
}
|
|
118
|
+
for (const [i, key] of testdata.map(d => d[0]).filter(k => k >= gte).sort().entries()) {
|
|
119
|
+
assert.equal(results[i][0], key);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
it('lists entries by key less than string', async () => {
|
|
123
|
+
const empty = await ShardBlock.create();
|
|
124
|
+
const blocks = new Blockstore();
|
|
125
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
126
|
+
/** @type {Array<[string, API.UnknownLink]>} */
|
|
127
|
+
const testdata = [
|
|
128
|
+
['cccc', await randomCID(32)],
|
|
129
|
+
['deee', await randomCID(32)],
|
|
130
|
+
['dooo', await randomCID(32)],
|
|
131
|
+
['beee', await randomCID(32)]
|
|
132
|
+
];
|
|
133
|
+
/** @type {API.ShardLink} */
|
|
134
|
+
let root = empty.cid;
|
|
135
|
+
for (const [k, v] of testdata) {
|
|
136
|
+
const res = await put(blocks, root, k, v);
|
|
137
|
+
for (const b of res.additions) {
|
|
138
|
+
await blocks.put(b.cid, b.bytes);
|
|
139
|
+
}
|
|
140
|
+
root = res.root;
|
|
141
|
+
}
|
|
142
|
+
const lt = 'doo';
|
|
143
|
+
const results = [];
|
|
144
|
+
for await (const entry of entries(blocks, root, { lt })) {
|
|
145
|
+
results.push(entry);
|
|
146
|
+
}
|
|
147
|
+
for (const [i, key] of testdata.map(d => d[0]).filter(k => k < lt).sort().entries()) {
|
|
148
|
+
assert.equal(results[i][0], key);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
it('lists entries by key less than or equal to string', async () => {
|
|
152
|
+
const empty = await ShardBlock.create();
|
|
153
|
+
const blocks = new Blockstore();
|
|
154
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
155
|
+
/** @type {Array<[string, API.UnknownLink]>} */
|
|
156
|
+
const testdata = [
|
|
157
|
+
['cccc', await randomCID(32)],
|
|
158
|
+
['deee', await randomCID(32)],
|
|
159
|
+
['dooo', await randomCID(32)],
|
|
160
|
+
['beee', await randomCID(32)]
|
|
161
|
+
];
|
|
162
|
+
/** @type {API.ShardLink} */
|
|
163
|
+
let root = empty.cid;
|
|
164
|
+
for (const [k, v] of testdata) {
|
|
165
|
+
const res = await put(blocks, root, k, v);
|
|
166
|
+
for (const b of res.additions) {
|
|
167
|
+
await blocks.put(b.cid, b.bytes);
|
|
168
|
+
}
|
|
169
|
+
root = res.root;
|
|
170
|
+
}
|
|
171
|
+
const lte = 'dooo';
|
|
172
|
+
const results = [];
|
|
173
|
+
for await (const entry of entries(blocks, root, { lte })) {
|
|
174
|
+
results.push(entry);
|
|
175
|
+
}
|
|
176
|
+
for (const [i, key] of testdata.map(d => d[0]).filter(k => k <= lte).sort().entries()) {
|
|
177
|
+
assert.equal(results[i][0], key);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
it('lists entries by key greater than and less than or equal to string', async () => {
|
|
181
|
+
const empty = await ShardBlock.create();
|
|
182
|
+
const blocks = new Blockstore();
|
|
183
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
184
|
+
/** @type {Array<[string, API.UnknownLink]>} */
|
|
185
|
+
const testdata = [
|
|
186
|
+
['cccc', await randomCID(32)],
|
|
187
|
+
['deee', await randomCID(32)],
|
|
188
|
+
['dooo', await randomCID(32)],
|
|
189
|
+
['beee', await randomCID(32)]
|
|
190
|
+
];
|
|
191
|
+
/** @type {API.ShardLink} */
|
|
192
|
+
let root = empty.cid;
|
|
193
|
+
for (const [k, v] of testdata) {
|
|
194
|
+
const res = await put(blocks, root, k, v);
|
|
195
|
+
for (const b of res.additions) {
|
|
196
|
+
await blocks.put(b.cid, b.bytes);
|
|
197
|
+
}
|
|
198
|
+
root = res.root;
|
|
199
|
+
}
|
|
200
|
+
const gt = 'c';
|
|
201
|
+
const lte = 'deee';
|
|
202
|
+
const results = [];
|
|
203
|
+
for await (const entry of entries(blocks, root, { gt, lte })) {
|
|
204
|
+
results.push(entry);
|
|
205
|
+
}
|
|
206
|
+
for (const [i, key] of testdata.map(d => d[0]).filter(k => k > gt && k <= lte).sort().entries()) {
|
|
207
|
+
assert.equal(results[i][0], key);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get.test.d.ts","sourceRoot":"","sources":["../../test/get.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { put, get } from '../src/index.js';
|
|
2
|
+
import { ShardBlock } from '../src/shard.js';
|
|
3
|
+
import { Blockstore, randomCID } from './helpers.js';
|
|
4
|
+
describe('get', () => {
|
|
5
|
+
it('get from root shard', async () => {
|
|
6
|
+
const empty = await ShardBlock.create();
|
|
7
|
+
const blocks = new Blockstore();
|
|
8
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
9
|
+
const dataCID = await randomCID(32);
|
|
10
|
+
const { root, additions } = await put(blocks, empty.cid, 'test', dataCID);
|
|
11
|
+
for (const b of additions) {
|
|
12
|
+
await blocks.put(b.cid, b.bytes);
|
|
13
|
+
}
|
|
14
|
+
const res = await get(blocks, root, 'test');
|
|
15
|
+
assert(res);
|
|
16
|
+
assert(res.toString(), dataCID.toString());
|
|
17
|
+
});
|
|
18
|
+
it('returns undefined when not found', async () => {
|
|
19
|
+
const empty = await ShardBlock.create();
|
|
20
|
+
const blocks = new Blockstore();
|
|
21
|
+
await blocks.put(empty.cid, empty.bytes);
|
|
22
|
+
const res = await get(blocks, empty.cid, 'test');
|
|
23
|
+
assert.strictEqual(res, undefined);
|
|
24
|
+
});
|
|
25
|
+
// TODO: test get when key is also shard link
|
|
26
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {number} min
|
|
3
|
+
* @param {number} max
|
|
4
|
+
*/
|
|
5
|
+
export function randomInteger(min: number, max: number): number;
|
|
6
|
+
/**
|
|
7
|
+
* @param {number} size
|
|
8
|
+
*/
|
|
9
|
+
export function randomString(size: number, alphabet?: string): string;
|
|
10
|
+
/** @param {number} [size] Number of random bytes to hash. */
|
|
11
|
+
export function randomCID(size?: number): Promise<Link.Link<any, 85, 18, 1>>;
|
|
12
|
+
/**
|
|
13
|
+
* @param {number} size
|
|
14
|
+
*/
|
|
15
|
+
export function randomBytes(size: number): Promise<Uint8Array<ArrayBuffer>>;
|
|
16
|
+
export class Blockstore extends MemoryBlockstore {
|
|
17
|
+
/**
|
|
18
|
+
* @param {import('../src/api.js').ShardLink} cid
|
|
19
|
+
*/
|
|
20
|
+
getShardBlock(cid: import("../src/api.js").ShardLink): Promise<API.ShardBlockView>;
|
|
21
|
+
}
|
|
22
|
+
export function vis(blocks: API.BlockFetcher, root: API.ShardLink): Promise<void>;
|
|
23
|
+
export function materialize(blocks: API.BlockFetcher, root: API.ShardLink): Promise<any[]>;
|
|
24
|
+
export function putAll(blocks: Blockstore, root: API.ShardLink, items: Array<[string, API.UnknownLink]>): Promise<{
|
|
25
|
+
root: API.ShardLink;
|
|
26
|
+
}>;
|
|
27
|
+
export function verify(blocks: MemoryBlockstore, root: API.ShardLink, data: Map<string, API.UnknownLink>): Promise<void>;
|
|
28
|
+
export function clockVis<T>(blocks: API.BlockFetcher, head: ClockAPI.EventLink<T>[], options?: {
|
|
29
|
+
renderNodeLabel?: ((b: ClockAPI.EventBlockView<T>) => string) | undefined;
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
import * as Link from 'multiformats/link';
|
|
32
|
+
import { MemoryBlockstore } from '../src/block.js';
|
|
33
|
+
import * as API from '../src/api.js';
|
|
34
|
+
import * as ClockAPI from '../src/clock/api.js';
|
|
35
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../test/helpers.js"],"names":[],"mappings":"AAcA;;;GAGG;AACH,mCAHW,MAAM,OACN,MAAM,UAMhB;AAID;;GAEG;AACH,mCAFW,MAAM,6BAQhB;AAED,6DAA6D;AAC7D,iCADY,MAAM,sCAIjB;AAyGD;;GAEG;AACH,kCAFW,MAAM,oCAahB;AArHD;IACE;;OAEG;IACH,mBAFW,OAAO,eAAe,EAAE,SAAS,+BAM3C;CACF;AAMM,4BAHI,GAAG,CAAC,YAAY,QAChB,GAAG,CAAC,SAAS,iBA8BvB;AAMM,oCAHI,GAAG,CAAC,YAAY,QAChB,GAAG,CAAC,SAAS,kBAkBvB;AAOM,+BAJI,UAAU,QACV,GAAG,CAAC,SAAS,SACb,KAAK,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;;GAc1C;AAOM,+BAJI,gBAAgB,QAChB,GAAG,CAAC,SAAS,QACb,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,iBAYtC;AAyBM,yBANM,CAAC,UACH,GAAG,CAAC,YAAY,QAChB,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,YAE/B;IAA4D,eAAe,QAA/D,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM;CAA2B,iBAQ9E;sBA/KqB,mBAAmB;iCAUR,iBAAiB;qBAJ7B,eAAe;0BAEV,qBAAqB"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import * as Link from 'multiformats/link';
|
|
2
|
+
import * as raw from 'multiformats/codecs/raw';
|
|
3
|
+
import { sha256 } from 'multiformats/hashes/sha2';
|
|
4
|
+
import clc from 'cli-color';
|
|
5
|
+
import archy from 'archy';
|
|
6
|
+
// eslint-disable-next-line no-unused-vars
|
|
7
|
+
import * as API from '../src/api.js';
|
|
8
|
+
// eslint-disable-next-line no-unused-vars
|
|
9
|
+
import * as ClockAPI from '../src/clock/api.js';
|
|
10
|
+
import { ShardFetcher, decodeBlock } from '../src/shard.js';
|
|
11
|
+
import { MemoryBlockstore } from '../src/block.js';
|
|
12
|
+
import { entries, get, put } from '../src/index.js';
|
|
13
|
+
import * as Clock from '../src/clock/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* @param {number} min
|
|
16
|
+
* @param {number} max
|
|
17
|
+
*/
|
|
18
|
+
export function randomInteger(min, max) {
|
|
19
|
+
min = Math.ceil(min);
|
|
20
|
+
max = Math.floor(max);
|
|
21
|
+
return Math.floor(Math.random() * (max - min) + min);
|
|
22
|
+
}
|
|
23
|
+
const Alphabet = 'abcdefghijklmnopqrstuvwxyz-/_';
|
|
24
|
+
/**
|
|
25
|
+
* @param {number} size
|
|
26
|
+
*/
|
|
27
|
+
export function randomString(size, alphabet = Alphabet) {
|
|
28
|
+
let str = '';
|
|
29
|
+
while (str.length < size) {
|
|
30
|
+
str += alphabet[randomInteger(0, alphabet.length)];
|
|
31
|
+
}
|
|
32
|
+
return str;
|
|
33
|
+
}
|
|
34
|
+
/** @param {number} [size] Number of random bytes to hash. */
|
|
35
|
+
export async function randomCID(size = 32) {
|
|
36
|
+
const hash = await sha256.digest(await randomBytes(size));
|
|
37
|
+
return Link.create(raw.code, hash);
|
|
38
|
+
}
|
|
39
|
+
export class Blockstore extends MemoryBlockstore {
|
|
40
|
+
/**
|
|
41
|
+
* @param {import('../src/api.js').ShardLink} cid
|
|
42
|
+
*/
|
|
43
|
+
async getShardBlock(cid) {
|
|
44
|
+
const blk = await this.get(cid);
|
|
45
|
+
assert(blk);
|
|
46
|
+
return decodeBlock(blk.bytes);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* @param {API.BlockFetcher} blocks Block storage.
|
|
51
|
+
* @param {API.ShardLink} root
|
|
52
|
+
*/
|
|
53
|
+
export const vis = async (blocks, root) => {
|
|
54
|
+
const shards = new ShardFetcher(blocks);
|
|
55
|
+
const rshard = await shards.get(root);
|
|
56
|
+
/** @type {archy.Data} */
|
|
57
|
+
const archyRoot = { label: `Shard(${clc.yellow(rshard.cid.toString())}) ${rshard.bytes.length + 'b'}`, nodes: [] };
|
|
58
|
+
/** @param {API.ShardEntry} entry */
|
|
59
|
+
const getData = async ([k, v]) => {
|
|
60
|
+
if (!Array.isArray(v)) {
|
|
61
|
+
return { label: `Key(${clc.magenta(k)})`, nodes: [{ label: `Value(${clc.cyan(v)})` }] };
|
|
62
|
+
}
|
|
63
|
+
/** @type {archy.Data} */
|
|
64
|
+
const data = { label: `Key(${clc.magenta(k)})`, nodes: [] };
|
|
65
|
+
if (v[1])
|
|
66
|
+
data.nodes?.push({ label: `Value(${clc.cyan(v[1])})` });
|
|
67
|
+
const blk = await shards.get(v[0]);
|
|
68
|
+
data.nodes?.push({
|
|
69
|
+
label: `Shard(${clc.yellow(v[0])}) ${blk.bytes.length + 'b'}`,
|
|
70
|
+
nodes: await Promise.all(blk.value.entries.map(e => getData(e)))
|
|
71
|
+
});
|
|
72
|
+
return data;
|
|
73
|
+
};
|
|
74
|
+
for (const entry of rshard.value.entries) {
|
|
75
|
+
archyRoot.nodes?.push(await getData(entry));
|
|
76
|
+
}
|
|
77
|
+
console.log(archy(archyRoot));
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* @param {API.BlockFetcher} blocks
|
|
81
|
+
* @param {API.ShardLink} root
|
|
82
|
+
*/
|
|
83
|
+
export const materialize = async (blocks, root) => {
|
|
84
|
+
const shards = new ShardFetcher(blocks);
|
|
85
|
+
const shard = await shards.get(root);
|
|
86
|
+
/** @type {any[]} */
|
|
87
|
+
const entries = [];
|
|
88
|
+
for (const e of shard.value.entries) {
|
|
89
|
+
if (Array.isArray(e[1])) {
|
|
90
|
+
const v = [...e[1]];
|
|
91
|
+
// @ts-expect-error
|
|
92
|
+
v[0] = await materialize(blocks, e[1][0]);
|
|
93
|
+
entries.push([e[0], v]);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
entries.push([...e]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return entries;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* @param {Blockstore} blocks
|
|
103
|
+
* @param {API.ShardLink} root
|
|
104
|
+
* @param {Array<[string, API.UnknownLink]>} items
|
|
105
|
+
*/
|
|
106
|
+
export const putAll = async (blocks, root, items) => {
|
|
107
|
+
for (const [k, v] of items) {
|
|
108
|
+
const res = await put(blocks, root, k, v);
|
|
109
|
+
for (const b of res.additions) {
|
|
110
|
+
blocks.putSync(b.cid, b.bytes);
|
|
111
|
+
}
|
|
112
|
+
for (const b of res.removals) {
|
|
113
|
+
blocks.deleteSync(b.cid);
|
|
114
|
+
}
|
|
115
|
+
root = res.root;
|
|
116
|
+
}
|
|
117
|
+
return { root };
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* @param {MemoryBlockstore} blocks
|
|
121
|
+
* @param {API.ShardLink} root
|
|
122
|
+
* @param {Map<string, API.UnknownLink>} data
|
|
123
|
+
*/
|
|
124
|
+
export const verify = async (blocks, root, data) => {
|
|
125
|
+
for (const [k, v] of data) {
|
|
126
|
+
const result = await get(blocks, root, k);
|
|
127
|
+
if (!result)
|
|
128
|
+
throw new Error(`missing item: "${k}": ${v}`);
|
|
129
|
+
if (result.toString() !== v.toString())
|
|
130
|
+
throw new Error(`incorrect value for ${k}: ${result} !== ${v}`);
|
|
131
|
+
}
|
|
132
|
+
let total = 0;
|
|
133
|
+
// eslint-disable-next-line no-unused-vars
|
|
134
|
+
for await (const _ of entries(blocks, root))
|
|
135
|
+
total++;
|
|
136
|
+
if (data.size !== total)
|
|
137
|
+
throw new Error(`incorrect entry count: ${total} !== ${data.size}`);
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* @param {number} size
|
|
141
|
+
*/
|
|
142
|
+
export async function randomBytes(size) {
|
|
143
|
+
/** @type {{getRandomValues: (u: Uint8Array) => Uint8Array}} */
|
|
144
|
+
let myCrypto;
|
|
145
|
+
if ('crypto' in globalThis && 'getRandomValues' in globalThis.crypto) {
|
|
146
|
+
myCrypto = globalThis.crypto;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
myCrypto = await import('node:crypto');
|
|
150
|
+
}
|
|
151
|
+
const bytes = new Uint8Array(size);
|
|
152
|
+
myCrypto.getRandomValues(bytes);
|
|
153
|
+
return bytes;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* @template T
|
|
157
|
+
* @param {API.BlockFetcher} blocks Block storage.
|
|
158
|
+
* @param {ClockAPI.EventLink<T>[]} head
|
|
159
|
+
* @param {object} [options]
|
|
160
|
+
* @param {(b: ClockAPI.EventBlockView<T>) => string} [options.renderNodeLabel]
|
|
161
|
+
*/
|
|
162
|
+
export const clockVis = async (blocks, head, options) => {
|
|
163
|
+
const lines = [];
|
|
164
|
+
for await (const line of Clock.vis(blocks, head, options)) {
|
|
165
|
+
lines.push(line);
|
|
166
|
+
}
|
|
167
|
+
console.log(lines.join('\n'));
|
|
168
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"put.test.d.ts","sourceRoot":"","sources":["../../test/put.test.js"],"names":[],"mappings":""}
|