@dxos/feed-store 2.33.4-dev.faf06c70 → 2.33.5-dev.1fc05a51

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.
@@ -20,7 +20,7 @@ describe('FeedDescriptor', () => {
20
20
  beforeEach(async () => {
21
21
  const { publicKey, secretKey } = createKeyPair();
22
22
  fd = new FeedDescriptor({
23
- storage: createStorage('', StorageType.RAM),
23
+ directory: createStorage('', StorageType.RAM).directory('feed'),
24
24
  key: PublicKey.from(publicKey),
25
25
  secretKey,
26
26
  hypercore: defaultHypercore
@@ -41,7 +41,7 @@ describe('FeedDescriptor', () => {
41
41
  // When this behaviour was changed, suddenly `protocol-plugin-replicator` tests started hanging forever on network generation.
42
42
  const { publicKey } = createKeyPair();
43
43
  const key = PublicKey.from(publicKey);
44
- const fd = new FeedDescriptor({ key, storage: createStorage('', StorageType.NODE), hypercore: defaultHypercore });
44
+ const fd = new FeedDescriptor({ key, directory: createStorage('', StorageType.NODE).directory('feed'), hypercore: defaultHypercore });
45
45
  expect(fd.key).toEqual(key);
46
46
  expect(fd.secretKey).toBeUndefined();
47
47
  });
@@ -50,7 +50,7 @@ describe('FeedDescriptor', () => {
50
50
  const { publicKey, secretKey } = createKeyPair();
51
51
 
52
52
  const fd = new FeedDescriptor({
53
- storage: createStorage('', StorageType.RAM),
53
+ directory: createStorage('', StorageType.RAM).directory('feed'),
54
54
  key: PublicKey.from(publicKey),
55
55
  secretKey,
56
56
  valueEncoding: 'json',
@@ -92,7 +92,7 @@ describe('FeedDescriptor', () => {
92
92
  // If we try to close a feed that is opening should wait for the open result.
93
93
  const { publicKey, secretKey } = createKeyPair();
94
94
  const fd2 = new FeedDescriptor({
95
- storage: createStorage('', StorageType.RAM),
95
+ directory: createStorage('', StorageType.RAM).directory('feed'),
96
96
  key: PublicKey.from(publicKey),
97
97
  secretKey,
98
98
  hypercore: defaultHypercore
@@ -108,7 +108,7 @@ describe('FeedDescriptor', () => {
108
108
 
109
109
  const { publicKey, secretKey } = createKeyPair();
110
110
  const fd = new FeedDescriptor({
111
- storage: createStorage(root, StorageType.NODE),
111
+ directory: createStorage(root, StorageType.NODE).directory('feed'),
112
112
  key: PublicKey.from(publicKey),
113
113
  secretKey,
114
114
  valueEncoding: 'utf-8',
@@ -135,7 +135,7 @@ describe('FeedDescriptor', () => {
135
135
  test('on open error should unlock the resource', async () => {
136
136
  const { publicKey, secretKey } = createKeyPair();
137
137
  const fd = new FeedDescriptor({
138
- storage: createStorage('', StorageType.RAM),
138
+ directory: createStorage('', StorageType.RAM).directory('feed'),
139
139
  key: PublicKey.from(publicKey),
140
140
  secretKey,
141
141
  hypercore: () => {
@@ -149,16 +149,16 @@ describe('FeedDescriptor', () => {
149
149
  test('on close error should unlock the resource', async () => {
150
150
  const { publicKey, secretKey } = createKeyPair();
151
151
  const fd = new FeedDescriptor({
152
- storage: createStorage('', StorageType.RAM),
152
+ directory: createStorage('', StorageType.RAM).directory('feed'),
153
153
  key: PublicKey.from(publicKey),
154
154
  secretKey,
155
155
  hypercore: () => ({
156
156
  opened: true,
157
- on () {},
158
- ready (cb: () => void) {
157
+ on: () => {},
158
+ ready: (cb: () => void) => {
159
159
  cb();
160
160
  },
161
- close () {
161
+ close: () => {
162
162
  throw new Error('close error');
163
163
  }
164
164
  } as any)
@@ -8,17 +8,18 @@ import pify from 'pify';
8
8
 
9
9
  import { Lock } from '@dxos/async';
10
10
  import { PublicKey } from '@dxos/crypto';
11
- import type { File, IStorage } from '@dxos/random-access-multi-storage';
11
+ import type { Directory, File } from '@dxos/random-access-multi-storage';
12
12
 
13
13
  import type { HypercoreFeed, Hypercore } from './hypercore-types';
14
14
  import type { ValueEncoding } from './types';
15
15
 
16
16
  interface FeedDescriptorOptions {
17
- storage: IStorage,
17
+ directory: Directory,
18
18
  key: PublicKey,
19
19
  hypercore: Hypercore,
20
20
  secretKey?: Buffer,
21
21
  valueEncoding?: ValueEncoding
22
+ disableSigning?: boolean
22
23
  }
23
24
 
24
25
  /**
@@ -27,29 +28,32 @@ interface FeedDescriptorOptions {
27
28
  * Abstract handler for an Hypercore instance.
28
29
  */
29
30
  export class FeedDescriptor {
30
- private readonly _storage: IStorage;
31
+ private readonly _directory: Directory;
31
32
  private readonly _key: PublicKey;
32
33
  private readonly _secretKey?: Buffer;
33
34
  private readonly _valueEncoding?: ValueEncoding;
34
35
  private readonly _hypercore: Hypercore;
35
36
  private readonly _lock: Lock;
37
+ private readonly _disableSigning: boolean;
36
38
 
37
39
  private _feed: HypercoreFeed | null;
38
40
 
39
41
  constructor (options: FeedDescriptorOptions) {
40
42
  const {
41
- storage,
43
+ directory,
42
44
  key,
43
45
  secretKey,
44
46
  valueEncoding,
45
- hypercore = defaultHypercore
47
+ hypercore = defaultHypercore,
48
+ disableSigning = false
46
49
  } = options;
47
50
 
48
- this._storage = storage;
51
+ this._directory = directory;
49
52
  this._valueEncoding = valueEncoding;
50
53
  this._hypercore = hypercore;
51
54
  this._key = key;
52
55
  this._secretKey = secretKey;
56
+ this._disableSigning = !!disableSigning;
53
57
 
54
58
  this._lock = new Lock();
55
59
 
@@ -117,7 +121,7 @@ export class FeedDescriptor {
117
121
  */
118
122
  private _createStorage (dir = ''): (name: string) => File {
119
123
  return (name) => {
120
- return this._storage.createOrOpen(`${dir}/${name}`);
124
+ return this._directory.createOrOpen(`${dir}/${name}`);
121
125
  };
122
126
  }
123
127
 
@@ -127,7 +131,8 @@ export class FeedDescriptor {
127
131
  this._key.asBuffer(),
128
132
  {
129
133
  secretKey: this._secretKey,
130
- valueEncoding: this._valueEncoding
134
+ valueEncoding: this._valueEncoding,
135
+ crypto: this._disableSigning ? MOCK_CRYPTO : undefined
131
136
  }
132
137
  );
133
138
 
@@ -141,3 +146,12 @@ export class FeedDescriptor {
141
146
  }
142
147
 
143
148
  export default FeedDescriptor;
149
+
150
+ const MOCK_CRYPTO = {
151
+ sign: (data: any, secretKey: any, cb: any) => {
152
+ cb(null, Buffer.from(''));
153
+ },
154
+ verify: (signature: any, data: any, key: any, cb: any) => {
155
+ cb(null, true);
156
+ }
157
+ };
@@ -12,7 +12,7 @@ import tempy from 'tempy';
12
12
 
13
13
  import { sleep } from '@dxos/async';
14
14
  import { PublicKey, createKeyPair } from '@dxos/crypto';
15
- import { IStorage, StorageType, createStorage } from '@dxos/random-access-multi-storage';
15
+ import { Storage, StorageType, createStorage } from '@dxos/random-access-multi-storage';
16
16
 
17
17
  import { FeedDescriptor } from './feed-descriptor';
18
18
  import { FeedStore } from './feed-store';
@@ -25,40 +25,32 @@ interface KeyPair {
25
25
 
26
26
  const feedNames = ['booksFeed', 'usersFeed', 'groupsFeed'];
27
27
 
28
- const createFeedStore = (storage: IStorage, options = {}) => {
29
- const feedStore = new FeedStore(storage, options);
28
+ const createFeedStore = (storage: Storage, options = {}) => {
29
+ const feedStore = new FeedStore(storage.directory('feed'), options);
30
30
  return feedStore;
31
31
  };
32
32
 
33
- async function createDefault () {
33
+ const createDefault = async () => {
34
34
  const directory = tempy.directory();
35
35
 
36
36
  return {
37
37
  directory,
38
38
  feedStore: createFeedStore(createStorage(directory, StorageType.NODE), { valueEncoding: 'utf-8' })
39
39
  };
40
- }
40
+ };
41
41
 
42
- async function defaultFeeds (feedStore: FeedStore, keys: Record<string, KeyPair>) : Promise<Record<string, FeedDescriptor>> {
43
- return Object.fromEntries(await Promise.all(Object.entries<KeyPair>(keys).map(async ([feed, keyPair]) =>
44
- [feed, await feedStore.openReadWriteFeed(keyPair.key, keyPair.secretKey)]
45
- )));
46
- }
42
+ const defaultFeeds = async (feedStore: FeedStore, keys: Record<string, KeyPair>): Promise<Record<string, FeedDescriptor>> => Object.fromEntries(await Promise.all(Object.entries<KeyPair>(keys).map(async ([feed, keyPair]) =>
43
+ [feed, await feedStore.openReadWriteFeed(keyPair.key, keyPair.secretKey)]
44
+ )));
47
45
 
48
- function append (feed: HypercoreFeed, message: any) {
49
- return pify(feed.append.bind(feed))(message);
50
- }
46
+ const append = (feed: HypercoreFeed, message: any) => pify(feed.append.bind(feed))(message);
51
47
 
52
- function head (feed: HypercoreFeed) {
53
- return pify(feed.head.bind(feed))();
54
- }
48
+ const head = (feed: HypercoreFeed) => pify(feed.head.bind(feed))();
55
49
 
56
- const createKeyPairs = () => {
57
- return Object.fromEntries<KeyPair>(feedNames.map(feed => {
58
- const { publicKey, secretKey } = createKeyPair();
59
- return [feed, { key: PublicKey.from(publicKey), secretKey }];
60
- }));
61
- };
50
+ const createKeyPairs = () => Object.fromEntries<KeyPair>(feedNames.map(feed => {
51
+ const { publicKey, secretKey } = createKeyPair();
52
+ return [feed, { key: PublicKey.from(publicKey), secretKey }];
53
+ }));
62
54
 
63
55
  describe('FeedStore', () => {
64
56
  const keys = createKeyPairs();
@@ -67,17 +59,16 @@ describe('FeedStore', () => {
67
59
  const feedStore = await createFeedStore(createStorage('', StorageType.RAM));
68
60
  expect(feedStore).toBeInstanceOf(FeedStore);
69
61
 
70
- const feedStore2 = new FeedStore(createStorage('', StorageType.RAM));
62
+ const feedStore2 = new FeedStore(createStorage('', StorageType.RAM).directory('feed'));
71
63
  expect(feedStore2).toBeInstanceOf(FeedStore);
72
64
  });
73
65
 
74
66
  test('Config default + custom database + custom hypercore', async () => {
75
- const customHypercore = jest.fn((...args) => {
76
- return hypercore(args[0], args[1], args[2]);
77
- });
67
+ const customHypercore = jest.fn((...args) => hypercore(args[0], args[1], args[2]));
78
68
 
79
69
  const storage = createStorage('', StorageType.RAM);
80
- const database = hypertrie(storage.createOrOpen.bind(storage), { valueEncoding: 'json' });
70
+ const directory = storage.directory('');
71
+ const database = hypertrie(directory.createOrOpen.bind(directory), { valueEncoding: 'json' });
81
72
  database.list = jest.fn((_, cb) => cb(null, []));
82
73
 
83
74
  const feedStore = createFeedStore(createStorage('', StorageType.RAM), {
@@ -175,11 +166,11 @@ describe('FeedStore', () => {
175
166
  const feedStore = createFeedStore(createStorage('', StorageType.RAM), {
176
167
  hypercore: () => ({
177
168
  opened: true,
178
- ready (cb: () => void) {
169
+ ready: (cb: () => void) => {
179
170
  cb();
180
171
  },
181
- on () {},
182
- close () {
172
+ on: () => {},
173
+ close: () => {
183
174
  throw new Error('close error');
184
175
  }
185
176
  })
package/src/feed-store.ts CHANGED
@@ -7,7 +7,7 @@ import defaultHypercore from 'hypercore';
7
7
 
8
8
  import { synchronized, Event } from '@dxos/async';
9
9
  import { PublicKey } from '@dxos/crypto';
10
- import { IStorage } from '@dxos/random-access-multi-storage';
10
+ import { Directory } from '@dxos/random-access-multi-storage';
11
11
 
12
12
  import FeedDescriptor from './feed-descriptor';
13
13
  import type { Hypercore } from './hypercore-types';
@@ -45,7 +45,7 @@ export interface FeedStoreOptions {
45
45
  * into a persist repository storage.
46
46
  */
47
47
  export class FeedStore {
48
- private _storage: IStorage;
48
+ private _directory: Directory;
49
49
  private _valueEncoding: ValueEncoding | undefined;
50
50
  private _hypercore: Hypercore;
51
51
  private _descriptors: Map<string, FeedDescriptor>;
@@ -56,13 +56,13 @@ export class FeedStore {
56
56
  readonly feedOpenedEvent = new Event<FeedDescriptor>();
57
57
 
58
58
  /**
59
- * @param storage RandomAccessStorage to use by default by the feeds.
59
+ * @param directory RandomAccessStorage to use by default by the feeds.
60
60
  * @param options Feedstore options.
61
61
  */
62
- constructor (storage: IStorage, options: FeedStoreOptions = {}) {
63
- assert(storage, 'The storage is required.');
62
+ constructor (directory: Directory, options: FeedStoreOptions = {}) {
63
+ assert(directory, 'The storage is required.');
64
64
 
65
- this._storage = storage;
65
+ this._directory = directory;
66
66
 
67
67
  const {
68
68
  valueEncoding,
@@ -79,7 +79,7 @@ export class FeedStore {
79
79
  * @type {RandomAccessStorage}
80
80
  */
81
81
  get storage () {
82
- return this._storage;
82
+ return this._directory;
83
83
  }
84
84
 
85
85
  @synchronized
@@ -114,7 +114,7 @@ export class FeedStore {
114
114
  const { key, secretKey } = options;
115
115
 
116
116
  const descriptor = new FeedDescriptor({
117
- storage: this._storage,
117
+ directory: this._directory,
118
118
  key,
119
119
  secretKey,
120
120
  valueEncoding: this._valueEncoding,
@@ -133,7 +133,7 @@ export class FeedStore {
133
133
  }
134
134
  }
135
135
 
136
- function patchBufferCodec (encoding: ValueEncoding): ValueEncoding {
136
+ const patchBufferCodec = (encoding: ValueEncoding): ValueEncoding => {
137
137
  if (typeof encoding === 'string') {
138
138
  return encoding;
139
139
  }
@@ -141,4 +141,4 @@ function patchBufferCodec (encoding: ValueEncoding): ValueEncoding {
141
141
  encode: (x: any) => Buffer.from(encoding.encode(x)),
142
142
  decode: encoding.decode.bind(encoding)
143
143
  };
144
- }
144
+ };
package/src/stream.ts CHANGED
@@ -20,62 +20,54 @@ const error = debug('dxos:stream:error');
20
20
  * @returns {NodeJS.WritableStream}
21
21
  */
22
22
  // TODO(burdon): Move to @dxos/codec.
23
- export function createWritableFeedStream (feed: HypercoreFeed) {
24
- return new Writable({
25
- objectMode: true,
26
- write (message, _, callback) {
27
- feed.append(message, callback);
28
- }
29
- });
30
- }
23
+ export const createWritableFeedStream = (feed: HypercoreFeed) => new Writable({
24
+ objectMode: true,
25
+ write: (message, _, callback) => {
26
+ feed.append(message, callback);
27
+ }
28
+ });
31
29
 
32
30
  /**
33
31
  * Creates a readStream stream that can be used as a buffer into which messages can be pushed.
34
32
  */
35
- export function createReadable (): Readable {
36
- return new Readable({
37
- objectMode: true,
38
- read () {}
39
- });
40
- }
33
+ export const createReadable = (): Readable => new Readable({
34
+ objectMode: true,
35
+ read: () => {}
36
+ });
41
37
 
42
38
  /**
43
39
  * Creates a writeStream object stream.
44
40
  * @param callback
45
41
  */
46
- export function createWritable<T> (callback: (message: T) => Promise<void>): NodeJS.WritableStream {
47
- return new Writable({
48
- objectMode: true,
49
- write: async (message: T, _, next) => {
50
- try {
51
- await callback(message);
52
- next();
53
- } catch (err: any) {
54
- error(err);
55
- next(err);
56
- }
42
+ export const createWritable = <T>(callback: (message: T) => Promise<void>): NodeJS.WritableStream => new Writable({
43
+ objectMode: true,
44
+ write: async (message: T, _, next) => {
45
+ try {
46
+ await callback(message);
47
+ next();
48
+ } catch (err: any) {
49
+ error(err);
50
+ next(err);
57
51
  }
58
- });
59
- }
52
+ }
53
+ });
60
54
 
61
55
  /**
62
56
  * Creates a transform object stream.
63
57
  * @param callback
64
58
  */
65
- export function createTransform<R, W> (callback: (message: R) => Promise<W | undefined>): Transform {
66
- return new Transform({
67
- objectMode: true,
68
- transform: async (message: R, _, next) => {
69
- try {
70
- const response = await callback(message);
71
- next(null, response);
72
- } catch (err: any) {
73
- error(err);
74
- next(err);
75
- }
59
+ export const createTransform = <R, W>(callback: (message: R) => Promise<W | undefined>): Transform => new Transform({
60
+ objectMode: true,
61
+ transform: async (message: R, _, next) => {
62
+ try {
63
+ const response = await callback(message);
64
+ next(null, response);
65
+ } catch (err: any) {
66
+ error(err);
67
+ next(err);
76
68
  }
77
- });
78
- }
69
+ }
70
+ });
79
71
 
80
72
  /**
81
73
  * Wriable stream that collects objects (e.g., for testing).