@dxos/feed-store 2.33.5-dev.ea3876ba → 2.33.5-dev.ebc105f7

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.
@@ -13,15 +13,13 @@ import { FeedStore } from './feed-store';
13
13
  import { HypercoreFeed } from './hypercore-types';
14
14
 
15
15
  const createFeed = async () => {
16
- const feedStore = new FeedStore(createStorage('', StorageType.RAM), { valueEncoding: 'utf-8' });
16
+ const feedStore = new FeedStore(createStorage('', StorageType.RAM).directory('feed'), { valueEncoding: 'utf-8' });
17
17
  const { publicKey, secretKey } = createKeyPair();
18
18
  const { feed } = await feedStore.openReadWriteFeed(PublicKey.from(publicKey), secretKey);
19
19
  return feed;
20
20
  };
21
21
 
22
- const append = (feed: HypercoreFeed, message: any) => {
23
- return pify(feed.append.bind(feed))(message);
24
- };
22
+ const append = (feed: HypercoreFeed, message: any) => pify(feed.append.bind(feed))(message);
25
23
 
26
24
  describe('Batch stream', () => {
27
25
  test('Single message', async () => {
@@ -17,7 +17,7 @@ export interface CreateBatchStreamOptions {
17
17
  tail?: boolean
18
18
  }
19
19
 
20
- export function createBatchStream (feed: HypercoreFeed, opts: CreateBatchStreamOptions = {}) {
20
+ export const createBatchStream = (feed: HypercoreFeed, opts: CreateBatchStreamOptions = {}) => {
21
21
  assert(!opts.batch || opts.batch > 0, 'batch must be major or equal to 1');
22
22
 
23
23
  let start = opts.start || 0;
@@ -34,9 +34,7 @@ export function createBatchStream (feed: HypercoreFeed, opts: CreateBatchStreamO
34
34
 
35
35
  let range = feed.download({ start, end, linear: true });
36
36
 
37
- return streamFrom.obj(read).on('end', cleanup).on('close', cleanup);
38
-
39
- function read (size: any, cb?: any) {
37
+ const read = (size: any, cb?: any) => {
40
38
  if (!feed.opened) {
41
39
  return open(size, cb);
42
40
  }
@@ -103,9 +101,9 @@ export function createBatchStream (feed: HypercoreFeed, opts: CreateBatchStreamO
103
101
 
104
102
  cb(null, messages.map(buildMessage));
105
103
  });
106
- }
104
+ };
107
105
 
108
- function buildMessage (data: object) {
106
+ const buildMessage = (data: object) => {
109
107
  const message = {
110
108
  key: feed.key,
111
109
  seq: seq++,
@@ -115,26 +113,26 @@ export function createBatchStream (feed: HypercoreFeed, opts: CreateBatchStreamO
115
113
  };
116
114
 
117
115
  return message;
118
- }
116
+ };
119
117
 
120
- function cleanup () {
118
+ const cleanup = () => {
121
119
  if (!range) {
122
120
  return;
123
121
  }
124
122
  feed.undownload(range);
125
123
  range = null;
126
- }
124
+ };
127
125
 
128
- function open (size: any, cb: (err: Error) => void) {
129
- feed.ready(function (err: Error) {
126
+ const open = (size: any, cb: (err: Error) => void) => {
127
+ feed.ready((err: Error) => {
130
128
  if (err) {
131
129
  return cb(err);
132
130
  }
133
131
  read(size, cb);
134
132
  });
135
- }
133
+ };
136
134
 
137
- function setStart (value: number) {
135
+ const setStart = (value: number) => {
138
136
  const prevStart = start;
139
137
  start = value;
140
138
  range.start = start;
@@ -142,5 +140,7 @@ export function createBatchStream (feed: HypercoreFeed, opts: CreateBatchStreamO
142
140
  range.iterator.start = start;
143
141
  }
144
142
  return prevStart;
145
- }
146
- }
143
+ };
144
+
145
+ return streamFrom.obj(read).on('end', cleanup).on('close', cleanup);
146
+ };
@@ -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, Storage } 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: Storage,
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: Storage;
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
+ };
@@ -26,61 +26,52 @@ interface KeyPair {
26
26
  const feedNames = ['booksFeed', 'usersFeed', 'groupsFeed'];
27
27
 
28
28
  const createFeedStore = (storage: Storage, options = {}) => {
29
- const feedStore = new FeedStore(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();
65
57
 
66
58
  test('Config default', async () => {
67
- const feedStore = await createFeedStore(createStorage('feed', StorageType.RAM));
59
+ const feedStore = await createFeedStore(createStorage('', StorageType.RAM));
68
60
  expect(feedStore).toBeInstanceOf(FeedStore);
69
61
 
70
- const feedStore2 = new FeedStore(createStorage('feed', 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
- const feedStore = createFeedStore(createStorage('feed', StorageType.RAM), {
74
+ const feedStore = createFeedStore(createStorage('', StorageType.RAM), {
84
75
  hypercore: customHypercore
85
76
  });
86
77
 
@@ -161,7 +152,7 @@ describe('FeedStore', () => {
161
152
  });
162
153
 
163
154
  test('Default codec: binary', async () => {
164
- const feedStore = createFeedStore(createStorage('feed', StorageType.RAM));
155
+ const feedStore = createFeedStore(createStorage('', StorageType.RAM));
165
156
  expect(feedStore).toBeInstanceOf(FeedStore);
166
157
 
167
158
  const { publicKey, secretKey } = createKeyPair();
@@ -172,14 +163,14 @@ describe('FeedStore', () => {
172
163
  });
173
164
 
174
165
  test('on close error should unlock the descriptor', async () => {
175
- const feedStore = createFeedStore(createStorage('feed', StorageType.RAM), {
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 { Storage } 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: Storage;
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: Storage, 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).