@fireproof/vendor 2.0.2 → 3.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.
Files changed (73) hide show
  1. package/package.json +6 -60
  2. package/src/p-limit/index.d.ts +81 -0
  3. package/src/p-limit/index.js +104 -0
  4. package/src/p-limit/license +9 -0
  5. package/src/p-limit/readme.md +129 -0
  6. package/src/@web3-storage/pail/LICENSE.md +0 -232
  7. package/src/@web3-storage/pail/README.md +0 -84
  8. package/src/@web3-storage/pail/cli.js +0 -218
  9. package/src/@web3-storage/pail/dist/src/api.d.ts +0 -61
  10. package/src/@web3-storage/pail/dist/src/api.d.ts.map +0 -1
  11. package/src/@web3-storage/pail/dist/src/api.js +0 -1
  12. package/src/@web3-storage/pail/dist/src/batch/api.d.ts +0 -31
  13. package/src/@web3-storage/pail/dist/src/batch/api.d.ts.map +0 -1
  14. package/src/@web3-storage/pail/dist/src/batch/api.js +0 -1
  15. package/src/@web3-storage/pail/dist/src/batch/index.d.ts +0 -23
  16. package/src/@web3-storage/pail/dist/src/batch/index.d.ts.map +0 -1
  17. package/src/@web3-storage/pail/dist/src/batch/index.js +0 -241
  18. package/src/@web3-storage/pail/dist/src/batch/shard.d.ts +0 -3
  19. package/src/@web3-storage/pail/dist/src/batch/shard.d.ts.map +0 -1
  20. package/src/@web3-storage/pail/dist/src/batch/shard.js +0 -12
  21. package/src/@web3-storage/pail/dist/src/block.d.ts +0 -35
  22. package/src/@web3-storage/pail/dist/src/block.d.ts.map +0 -1
  23. package/src/@web3-storage/pail/dist/src/block.js +0 -66
  24. package/src/@web3-storage/pail/dist/src/clock/api.d.ts +0 -10
  25. package/src/@web3-storage/pail/dist/src/clock/api.d.ts.map +0 -1
  26. package/src/@web3-storage/pail/dist/src/clock/api.js +0 -1
  27. package/src/@web3-storage/pail/dist/src/clock/index.d.ts +0 -48
  28. package/src/@web3-storage/pail/dist/src/clock/index.d.ts.map +0 -1
  29. package/src/@web3-storage/pail/dist/src/clock/index.js +0 -178
  30. package/src/@web3-storage/pail/dist/src/crdt/api.d.ts +0 -26
  31. package/src/@web3-storage/pail/dist/src/crdt/api.d.ts.map +0 -1
  32. package/src/@web3-storage/pail/dist/src/crdt/api.js +0 -1
  33. package/src/@web3-storage/pail/dist/src/crdt/batch/api.d.ts +0 -11
  34. package/src/@web3-storage/pail/dist/src/crdt/batch/api.d.ts.map +0 -1
  35. package/src/@web3-storage/pail/dist/src/crdt/batch/api.js +0 -1
  36. package/src/@web3-storage/pail/dist/src/crdt/batch/index.d.ts +0 -5
  37. package/src/@web3-storage/pail/dist/src/crdt/batch/index.d.ts.map +0 -1
  38. package/src/@web3-storage/pail/dist/src/crdt/batch/index.js +0 -140
  39. package/src/@web3-storage/pail/dist/src/crdt/index.d.ts +0 -9
  40. package/src/@web3-storage/pail/dist/src/crdt/index.d.ts.map +0 -1
  41. package/src/@web3-storage/pail/dist/src/crdt/index.js +0 -344
  42. package/src/@web3-storage/pail/dist/src/diff.d.ts +0 -13
  43. package/src/@web3-storage/pail/dist/src/diff.d.ts.map +0 -1
  44. package/src/@web3-storage/pail/dist/src/diff.js +0 -151
  45. package/src/@web3-storage/pail/dist/src/index.d.ts +0 -10
  46. package/src/@web3-storage/pail/dist/src/index.d.ts.map +0 -1
  47. package/src/@web3-storage/pail/dist/src/index.js +0 -356
  48. package/src/@web3-storage/pail/dist/src/merge.d.ts +0 -5
  49. package/src/@web3-storage/pail/dist/src/merge.d.ts.map +0 -1
  50. package/src/@web3-storage/pail/dist/src/merge.js +0 -42
  51. package/src/@web3-storage/pail/dist/src/shard.d.ts +0 -43
  52. package/src/@web3-storage/pail/dist/src/shard.d.ts.map +0 -1
  53. package/src/@web3-storage/pail/dist/src/shard.js +0 -166
  54. package/src/@web3-storage/pail/dist/tsconfig.tsbuildinfo +0 -1
  55. package/src/@web3-storage/pail/src/api.ts +0 -92
  56. package/src/@web3-storage/pail/src/batch/api.js +0 -1
  57. package/src/@web3-storage/pail/src/batch/api.ts +0 -59
  58. package/src/@web3-storage/pail/src/batch/index.js +0 -258
  59. package/src/@web3-storage/pail/src/batch/shard.js +0 -13
  60. package/src/@web3-storage/pail/src/block.js +0 -75
  61. package/src/@web3-storage/pail/src/clock/api.js +0 -1
  62. package/src/@web3-storage/pail/src/clock/api.ts +0 -12
  63. package/src/@web3-storage/pail/src/clock/index.js +0 -182
  64. package/src/@web3-storage/pail/src/crdt/api.js +0 -1
  65. package/src/@web3-storage/pail/src/crdt/api.ts +0 -33
  66. package/src/@web3-storage/pail/src/crdt/batch/api.js +0 -1
  67. package/src/@web3-storage/pail/src/crdt/batch/api.ts +0 -30
  68. package/src/@web3-storage/pail/src/crdt/batch/index.js +0 -155
  69. package/src/@web3-storage/pail/src/crdt/index.js +0 -354
  70. package/src/@web3-storage/pail/src/diff.js +0 -151
  71. package/src/@web3-storage/pail/src/index.js +0 -406
  72. package/src/@web3-storage/pail/src/merge.js +0 -43
  73. package/src/@web3-storage/pail/src/shard.js +0 -180
@@ -1,406 +0,0 @@
1
- // eslint-disable-next-line no-unused-vars
2
- import * as API from './api.js'
3
- import { ShardFetcher, isPrintableASCII } from './shard.js'
4
- import * as Shard from './shard.js'
5
-
6
- /**
7
- * Put a value (a CID) for the given key. If the key exists it's value is
8
- * overwritten.
9
- *
10
- * @param {API.BlockFetcher} blocks Bucket block storage.
11
- * @param {API.ShardLink} root CID of the root node of the bucket.
12
- * @param {string} key The key of the value to put.
13
- * @param {API.UnknownLink} value The value to put.
14
- * @returns {Promise<{ root: API.ShardLink } & API.ShardDiff>}
15
- */
16
- export const put = async (blocks, root, key, value) => {
17
- const shards = new ShardFetcher(blocks)
18
- const rshard = await shards.get(root)
19
-
20
- if (rshard.value.keyChars !== Shard.KeyCharsASCII) {
21
- throw new Error(`unsupported key character set: ${rshard.value.keyChars}`)
22
- }
23
- if (!isPrintableASCII(key)) {
24
- throw new Error('key contains non-ASCII characters')
25
- }
26
- // ensure utf8 encoded key is smaller than max
27
- if (new TextEncoder().encode(key).length > rshard.value.maxKeySize) {
28
- throw new Error(`UTF-8 encoded key exceeds max size of ${rshard.value.maxKeySize} bytes`)
29
- }
30
-
31
- const path = await traverse(shards, rshard, key)
32
- const target = path[path.length - 1]
33
- const skey = key.slice(target.value.prefix.length) // key within the shard
34
-
35
- /** @type {API.ShardEntry} */
36
- let entry = [skey, value]
37
- let targetEntries = [...target.value.entries]
38
-
39
- /** @type {API.ShardBlockView[]} */
40
- const additions = []
41
-
42
- for (const [i, e] of targetEntries.entries()) {
43
- const [k, v] = e
44
-
45
- // is this just a replace?
46
- if (k === skey) break
47
-
48
- // do we need to shard this entry?
49
- const shortest = k.length < skey.length ? k : skey
50
- const other = shortest === k ? skey : k
51
- let common = ''
52
- for (const char of shortest) {
53
- const next = common + char
54
- if (!other.startsWith(next)) break
55
- common = next
56
- }
57
- if (common.length) {
58
- /** @type {API.ShardEntry[]} */
59
- let entries = []
60
-
61
- // if the existing entry key or new key is equal to the common prefix,
62
- // then the existing value / new value needs to persist in the parent
63
- // shard. Otherwise they persist in this new shard.
64
- if (common !== skey) {
65
- entries = Shard.putEntry(entries, [skey.slice(common.length), value])
66
- }
67
- if (common !== k) {
68
- entries = Shard.putEntry(entries, [k.slice(common.length), v])
69
- }
70
-
71
- let child = await Shard.encodeBlock(
72
- Shard.withEntries(entries, { ...target.value, prefix: target.value.prefix + common })
73
- )
74
- additions.push(child)
75
-
76
- // need to spread as access by index does not consider utf-16 surrogates
77
- const commonChars = [...common]
78
-
79
- // create parent shards for each character of the common prefix
80
- for (let i = commonChars.length - 1; i > 0; i--) {
81
- const parentConfig = { ...target.value, prefix: target.value.prefix + commonChars.slice(0, i).join('') }
82
- /** @type {API.ShardEntryLinkValue | API.ShardEntryValueValue | API.ShardEntryLinkAndValueValue} */
83
- let parentValue
84
- // if the first iteration and the existing entry key is equal to the
85
- // common prefix, then existing value needs to persist in this parent
86
- if (i === commonChars.length - 1 && common === k) {
87
- if (Array.isArray(v)) throw new Error('found a shard link when expecting a value')
88
- parentValue = [child.cid, v]
89
- } else if (i === commonChars.length - 1 && common === skey) {
90
- parentValue = [child.cid, value]
91
- } else {
92
- parentValue = [child.cid]
93
- }
94
- const parent = await Shard.encodeBlock(Shard.withEntries([[commonChars[i], parentValue]], parentConfig))
95
- additions.push(parent)
96
- child = parent
97
- }
98
-
99
- // remove the sharded entry
100
- targetEntries.splice(i, 1)
101
-
102
- // create the entry that will be added to target
103
- if (commonChars.length === 1 && common === k) {
104
- if (Array.isArray(v)) throw new Error('found a shard link when expecting a value')
105
- entry = [commonChars[0], [child.cid, v]]
106
- } else if (commonChars.length === 1 && common === skey) {
107
- entry = [commonChars[0], [child.cid, value]]
108
- } else {
109
- entry = [commonChars[0], [child.cid]]
110
- }
111
- break
112
- }
113
- }
114
-
115
- const shard = Shard.withEntries(Shard.putEntry(targetEntries, entry), target.value)
116
- let child = await Shard.encodeBlock(shard)
117
-
118
- // if no change in the target then we're done
119
- if (child.cid.toString() === target.cid.toString()) {
120
- return { root, additions: [], removals: [] }
121
- }
122
-
123
- additions.push(child)
124
-
125
- // path is root -> target, so work backwards, propagating the new shard CID
126
- for (let i = path.length - 2; i >= 0; i--) {
127
- const parent = path[i]
128
- const key = child.value.prefix.slice(parent.value.prefix.length)
129
- const value = Shard.withEntries(
130
- parent.value.entries.map((entry) => {
131
- const [k, v] = entry
132
- if (k !== key) return entry
133
- if (!Array.isArray(v)) throw new Error(`"${key}" is not a shard link in: ${parent.cid}`)
134
- return /** @type {API.ShardEntry} */(v[1] == null ? [k, [child.cid]] : [k, [child.cid, v[1]]])
135
- }),
136
- parent.value
137
- )
138
-
139
- child = await Shard.encodeBlock(value)
140
- additions.push(child)
141
- }
142
-
143
- return { root: additions[additions.length - 1].cid, additions, removals: path }
144
- }
145
-
146
- /**
147
- * Get the stored value for the given key from the bucket. If the key is not
148
- * found, `undefined` is returned.
149
- *
150
- * @param {API.BlockFetcher} blocks Bucket block storage.
151
- * @param {API.ShardLink} root CID of the root node of the bucket.
152
- * @param {string} key The key of the value to get.
153
- * @returns {Promise<API.UnknownLink | undefined>}
154
- */
155
- export const get = async (blocks, root, key) => {
156
- const shards = new ShardFetcher(blocks)
157
- const rshard = await shards.get(root)
158
- const path = await traverse(shards, rshard, key)
159
- const target = path[path.length - 1]
160
- const skey = key.slice(target.value.prefix.length) // key within the shard
161
- const entry = target.value.entries.find(([k]) => k === skey)
162
- if (!entry) return
163
- return Array.isArray(entry[1]) ? entry[1][1] : entry[1]
164
- }
165
-
166
- /**
167
- * Delete the value for the given key from the bucket. If the key is not found
168
- * no operation occurs.
169
- *
170
- * @param {API.BlockFetcher} blocks Bucket block storage.
171
- * @param {API.ShardLink} root CID of the root node of the bucket.
172
- * @param {string} key The key of the value to delete.
173
- * @returns {Promise<{ root: API.ShardLink } & API.ShardDiff>}
174
- */
175
- export const del = async (blocks, root, key) => {
176
- const shards = new ShardFetcher(blocks)
177
- const rshard = await shards.get(root)
178
- const path = await traverse(shards, rshard, key)
179
- const target = path[path.length - 1]
180
- const skey = key.slice(target.value.prefix.length) // key within the shard
181
-
182
- const entryidx = target.value.entries.findIndex(([k]) => k === skey)
183
- if (entryidx === -1) return { root, additions: [], removals: [] }
184
-
185
- const entry = target.value.entries[entryidx]
186
- // cannot delete a shard (without data)
187
- if (Array.isArray(entry[1]) && entry[1][1] == null) {
188
- return { root, additions: [], removals: [] }
189
- }
190
-
191
- /** @type {API.ShardBlockView[]} */
192
- const additions = []
193
- /** @type {API.ShardBlockView[]} */
194
- const removals = [...path]
195
-
196
- let shard = Shard.withEntries([...target.value.entries], target.value)
197
-
198
- if (Array.isArray(entry[1])) {
199
- // remove the value from this link+value
200
- shard.entries[entryidx] = [entry[0], [entry[1][0]]]
201
- } else {
202
- shard.entries.splice(entryidx, 1)
203
- // if now empty, remove from parent
204
- while (!shard.entries.length) {
205
- const child = path[path.length - 1]
206
- const parent = path[path.length - 2]
207
- if (!parent) break
208
- path.pop()
209
- shard = Shard.withEntries(
210
- parent.value.entries.filter(e => {
211
- if (!Array.isArray(e[1])) return true
212
- return e[1][0].toString() !== child.cid.toString()
213
- }),
214
- parent.value
215
- )
216
- }
217
- }
218
-
219
- let child = await Shard.encodeBlock(shard)
220
- additions.push(child)
221
-
222
- // path is root -> shard, so work backwards, propagating the new shard CID
223
- for (let i = path.length - 2; i >= 0; i--) {
224
- const parent = path[i]
225
- const key = child.value.prefix.slice(parent.value.prefix.length)
226
- const value = Shard.withEntries(
227
- parent.value.entries.map((entry) => {
228
- const [k, v] = entry
229
- if (k !== key) return entry
230
- if (!Array.isArray(v)) throw new Error(`"${key}" is not a shard link in: ${parent.cid}`)
231
- return /** @type {API.ShardEntry} */(v[1] == null ? [k, [child.cid]] : [k, [child.cid, v[1]]])
232
- }),
233
- parent.value
234
- )
235
-
236
- child = await Shard.encodeBlock(value)
237
- additions.push(child)
238
- }
239
-
240
- return { root: additions[additions.length - 1].cid, additions, removals }
241
- }
242
-
243
- /**
244
- * @param {API.EntriesOptions} [options]
245
- * @returns {options is API.KeyPrefixOption}
246
- */
247
- const isKeyPrefixOption = options => {
248
- const opts = options ?? {}
249
- return 'prefix' in opts && Boolean(opts.prefix)
250
- }
251
-
252
- /**
253
- * @param {API.EntriesOptions} [options]
254
- * @returns {options is API.KeyRangeOption}
255
- */
256
- const isKeyRangeOption = options => {
257
- const opts = options ?? {}
258
- return ('gt' in opts && Boolean(opts.gt)) || ('gte' in opts && Boolean(opts.gte)) || ('lt' in opts && Boolean(opts.lt)) || ('lte' in opts && Boolean(opts.lte))
259
- }
260
-
261
- /**
262
- * @param {API.KeyRangeOption} options
263
- * @returns {options is API.KeyLowerBoundRangeOption}
264
- */
265
- const isKeyLowerBoundRangeOption = options => ('gt' in options && Boolean(options.gt)) || ('gte' in options && Boolean(options.gte))
266
-
267
- /**
268
- * @param {API.KeyLowerBoundRangeOption} options
269
- * @returns {options is API.KeyLowerBoundRangeInclusiveOption}
270
- */
271
- const isKeyLowerBoundRangeInclusiveOption = options => 'gte' in options && Boolean(options.gte)
272
-
273
- /**
274
- * @param {API.KeyLowerBoundRangeOption} options
275
- * @returns {options is API.KeyLowerBoundRangeExclusiveOption}
276
- */
277
- const isKeyLowerBoundRangeExclusiveOption = options => 'gt' in options && Boolean(options.gt)
278
-
279
- /**
280
- * @param {API.KeyRangeOption} options
281
- * @returns {options is API.KeyUpperBoundRangeOption}
282
- */
283
- const isKeyUpperBoundRangeOption = options => ('lt' in options && Boolean(options.lt)) || ('lte' in options && Boolean(options.lte))
284
-
285
- /**
286
- * @param {API.KeyUpperBoundRangeOption} options
287
- * @returns {options is API.KeyUpperBoundRangeInclusiveOption}
288
- */
289
- const isKeyUpperBoundRangeInclusiveOption = options => 'lte' in options && Boolean(options.lte)
290
-
291
- /**
292
- * @param {API.KeyUpperBoundRangeOption} options
293
- * @returns {options is API.KeyUpperBoundRangeExclusiveOption}
294
- */
295
- const isKeyUpperBoundRangeExclusiveOption = options => 'lt' in options && Boolean(options.lt)
296
-
297
- /**
298
- * List entries in the bucket.
299
- *
300
- * @param {API.BlockFetcher} blocks Bucket block storage.
301
- * @param {API.ShardLink} root CID of the root node of the bucket.
302
- * @param {API.EntriesOptions} [options]
303
- * @returns {AsyncIterableIterator<API.ShardValueEntry>}
304
- */
305
- export const entries = async function * (blocks, root, options) {
306
- const hasKeyPrefix = isKeyPrefixOption(options)
307
- const hasKeyRange = isKeyRangeOption(options)
308
- const hasKeyLowerBoundRange = hasKeyRange && isKeyLowerBoundRangeOption(options)
309
- const hasKeyLowerBoundRangeInclusive = hasKeyLowerBoundRange && isKeyLowerBoundRangeInclusiveOption(options)
310
- const hasKeyLowerBoundRangeExclusive = hasKeyLowerBoundRange && isKeyLowerBoundRangeExclusiveOption(options)
311
- const hasKeyUpperBoundRange = hasKeyRange && isKeyUpperBoundRangeOption(options)
312
- const hasKeyUpperBoundRangeInclusive = hasKeyUpperBoundRange && isKeyUpperBoundRangeInclusiveOption(options)
313
- const hasKeyUpperBoundRangeExclusive = hasKeyUpperBoundRange && isKeyUpperBoundRangeExclusiveOption(options)
314
- const hasKeyUpperAndLowerBoundRange = hasKeyLowerBoundRange && hasKeyUpperBoundRange
315
-
316
- const shards = new ShardFetcher(blocks)
317
- const rshard = await shards.get(root)
318
-
319
- yield * (
320
- /** @returns {AsyncIterableIterator<API.ShardValueEntry>} */
321
- (async function* ents(shard) {
322
- for (const entry of shard.value.entries) {
323
- const key = shard.value.prefix + entry[0]
324
-
325
- // if array, this is a link to a shard
326
- if (Array.isArray(entry[1])) {
327
- if (entry[1][1]) {
328
- if (
329
- (hasKeyPrefix && key.startsWith(options.prefix)) ||
330
- (hasKeyUpperAndLowerBoundRange && (
331
- ((hasKeyLowerBoundRangeExclusive && key > options.gt) || (hasKeyLowerBoundRangeInclusive && key >= options.gte)) &&
332
- ((hasKeyUpperBoundRangeExclusive && key < options.lt) || (hasKeyUpperBoundRangeInclusive && key <= options.lte))
333
- )) ||
334
- (hasKeyLowerBoundRangeExclusive && key > options.gt) ||
335
- (hasKeyLowerBoundRangeInclusive && key >= options.gte) ||
336
- (hasKeyUpperBoundRangeExclusive && key < options.lt) ||
337
- (hasKeyUpperBoundRangeInclusive && key <= options.lte) ||
338
- (!hasKeyPrefix && !hasKeyRange)
339
- ) {
340
- yield [key, entry[1][1]]
341
- }
342
- }
343
-
344
- if (hasKeyPrefix) {
345
- if (options.prefix.length <= key.length && !key.startsWith(options.prefix)) {
346
- continue
347
- }
348
- if (options.prefix.length > key.length && !options.prefix.startsWith(key)) {
349
- continue
350
- }
351
- } else if (
352
- (hasKeyLowerBoundRangeExclusive && (trunc(key, Math.min(key.length, options.gt.length)) < trunc(options.gt, Math.min(key.length, options.gt.length)))) ||
353
- (hasKeyLowerBoundRangeInclusive && (trunc(key, Math.min(key.length, options.gte.length)) < trunc(options.gte, Math.min(key.length, options.gte.length)))) ||
354
- (hasKeyUpperBoundRangeExclusive && (trunc(key, Math.min(key.length, options.lt.length)) > trunc(options.lt, Math.min(key.length, options.lt.length)))) ||
355
- (hasKeyUpperBoundRangeInclusive && (trunc(key, Math.min(key.length, options.lte.length)) > trunc(options.lte, Math.min(key.length, options.lte.length))))
356
- ) {
357
- continue
358
- }
359
- yield * ents(await shards.get(entry[1][0]))
360
- } else {
361
- if (
362
- (hasKeyPrefix && key.startsWith(options.prefix)) ||
363
- (hasKeyRange && hasKeyUpperAndLowerBoundRange && (
364
- ((hasKeyLowerBoundRangeExclusive && key > options.gt) || (hasKeyLowerBoundRangeInclusive && key >= options.gte)) &&
365
- ((hasKeyUpperBoundRangeExclusive && key < options.lt) || (hasKeyUpperBoundRangeInclusive && key <= options.lte))
366
- )) ||
367
- (hasKeyRange && !hasKeyUpperAndLowerBoundRange && (
368
- (hasKeyLowerBoundRangeExclusive && key > options.gt) || (hasKeyLowerBoundRangeInclusive && key >= options.gte) ||
369
- (hasKeyUpperBoundRangeExclusive && key < options.lt) || (hasKeyUpperBoundRangeInclusive && key <= options.lte)
370
- )) ||
371
- (!hasKeyPrefix && !hasKeyRange)
372
- ) {
373
- yield [key, entry[1]]
374
- }
375
- }
376
- }
377
- })
378
- )(rshard)
379
- }
380
-
381
- /**
382
- * @param {string} str
383
- * @param {number} len
384
- */
385
- const trunc = (str, len) => str.length <= len ? str : str.slice(0, len)
386
-
387
- /**
388
- * Traverse from the passed shard block to the target shard block using the
389
- * passed key. All traversed shards are returned, starting with the passed
390
- * shard and ending with the target.
391
- *
392
- * @param {ShardFetcher} shards
393
- * @param {API.ShardBlockView} shard
394
- * @param {string} key
395
- * @returns {Promise<[API.ShardBlockView, ...Array<API.ShardBlockView>]>}
396
- */
397
- const traverse = async (shards, shard, key) => {
398
- for (const [k, v] of shard.value.entries) {
399
- if (key === k) return [shard]
400
- if (key.startsWith(k) && Array.isArray(v)) {
401
- const path = await traverse(shards, await shards.get(v[0]), key.slice(k.length))
402
- return [shard, ...path]
403
- }
404
- }
405
- return [shard]
406
- }
@@ -1,43 +0,0 @@
1
- // eslint-disable-next-line no-unused-vars
2
- import * as API from './api.js'
3
- import { difference } from './diff.js'
4
- import { put, del } from './index.js'
5
-
6
- /**
7
- * @param {API.BlockFetcher} blocks Bucket block storage.
8
- * @param {API.ShardLink} base Merge base. Common parent of target DAGs.
9
- * @param {API.ShardLink[]} targets Target DAGs to merge.
10
- * @returns {Promise<{ root: API.ShardLink } & API.ShardDiff>}
11
- */
12
- export const merge = async (blocks, base, targets) => {
13
- const diffs = await Promise.all(targets.map(t => difference(blocks, base, t)))
14
- const additions = new Map()
15
- const removals = new Map()
16
- /** @type {API.BlockFetcher} */
17
- const fetcher = { get: cid => additions.get(cid.toString()) ?? blocks.get(cid) }
18
-
19
- let root = base
20
- for (const { keys } of diffs) {
21
- for (const [k, v] of keys) {
22
- let res
23
- if (v[1] == null) {
24
- res = await del(fetcher, root, k)
25
- } else {
26
- res = await put(fetcher, root, k, v[1])
27
- }
28
- for (const blk of res.removals) {
29
- if (additions.has(blk.cid.toString())) {
30
- additions.delete(blk.cid.toString())
31
- } else {
32
- removals.set(blk.cid.toString(), blk)
33
- }
34
- }
35
- for (const blk of res.additions) {
36
- additions.set(blk.cid.toString(), blk)
37
- }
38
- root = res.root
39
- }
40
- }
41
-
42
- return { root, additions: [...additions.values()], removals: [...removals.values()] }
43
- }
@@ -1,180 +0,0 @@
1
- import * as Link from 'multiformats/link'
2
- import { Block, encode, decode } from 'multiformats/block'
3
- import { sha256 } from 'multiformats/hashes/sha2'
4
- import * as dagCBOR from '@ipld/dag-cbor'
5
- // eslint-disable-next-line no-unused-vars
6
- import * as API from './api.js'
7
-
8
- export const KeyCharsASCII = 'ascii'
9
- export const MaxKeySize = 4096
10
-
11
- /**
12
- * @extends {Block<API.Shard, typeof dagCBOR.code, typeof sha256.code, 1>}
13
- * @implements {API.ShardBlockView}
14
- */
15
- export class ShardBlock extends Block {
16
- /**
17
- * @param {object} config
18
- * @param {API.ShardLink} config.cid
19
- * @param {API.Shard} config.value
20
- * @param {Uint8Array} config.bytes
21
- */
22
- constructor ({ cid, value, bytes }) {
23
- // @ts-expect-error
24
- super({ cid, value, bytes })
25
- }
26
-
27
- /** @param {API.ShardOptions} [options] */
28
- static create (options) {
29
- return encodeBlock(create(options))
30
- }
31
- }
32
-
33
- /**
34
- * @param {API.ShardOptions} [options]
35
- * @returns {API.Shard}
36
- */
37
- export const create = (options) => ({ entries: [], ...configure(options) })
38
-
39
- /**
40
- * @param {API.ShardOptions} [options]
41
- * @returns {API.ShardConfig}
42
- */
43
- export const configure = (options) => ({
44
- version: 1,
45
- keyChars: options?.keyChars ?? KeyCharsASCII,
46
- maxKeySize: options?.maxKeySize ?? MaxKeySize,
47
- prefix: options?.prefix ?? ''
48
- })
49
-
50
- /**
51
- * @param {API.ShardEntry[]} entries
52
- * @param {API.ShardOptions} [options]
53
- * @returns {API.Shard}
54
- */
55
- export const withEntries = (entries, options) => ({ ...create(options), entries })
56
-
57
- /** @type {WeakMap<Uint8Array, API.ShardBlockView>} */
58
- const decodeCache = new WeakMap()
59
-
60
- /**
61
- * @param {API.Shard} value
62
- * @returns {Promise<API.ShardBlockView>}
63
- */
64
- export const encodeBlock = async value => {
65
- const { cid, bytes } = await encode({ value, codec: dagCBOR, hasher: sha256 })
66
- const block = new ShardBlock({ cid, value, bytes })
67
- decodeCache.set(block.bytes, block)
68
- return block
69
- }
70
-
71
- /**
72
- * @param {Uint8Array} bytes
73
- * @returns {Promise<API.ShardBlockView>}
74
- */
75
- export const decodeBlock = async bytes => {
76
- const block = decodeCache.get(bytes)
77
- if (block) return block
78
- const { cid, value } = await decode({ bytes, codec: dagCBOR, hasher: sha256 })
79
- if (!isShard(value)) throw new Error(`invalid shard: ${cid}`)
80
- return new ShardBlock({ cid, value, bytes })
81
- }
82
-
83
- /**
84
- * @param {any} value
85
- * @returns {value is API.Shard}
86
- */
87
- export const isShard = value =>
88
- value != null &&
89
- typeof value === 'object' &&
90
- Array.isArray(value.entries) &&
91
- value.version === 1 &&
92
- typeof value.maxKeySize === 'number' &&
93
- typeof value.keyChars === 'string' &&
94
- typeof value.prefix === 'string'
95
-
96
- /**
97
- * @param {any} value
98
- * @returns {value is API.ShardLink}
99
- */
100
- export const isShardLink = (value) =>
101
- Link.isLink(value) &&
102
- value.code === dagCBOR.code
103
-
104
- export class ShardFetcher {
105
- /** @param {API.BlockFetcher} blocks */
106
- constructor (blocks) {
107
- this._blocks = blocks
108
- }
109
-
110
- /**
111
- * @param {API.ShardLink} link
112
- * @returns {Promise<API.ShardBlockView>}
113
- */
114
- async get (link) {
115
- const block = await this._blocks.get(link)
116
- if (!block) throw new Error(`missing block: ${link}`)
117
- return decodeBlock(block.bytes)
118
- }
119
- }
120
-
121
- /**
122
- * @param {API.ShardEntry[]} target Entries to insert into.
123
- * @param {API.ShardEntry} newEntry
124
- * @returns {API.ShardEntry[]}
125
- */
126
- export const putEntry = (target, newEntry) => {
127
- /** @type {API.ShardEntry[]} */
128
- const entries = []
129
-
130
- for (const [i, entry] of target.entries()) {
131
- const [k, v] = entry
132
- if (newEntry[0] === k) {
133
- // if new value is link to shard...
134
- if (Array.isArray(newEntry[1])) {
135
- // and old value is link to shard
136
- // and old value is _also_ link to data
137
- // and new value does not have link to data
138
- // then preserve old data
139
- if (Array.isArray(v) && v[1] != null && newEntry[1][1] == null) {
140
- entries.push([k, [newEntry[1][0], v[1]]])
141
- } else {
142
- entries.push(newEntry)
143
- }
144
- } else {
145
- // shard as well as value?
146
- if (Array.isArray(v)) {
147
- entries.push([k, [v[0], newEntry[1]]])
148
- } else {
149
- entries.push(newEntry)
150
- }
151
- }
152
- for (let j = i + 1; j < target.length; j++) {
153
- entries.push(target[j])
154
- }
155
- return entries
156
- }
157
- if (i === 0 && newEntry[0] < k) {
158
- entries.push(newEntry)
159
- for (let j = i; j < target.length; j++) {
160
- entries.push(target[j])
161
- }
162
- return entries
163
- }
164
- if (i > 0 && newEntry[0] > target[i - 1][0] && newEntry[0] < k) {
165
- entries.push(newEntry)
166
- for (let j = i; j < target.length; j++) {
167
- entries.push(target[j])
168
- }
169
- return entries
170
- }
171
- entries.push(entry)
172
- }
173
-
174
- entries.push(newEntry)
175
-
176
- return entries
177
- }
178
-
179
- /** @param {string} s */
180
- export const isPrintableASCII = s => /^[\x20-\x7E]*$/.test(s)