@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.
Files changed (106) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +208 -0
  4. package/dist/scripts/randomcid.d.ts +2 -0
  5. package/dist/scripts/randomcid.d.ts.map +1 -0
  6. package/dist/scripts/randomcid.js +10 -0
  7. package/dist/scripts/words/gen.d.ts +2 -0
  8. package/dist/scripts/words/gen.d.ts.map +1 -0
  9. package/dist/scripts/words/gen.js +51 -0
  10. package/dist/src/api.d.ts +4 -2
  11. package/dist/src/api.d.ts.map +1 -1
  12. package/dist/src/api.js +1 -0
  13. package/dist/src/batch/api.d.ts +2 -2
  14. package/dist/src/batch/api.d.ts.map +1 -1
  15. package/dist/src/batch/api.js +1 -0
  16. package/dist/src/batch/index.d.ts +1 -53
  17. package/dist/src/batch/index.d.ts.map +1 -1
  18. package/dist/src/batch/index.js +241 -0
  19. package/dist/src/batch/shard.d.ts +1 -1
  20. package/dist/src/batch/shard.d.ts.map +1 -1
  21. package/dist/src/batch/shard.js +12 -0
  22. package/dist/src/block.d.ts +2 -2
  23. package/dist/src/block.d.ts.map +1 -1
  24. package/dist/src/block.js +66 -0
  25. package/dist/src/clock/api.d.ts +1 -1
  26. package/dist/src/clock/api.d.ts.map +1 -1
  27. package/dist/src/clock/api.js +1 -0
  28. package/dist/src/clock/index.d.ts +2 -2
  29. package/dist/src/clock/index.d.ts.map +1 -1
  30. package/dist/src/clock/index.js +199 -0
  31. package/dist/src/crdt/api.d.ts +1 -1
  32. package/dist/src/crdt/api.d.ts.map +1 -1
  33. package/dist/src/crdt/api.js +1 -0
  34. package/dist/src/crdt/batch/api.d.ts +1 -1
  35. package/dist/src/crdt/batch/api.d.ts.map +1 -1
  36. package/dist/src/crdt/batch/api.js +1 -0
  37. package/dist/src/crdt/batch/index.d.ts.map +1 -1
  38. package/dist/src/crdt/batch/index.js +140 -0
  39. package/dist/src/crdt/index.d.ts +2 -2
  40. package/dist/src/crdt/index.d.ts.map +1 -1
  41. package/dist/src/crdt/index.js +344 -0
  42. package/dist/src/diff.d.ts +3 -3
  43. package/dist/src/diff.d.ts.map +1 -1
  44. package/dist/src/diff.js +151 -0
  45. package/dist/src/index.d.ts +1 -1
  46. package/dist/src/index.d.ts.map +1 -1
  47. package/dist/src/index.js +356 -0
  48. package/dist/src/merge.d.ts.map +1 -1
  49. package/dist/src/merge.js +42 -0
  50. package/dist/src/shard.d.ts +4 -4
  51. package/dist/src/shard.d.ts.map +1 -1
  52. package/dist/src/shard.js +166 -0
  53. package/dist/test/batch.test.d.ts +2 -0
  54. package/dist/test/batch.test.d.ts.map +1 -0
  55. package/dist/test/batch.test.js +126 -0
  56. package/dist/test/clock.test.d.ts +2 -0
  57. package/dist/test/clock.test.d.ts.map +1 -0
  58. package/dist/test/clock.test.js +244 -0
  59. package/dist/test/crdt.test.d.ts +2 -0
  60. package/dist/test/crdt.test.d.ts.map +1 -0
  61. package/dist/test/crdt.test.js +271 -0
  62. package/dist/test/del.test.d.ts +2 -0
  63. package/dist/test/del.test.d.ts.map +1 -0
  64. package/dist/test/del.test.js +21 -0
  65. package/dist/test/diff.test.d.ts +2 -0
  66. package/dist/test/diff.test.d.ts.map +1 -0
  67. package/dist/test/diff.test.js +38 -0
  68. package/dist/test/entries.test.d.ts +2 -0
  69. package/dist/test/entries.test.d.ts.map +1 -0
  70. package/dist/test/entries.test.js +210 -0
  71. package/dist/test/get.test.d.ts +2 -0
  72. package/dist/test/get.test.d.ts.map +1 -0
  73. package/dist/test/get.test.js +26 -0
  74. package/dist/test/helpers.d.ts +35 -0
  75. package/dist/test/helpers.d.ts.map +1 -0
  76. package/dist/test/helpers.js +168 -0
  77. package/dist/test/put.test.d.ts +2 -0
  78. package/dist/test/put.test.d.ts.map +1 -0
  79. package/dist/test/put.test.js +165 -0
  80. package/dist/tsconfig.tsbuildinfo +1 -1
  81. package/dist/vitest.config.d.ts +3 -0
  82. package/dist/vitest.config.d.ts.map +1 -0
  83. package/dist/vitest.config.js +13 -0
  84. package/package.json +49 -94
  85. package/scripts/propernames/gen.sh +3 -0
  86. package/cli.js +0 -218
  87. package/src/api.js +0 -1
  88. package/src/api.ts +0 -90
  89. package/src/batch/api.js +0 -1
  90. package/src/batch/api.ts +0 -59
  91. package/src/batch/index.js +0 -258
  92. package/src/batch/shard.js +0 -13
  93. package/src/block.js +0 -75
  94. package/src/clock/api.js +0 -1
  95. package/src/clock/api.ts +0 -12
  96. package/src/clock/index.js +0 -182
  97. package/src/crdt/api.js +0 -1
  98. package/src/crdt/api.ts +0 -33
  99. package/src/crdt/batch/api.js +0 -1
  100. package/src/crdt/batch/api.ts +0 -30
  101. package/src/crdt/batch/index.js +0 -155
  102. package/src/crdt/index.js +0 -354
  103. package/src/diff.js +0 -151
  104. package/src/index.js +0 -406
  105. package/src/merge.js +0 -43
  106. 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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=diff.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=entries.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=get.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=put.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"put.test.d.ts","sourceRoot":"","sources":["../../test/put.test.js"],"names":[],"mappings":""}