@dxos/feed-store 0.8.4-main.fd6878d → 0.8.4-main.fffef41

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 (31) hide show
  1. package/dist/lib/browser/{chunk-4RBZO6L7.mjs → chunk-I36R5SR3.mjs} +100 -63
  2. package/dist/lib/browser/chunk-I36R5SR3.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +35 -23
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +8 -7
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node-esm/{chunk-KYPCBBNB.mjs → chunk-HJBZDWE4.mjs} +100 -63
  9. package/dist/lib/node-esm/chunk-HJBZDWE4.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +35 -23
  11. package/dist/lib/node-esm/index.mjs.map +3 -3
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +8 -7
  14. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  15. package/dist/types/src/feed-queue.d.ts.map +1 -1
  16. package/dist/types/src/feed-wrapper.d.ts +18 -19
  17. package/dist/types/src/feed-wrapper.d.ts.map +1 -1
  18. package/dist/types/src/testing/test-builder.d.ts +1 -1
  19. package/dist/types/src/testing/test-builder.d.ts.map +1 -1
  20. package/dist/types/src/testing/test-generator.d.ts +1 -1
  21. package/dist/types/src/testing/test-generator.d.ts.map +1 -1
  22. package/dist/types/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +19 -18
  24. package/src/feed-queue.ts +3 -1
  25. package/src/feed-store.node.test.ts +2 -2
  26. package/src/feed-wrapper.test.ts +36 -3
  27. package/src/feed-wrapper.ts +73 -34
  28. package/src/testing/test-builder.ts +1 -2
  29. package/src/testing/test-generator.ts +1 -2
  30. package/dist/lib/browser/chunk-4RBZO6L7.mjs.map +0 -7
  31. package/dist/lib/node-esm/chunk-KYPCBBNB.mjs.map +0 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/feed-store",
3
- "version": "0.8.4-main.fd6878d",
3
+ "version": "0.8.4-main.fffef41",
4
4
  "description": "A consistent store for hypercore feeds.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -38,29 +38,30 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "lodash.defaultsdeep": "^4.6.1",
41
- "race-as-promised": "^0.0.2",
41
+ "race-as-promised": "^0.0.3",
42
42
  "streamx": "^2.12.5",
43
- "@dxos/codec-protobuf": "0.8.4-main.fd6878d",
44
- "@dxos/context": "0.8.4-main.fd6878d",
45
- "@dxos/crypto": "0.8.4-main.fd6878d",
46
- "@dxos/debug": "0.8.4-main.fd6878d",
47
- "@dxos/invariant": "0.8.4-main.fd6878d",
48
- "@dxos/hypercore": "0.8.4-main.fd6878d",
49
- "@dxos/keyring": "0.8.4-main.fd6878d",
50
- "@dxos/keys": "0.8.4-main.fd6878d",
51
- "@dxos/async": "0.8.4-main.fd6878d",
52
- "@dxos/log": "0.8.4-main.fd6878d",
53
- "@dxos/node-std": "0.8.4-main.fd6878d",
54
- "@dxos/random-access-storage": "0.8.4-main.fd6878d",
55
- "@dxos/util": "0.8.4-main.fd6878d"
43
+ "@dxos/async": "0.8.4-main.fffef41",
44
+ "@dxos/context": "0.8.4-main.fffef41",
45
+ "@dxos/codec-protobuf": "0.8.4-main.fffef41",
46
+ "@dxos/crypto": "0.8.4-main.fffef41",
47
+ "@dxos/debug": "0.8.4-main.fffef41",
48
+ "@dxos/invariant": "0.8.4-main.fffef41",
49
+ "@dxos/keyring": "0.8.4-main.fffef41",
50
+ "@dxos/hypercore": "0.8.4-main.fffef41",
51
+ "@dxos/keys": "0.8.4-main.fffef41",
52
+ "@dxos/log": "0.8.4-main.fffef41",
53
+ "@dxos/node-std": "0.8.4-main.fffef41",
54
+ "@dxos/util": "0.8.4-main.fffef41",
55
+ "@dxos/random-access-storage": "0.8.4-main.fffef41",
56
+ "@dxos/vendor-hypercore": "0.8.4-main.fffef41"
56
57
  },
57
58
  "devDependencies": {
58
59
  "@types/lodash.defaultsdeep": "^4.6.6",
59
- "@dxos/keys": "0.8.4-main.fd6878d",
60
- "@dxos/random": "0.8.4-main.fd6878d"
60
+ "@dxos/keys": "0.8.4-main.fffef41",
61
+ "@dxos/random": "0.8.4-main.fffef41"
61
62
  },
62
63
  "optionalDependencies": {
63
- "@dxos/random": "0.8.4-main.fd6878d"
64
+ "@dxos/random": "0.8.4-main.fffef41"
64
65
  },
65
66
  "publishConfig": {
66
67
  "access": "public"
package/src/feed-queue.ts CHANGED
@@ -125,10 +125,12 @@ export class FeedQueue<T extends {}> {
125
125
  };
126
126
 
127
127
  const onError = (err?: Error) => {
128
+ if (!this.isOpen) {
129
+ return;
130
+ }
128
131
  if (!err) {
129
132
  return;
130
133
  }
131
-
132
134
  if (err.message === 'Writable stream closed prematurely' || err.message === 'Feed is closed') {
133
135
  return;
134
136
  }
@@ -7,7 +7,7 @@ import { describe, expect, test } from 'vitest';
7
7
  import { faker } from '@dxos/random';
8
8
  import { StorageType, createStorage } from '@dxos/random-access-storage';
9
9
 
10
- import { TestItemBuilder } from './testing';
10
+ import { type TestItem, TestItemBuilder } from './testing';
11
11
 
12
12
  describe('FeedStore', () => {
13
13
  test('reopens a feed and reads data from storage', async () => {
@@ -28,7 +28,7 @@ describe('FeedStore', () => {
28
28
  await feed.append({
29
29
  id: String(i),
30
30
  value: faker.lorem.sentence(),
31
- });
31
+ } as TestItem);
32
32
  }
33
33
 
34
34
  expect(feed.properties.length).to.eq(numBlocks);
@@ -97,7 +97,7 @@ describe('FeedWrapper', () => {
97
97
  await feed.append({
98
98
  id: String(i + 1),
99
99
  value: faker.lorem.sentence(),
100
- });
100
+ } as any);
101
101
  }
102
102
 
103
103
  expect(feed.properties.length).to.eq(numBlocks);
@@ -234,7 +234,7 @@ describe('FeedWrapper', () => {
234
234
  // Reader.
235
235
  {
236
236
  const start = 5;
237
- feed2.download({ start, linear: true }, (err: Error) => {
237
+ feed2.download({ start, linear: true }, (err: Error | null) => {
238
238
  if (err) {
239
239
  throw err;
240
240
  }
@@ -261,7 +261,7 @@ describe('FeedWrapper', () => {
261
261
  await feed2.open();
262
262
 
263
263
  for (const i of range(numBlocks)) {
264
- await feed1.append(`block-${i}`);
264
+ await feed1.append(`block-${i}` as any);
265
265
  }
266
266
 
267
267
  for (const i of range(numBlocks)) {
@@ -284,4 +284,37 @@ describe('FeedWrapper', () => {
284
284
  console.log('audit', { err, valid });
285
285
  });
286
286
  });
287
+
288
+ test('integrates blocks via putBuffer', async () => {
289
+ const numBlocks = 5;
290
+ const builder = new TestBuilder();
291
+ const feedFactory = builder.createFeedFactory();
292
+
293
+ const key = await builder.keyring.createKey();
294
+ const source = await feedFactory.createFeed(key, { writable: true });
295
+ const target = await feedFactory.createFeed(key);
296
+
297
+ await source.open();
298
+ await target.open();
299
+
300
+ // Append to source.
301
+ for (let i = 0; i < numBlocks; i++) {
302
+ await source.append(faker.lorem.sentence() as any);
303
+ }
304
+
305
+ // Integrate into target via putBuffer using proofs from source.
306
+ for (let i = 0; i < numBlocks; i++) {
307
+ const data = (await source.get(i, { valueEncoding: 'binary' })) as Uint8Array;
308
+ const proof = await source.proof(i);
309
+ await target.putBuffer(i, data, proof, null);
310
+ }
311
+
312
+ // Verify data and length.
313
+ expect(target.length).to.eq(numBlocks);
314
+ for (let i = 0; i < numBlocks; i++) {
315
+ const src = (await source.get(i, { valueEncoding: 'binary' })) as Uint8Array;
316
+ const dst = (await target.get(i, { valueEncoding: 'binary' })) as Uint8Array;
317
+ expect(Buffer.from(dst).equals(Buffer.from(src))).to.be.true;
318
+ }
319
+ });
287
320
  });
@@ -3,18 +3,19 @@
3
3
  //
4
4
 
5
5
  import { inspect } from 'node:util';
6
+ import { promisify } from 'node:util';
6
7
 
7
- import type { Proof } from 'hypercore';
8
8
  import { Readable, Transform } from 'streamx';
9
9
 
10
10
  import { Trigger } from '@dxos/async';
11
11
  import { StackTrace, inspectObject } from '@dxos/debug';
12
12
  import type { Hypercore, HypercoreProperties, ReadStreamOptions } from '@dxos/hypercore';
13
- import { invariant } from '@dxos/invariant';
13
+ import { assertArgument, invariant } from '@dxos/invariant';
14
14
  import { type PublicKey } from '@dxos/keys';
15
15
  import { log } from '@dxos/log';
16
16
  import { type Directory } from '@dxos/random-access-storage';
17
- import { arrayToBuffer, createBinder, rangeFromTo } from '@dxos/util';
17
+ import { arrayToBuffer, rangeFromTo } from '@dxos/util';
18
+ import type { GetOptions, Proof } from '@dxos/vendor-hypercore/hypercore';
18
19
 
19
20
  import { type FeedWriter, type WriteReceipt } from './feed-writer';
20
21
 
@@ -22,8 +23,8 @@ import { type FeedWriter, type WriteReceipt } from './feed-writer';
22
23
  * Async feed wrapper.
23
24
  */
24
25
  export class FeedWrapper<T extends {}> {
26
+ private _hypercore: Hypercore<T>;
25
27
  private readonly _pendingWrites = new Set<StackTrace>();
26
- private readonly _binder = createBinder(this._hypercore);
27
28
 
28
29
  // Pending while writes are happening. Resolves when there are no pending writes.
29
30
  private readonly _writeLock = new Trigger();
@@ -31,11 +32,12 @@ export class FeedWrapper<T extends {}> {
31
32
  private _closed = false;
32
33
 
33
34
  constructor(
34
- private _hypercore: Hypercore<T>,
35
+ hypercore: Hypercore<T>,
35
36
  private _key: PublicKey, // TODO(burdon): Required since currently patching the key inside factory.
36
37
  private _storageDirectory: Directory,
37
38
  ) {
38
- invariant(this._hypercore);
39
+ assertArgument(hypercore, 'hypercore');
40
+ this._hypercore = hypercore;
39
41
  invariant(this._key);
40
42
  this._writeLock.wake();
41
43
  }
@@ -144,31 +146,42 @@ export class FeedWrapper<T extends {}> {
144
146
  await this._storageDirectory.flush();
145
147
  }
146
148
 
147
- get opened() {
149
+ get opened(): boolean {
148
150
  return this._hypercore.opened;
149
151
  }
150
152
 
151
- get closed() {
153
+ get closed(): boolean {
152
154
  return this._hypercore.closed;
153
155
  }
154
156
 
155
- get readable() {
157
+ get readable(): boolean {
156
158
  return this._hypercore.readable;
157
159
  }
158
160
 
159
- get length() {
161
+ get length(): number {
160
162
  return this._hypercore.length;
161
163
  }
162
164
 
163
- get byteLength() {
165
+ get byteLength(): number {
164
166
  return this._hypercore.byteLength;
165
167
  }
166
168
 
167
- on = this._binder.fn(this._hypercore.on);
168
- off = this._binder.fn(this._hypercore.off);
169
+ on(...args: any[]) {
170
+ return (this._hypercore as any).on(...args);
171
+ }
172
+
173
+ off(...args: any[]) {
174
+ return (this._hypercore as any).off(...args);
175
+ }
176
+
177
+ open(...args: Parameters<Hypercore<T>['open']>) {
178
+ return promisify(this._hypercore.open.bind(this._hypercore) as any)(...args);
179
+ }
180
+
181
+ _close(...args: Parameters<Hypercore<T>['close']>) {
182
+ return promisify(this._hypercore.close.bind(this._hypercore) as any)(...args);
183
+ }
169
184
 
170
- open = this._binder.async(this._hypercore.open);
171
- private _close = this._binder.async(this._hypercore.close);
172
185
  close = async () => {
173
186
  if (this._pendingWrites.size) {
174
187
  log.warn('Closing feed with pending writes', {
@@ -182,27 +195,53 @@ export class FeedWrapper<T extends {}> {
182
195
  await this._close();
183
196
  };
184
197
 
185
- has = this._binder.fn(this._hypercore.has) as (start: number, end?: number) => boolean;
186
- get = this._binder.async(this._hypercore.get);
187
- append = this._binder.async(this._hypercore.append);
198
+ has(start: number, end?: number) {
199
+ return this._hypercore.has(start, end);
200
+ }
201
+
202
+ get(index: number, options?: GetOptions) {
203
+ return promisify(this._hypercore.get.bind(this._hypercore) as any)(index, options);
204
+ }
205
+
206
+ // TODO(dmaretskyi): Type better
207
+ append(data: any | any[]): Promise<number> {
208
+ return promisify(this._hypercore.append.bind(this._hypercore))(data);
209
+ }
188
210
 
189
211
  /**
190
212
  * Will not resolve if `end` parameter is not specified and the feed is not closed.
191
213
  */
192
- download = this._binder.fn(this._hypercore.download);
193
- undownload = this._binder.fn(this._hypercore.undownload);
194
- setDownloading = this._binder.fn(this._hypercore.setDownloading);
195
- replicate: Hypercore<T>['replicate'] = this._binder.fn(this._hypercore.replicate);
196
- clear = this._binder.async(this._hypercore.clear) as (start: number, end?: number) => Promise<void>;
197
-
198
- proof = this._binder.async(this._hypercore.proof) as (index: number) => Promise<Proof>;
199
- put = this._binder.async(this._hypercore.put) as (index: number, data: T, proof: Proof) => Promise<void>;
200
- putBuffer = this._binder.async((this._hypercore as any)._putBuffer) as (
201
- index: number,
202
- data: Buffer,
203
- proof: Proof,
204
- from: null,
205
- ) => Promise<void>;
214
+ download(...args: Parameters<Hypercore<T>['download']>) {
215
+ return this._hypercore.download(...args);
216
+ }
217
+
218
+ undownload(...args: Parameters<Hypercore<T>['undownload']>) {
219
+ return this._hypercore.undownload(...args);
220
+ }
221
+
222
+ setDownloading(...args: Parameters<Hypercore<T>['setDownloading']>) {
223
+ return this._hypercore.setDownloading(...args);
224
+ }
225
+
226
+ replicate(...args: Parameters<Hypercore<T>['replicate']>) {
227
+ return this._hypercore.replicate(...args);
228
+ }
229
+
230
+ clear(start: number, end?: number) {
231
+ return promisify(this._hypercore.clear.bind(this._hypercore))(start, end);
232
+ }
233
+
234
+ proof(index: number, options?: any) {
235
+ return promisify(this._hypercore.proof.bind(this._hypercore))(index);
236
+ }
237
+
238
+ put(index: number, data: T, proof: Proof) {
239
+ return promisify(this._hypercore.put.bind(this._hypercore))(index, data, proof);
240
+ }
241
+
242
+ putBuffer(index: number, data: Buffer | Uint8Array, proof: Proof, peer: null): Promise<void> {
243
+ return promisify((this._hypercore as any)._putBuffer.bind(this._hypercore) as any)(index, data, proof, peer);
244
+ }
206
245
 
207
246
  /**
208
247
  * Clear and check for integrity.
@@ -217,7 +256,7 @@ export class FeedWrapper<T extends {}> {
217
256
  const messagesBefore = await Promise.all(
218
257
  rangeFromTo(checkBegin, checkEnd).map((idx) =>
219
258
  this.get(idx, {
220
- valueEncoding: { decode: (x: Uint8Array) => x },
259
+ valueEncoding: { decode: (x: Uint8Array) => x } as any,
221
260
  }),
222
261
  ),
223
262
  );
@@ -227,7 +266,7 @@ export class FeedWrapper<T extends {}> {
227
266
  const messagesAfter = await Promise.all(
228
267
  rangeFromTo(checkBegin, checkEnd).map((idx) =>
229
268
  this.get(idx, {
230
- valueEncoding: { decode: (x: Uint8Array) => x },
269
+ valueEncoding: { decode: (x: Uint8Array) => x } as any,
231
270
  }),
232
271
  ),
233
272
  );
@@ -2,10 +2,9 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import type { ValueEncoding } from 'hypercore';
6
-
7
5
  import { Keyring } from '@dxos/keyring';
8
6
  import { type Directory, type Storage, StorageType, createStorage } from '@dxos/random-access-storage';
7
+ import type { ValueEncoding } from '@dxos/vendor-hypercore/hypercore';
9
8
 
10
9
  import { FeedFactory } from '../feed-factory';
11
10
  import { FeedStore } from '../feed-store';
@@ -2,12 +2,11 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import type { AbstractValueEncoding } from 'hypercore';
6
-
7
5
  import { sleep } from '@dxos/async';
8
6
  import { type Codec } from '@dxos/codec-protobuf';
9
7
  import { createCodecEncoding } from '@dxos/hypercore';
10
8
  import { faker } from '@dxos/random';
9
+ import type { AbstractValueEncoding } from '@dxos/vendor-hypercore/hypercore';
11
10
 
12
11
  import { type FeedWriter } from '../feed-writer';
13
12
 
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/feed-wrapper.ts", "../../../src/feed-factory.ts", "../../../src/feed-store.ts"],
4
- "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { inspect } from 'node:util';\n\nimport type { Proof } from 'hypercore';\nimport { Readable, Transform } from 'streamx';\n\nimport { Trigger } from '@dxos/async';\nimport { StackTrace, inspectObject } from '@dxos/debug';\nimport type { Hypercore, HypercoreProperties, ReadStreamOptions } from '@dxos/hypercore';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type Directory } from '@dxos/random-access-storage';\nimport { arrayToBuffer, createBinder, rangeFromTo } from '@dxos/util';\n\nimport { type FeedWriter, type WriteReceipt } from './feed-writer';\n\n/**\n * Async feed wrapper.\n */\nexport class FeedWrapper<T extends {}> {\n private readonly _pendingWrites = new Set<StackTrace>();\n private readonly _binder = createBinder(this._hypercore);\n\n // Pending while writes are happening. Resolves when there are no pending writes.\n private readonly _writeLock = new Trigger();\n\n private _closed = false;\n\n constructor(\n private _hypercore: Hypercore<T>,\n private _key: PublicKey, // TODO(burdon): Required since currently patching the key inside factory.\n private _storageDirectory: Directory,\n ) {\n invariant(this._hypercore);\n invariant(this._key);\n this._writeLock.wake();\n }\n\n [inspect.custom](): string {\n return inspectObject(this);\n }\n\n toJSON(): { feedKey: PublicKey; length: number; opened: boolean; closed: boolean } {\n return {\n feedKey: this._key,\n length: this.properties.length,\n opened: this.properties.opened,\n closed: this.properties.closed,\n };\n }\n\n get key(): PublicKey {\n return this._key;\n }\n\n get core(): Hypercore<T> {\n return this._hypercore;\n }\n\n // TODO(burdon): Create proxy.\n get properties(): HypercoreProperties {\n return this._hypercore;\n }\n\n createReadableStream(opts?: ReadStreamOptions): Readable {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n const transform = new Transform({\n transform(data: any, cb: (err?: Error | null, data?: any) => void) {\n // Delay until write is complete.\n void self._writeLock.wait().then(() => {\n this.push(data);\n cb();\n });\n },\n });\n const readStream =\n opts?.batch !== undefined && opts?.batch > 1\n ? new BatchedReadStream(this._hypercore, opts)\n : this._hypercore.createReadStream(opts);\n\n readStream.pipe(transform, (err: any) => {\n // Ignore errors.\n // We might get \"Writable stream closed prematurely\" error.\n // Its okay since the pipeline is closed and does not expect more messages.\n });\n\n return transform;\n }\n\n createFeedWriter(): FeedWriter<T> {\n return {\n write: async (data: T, { afterWrite } = {}) => {\n log('write', { feed: this._key, seq: this._hypercore.length });\n invariant(!this._closed, 'Feed closed');\n const stackTrace = new StackTrace();\n\n try {\n // Pending writes pause the read stream.\n this._pendingWrites.add(stackTrace);\n if (this._pendingWrites.size === 1) {\n this._writeLock.reset();\n }\n\n const receipt = await this.appendWithReceipt(data);\n\n // TODO(dmaretskyi): Removing this will make user-intiated writes faster but might result in a data-loss.\n await this.flushToDisk();\n\n await afterWrite?.(receipt);\n\n return receipt;\n } finally {\n // Unblock the read stream after the write (and callback) is complete.\n this._pendingWrites.delete(stackTrace);\n if (this._pendingWrites.size === 0) {\n this._writeLock.wake();\n }\n }\n },\n };\n }\n\n async appendWithReceipt(data: T): Promise<WriteReceipt> {\n const seq = await this.append(data);\n invariant(seq < this.length, 'Invalid seq after write');\n log('write complete', { feed: this._key, seq });\n const receipt: WriteReceipt = {\n feedKey: this.key,\n seq,\n };\n return receipt;\n }\n\n /**\n * Flush pending changes to disk.\n * Calling this is not required unless you want to explicitly wait for data to be written.\n */\n async flushToDisk(): Promise<void> {\n await this._storageDirectory.flush();\n }\n\n get opened() {\n return this._hypercore.opened;\n }\n\n get closed() {\n return this._hypercore.closed;\n }\n\n get readable() {\n return this._hypercore.readable;\n }\n\n get length() {\n return this._hypercore.length;\n }\n\n get byteLength() {\n return this._hypercore.byteLength;\n }\n\n on = this._binder.fn(this._hypercore.on);\n off = this._binder.fn(this._hypercore.off);\n\n open = this._binder.async(this._hypercore.open);\n private _close = this._binder.async(this._hypercore.close);\n close = async () => {\n if (this._pendingWrites.size) {\n log.warn('Closing feed with pending writes', {\n feed: this._key,\n count: this._pendingWrites.size,\n pendingWrites: Array.from(this._pendingWrites.values()).map((stack) => stack.getStack()),\n });\n }\n this._closed = true;\n await this.flushToDisk();\n await this._close();\n };\n\n has = this._binder.fn(this._hypercore.has) as (start: number, end?: number) => boolean;\n get = this._binder.async(this._hypercore.get);\n append = this._binder.async(this._hypercore.append);\n\n /**\n * Will not resolve if `end` parameter is not specified and the feed is not closed.\n */\n download = this._binder.fn(this._hypercore.download);\n undownload = this._binder.fn(this._hypercore.undownload);\n setDownloading = this._binder.fn(this._hypercore.setDownloading);\n replicate: Hypercore<T>['replicate'] = this._binder.fn(this._hypercore.replicate);\n clear = this._binder.async(this._hypercore.clear) as (start: number, end?: number) => Promise<void>;\n\n proof = this._binder.async(this._hypercore.proof) as (index: number) => Promise<Proof>;\n put = this._binder.async(this._hypercore.put) as (index: number, data: T, proof: Proof) => Promise<void>;\n putBuffer = this._binder.async((this._hypercore as any)._putBuffer) as (\n index: number,\n data: Buffer,\n proof: Proof,\n from: null,\n ) => Promise<void>;\n\n /**\n * Clear and check for integrity.\n */\n async safeClear(from: number, to: number): Promise<void> {\n invariant(from >= 0 && from < to && to <= this.length, 'Invalid range');\n\n const CHECK_MESSAGES = 20;\n const checkBegin = to;\n const checkEnd = Math.min(checkBegin + CHECK_MESSAGES, this.length);\n\n const messagesBefore = await Promise.all(\n rangeFromTo(checkBegin, checkEnd).map((idx) =>\n this.get(idx, {\n valueEncoding: { decode: (x: Uint8Array) => x },\n }),\n ),\n );\n\n await this.clear(from, to);\n\n const messagesAfter = await Promise.all(\n rangeFromTo(checkBegin, checkEnd).map((idx) =>\n this.get(idx, {\n valueEncoding: { decode: (x: Uint8Array) => x },\n }),\n ),\n );\n\n for (let i = 0; i < messagesBefore.length; i++) {\n const before = arrayToBuffer(messagesBefore[i]);\n const after = arrayToBuffer(messagesAfter[i]);\n if (!before.equals(after)) {\n throw new Error('Feed corruption on clear. There has likely been a data loss.');\n }\n }\n }\n}\n\nclass BatchedReadStream extends Readable {\n private readonly _feed: Hypercore<any>;\n private readonly _batch: number;\n private _cursor: number;\n private _reading = false;\n\n constructor(feed: Hypercore<any>, opts: ReadStreamOptions = {}) {\n super({ objectMode: true });\n invariant(opts.live === true, 'Only live mode supported');\n invariant(opts.batch !== undefined && opts.batch > 1);\n this._feed = feed;\n this._batch = opts.batch;\n this._cursor = opts.start ?? 0;\n }\n\n override _open(cb: (err: Error | null) => void): void {\n this._feed.ready(cb);\n }\n\n override _read(cb: (err: Error | null) => void): void {\n if (this._reading) {\n return;\n }\n\n if (this._feed.bitfield!.total(this._cursor, this._cursor + this._batch) === this._batch) {\n this._batchedRead(cb);\n } else {\n this._nonBatchedRead(cb);\n }\n }\n\n private _nonBatchedRead(cb: (err: Error | null) => void): void {\n this._feed.get(this._cursor, { wait: true }, (err, data) => {\n if (err) {\n cb(err);\n } else {\n this._cursor++;\n this._reading = false;\n this.push(data);\n cb(null);\n }\n });\n }\n\n private _batchedRead(cb: (err: Error | null) => void): void {\n this._feed.getBatch(this._cursor, this._cursor + this._batch, { wait: true }, (err, data) => {\n if (err) {\n cb(err);\n } else {\n this._cursor += data.length;\n this._reading = false;\n for (const item of data) {\n this.push(item);\n }\n cb(null);\n }\n });\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport defaultsDeep from 'lodash.defaultsdeep';\n\nimport { type Signer, subtleCrypto } from '@dxos/crypto';\nimport { failUndefined } from '@dxos/debug';\nimport type { HypercoreOptions } from '@dxos/hypercore';\nimport { createCrypto, hypercore } from '@dxos/hypercore';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type Directory } from '@dxos/random-access-storage';\n\nimport { FeedWrapper } from './feed-wrapper';\n\nexport type FeedFactoryOptions = {\n root: Directory;\n signer?: Signer;\n hypercore?: HypercoreOptions;\n};\n\nexport type FeedOptions = HypercoreOptions & {\n writable?: boolean;\n /**\n * Optional hook called before data is written after being verified.\n * Called for writes done by this peer as well as for data replicated from other peers.\n * NOTE: The callback must be invoked to complete the write operation.\n * @param peer Always null in hypercore@9.12.0.\n */\n onwrite?: (index: number, data: any, peer: null, cb: (err: Error | null) => void) => void;\n};\n\n/**\n * Hypercore factory.\n */\nexport class FeedFactory<T extends {}> {\n private readonly _root: Directory;\n private readonly _signer?: Signer;\n private readonly _hypercoreOptions?: HypercoreOptions;\n\n constructor({ root, signer, hypercore }: FeedFactoryOptions) {\n log('FeedFactory', { options: hypercore });\n this._root = root ?? failUndefined();\n this._signer = signer;\n this._hypercoreOptions = hypercore;\n }\n\n get storageRoot() {\n return this._root;\n }\n\n async createFeed(publicKey: PublicKey, options?: FeedOptions): Promise<FeedWrapper<T>> {\n if (options?.writable && !this._signer) {\n throw new Error('Signer required to create writable feeds.');\n }\n if (options?.secretKey) {\n log.warn('Secret key ignored due to signer.');\n }\n\n // Required due to hypercore's 32-byte key limit.\n const key = await subtleCrypto.digest('SHA-256', Buffer.from(publicKey.toHex()));\n\n const opts = defaultsDeep(\n {\n // sparse: false,\n // stats: false,\n },\n this._hypercoreOptions,\n {\n secretKey: this._signer && options?.writable ? Buffer.from('secret') : undefined,\n crypto: this._signer ? createCrypto(this._signer, publicKey) : undefined,\n onwrite: options?.onwrite,\n noiseKeyPair: {}, // We're not using noise.\n },\n options,\n );\n\n const storageDir = this._root.createDirectory(publicKey.toHex());\n const makeStorage = (filename: string) => {\n const { type, native } = storageDir.getOrCreateFile(filename);\n log('created', {\n path: `${type}:${this._root.path}/${publicKey.truncate()}/${filename}`,\n });\n\n return native;\n };\n\n const core = hypercore(makeStorage, Buffer.from(key), opts);\n return new FeedWrapper(core, publicKey, storageDir);\n }\n}\n", "//\n// Copyright 2019 DXOS.org\n//\n\nimport { Event, Mutex } from '@dxos/async';\nimport { failUndefined } from '@dxos/debug';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { ComplexMap, defaultMap } from '@dxos/util';\n\nimport { type FeedFactory, type FeedOptions } from './feed-factory';\nimport { type FeedWrapper } from './feed-wrapper';\n\nexport interface FeedStoreOptions<T extends {}> {\n factory: FeedFactory<T>;\n}\n\n/**\n * Persistent hypercore store.\n */\nexport class FeedStore<T extends {}> {\n private readonly _feeds: ComplexMap<PublicKey, FeedWrapper<T>> = new ComplexMap(PublicKey.hash);\n private readonly _mutexes = new ComplexMap<PublicKey, Mutex>(PublicKey.hash);\n private readonly _factory: FeedFactory<T>;\n\n private _closed = false;\n\n readonly feedOpened = new Event<FeedWrapper<T>>();\n\n constructor({ factory }: FeedStoreOptions<T>) {\n this._factory = factory ?? failUndefined();\n }\n\n get size() {\n return this._feeds.size;\n }\n\n get feeds() {\n return Array.from(this._feeds.values());\n }\n\n /**\n * Get the open feed if it exists.\n */\n getFeed(publicKey: PublicKey): FeedWrapper<T> | undefined {\n return this._feeds.get(publicKey);\n }\n\n /**\n * Gets or opens a feed.\n * The feed is readonly unless a secret key is provided.\n */\n async openFeed(feedKey: PublicKey, { writable, sparse }: FeedOptions = {}): Promise<FeedWrapper<T>> {\n log('opening feed', { feedKey });\n invariant(feedKey);\n invariant(!this._closed, 'Feed store is closed');\n\n const mutex = defaultMap(this._mutexes, feedKey, () => new Mutex());\n\n return mutex.executeSynchronized(async () => {\n let feed = this.getFeed(feedKey);\n if (feed) {\n // TODO(burdon): Need to check that there's another instance being used (create test and break this).\n // TODO(burdon): Remove from store if feed is closed externally? (remove wrapped open/close methods?)\n if (writable && !feed.properties.writable) {\n throw new Error(`Read-only feed is already open: ${feedKey.truncate()}`);\n } else if ((sparse ?? false) !== feed.properties.sparse) {\n throw new Error(\n `Feed already open with different sparse setting: ${feedKey.truncate()} [${sparse} !== ${\n feed.properties.sparse\n }]`,\n );\n } else {\n await feed.open();\n return feed;\n }\n }\n\n feed = await this._factory.createFeed(feedKey, { writable, sparse });\n this._feeds.set(feed.key, feed);\n\n await feed.open();\n this.feedOpened.emit(feed);\n log('opened', { feedKey });\n return feed;\n });\n }\n\n /**\n * Close all feeds.\n */\n async close(): Promise<void> {\n log('closing...');\n this._closed = true;\n await Promise.all(\n Array.from(this._feeds.values()).map(async (feed) => {\n await feed.close();\n invariant(feed.closed);\n // TODO(burdon): SpaceProxy still being initialized.\n // SpaceProxy.initialize => Database.createItem => ... => FeedWrapper.append\n // Uncaught Error: Closed [random-access-storage/index.js:181:38]\n // await sleep(100);\n }),\n );\n\n this._feeds.clear();\n log('closed');\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["inspect", "Readable", "Transform", "Trigger", "StackTrace", "inspectObject", "invariant", "log", "arrayToBuffer", "createBinder", "rangeFromTo", "FeedWrapper", "_hypercore", "_key", "_storageDirectory", "_pendingWrites", "Set", "_binder", "_writeLock", "_closed", "on", "fn", "off", "open", "async", "_close", "close", "size", "warn", "feed", "count", "pendingWrites", "Array", "from", "values", "map", "stack", "getStack", "flushToDisk", "has", "get", "append", "download", "undownload", "setDownloading", "replicate", "clear", "proof", "put", "putBuffer", "_putBuffer", "wake", "custom", "toJSON", "feedKey", "length", "properties", "opened", "closed", "key", "core", "createReadableStream", "opts", "self", "transform", "data", "cb", "wait", "then", "push", "readStream", "batch", "undefined", "BatchedReadStream", "createReadStream", "pipe", "err", "createFeedWriter", "write", "afterWrite", "seq", "stackTrace", "add", "reset", "receipt", "appendWithReceipt", "delete", "flush", "readable", "byteLength", "safeClear", "to", "CHECK_MESSAGES", "checkBegin", "checkEnd", "Math", "min", "messagesBefore", "Promise", "all", "idx", "valueEncoding", "decode", "x", "messagesAfter", "i", "before", "after", "equals", "Error", "objectMode", "_reading", "live", "_feed", "_batch", "_cursor", "start", "_open", "ready", "_read", "bitfield", "total", "_batchedRead", "_nonBatchedRead", "getBatch", "item", "defaultsDeep", "subtleCrypto", "failUndefined", "createCrypto", "hypercore", "log", "FeedFactory", "root", "signer", "hypercore", "log", "options", "_root", "failUndefined", "_signer", "_hypercoreOptions", "storageRoot", "createFeed", "publicKey", "writable", "Error", "secretKey", "warn", "key", "subtleCrypto", "digest", "Buffer", "from", "toHex", "opts", "defaultsDeep", "undefined", "crypto", "createCrypto", "onwrite", "noiseKeyPair", "storageDir", "createDirectory", "makeStorage", "filename", "type", "native", "getOrCreateFile", "path", "truncate", "core", "FeedWrapper", "Event", "Mutex", "failUndefined", "invariant", "PublicKey", "log", "ComplexMap", "defaultMap", "FeedStore", "factory", "_feeds", "hash", "_mutexes", "_closed", "feedOpened", "_factory", "size", "feeds", "Array", "from", "values", "getFeed", "publicKey", "get", "openFeed", "feedKey", "writable", "sparse", "mutex", "executeSynchronized", "feed", "properties", "Error", "truncate", "open", "createFeed", "set", "key", "emit", "close", "Promise", "all", "map", "closed", "clear"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/feed-wrapper.ts", "../../../src/feed-factory.ts", "../../../src/feed-store.ts"],
4
- "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { inspect } from 'node:util';\n\nimport type { Proof } from 'hypercore';\nimport { Readable, Transform } from 'streamx';\n\nimport { Trigger } from '@dxos/async';\nimport { StackTrace, inspectObject } from '@dxos/debug';\nimport type { Hypercore, HypercoreProperties, ReadStreamOptions } from '@dxos/hypercore';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type Directory } from '@dxos/random-access-storage';\nimport { arrayToBuffer, createBinder, rangeFromTo } from '@dxos/util';\n\nimport { type FeedWriter, type WriteReceipt } from './feed-writer';\n\n/**\n * Async feed wrapper.\n */\nexport class FeedWrapper<T extends {}> {\n private readonly _pendingWrites = new Set<StackTrace>();\n private readonly _binder = createBinder(this._hypercore);\n\n // Pending while writes are happening. Resolves when there are no pending writes.\n private readonly _writeLock = new Trigger();\n\n private _closed = false;\n\n constructor(\n private _hypercore: Hypercore<T>,\n private _key: PublicKey, // TODO(burdon): Required since currently patching the key inside factory.\n private _storageDirectory: Directory,\n ) {\n invariant(this._hypercore);\n invariant(this._key);\n this._writeLock.wake();\n }\n\n [inspect.custom](): string {\n return inspectObject(this);\n }\n\n toJSON(): { feedKey: PublicKey; length: number; opened: boolean; closed: boolean } {\n return {\n feedKey: this._key,\n length: this.properties.length,\n opened: this.properties.opened,\n closed: this.properties.closed,\n };\n }\n\n get key(): PublicKey {\n return this._key;\n }\n\n get core(): Hypercore<T> {\n return this._hypercore;\n }\n\n // TODO(burdon): Create proxy.\n get properties(): HypercoreProperties {\n return this._hypercore;\n }\n\n createReadableStream(opts?: ReadStreamOptions): Readable {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n const transform = new Transform({\n transform(data: any, cb: (err?: Error | null, data?: any) => void) {\n // Delay until write is complete.\n void self._writeLock.wait().then(() => {\n this.push(data);\n cb();\n });\n },\n });\n const readStream =\n opts?.batch !== undefined && opts?.batch > 1\n ? new BatchedReadStream(this._hypercore, opts)\n : this._hypercore.createReadStream(opts);\n\n readStream.pipe(transform, (err: any) => {\n // Ignore errors.\n // We might get \"Writable stream closed prematurely\" error.\n // Its okay since the pipeline is closed and does not expect more messages.\n });\n\n return transform;\n }\n\n createFeedWriter(): FeedWriter<T> {\n return {\n write: async (data: T, { afterWrite } = {}) => {\n log('write', { feed: this._key, seq: this._hypercore.length });\n invariant(!this._closed, 'Feed closed');\n const stackTrace = new StackTrace();\n\n try {\n // Pending writes pause the read stream.\n this._pendingWrites.add(stackTrace);\n if (this._pendingWrites.size === 1) {\n this._writeLock.reset();\n }\n\n const receipt = await this.appendWithReceipt(data);\n\n // TODO(dmaretskyi): Removing this will make user-intiated writes faster but might result in a data-loss.\n await this.flushToDisk();\n\n await afterWrite?.(receipt);\n\n return receipt;\n } finally {\n // Unblock the read stream after the write (and callback) is complete.\n this._pendingWrites.delete(stackTrace);\n if (this._pendingWrites.size === 0) {\n this._writeLock.wake();\n }\n }\n },\n };\n }\n\n async appendWithReceipt(data: T): Promise<WriteReceipt> {\n const seq = await this.append(data);\n invariant(seq < this.length, 'Invalid seq after write');\n log('write complete', { feed: this._key, seq });\n const receipt: WriteReceipt = {\n feedKey: this.key,\n seq,\n };\n return receipt;\n }\n\n /**\n * Flush pending changes to disk.\n * Calling this is not required unless you want to explicitly wait for data to be written.\n */\n async flushToDisk(): Promise<void> {\n await this._storageDirectory.flush();\n }\n\n get opened() {\n return this._hypercore.opened;\n }\n\n get closed() {\n return this._hypercore.closed;\n }\n\n get readable() {\n return this._hypercore.readable;\n }\n\n get length() {\n return this._hypercore.length;\n }\n\n get byteLength() {\n return this._hypercore.byteLength;\n }\n\n on = this._binder.fn(this._hypercore.on);\n off = this._binder.fn(this._hypercore.off);\n\n open = this._binder.async(this._hypercore.open);\n private _close = this._binder.async(this._hypercore.close);\n close = async () => {\n if (this._pendingWrites.size) {\n log.warn('Closing feed with pending writes', {\n feed: this._key,\n count: this._pendingWrites.size,\n pendingWrites: Array.from(this._pendingWrites.values()).map((stack) => stack.getStack()),\n });\n }\n this._closed = true;\n await this.flushToDisk();\n await this._close();\n };\n\n has = this._binder.fn(this._hypercore.has) as (start: number, end?: number) => boolean;\n get = this._binder.async(this._hypercore.get);\n append = this._binder.async(this._hypercore.append);\n\n /**\n * Will not resolve if `end` parameter is not specified and the feed is not closed.\n */\n download = this._binder.fn(this._hypercore.download);\n undownload = this._binder.fn(this._hypercore.undownload);\n setDownloading = this._binder.fn(this._hypercore.setDownloading);\n replicate: Hypercore<T>['replicate'] = this._binder.fn(this._hypercore.replicate);\n clear = this._binder.async(this._hypercore.clear) as (start: number, end?: number) => Promise<void>;\n\n proof = this._binder.async(this._hypercore.proof) as (index: number) => Promise<Proof>;\n put = this._binder.async(this._hypercore.put) as (index: number, data: T, proof: Proof) => Promise<void>;\n putBuffer = this._binder.async((this._hypercore as any)._putBuffer) as (\n index: number,\n data: Buffer,\n proof: Proof,\n from: null,\n ) => Promise<void>;\n\n /**\n * Clear and check for integrity.\n */\n async safeClear(from: number, to: number): Promise<void> {\n invariant(from >= 0 && from < to && to <= this.length, 'Invalid range');\n\n const CHECK_MESSAGES = 20;\n const checkBegin = to;\n const checkEnd = Math.min(checkBegin + CHECK_MESSAGES, this.length);\n\n const messagesBefore = await Promise.all(\n rangeFromTo(checkBegin, checkEnd).map((idx) =>\n this.get(idx, {\n valueEncoding: { decode: (x: Uint8Array) => x },\n }),\n ),\n );\n\n await this.clear(from, to);\n\n const messagesAfter = await Promise.all(\n rangeFromTo(checkBegin, checkEnd).map((idx) =>\n this.get(idx, {\n valueEncoding: { decode: (x: Uint8Array) => x },\n }),\n ),\n );\n\n for (let i = 0; i < messagesBefore.length; i++) {\n const before = arrayToBuffer(messagesBefore[i]);\n const after = arrayToBuffer(messagesAfter[i]);\n if (!before.equals(after)) {\n throw new Error('Feed corruption on clear. There has likely been a data loss.');\n }\n }\n }\n}\n\nclass BatchedReadStream extends Readable {\n private readonly _feed: Hypercore<any>;\n private readonly _batch: number;\n private _cursor: number;\n private _reading = false;\n\n constructor(feed: Hypercore<any>, opts: ReadStreamOptions = {}) {\n super({ objectMode: true });\n invariant(opts.live === true, 'Only live mode supported');\n invariant(opts.batch !== undefined && opts.batch > 1);\n this._feed = feed;\n this._batch = opts.batch;\n this._cursor = opts.start ?? 0;\n }\n\n override _open(cb: (err: Error | null) => void): void {\n this._feed.ready(cb);\n }\n\n override _read(cb: (err: Error | null) => void): void {\n if (this._reading) {\n return;\n }\n\n if (this._feed.bitfield!.total(this._cursor, this._cursor + this._batch) === this._batch) {\n this._batchedRead(cb);\n } else {\n this._nonBatchedRead(cb);\n }\n }\n\n private _nonBatchedRead(cb: (err: Error | null) => void): void {\n this._feed.get(this._cursor, { wait: true }, (err, data) => {\n if (err) {\n cb(err);\n } else {\n this._cursor++;\n this._reading = false;\n this.push(data);\n cb(null);\n }\n });\n }\n\n private _batchedRead(cb: (err: Error | null) => void): void {\n this._feed.getBatch(this._cursor, this._cursor + this._batch, { wait: true }, (err, data) => {\n if (err) {\n cb(err);\n } else {\n this._cursor += data.length;\n this._reading = false;\n for (const item of data) {\n this.push(item);\n }\n cb(null);\n }\n });\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport defaultsDeep from 'lodash.defaultsdeep';\n\nimport { type Signer, subtleCrypto } from '@dxos/crypto';\nimport { failUndefined } from '@dxos/debug';\nimport type { HypercoreOptions } from '@dxos/hypercore';\nimport { createCrypto, hypercore } from '@dxos/hypercore';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type Directory } from '@dxos/random-access-storage';\n\nimport { FeedWrapper } from './feed-wrapper';\n\nexport type FeedFactoryOptions = {\n root: Directory;\n signer?: Signer;\n hypercore?: HypercoreOptions;\n};\n\nexport type FeedOptions = HypercoreOptions & {\n writable?: boolean;\n /**\n * Optional hook called before data is written after being verified.\n * Called for writes done by this peer as well as for data replicated from other peers.\n * NOTE: The callback must be invoked to complete the write operation.\n * @param peer Always null in hypercore@9.12.0.\n */\n onwrite?: (index: number, data: any, peer: null, cb: (err: Error | null) => void) => void;\n};\n\n/**\n * Hypercore factory.\n */\nexport class FeedFactory<T extends {}> {\n private readonly _root: Directory;\n private readonly _signer?: Signer;\n private readonly _hypercoreOptions?: HypercoreOptions;\n\n constructor({ root, signer, hypercore }: FeedFactoryOptions) {\n log('FeedFactory', { options: hypercore });\n this._root = root ?? failUndefined();\n this._signer = signer;\n this._hypercoreOptions = hypercore;\n }\n\n get storageRoot() {\n return this._root;\n }\n\n async createFeed(publicKey: PublicKey, options?: FeedOptions): Promise<FeedWrapper<T>> {\n if (options?.writable && !this._signer) {\n throw new Error('Signer required to create writable feeds.');\n }\n if (options?.secretKey) {\n log.warn('Secret key ignored due to signer.');\n }\n\n // Required due to hypercore's 32-byte key limit.\n const key = await subtleCrypto.digest('SHA-256', Buffer.from(publicKey.toHex()));\n\n const opts = defaultsDeep(\n {\n // sparse: false,\n // stats: false,\n },\n this._hypercoreOptions,\n {\n secretKey: this._signer && options?.writable ? Buffer.from('secret') : undefined,\n crypto: this._signer ? createCrypto(this._signer, publicKey) : undefined,\n onwrite: options?.onwrite,\n noiseKeyPair: {}, // We're not using noise.\n },\n options,\n );\n\n const storageDir = this._root.createDirectory(publicKey.toHex());\n const makeStorage = (filename: string) => {\n const { type, native } = storageDir.getOrCreateFile(filename);\n log('created', {\n path: `${type}:${this._root.path}/${publicKey.truncate()}/${filename}`,\n });\n\n return native;\n };\n\n const core = hypercore(makeStorage, Buffer.from(key), opts);\n return new FeedWrapper(core, publicKey, storageDir);\n }\n}\n", "//\n// Copyright 2019 DXOS.org\n//\n\nimport { Event, Mutex } from '@dxos/async';\nimport { failUndefined } from '@dxos/debug';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { ComplexMap, defaultMap } from '@dxos/util';\n\nimport { type FeedFactory, type FeedOptions } from './feed-factory';\nimport { type FeedWrapper } from './feed-wrapper';\n\nexport interface FeedStoreOptions<T extends {}> {\n factory: FeedFactory<T>;\n}\n\n/**\n * Persistent hypercore store.\n */\nexport class FeedStore<T extends {}> {\n private readonly _feeds: ComplexMap<PublicKey, FeedWrapper<T>> = new ComplexMap(PublicKey.hash);\n private readonly _mutexes = new ComplexMap<PublicKey, Mutex>(PublicKey.hash);\n private readonly _factory: FeedFactory<T>;\n\n private _closed = false;\n\n readonly feedOpened = new Event<FeedWrapper<T>>();\n\n constructor({ factory }: FeedStoreOptions<T>) {\n this._factory = factory ?? failUndefined();\n }\n\n get size() {\n return this._feeds.size;\n }\n\n get feeds() {\n return Array.from(this._feeds.values());\n }\n\n /**\n * Get the open feed if it exists.\n */\n getFeed(publicKey: PublicKey): FeedWrapper<T> | undefined {\n return this._feeds.get(publicKey);\n }\n\n /**\n * Gets or opens a feed.\n * The feed is readonly unless a secret key is provided.\n */\n async openFeed(feedKey: PublicKey, { writable, sparse }: FeedOptions = {}): Promise<FeedWrapper<T>> {\n log('opening feed', { feedKey });\n invariant(feedKey);\n invariant(!this._closed, 'Feed store is closed');\n\n const mutex = defaultMap(this._mutexes, feedKey, () => new Mutex());\n\n return mutex.executeSynchronized(async () => {\n let feed = this.getFeed(feedKey);\n if (feed) {\n // TODO(burdon): Need to check that there's another instance being used (create test and break this).\n // TODO(burdon): Remove from store if feed is closed externally? (remove wrapped open/close methods?)\n if (writable && !feed.properties.writable) {\n throw new Error(`Read-only feed is already open: ${feedKey.truncate()}`);\n } else if ((sparse ?? false) !== feed.properties.sparse) {\n throw new Error(\n `Feed already open with different sparse setting: ${feedKey.truncate()} [${sparse} !== ${\n feed.properties.sparse\n }]`,\n );\n } else {\n await feed.open();\n return feed;\n }\n }\n\n feed = await this._factory.createFeed(feedKey, { writable, sparse });\n this._feeds.set(feed.key, feed);\n\n await feed.open();\n this.feedOpened.emit(feed);\n log('opened', { feedKey });\n return feed;\n });\n }\n\n /**\n * Close all feeds.\n */\n async close(): Promise<void> {\n log('closing...');\n this._closed = true;\n await Promise.all(\n Array.from(this._feeds.values()).map(async (feed) => {\n await feed.close();\n invariant(feed.closed);\n // TODO(burdon): SpaceProxy still being initialized.\n // SpaceProxy.initialize => Database.createItem => ... => FeedWrapper.append\n // Uncaught Error: Closed [random-access-storage/index.js:181:38]\n // await sleep(100);\n }),\n );\n\n this._feeds.clear();\n log('closed');\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["inspect", "Readable", "Transform", "Trigger", "StackTrace", "inspectObject", "invariant", "log", "arrayToBuffer", "createBinder", "rangeFromTo", "FeedWrapper", "_hypercore", "_key", "_storageDirectory", "_pendingWrites", "Set", "_binder", "_writeLock", "_closed", "on", "fn", "off", "open", "async", "_close", "close", "size", "warn", "feed", "count", "pendingWrites", "Array", "from", "values", "map", "stack", "getStack", "flushToDisk", "has", "get", "append", "download", "undownload", "setDownloading", "replicate", "clear", "proof", "put", "putBuffer", "_putBuffer", "wake", "custom", "toJSON", "feedKey", "length", "properties", "opened", "closed", "key", "core", "createReadableStream", "opts", "self", "transform", "data", "cb", "wait", "then", "push", "readStream", "batch", "undefined", "BatchedReadStream", "createReadStream", "pipe", "err", "createFeedWriter", "write", "afterWrite", "seq", "stackTrace", "add", "reset", "receipt", "appendWithReceipt", "delete", "flush", "readable", "byteLength", "safeClear", "to", "CHECK_MESSAGES", "checkBegin", "checkEnd", "Math", "min", "messagesBefore", "Promise", "all", "idx", "valueEncoding", "decode", "x", "messagesAfter", "i", "before", "after", "equals", "Error", "objectMode", "_reading", "live", "_feed", "_batch", "_cursor", "start", "_open", "ready", "_read", "bitfield", "total", "_batchedRead", "_nonBatchedRead", "getBatch", "item", "defaultsDeep", "subtleCrypto", "failUndefined", "createCrypto", "hypercore", "log", "FeedFactory", "root", "signer", "hypercore", "log", "options", "_root", "failUndefined", "_signer", "_hypercoreOptions", "storageRoot", "createFeed", "publicKey", "writable", "Error", "secretKey", "warn", "key", "subtleCrypto", "digest", "Buffer", "from", "toHex", "opts", "defaultsDeep", "undefined", "crypto", "createCrypto", "onwrite", "noiseKeyPair", "storageDir", "createDirectory", "makeStorage", "filename", "type", "native", "getOrCreateFile", "path", "truncate", "core", "FeedWrapper", "Event", "Mutex", "failUndefined", "invariant", "PublicKey", "log", "ComplexMap", "defaultMap", "FeedStore", "factory", "_feeds", "hash", "_mutexes", "_closed", "feedOpened", "_factory", "size", "feeds", "Array", "from", "values", "getFeed", "publicKey", "get", "openFeed", "feedKey", "writable", "sparse", "mutex", "executeSynchronized", "feed", "properties", "Error", "truncate", "open", "createFeed", "set", "key", "emit", "close", "Promise", "all", "map", "closed", "clear"]
7
- }