@dxos/feed-store 2.33.5-dev.0a40e013 → 2.33.5-dev.0d84e06f
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.
- package/dist/src/benchmark.js +22 -26
- package/dist/src/benchmark.js.map +1 -1
- package/dist/src/create-batch-stream.d.ts +1 -1
- package/dist/src/create-batch-stream.d.ts.map +1 -1
- package/dist/src/create-batch-stream.js +14 -14
- package/dist/src/create-batch-stream.js.map +1 -1
- package/dist/src/create-batch-stream.test.js +2 -4
- package/dist/src/create-batch-stream.test.js.map +1 -1
- package/dist/src/feed-descriptor.d.ts +3 -3
- package/dist/src/feed-descriptor.d.ts.map +1 -1
- package/dist/src/feed-descriptor.js +3 -3
- package/dist/src/feed-descriptor.js.map +1 -1
- package/dist/src/feed-descriptor.test.js +10 -10
- package/dist/src/feed-descriptor.test.js.map +1 -1
- package/dist/src/feed-store.d.ts +5 -5
- package/dist/src/feed-store.d.ts.map +1 -1
- package/dist/src/feed-store.js +8 -8
- package/dist/src/feed-store.js.map +1 -1
- package/dist/src/feed-store.test.js +20 -29
- package/dist/src/feed-store.test.js.map +1 -1
- package/dist/src/stream.d.ts +4 -4
- package/dist/src/stream.d.ts.map +1 -1
- package/dist/src/stream.js +34 -42
- package/dist/src/stream.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/benchmark.ts +24 -28
- package/src/create-batch-stream.test.ts +2 -4
- package/src/create-batch-stream.ts +15 -15
- package/src/feed-descriptor.test.ts +10 -10
- package/src/feed-descriptor.ts +6 -6
- package/src/feed-store.test.ts +23 -32
- package/src/feed-store.ts +10 -10
- package/src/stream.ts +32 -40
|
@@ -20,7 +20,7 @@ describe('FeedDescriptor', () => {
|
|
|
20
20
|
beforeEach(async () => {
|
|
21
21
|
const { publicKey, secretKey } = createKeyPair();
|
|
22
22
|
fd = new FeedDescriptor({
|
|
23
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
package/src/feed-descriptor.ts
CHANGED
|
@@ -8,13 +8,13 @@ import pify from 'pify';
|
|
|
8
8
|
|
|
9
9
|
import { Lock } from '@dxos/async';
|
|
10
10
|
import { PublicKey } from '@dxos/crypto';
|
|
11
|
-
import type {
|
|
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
|
-
|
|
17
|
+
directory: Directory,
|
|
18
18
|
key: PublicKey,
|
|
19
19
|
hypercore: Hypercore,
|
|
20
20
|
secretKey?: Buffer,
|
|
@@ -28,7 +28,7 @@ interface FeedDescriptorOptions {
|
|
|
28
28
|
* Abstract handler for an Hypercore instance.
|
|
29
29
|
*/
|
|
30
30
|
export class FeedDescriptor {
|
|
31
|
-
private readonly
|
|
31
|
+
private readonly _directory: Directory;
|
|
32
32
|
private readonly _key: PublicKey;
|
|
33
33
|
private readonly _secretKey?: Buffer;
|
|
34
34
|
private readonly _valueEncoding?: ValueEncoding;
|
|
@@ -40,7 +40,7 @@ export class FeedDescriptor {
|
|
|
40
40
|
|
|
41
41
|
constructor (options: FeedDescriptorOptions) {
|
|
42
42
|
const {
|
|
43
|
-
|
|
43
|
+
directory,
|
|
44
44
|
key,
|
|
45
45
|
secretKey,
|
|
46
46
|
valueEncoding,
|
|
@@ -48,7 +48,7 @@ export class FeedDescriptor {
|
|
|
48
48
|
disableSigning = false
|
|
49
49
|
} = options;
|
|
50
50
|
|
|
51
|
-
this.
|
|
51
|
+
this._directory = directory;
|
|
52
52
|
this._valueEncoding = valueEncoding;
|
|
53
53
|
this._hypercore = hypercore;
|
|
54
54
|
this._key = key;
|
|
@@ -121,7 +121,7 @@ export class FeedDescriptor {
|
|
|
121
121
|
*/
|
|
122
122
|
private _createStorage (dir = ''): (name: string) => File {
|
|
123
123
|
return (name) => {
|
|
124
|
-
return this.
|
|
124
|
+
return this._directory.createOrOpen(`${dir}/${name}`);
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
127
|
|
package/src/feed-store.test.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
|
|
53
|
-
return pify(feed.head.bind(feed))();
|
|
54
|
-
}
|
|
48
|
+
const head = (feed: HypercoreFeed) => pify(feed.head.bind(feed))();
|
|
55
49
|
|
|
56
|
-
const createKeyPairs = () => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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('
|
|
59
|
+
const feedStore = await createFeedStore(createStorage('', StorageType.RAM));
|
|
68
60
|
expect(feedStore).toBeInstanceOf(FeedStore);
|
|
69
61
|
|
|
70
|
-
const feedStore2 = new FeedStore(createStorage('
|
|
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
|
|
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('
|
|
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('
|
|
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('
|
|
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 {
|
|
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
|
|
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
|
|
59
|
+
* @param directory RandomAccessStorage to use by default by the feeds.
|
|
60
60
|
* @param options Feedstore options.
|
|
61
61
|
*/
|
|
62
|
-
constructor (
|
|
63
|
-
assert(
|
|
62
|
+
constructor (directory: Directory, options: FeedStoreOptions = {}) {
|
|
63
|
+
assert(directory, 'The storage is required.');
|
|
64
64
|
|
|
65
|
-
this.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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).
|