@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.
- 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 +5 -3
- package/dist/src/feed-descriptor.d.ts.map +1 -1
- package/dist/src/feed-descriptor.js +14 -4
- 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 +22 -8
- package/src/feed-store.test.ts +23 -32
- package/src/feed-store.ts +10 -10
- package/src/stream.ts +32 -40
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
feed.ready(
|
|
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
|
-
|
|
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
|
-
|
|
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,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 {
|
|
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,
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
+
};
|
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).
|