@libp2p/multistream-select 2.0.0 → 3.0.0

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/README.md CHANGED
@@ -1,41 +1,39 @@
1
- # js-multistream-select <!-- omit in toc -->
1
+ # @libp2p/multistream-select <!-- omit in toc -->
2
2
 
3
- [![test & maybe release](https://github.com/libp2p/js-libp2p-multistream-select/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-multistream-select/actions/workflows/js-test-and-release.yml)
3
+ [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
4
+ [![IRC](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p)
5
+ [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io)
6
+ [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-multistream-select.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-multistream-select)
7
+ [![CI](https://img.shields.io/github/workflow/status/libp2p/js-libp2p-interfaces/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/libp2p/js-libp2p-multistream-select/actions/workflows/js-test-and-release.yml)
4
8
 
5
- > JavaScript implementation of [multistream-select](https://github.com/multiformats/multistream-select)
9
+ > JavaScript implementation of multistream-select
6
10
 
7
- ## Table of Contents <!-- omit in toc -->
11
+ ## Table of contents <!-- omit in toc -->
8
12
 
13
+ - [Install](#install)
9
14
  - [Background](#background)
10
15
  - [What is `multistream-select`?](#what-is-multistream-select)
11
16
  - [Select a protocol flow](#select-a-protocol-flow)
12
- - [Install](#install)
13
17
  - [Usage](#usage)
14
18
  - [Dialer](#dialer)
15
19
  - [Listener](#listener)
16
20
  - [API](#api)
17
- - [`new Dialer(duplex)`](#new-dialerduplex)
21
+ - [`mss.select(dulpex, protocols, [options])`](#mssselectdulpex-protocols-options)
18
22
  - [Parameters](#parameters)
19
23
  - [Returns](#returns)
20
24
  - [Examples](#examples)
21
- - [`dialer.select(protocols, [options])`](#dialerselectprotocols-options)
25
+ - [`mss.handle(duplex, protocols, [options])`](#msshandleduplex-protocols-options)
22
26
  - [Parameters](#parameters-1)
23
27
  - [Returns](#returns-1)
24
28
  - [Examples](#examples-1)
25
- - [`dialer.ls([options])`](#dialerlsoptions)
26
- - [Parameters](#parameters-2)
27
- - [Returns](#returns-2)
28
- - [Examples](#examples-2)
29
- - [`new Listener(duplex)`](#new-listenerduplex)
30
- - [Parameters](#parameters-3)
31
- - [Returns](#returns-3)
32
- - [Examples](#examples-3)
33
- - [`listener.handle(protocols, [options])`](#listenerhandleprotocols-options)
34
- - [Parameters](#parameters-4)
35
- - [Returns](#returns-4)
36
- - [Examples](#examples-4)
37
29
  - [License](#license)
38
- - [Contribution](#contribution)
30
+ - [Contribution](#contribution)
31
+
32
+ ## Install
33
+
34
+ ```console
35
+ $ npm i @libp2p/multistream-select
36
+ ```
39
37
 
40
38
  ## Background
41
39
 
@@ -59,39 +57,29 @@ The caller will send "interactive" messages, expecting for some acknowledgement
59
57
  > <dht-message>
60
58
  ```
61
59
 
62
- This mode also packs a `ls` option, so that the callee can list the protocols it currently supports
63
-
64
- ## Install
65
-
66
- ```sh
67
- npm i @libp2p/multistream-select
68
- ```
69
-
70
60
  ## Usage
71
61
 
72
62
  ```js
73
- import { Dialer, Listener } from '@libp2p/multistream-select'
63
+ import { select, handle } from '@libp2p/multistream-select'
74
64
  // You can now use
75
- // Dialer - actively select a protocol with a remote
76
- // Listener - handle a protocol with a remote
65
+ // select - actively select a protocol with a remote
66
+ // handle - handle a protocol with a remote
77
67
  ```
78
68
 
79
69
  ### Dialer
80
70
 
81
71
  ```js
82
72
  import { pipe } from 'it-pipe'
83
- import { Dialer } from '@libp2p/multistream-select'
73
+ import * as mss from '@libp2p/multistream-select'
84
74
  import { Mplex } from '@libp2p/mplex'
85
75
 
86
76
  const muxer = new Mplex()
87
77
  const muxedStream = muxer.newStream()
88
78
 
89
- const mss = new Dialer(muxedStream)
90
-
91
79
  // mss.select(protocol(s))
92
80
  // Select from one of the passed protocols (in priority order)
93
81
  // Returns selected stream and protocol
94
- const { stream: dhtStream, protocol } = await mss.select([
82
+ const { stream: dhtStream, protocol } = await mss.select(muxedStream, [
95
83
  // This might just be different versions of DHT, but could be different impls
96
84
  '/ipfs-dht/2.0.0', // Most of the time this will probably just be one item.
97
85
  '/ipfs-dht/1.0.0'
@@ -118,16 +106,14 @@ const { stream: dhtStream, protocol } = await mss.select([
118
106
 
119
107
  ```js
120
108
  import { pipe } from 'it-pipe'
121
- import { Listener } from '@libp2p/multistream-select'
109
+ import * as mss from '@libp2p/multistream-select'
122
110
  import { Mplex } from '@libp2p/mplex'
123
111
 
124
112
  const muxer = new Mplex({
125
113
  async onStream (muxedStream) {
126
- const mss = new Listener(muxedStream)
127
-
128
114
  // mss.handle(handledProtocols)
129
115
  // Returns selected stream and protocol
130
- const { stream, protocol } = await mss.handle([
116
+ const { stream, protocol } = await mss.handle(muxedStream, [
131
117
  '/ipfs-dht/1.0.0',
132
118
  '/ipfs-bitswap/1.0.0'
133
119
  ])
@@ -155,36 +141,19 @@ const muxer = new Mplex({
155
141
 
156
142
  ## API
157
143
 
158
- ### `new Dialer(duplex)`
159
-
160
- Create a new multistream select "dialer" instance which can be used to negotiate a protocol to use, list all available protocols the remote supports, or do both.
161
-
162
- #### Parameters
163
-
164
- * `duplex` (`Object`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to dial on.
165
-
166
- #### Returns
167
-
168
- A new multistream select dialer instance.
169
-
170
- #### Examples
171
-
172
- ```js
173
- const dialer = new MSS.Dialer(duplex)
174
- ```
175
-
176
- ### `dialer.select(protocols, [options])`
144
+ ### `mss.select(dulpex, protocols, [options])`
177
145
 
178
146
  Negotiate a protocol to use from a list of protocols.
179
147
 
180
148
  #### Parameters
181
149
 
182
- * `protocols` (`String[]`/`String`) - A list of protocols (or single protocol) to negotiate with. Protocols are attempted in order until a match is made.
183
- * `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal
150
+ - `duplex` (`Duplex`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to dial on.
151
+ - `protocols` (`string[]`/`string`) - A list of protocols (or single protocol) to negotiate with. Protocols are attempted in order until a match is made.
152
+ - `options` (`{ signal: AbortSignal, writeBytes?: boolean }`) - an options object containing an AbortSignal and an optional boolean `writeBytes` - if this is true, `Uint8Array`s will be written into `duplex`, otherwise `Uint8ArrayList`s will
184
153
 
185
154
  #### Returns
186
155
 
187
- `Promise<{ stream<Object>, protocol<String> }>` - A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`.
156
+ `Promise<{ stream<Duplex>, protocol<string> }>` - A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`.
188
157
 
189
158
  Note that after a protocol is selected `dialer` can no longer be used.
190
159
 
@@ -199,68 +168,26 @@ const { stream, protocol } = await dialer.select([
199
168
  // Now talk `protocol` on `stream`
200
169
  ```
201
170
 
202
- ### `dialer.ls([options])`
203
-
204
- List protocols that the remote supports.
205
-
206
- #### Parameters
207
-
208
- * `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal
209
-
210
- #### Returns
211
-
212
- `String[]` - A list of all the protocols the remote supports.
213
-
214
- #### Examples
215
-
216
- ```js
217
- const protocols = await dialer.ls()
218
- const wantedProto = '/ipfs-dht/2.0.0'
219
-
220
- if (!protocols.includes(wantedProto)) {
221
- throw new Error('remote does not support ' + wantedProto)
222
- }
223
-
224
- // Now use dialer.select to use wantedProto, safe in the knowledge it is supported
225
- ```
226
-
227
- ### `new Listener(duplex)`
228
-
229
- Construct a new multistream select "listener" instance which can be used to handle multistream protocol selections for particular protocols.
230
-
231
- #### Parameters
232
-
233
- * `duplex` (`Object`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to listen on.
234
-
235
- #### Returns
236
-
237
- A new multistream select listener instance.
238
-
239
- #### Examples
240
-
241
- ```js
242
- const listener = new MSS.Listener(duplex)
243
- ```
244
-
245
- ### `listener.handle(protocols, [options])`
171
+ ### `mss.handle(duplex, protocols, [options])`
246
172
 
247
173
  Handle multistream protocol selections for the given list of protocols.
248
174
 
249
175
  #### Parameters
250
176
 
251
- * `protocols` (`String[]`/`String`) - A list of protocols (or single protocol) that this listener is able to speak.
252
- * `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal
177
+ - `duplex` (`Duplex`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to listen on.
178
+ - `protocols` (`String[]`/`String`) - A list of protocols (or single protocol) that this listener is able to speak.
179
+ - `options` (`{ signal: AbortSignal, writeBytes?: boolean }`) - an options object containing an AbortSignal and an optional boolean `writeBytes` - if this is true, `Uint8Array`s will be written into `duplex`, otherwise `Uint8ArrayList`s will
253
180
 
254
181
  #### Returns
255
182
 
256
- `Promise<{ stream<Object>, protocol<String> }>` - A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`.
183
+ `Promise<{ stream<Duplex>, protocol<string> }>` - A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`.
257
184
 
258
185
  Note that after a protocol is handled `listener` can no longer be used.
259
186
 
260
187
  #### Examples
261
188
 
262
189
  ```js
263
- const { stream, protocol } = await listener.handle([
190
+ const { stream, protocol } = await mss.handle(duplex, [
264
191
  '/ipfs-dht/1.0.0',
265
192
  '/ipfs-bitswap/1.0.0'
266
193
  ])
@@ -271,9 +198,9 @@ const { stream, protocol } = await listener.handle([
271
198
 
272
199
  Licensed under either of
273
200
 
274
- * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0)
275
- * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT)
201
+ - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
202
+ - MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
276
203
 
277
- ### Contribution
204
+ ## Contribution
278
205
 
279
206
  Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
@@ -1,7 +1,6 @@
1
- import type { AbortOptions } from '@libp2p/interfaces';
1
+ import { Uint8ArrayList } from 'uint8arraylist';
2
2
  import type { Duplex } from 'it-stream-types';
3
- export declare function handle(stream: Duplex<Uint8Array>, protocols: string | string[], options?: AbortOptions): Promise<{
4
- stream: Duplex<Uint8Array, Uint8Array, Promise<void>>;
5
- protocol: string;
6
- }>;
3
+ import type { ByteArrayInit, ByteListInit, ProtocolStream } from './index.js';
4
+ export declare function handle(stream: Duplex<Uint8Array>, protocols: string | string[], options: ByteArrayInit): Promise<ProtocolStream<Uint8Array>>;
5
+ export declare function handle(stream: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>, protocols: string | string[], options?: ByteListInit): Promise<ProtocolStream<Uint8ArrayList, Uint8ArrayList | Uint8Array>>;
7
6
  //# sourceMappingURL=handle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handle.d.ts","sourceRoot":"","sources":["../../src/handle.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAI7C,wBAAsB,MAAM,CAAE,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY;;;GA+B7G"}
1
+ {"version":3,"file":"handle.d.ts","sourceRoot":"","sources":["../../src/handle.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAyB,cAAc,EAAE,MAAM,YAAY,CAAA;AAIpG,wBAAsB,MAAM,CAAE,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;AACpJ,wBAAsB,MAAM,CAAE,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,cAAc,GAAG,UAAU,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,cAAc,GAAG,UAAU,CAAC,CAAC,CAAA"}
@@ -13,22 +13,23 @@ export async function handle(stream, protocols, options) {
13
13
  log('read "%s"', protocol);
14
14
  if (protocol === PROTOCOL_ID) {
15
15
  log('respond with "%s" for "%s"', PROTOCOL_ID, protocol);
16
- multistream.write(writer, uint8ArrayFromString(PROTOCOL_ID));
16
+ multistream.write(writer, uint8ArrayFromString(PROTOCOL_ID), options);
17
17
  continue;
18
18
  }
19
19
  if (protocols.includes(protocol)) {
20
- multistream.write(writer, uint8ArrayFromString(protocol));
20
+ multistream.write(writer, uint8ArrayFromString(protocol), options);
21
21
  log('respond with "%s" for "%s"', protocol, protocol);
22
22
  rest();
23
23
  return { stream: shakeStream, protocol };
24
24
  }
25
25
  if (protocol === 'ls') {
26
26
  // <varint-msg-len><varint-proto-name-len><proto-name>\n<varint-proto-name-len><proto-name>\n\n
27
- multistream.write(writer, new Uint8ArrayList(...protocols.map(p => multistream.encode(uint8ArrayFromString(p)))));
27
+ multistream.write(writer, new Uint8ArrayList(...protocols.map(p => multistream.encode(uint8ArrayFromString(p)))), options);
28
+ // multistream.writeAll(writer, protocols.map(p => uint8ArrayFromString(p)))
28
29
  log('respond with "%s" for %s', protocols, protocol);
29
30
  continue;
30
31
  }
31
- multistream.write(writer, uint8ArrayFromString('na'));
32
+ multistream.write(writer, uint8ArrayFromString('na'), options);
32
33
  log('respond with "na" for "%s"', protocol);
33
34
  }
34
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"handle.js","sourceRoot":"","sources":["../../src/handle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAI/C,MAAM,GAAG,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAA;AAEvC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAE,MAA0B,EAAE,SAA4B,EAAE,OAAsB;IAC5G,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAEvE,OAAO,IAAI,EAAE;QACX,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9D,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QAE1B,IAAI,QAAQ,KAAK,WAAW,EAAE;YAC5B,GAAG,CAAC,4BAA4B,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAA;YACxD,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAA;YAC5D,SAAQ;SACT;QAED,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YAChC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAA;YACzD,GAAG,CAAC,4BAA4B,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YACrD,IAAI,EAAE,CAAA;YACN,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAA;SACzC;QAED,IAAI,QAAQ,KAAK,IAAI,EAAE;YACrB,+FAA+F;YAC/F,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,cAAc,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YACjH,GAAG,CAAC,0BAA0B,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;YACpD,SAAQ;SACT;QAED,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAA;QACrD,GAAG,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAA;KAC5C;AACH,CAAC"}
1
+ {"version":3,"file":"handle.js","sourceRoot":"","sources":["../../src/handle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAI/C,MAAM,GAAG,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAA;AAIvC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAE,MAAmB,EAAE,SAA4B,EAAE,OAA+B;IAC9G,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAEvE,OAAO,IAAI,EAAE;QACX,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9D,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QAE1B,IAAI,QAAQ,KAAK,WAAW,EAAE;YAC5B,GAAG,CAAC,4BAA4B,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAA;YACxD,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAA;YACrE,SAAQ;SACT;QAED,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YAChC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAA;YAClE,GAAG,CAAC,4BAA4B,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YACrD,IAAI,EAAE,CAAA;YACN,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAA;SACzC;QAED,IAAI,QAAQ,KAAK,IAAI,EAAE;YACrB,+FAA+F;YAC/F,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,cAAc,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;YAC1H,4EAA4E;YAC5E,GAAG,CAAC,0BAA0B,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;YACpD,SAAQ;SACT;QAED,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;QAC9D,GAAG,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAA;KAC5C;AACH,CAAC"}
@@ -2,25 +2,19 @@ import { PROTOCOL_ID } from './constants.js';
2
2
  import type { Duplex } from 'it-stream-types';
3
3
  import type { AbortOptions } from '@libp2p/interfaces';
4
4
  export { PROTOCOL_ID };
5
- export interface ProtocolStream {
6
- stream: Duplex<Uint8Array>;
5
+ export interface ProtocolStream<TSource, TSink = TSource> {
6
+ stream: Duplex<TSource, TSink>;
7
7
  protocol: string;
8
8
  }
9
- declare class MultistreamSelect {
10
- protected stream: Duplex<Uint8Array>;
11
- protected shaken: boolean;
12
- constructor(stream: Duplex<Uint8Array>);
13
- /**
14
- * Perform the multistream-select handshake
15
- *
16
- * @param {AbortOptions} [options]
17
- */
18
- _handshake(options?: AbortOptions): Promise<void>;
9
+ export interface ByteArrayInit extends AbortOptions {
10
+ writeBytes: true;
19
11
  }
20
- export declare class Dialer extends MultistreamSelect {
21
- select(protocols: string | string[], options?: AbortOptions): Promise<ProtocolStream>;
12
+ export interface ByteListInit extends AbortOptions {
13
+ writeBytes?: false;
22
14
  }
23
- export declare class Listener extends MultistreamSelect {
24
- handle(protocols: string | string[], options?: AbortOptions): Promise<ProtocolStream>;
15
+ export interface MultistreamSelectInit extends AbortOptions {
16
+ writeBytes?: boolean;
25
17
  }
18
+ export { select } from './select.js';
19
+ export { handle } from './handle.js';
26
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,EAAE,WAAW,EAAE,CAAA;AAEtB,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;IAC1B,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,cAAM,iBAAiB;IACrB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;IACpC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAA;gBAEZ,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC;IAKvC;;;;OAIG;IACG,UAAU,CAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CASzD;AAED,qBAAa,MAAO,SAAQ,iBAAiB;IACrC,MAAM,CAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;CAG7F;AAED,qBAAa,QAAS,SAAQ,iBAAiB;IACvC,MAAM,CAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;CAG7F"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,EAAE,WAAW,EAAE,CAAA;AAEtB,MAAM,WAAW,cAAc,CAAC,OAAO,EAAE,KAAK,GAAG,OAAO;IACtD,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC9B,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,UAAU,EAAE,IAAI,CAAA;CACjB;AAED,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB;AAED,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACzD,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA"}
package/dist/src/index.js CHANGED
@@ -1,34 +1,5 @@
1
- import { select } from './select.js';
2
- import { handle } from './handle.js';
3
1
  import { PROTOCOL_ID } from './constants.js';
4
2
  export { PROTOCOL_ID };
5
- class MultistreamSelect {
6
- constructor(stream) {
7
- this.stream = stream;
8
- this.shaken = false;
9
- }
10
- /**
11
- * Perform the multistream-select handshake
12
- *
13
- * @param {AbortOptions} [options]
14
- */
15
- async _handshake(options) {
16
- if (this.shaken) {
17
- return;
18
- }
19
- const { stream } = await select(this.stream, PROTOCOL_ID, undefined, options);
20
- this.stream = stream;
21
- this.shaken = true;
22
- }
23
- }
24
- export class Dialer extends MultistreamSelect {
25
- async select(protocols, options) {
26
- return await select(this.stream, protocols, this.shaken ? undefined : PROTOCOL_ID, options);
27
- }
28
- }
29
- export class Listener extends MultistreamSelect {
30
- async handle(protocols, options) {
31
- return await handle(this.stream, protocols, options);
32
- }
33
- }
3
+ export { select } from './select.js';
4
+ export { handle } from './handle.js';
34
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAI5C,OAAO,EAAE,WAAW,EAAE,CAAA;AAOtB,MAAM,iBAAiB;IAIrB,YAAa,MAA0B;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;IACrB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAE,OAAsB;QACtC,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,OAAM;SACP;QAED,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;QAC7E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;IACpB,CAAC;CACF;AAED,MAAM,OAAO,MAAO,SAAQ,iBAAiB;IAC3C,KAAK,CAAC,MAAM,CAAE,SAA4B,EAAE,OAAsB;QAChE,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAC7F,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,iBAAiB;IAC7C,KAAK,CAAC,MAAM,CAAE,SAA4B,EAAE,OAAsB;QAChE,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IACtD,CAAC;CACF"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAI5C,OAAO,EAAE,WAAW,EAAE,CAAA;AAmBtB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA"}
@@ -2,15 +2,16 @@ import { Uint8ArrayList } from 'uint8arraylist';
2
2
  import type { Pushable } from 'it-pushable';
3
3
  import type { AbortOptions } from '@libp2p/interfaces';
4
4
  import type { Reader } from 'it-reader';
5
- export declare function encode(buffer: Uint8Array | Uint8ArrayList): Uint8Array;
5
+ import type { MultistreamSelectInit } from '.';
6
+ export declare function encode(buffer: Uint8Array | Uint8ArrayList): Uint8ArrayList;
6
7
  /**
7
8
  * `write` encodes and writes a single buffer
8
9
  */
9
- export declare function write(writer: Pushable<Uint8Array>, buffer: Uint8Array | Uint8ArrayList): void;
10
+ export declare function write(writer: Pushable<any>, buffer: Uint8Array | Uint8ArrayList, options?: MultistreamSelectInit): void;
10
11
  /**
11
12
  * `writeAll` behaves like `write`, except it encodes an array of items as a single write
12
13
  */
13
- export declare function writeAll(writer: Pushable<Uint8Array>, buffers: Uint8Array[]): void;
14
- export declare function read(reader: Reader, options?: AbortOptions): Promise<Uint8Array>;
14
+ export declare function writeAll(writer: Pushable<any>, buffers: Uint8Array[], options?: MultistreamSelectInit): void;
15
+ export declare function read(reader: Reader, options?: AbortOptions): Promise<Uint8ArrayList>;
15
16
  export declare function readString(reader: Reader, options?: AbortOptions): Promise<string>;
16
17
  //# sourceMappingURL=multistream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"multistream.d.ts","sourceRoot":"","sources":["../../src/multistream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAQ/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAIvC,wBAAgB,MAAM,CAAE,MAAM,EAAE,UAAU,GAAG,cAAc,GAAG,UAAU,CAIvE;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,cAAc,QAEvF;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,QAQ5E;AAED,wBAAsB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,uBAiCjE;AAED,wBAAsB,UAAU,CAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,mBAIvE"}
1
+ {"version":3,"file":"multistream.d.ts","sourceRoot":"","sources":["../../src/multistream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAQ/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,GAAG,CAAA;AAI9C,wBAAgB,MAAM,CAAE,MAAM,EAAE,UAAU,GAAG,cAAc,GAAG,cAAc,CAI3E;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,cAAc,EAAE,OAAO,GAAE,qBAA0B,QAQrH;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,OAAO,GAAE,qBAA0B,QAY1G;AAED,wBAAsB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAmC3F;AAED,wBAAsB,UAAU,CAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,mBAIvE"}
@@ -9,23 +9,34 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
9
9
  const NewLine = uint8ArrayFromString('\n');
10
10
  export function encode(buffer) {
11
11
  const list = new Uint8ArrayList(buffer, NewLine);
12
- return lp.encode.single(list).slice();
12
+ return lp.encode.single(list);
13
13
  }
14
14
  /**
15
15
  * `write` encodes and writes a single buffer
16
16
  */
17
- export function write(writer, buffer) {
18
- writer.push(encode(buffer).slice());
17
+ export function write(writer, buffer, options = {}) {
18
+ const encoded = encode(buffer);
19
+ if (options.writeBytes === true) {
20
+ writer.push(encoded.subarray());
21
+ }
22
+ else {
23
+ writer.push(encoded);
24
+ }
19
25
  }
20
26
  /**
21
27
  * `writeAll` behaves like `write`, except it encodes an array of items as a single write
22
28
  */
23
- export function writeAll(writer, buffers) {
29
+ export function writeAll(writer, buffers, options = {}) {
24
30
  const list = new Uint8ArrayList();
25
31
  for (const buf of buffers) {
26
32
  list.append(encode(buf));
27
33
  }
28
- writer.push(list.slice());
34
+ if (options.writeBytes === true) {
35
+ writer.push(list.subarray());
36
+ }
37
+ else {
38
+ writer.push(list);
39
+ }
29
40
  }
30
41
  export async function read(reader, options) {
31
42
  let byteLength = 1; // Read single byte chunks until the length is known
@@ -40,18 +51,20 @@ export async function read(reader, options) {
40
51
  input = abortableSource(varByteSource, options.signal);
41
52
  }
42
53
  // Once the length has been parsed, read chunk for that length
43
- const onLength = (l) => { byteLength = l; };
54
+ const onLength = (l) => {
55
+ byteLength = l;
56
+ };
44
57
  const buf = await pipe(input, lp.decode({ onLength }), async (source) => await first(source));
45
58
  if (buf == null) {
46
59
  throw errCode(new Error('no buffer returned'), 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE');
47
60
  }
48
- if (buf[buf.length - 1] !== NewLine[0]) {
61
+ if (buf.get(buf.byteLength - 1) !== NewLine[0]) {
49
62
  throw errCode(new Error('missing newline'), 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE');
50
63
  }
51
- return buf.slice(0, -1); // Remove newline
64
+ return buf.sublist(0, -1); // Remove newline
52
65
  }
53
66
  export async function readString(reader, options) {
54
67
  const buf = await read(reader, options);
55
- return uint8ArrayToString(buf);
68
+ return uint8ArrayToString(buf.subarray());
56
69
  }
57
70
  //# sourceMappingURL=multistream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"multistream.js","sourceRoot":"","sources":["../../src/multistream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,KAAK,MAAM,UAAU,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAMtE,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;AAE1C,MAAM,UAAU,MAAM,CAAE,MAAmC;IACzD,MAAM,IAAI,GAAG,IAAI,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAEhD,OAAO,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAA;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAE,MAA4B,EAAE,MAAmC;IACtF,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAA;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAE,MAA4B,EAAE,OAAqB;IAC3E,MAAM,IAAI,GAAG,IAAI,cAAc,EAAE,CAAA;IAEjC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE;QACzB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;KACzB;IAED,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAE,MAAc,EAAE,OAAsB;IAChE,IAAI,UAAU,GAAG,CAAC,CAAA,CAAC,oDAAoD;IACvE,MAAM,aAAa,GAAG;QACpB,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,GAAG,EAAE,CAAC,aAAa;QAC3C,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;KAChD,CAAA;IAED,IAAI,KAAK,GAA2B,aAAa,CAAA;IAEjD,gFAAgF;IAChF,uDAAuD;IACvD,IAAI,OAAO,EAAE,MAAM,IAAI,IAAI,EAAE;QAC3B,KAAK,GAAG,eAAe,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;KACvD;IAED,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,EAAE,GAAG,UAAU,GAAG,CAAC,CAAA,CAAC,CAAC,CAAA;IAElD,MAAM,GAAG,GAAG,MAAM,IAAI,CACpB,KAAK,EACL,EAAE,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,EACvB,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,CACtC,CAAA;IAED,IAAI,GAAG,IAAI,IAAI,EAAE;QACf,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,EAAE,wCAAwC,CAAC,CAAA;KACzF;IAED,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE;QACtC,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,wCAAwC,CAAC,CAAA;KACtF;IAED,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA,CAAC,iBAAiB;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAE,MAAc,EAAE,OAAsB;IACtE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAEvC,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAA;AAChC,CAAC"}
1
+ {"version":3,"file":"multistream.js","sourceRoot":"","sources":["../../src/multistream.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- import type { AbortOptions } from '@libp2p/interfaces';
2
1
  import type { Duplex } from 'it-stream-types';
3
- export declare function select(stream: Duplex<Uint8Array>, protocols: string | string[], protocolId?: string, options?: AbortOptions): Promise<{
4
- stream: Duplex<Uint8Array, Uint8Array, Promise<void>>;
5
- protocol: string;
6
- }>;
2
+ import type { Uint8ArrayList } from 'uint8arraylist';
3
+ import type { ByteArrayInit, ByteListInit, ProtocolStream } from './index.js';
4
+ export declare function select(stream: Duplex<Uint8Array>, protocols: string | string[], options: ByteArrayInit): Promise<ProtocolStream<Uint8Array>>;
5
+ export declare function select(stream: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>, protocols: string | string[], options?: ByteListInit): Promise<ProtocolStream<Uint8ArrayList, Uint8ArrayList | Uint8Array>>;
7
6
  //# sourceMappingURL=select.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/select.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAI7C,wBAAsB,MAAM,CAAE,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;;;GAgDlI"}
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/select.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAyB,cAAc,EAAE,MAAM,YAAY,CAAA;AAIpG,wBAAsB,MAAM,CAAE,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;AACpJ,wBAAsB,MAAM,CAAE,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,cAAc,GAAG,UAAU,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,cAAc,GAAG,UAAU,CAAC,CAAC,CAAA"}
@@ -3,26 +3,23 @@ import errCode from 'err-code';
3
3
  import * as multistream from './multistream.js';
4
4
  import { handshake } from 'it-handshake';
5
5
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
6
+ import { PROTOCOL_ID } from './index.js';
6
7
  const log = logger('libp2p:mss:select');
7
- export async function select(stream, protocols, protocolId, options) {
8
+ export async function select(stream, protocols, options = {}) {
8
9
  protocols = Array.isArray(protocols) ? [...protocols] : [protocols];
9
10
  const { reader, writer, rest, stream: shakeStream } = handshake(stream);
10
11
  const protocol = protocols.shift();
11
12
  if (protocol == null) {
12
13
  throw new Error('At least one protocol must be specified');
13
14
  }
14
- if (protocolId != null) {
15
- log('select: write ["%s", "%s"]', protocolId, protocol);
16
- multistream.writeAll(writer, [uint8ArrayFromString(protocolId), uint8ArrayFromString(protocol)]);
17
- }
18
- else {
19
- log('select: write "%s"', protocol);
20
- multistream.write(writer, uint8ArrayFromString(protocol));
21
- }
15
+ log('select: write ["%s", "%s"]', PROTOCOL_ID, protocol);
16
+ const p1 = uint8ArrayFromString(PROTOCOL_ID);
17
+ const p2 = uint8ArrayFromString(protocol);
18
+ multistream.writeAll(writer, [p1, p2], options);
22
19
  let response = await multistream.readString(reader, options);
23
20
  log('select: read "%s"', response);
24
21
  // Read the protocol response if we got the protocolId in return
25
- if (response === protocolId) {
22
+ if (response === PROTOCOL_ID) {
26
23
  response = await multistream.readString(reader, options);
27
24
  log('select: read "%s"', response);
28
25
  }
@@ -34,7 +31,7 @@ export async function select(stream, protocols, protocolId, options) {
34
31
  // We haven't gotten a valid ack, try the other protocols
35
32
  for (const protocol of protocols) {
36
33
  log('select: write "%s"', protocol);
37
- multistream.write(writer, uint8ArrayFromString(protocol));
34
+ multistream.write(writer, uint8ArrayFromString(protocol), options);
38
35
  const response = await multistream.readString(reader, options);
39
36
  log('select: read "%s" for "%s"', response, protocol);
40
37
  if (response === protocol) {
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAI5E,MAAM,GAAG,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAA;AAEvC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAE,MAA0B,EAAE,SAA4B,EAAE,UAAmB,EAAE,OAAsB;IACjI,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IACnE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAEvE,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,EAAE,CAAA;IAElC,IAAI,QAAQ,IAAI,IAAI,EAAE;QACpB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;KAC3D;IAED,IAAI,UAAU,IAAI,IAAI,EAAE;QACtB,GAAG,CAAC,4BAA4B,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAA;QACvD,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,oBAAoB,CAAC,UAAU,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;KACjG;SAAM;QACL,GAAG,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAA;QACnC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAA;KAC1D;IAED,IAAI,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5D,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAA;IAElC,gEAAgE;IAChE,IAAI,QAAQ,KAAK,UAAU,EAAE;QAC3B,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACxD,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAA;KACnC;IAED,aAAa;IACb,IAAI,QAAQ,KAAK,QAAQ,EAAE;QACzB,IAAI,EAAE,CAAA;QACN,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAA;KACzC;IAED,yDAAyD;IACzD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;QAChC,GAAG,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAA;QACnC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAA;QACzD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9D,GAAG,CAAC,4BAA4B,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;QAErD,IAAI,QAAQ,KAAK,QAAQ,EAAE;YACzB,IAAI,EAAE,CAAA,CAAC,uDAAuD;YAC9D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAA;SACzC;KACF;IAED,IAAI,EAAE,CAAA;IACN,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE,0BAA0B,CAAC,CAAA;AACnF,CAAC"}
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAKxC,MAAM,GAAG,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAA;AAIvC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAE,MAAmB,EAAE,SAA4B,EAAE,UAAiC,EAAE;IAClH,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IACnE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAEvE,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,EAAE,CAAA;IAElC,IAAI,QAAQ,IAAI,IAAI,EAAE;QACpB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;KAC3D;IAED,GAAG,CAAC,4BAA4B,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAA;IACxD,MAAM,EAAE,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAA;IAC5C,MAAM,EAAE,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IACzC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;IAE/C,IAAI,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5D,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAA;IAElC,gEAAgE;IAChE,IAAI,QAAQ,KAAK,WAAW,EAAE;QAC5B,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACxD,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAA;KACnC;IAED,aAAa;IACb,IAAI,QAAQ,KAAK,QAAQ,EAAE;QACzB,IAAI,EAAE,CAAA;QACN,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAA;KACzC;IAED,yDAAyD;IACzD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;QAChC,GAAG,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAA;QACnC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAA;QAClE,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9D,GAAG,CAAC,4BAA4B,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;QAErD,IAAI,QAAQ,KAAK,QAAQ,EAAE;YACzB,IAAI,EAAE,CAAA,CAAC,uDAAuD;YAC9D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAA;SACzC;KACF;IAED,IAAI,EAAE,CAAA;IACN,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE,0BAA0B,CAAC,CAAA;AACnF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libp2p/multistream-select",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "JavaScript implementation of multistream-select",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/libp2p/js-libp2p-multistream-select#readme",
@@ -32,6 +32,7 @@
32
32
  ],
33
33
  "exports": {
34
34
  ".": {
35
+ "types": "./dist/src/index.d.ts",
35
36
  "import": "./dist/src/index.js"
36
37
  }
37
38
  },
@@ -68,15 +69,15 @@
68
69
  "release": "patch"
69
70
  },
70
71
  {
71
- "type": "chore",
72
+ "type": "docs",
72
73
  "release": "patch"
73
74
  },
74
75
  {
75
- "type": "docs",
76
+ "type": "test",
76
77
  "release": "patch"
77
78
  },
78
79
  {
79
- "type": "test",
80
+ "type": "deps",
80
81
  "release": "patch"
81
82
  },
82
83
  {
@@ -106,7 +107,11 @@
106
107
  },
107
108
  {
108
109
  "type": "docs",
109
- "section": "Trivial Changes"
110
+ "section": "Documentation"
111
+ },
112
+ {
113
+ "type": "deps",
114
+ "section": "Dependencies"
110
115
  },
111
116
  {
112
117
  "type": "test",
@@ -137,18 +142,19 @@
137
142
  "release": "aegir release"
138
143
  },
139
144
  "dependencies": {
140
- "@libp2p/logger": "^1.1.0",
145
+ "@libp2p/interfaces": "^3.0.2",
146
+ "@libp2p/logger": "^2.0.0",
141
147
  "abortable-iterator": "^4.0.2",
142
148
  "err-code": "^3.0.1",
143
149
  "it-first": "^1.0.6",
144
- "it-handshake": "^4.0.0",
145
- "it-length-prefixed": "^7.0.1",
150
+ "it-handshake": "^4.0.1",
151
+ "it-length-prefixed": "^8.0.2",
146
152
  "it-pipe": "^2.0.3",
147
153
  "it-pushable": "^3.0.0",
148
- "it-reader": "^5.0.0",
154
+ "it-reader": "^6.0.1",
149
155
  "it-stream-types": "^1.0.4",
150
156
  "p-defer": "^4.0.0",
151
- "uint8arraylist": "^1.5.1",
157
+ "uint8arraylist": "^2.3.1",
152
158
  "uint8arrays": "^3.0.0"
153
159
  },
154
160
  "devDependencies": {
@@ -158,7 +164,7 @@
158
164
  "it-all": "^1.0.6",
159
165
  "it-map": "^1.0.6",
160
166
  "it-pair": "^2.0.2",
161
- "p-timeout": "^5.0.2",
167
+ "p-timeout": "^6.0.0",
162
168
  "timeout-abort-controller": "^3.0.0",
163
169
  "util": "^0.12.4",
164
170
  "varint": "^6.0.0"
package/src/handle.ts CHANGED
@@ -4,12 +4,14 @@ import { handshake } from 'it-handshake'
4
4
  import { PROTOCOL_ID } from './constants.js'
5
5
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
6
  import { Uint8ArrayList } from 'uint8arraylist'
7
- import type { AbortOptions } from '@libp2p/interfaces'
8
7
  import type { Duplex } from 'it-stream-types'
8
+ import type { ByteArrayInit, ByteListInit, MultistreamSelectInit, ProtocolStream } from './index.js'
9
9
 
10
10
  const log = logger('libp2p:mss:handle')
11
11
 
12
- export async function handle (stream: Duplex<Uint8Array>, protocols: string | string[], options?: AbortOptions) {
12
+ export async function handle (stream: Duplex<Uint8Array>, protocols: string | string[], options: ByteArrayInit): Promise<ProtocolStream<Uint8Array>>
13
+ export async function handle (stream: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>, protocols: string | string[], options?: ByteListInit): Promise<ProtocolStream<Uint8ArrayList, Uint8ArrayList | Uint8Array>>
14
+ export async function handle (stream: Duplex<any>, protocols: string | string[], options?: MultistreamSelectInit): Promise<ProtocolStream<any>> {
13
15
  protocols = Array.isArray(protocols) ? protocols : [protocols]
14
16
  const { writer, reader, rest, stream: shakeStream } = handshake(stream)
15
17
 
@@ -19,12 +21,12 @@ export async function handle (stream: Duplex<Uint8Array>, protocols: string | st
19
21
 
20
22
  if (protocol === PROTOCOL_ID) {
21
23
  log('respond with "%s" for "%s"', PROTOCOL_ID, protocol)
22
- multistream.write(writer, uint8ArrayFromString(PROTOCOL_ID))
24
+ multistream.write(writer, uint8ArrayFromString(PROTOCOL_ID), options)
23
25
  continue
24
26
  }
25
27
 
26
28
  if (protocols.includes(protocol)) {
27
- multistream.write(writer, uint8ArrayFromString(protocol))
29
+ multistream.write(writer, uint8ArrayFromString(protocol), options)
28
30
  log('respond with "%s" for "%s"', protocol, protocol)
29
31
  rest()
30
32
  return { stream: shakeStream, protocol }
@@ -32,12 +34,13 @@ export async function handle (stream: Duplex<Uint8Array>, protocols: string | st
32
34
 
33
35
  if (protocol === 'ls') {
34
36
  // <varint-msg-len><varint-proto-name-len><proto-name>\n<varint-proto-name-len><proto-name>\n\n
35
- multistream.write(writer, new Uint8ArrayList(...protocols.map(p => multistream.encode(uint8ArrayFromString(p)))))
37
+ multistream.write(writer, new Uint8ArrayList(...protocols.map(p => multistream.encode(uint8ArrayFromString(p)))), options)
38
+ // multistream.writeAll(writer, protocols.map(p => uint8ArrayFromString(p)))
36
39
  log('respond with "%s" for %s', protocols, protocol)
37
40
  continue
38
41
  }
39
42
 
40
- multistream.write(writer, uint8ArrayFromString('na'))
43
+ multistream.write(writer, uint8ArrayFromString('na'), options)
41
44
  log('respond with "na" for "%s"', protocol)
42
45
  }
43
46
  }
package/src/index.ts CHANGED
@@ -1,49 +1,25 @@
1
- import { select } from './select.js'
2
- import { handle } from './handle.js'
3
1
  import { PROTOCOL_ID } from './constants.js'
4
2
  import type { Duplex } from 'it-stream-types'
5
3
  import type { AbortOptions } from '@libp2p/interfaces'
6
4
 
7
5
  export { PROTOCOL_ID }
8
6
 
9
- export interface ProtocolStream {
10
- stream: Duplex<Uint8Array>
7
+ export interface ProtocolStream<TSource, TSink = TSource> {
8
+ stream: Duplex<TSource, TSink>
11
9
  protocol: string
12
10
  }
13
11
 
14
- class MultistreamSelect {
15
- protected stream: Duplex<Uint8Array>
16
- protected shaken: boolean
17
-
18
- constructor (stream: Duplex<Uint8Array>) {
19
- this.stream = stream
20
- this.shaken = false
21
- }
22
-
23
- /**
24
- * Perform the multistream-select handshake
25
- *
26
- * @param {AbortOptions} [options]
27
- */
28
- async _handshake (options?: AbortOptions): Promise<void> {
29
- if (this.shaken) {
30
- return
31
- }
32
-
33
- const { stream } = await select(this.stream, PROTOCOL_ID, undefined, options)
34
- this.stream = stream
35
- this.shaken = true
36
- }
12
+ export interface ByteArrayInit extends AbortOptions {
13
+ writeBytes: true
37
14
  }
38
15
 
39
- export class Dialer extends MultistreamSelect {
40
- async select (protocols: string | string[], options?: AbortOptions): Promise<ProtocolStream> {
41
- return await select(this.stream, protocols, this.shaken ? undefined : PROTOCOL_ID, options)
42
- }
16
+ export interface ByteListInit extends AbortOptions {
17
+ writeBytes?: false
43
18
  }
44
19
 
45
- export class Listener extends MultistreamSelect {
46
- async handle (protocols: string | string[], options?: AbortOptions): Promise<ProtocolStream> {
47
- return await handle(this.stream, protocols, options)
48
- }
20
+ export interface MultistreamSelectInit extends AbortOptions {
21
+ writeBytes?: boolean
49
22
  }
23
+
24
+ export { select } from './select.js'
25
+ export { handle } from './handle.js'
@@ -11,36 +11,47 @@ import type { Pushable } from 'it-pushable'
11
11
  import type { AbortOptions } from '@libp2p/interfaces'
12
12
  import type { Source } from 'it-stream-types'
13
13
  import type { Reader } from 'it-reader'
14
+ import type { MultistreamSelectInit } from '.'
14
15
 
15
16
  const NewLine = uint8ArrayFromString('\n')
16
17
 
17
- export function encode (buffer: Uint8Array | Uint8ArrayList): Uint8Array {
18
+ export function encode (buffer: Uint8Array | Uint8ArrayList): Uint8ArrayList {
18
19
  const list = new Uint8ArrayList(buffer, NewLine)
19
20
 
20
- return lp.encode.single(list).slice()
21
+ return lp.encode.single(list)
21
22
  }
22
23
 
23
24
  /**
24
25
  * `write` encodes and writes a single buffer
25
26
  */
26
- export function write (writer: Pushable<Uint8Array>, buffer: Uint8Array | Uint8ArrayList) {
27
- writer.push(encode(buffer).slice())
27
+ export function write (writer: Pushable<any>, buffer: Uint8Array | Uint8ArrayList, options: MultistreamSelectInit = {}) {
28
+ const encoded = encode(buffer)
29
+
30
+ if (options.writeBytes === true) {
31
+ writer.push(encoded.subarray())
32
+ } else {
33
+ writer.push(encoded)
34
+ }
28
35
  }
29
36
 
30
37
  /**
31
38
  * `writeAll` behaves like `write`, except it encodes an array of items as a single write
32
39
  */
33
- export function writeAll (writer: Pushable<Uint8Array>, buffers: Uint8Array[]) {
40
+ export function writeAll (writer: Pushable<any>, buffers: Uint8Array[], options: MultistreamSelectInit = {}) {
34
41
  const list = new Uint8ArrayList()
35
42
 
36
43
  for (const buf of buffers) {
37
44
  list.append(encode(buf))
38
45
  }
39
46
 
40
- writer.push(list.slice())
47
+ if (options.writeBytes === true) {
48
+ writer.push(list.subarray())
49
+ } else {
50
+ writer.push(list)
51
+ }
41
52
  }
42
53
 
43
- export async function read (reader: Reader, options?: AbortOptions) {
54
+ export async function read (reader: Reader, options?: AbortOptions): Promise<Uint8ArrayList> {
44
55
  let byteLength = 1 // Read single byte chunks until the length is known
45
56
  const varByteSource = { // No return impl - we want the reader to remain readable
46
57
  [Symbol.asyncIterator]: () => varByteSource,
@@ -56,7 +67,9 @@ export async function read (reader: Reader, options?: AbortOptions) {
56
67
  }
57
68
 
58
69
  // Once the length has been parsed, read chunk for that length
59
- const onLength = (l: number) => { byteLength = l }
70
+ const onLength = (l: number) => {
71
+ byteLength = l
72
+ }
60
73
 
61
74
  const buf = await pipe(
62
75
  input,
@@ -68,15 +81,15 @@ export async function read (reader: Reader, options?: AbortOptions) {
68
81
  throw errCode(new Error('no buffer returned'), 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE')
69
82
  }
70
83
 
71
- if (buf[buf.length - 1] !== NewLine[0]) {
84
+ if (buf.get(buf.byteLength - 1) !== NewLine[0]) {
72
85
  throw errCode(new Error('missing newline'), 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE')
73
86
  }
74
87
 
75
- return buf.slice(0, -1) // Remove newline
88
+ return buf.sublist(0, -1) // Remove newline
76
89
  }
77
90
 
78
91
  export async function readString (reader: Reader, options?: AbortOptions) {
79
92
  const buf = await read(reader, options)
80
93
 
81
- return uint8ArrayToString(buf)
94
+ return uint8ArrayToString(buf.subarray())
82
95
  }
package/src/select.ts CHANGED
@@ -3,12 +3,16 @@ import errCode from 'err-code'
3
3
  import * as multistream from './multistream.js'
4
4
  import { handshake } from 'it-handshake'
5
5
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
- import type { AbortOptions } from '@libp2p/interfaces'
6
+ import { PROTOCOL_ID } from './index.js'
7
7
  import type { Duplex } from 'it-stream-types'
8
+ import type { Uint8ArrayList } from 'uint8arraylist'
9
+ import type { ByteArrayInit, ByteListInit, MultistreamSelectInit, ProtocolStream } from './index.js'
8
10
 
9
11
  const log = logger('libp2p:mss:select')
10
12
 
11
- export async function select (stream: Duplex<Uint8Array>, protocols: string | string[], protocolId?: string, options?: AbortOptions) {
13
+ export async function select (stream: Duplex<Uint8Array>, protocols: string | string[], options: ByteArrayInit): Promise<ProtocolStream<Uint8Array>>
14
+ export async function select (stream: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>, protocols: string | string[], options?: ByteListInit): Promise<ProtocolStream<Uint8ArrayList, Uint8ArrayList | Uint8Array>>
15
+ export async function select (stream: Duplex<any>, protocols: string | string[], options: MultistreamSelectInit = {}): Promise<ProtocolStream<any>> {
12
16
  protocols = Array.isArray(protocols) ? [...protocols] : [protocols]
13
17
  const { reader, writer, rest, stream: shakeStream } = handshake(stream)
14
18
 
@@ -18,19 +22,16 @@ export async function select (stream: Duplex<Uint8Array>, protocols: string | st
18
22
  throw new Error('At least one protocol must be specified')
19
23
  }
20
24
 
21
- if (protocolId != null) {
22
- log('select: write ["%s", "%s"]', protocolId, protocol)
23
- multistream.writeAll(writer, [uint8ArrayFromString(protocolId), uint8ArrayFromString(protocol)])
24
- } else {
25
- log('select: write "%s"', protocol)
26
- multistream.write(writer, uint8ArrayFromString(protocol))
27
- }
25
+ log('select: write ["%s", "%s"]', PROTOCOL_ID, protocol)
26
+ const p1 = uint8ArrayFromString(PROTOCOL_ID)
27
+ const p2 = uint8ArrayFromString(protocol)
28
+ multistream.writeAll(writer, [p1, p2], options)
28
29
 
29
30
  let response = await multistream.readString(reader, options)
30
31
  log('select: read "%s"', response)
31
32
 
32
33
  // Read the protocol response if we got the protocolId in return
33
- if (response === protocolId) {
34
+ if (response === PROTOCOL_ID) {
34
35
  response = await multistream.readString(reader, options)
35
36
  log('select: read "%s"', response)
36
37
  }
@@ -44,7 +45,7 @@ export async function select (stream: Duplex<Uint8Array>, protocols: string | st
44
45
  // We haven't gotten a valid ack, try the other protocols
45
46
  for (const protocol of protocols) {
46
47
  log('select: write "%s"', protocol)
47
- multistream.write(writer, uint8ArrayFromString(protocol))
48
+ multistream.write(writer, uint8ArrayFromString(protocol), options)
48
49
  const response = await multistream.readString(reader, options)
49
50
  log('select: read "%s" for "%s"', response, protocol)
50
51