@libp2p/multistream-select 0.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.
Files changed (49) hide show
  1. package/README.md +290 -0
  2. package/dist/src/constants.d.ts +2 -0
  3. package/dist/src/constants.d.ts.map +1 -0
  4. package/dist/src/constants.js +2 -0
  5. package/dist/src/constants.js.map +1 -0
  6. package/dist/src/handle.d.ts +7 -0
  7. package/dist/src/handle.d.ts.map +1 -0
  8. package/dist/src/handle.js +35 -0
  9. package/dist/src/handle.js.map +1 -0
  10. package/dist/src/index.d.ts +27 -0
  11. package/dist/src/index.d.ts.map +1 -0
  12. package/dist/src/index.js +42 -0
  13. package/dist/src/index.js.map +1 -0
  14. package/dist/src/ls.d.ts +7 -0
  15. package/dist/src/ls.d.ts.map +1 -0
  16. package/dist/src/ls.js +32 -0
  17. package/dist/src/ls.js.map +1 -0
  18. package/dist/src/multistream.d.ts +16 -0
  19. package/dist/src/multistream.d.ts.map +1 -0
  20. package/dist/src/multistream.js +57 -0
  21. package/dist/src/multistream.js.map +1 -0
  22. package/dist/src/select.d.ts +7 -0
  23. package/dist/src/select.d.ts.map +1 -0
  24. package/dist/src/select.js +48 -0
  25. package/dist/src/select.js.map +1 -0
  26. package/dist/test/dialer.spec.d.ts +2 -0
  27. package/dist/test/dialer.spec.d.ts.map +1 -0
  28. package/dist/test/dialer.spec.js +144 -0
  29. package/dist/test/dialer.spec.js.map +1 -0
  30. package/dist/test/integration.spec.d.ts +2 -0
  31. package/dist/test/integration.spec.d.ts.map +1 -0
  32. package/dist/test/integration.spec.js +55 -0
  33. package/dist/test/integration.spec.js.map +1 -0
  34. package/dist/test/listener.spec.d.ts +2 -0
  35. package/dist/test/listener.spec.d.ts.map +1 -0
  36. package/dist/test/listener.spec.js +123 -0
  37. package/dist/test/listener.spec.js.map +1 -0
  38. package/dist/test/multistream.spec.d.ts +2 -0
  39. package/dist/test/multistream.spec.d.ts.map +1 -0
  40. package/dist/test/multistream.spec.js +86 -0
  41. package/dist/test/multistream.spec.js.map +1 -0
  42. package/dist/tsconfig.tsbuildinfo +1 -0
  43. package/package.json +80 -0
  44. package/src/constants.ts +2 -0
  45. package/src/handle.ts +43 -0
  46. package/src/index.ts +58 -0
  47. package/src/ls.ts +45 -0
  48. package/src/multistream.ts +82 -0
  49. package/src/select.ts +59 -0
package/README.md ADDED
@@ -0,0 +1,290 @@
1
+ # js-multistream-select <!-- omit in toc -->
2
+
3
+ [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai)
4
+ [![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats)
5
+ [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs)
6
+ [![](https://img.shields.io/codecov/c/github/multiformats/js-multistream-select.svg?style=flat-square)](https://codecov.io/gh/multiformats/js-multistream-select)
7
+ [![](https://img.shields.io/travis/multiformats/js-multistream-select.svg?style=flat-square)](https://travis-ci.com/multiformats/js-multistream-select)
8
+ [![Dependency Status](https://david-dm.org/multiformats/js-multistream-select.svg?style=flat-square)](https://david-dm.org/multiformats/js-multistream-select)
9
+ [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
10
+
11
+ > JavaScript implementation of [multistream-select](https://github.com/multiformats/multistream-select)
12
+
13
+ ## Lead Maintainer <!-- omit in toc -->
14
+
15
+ [Jacob Heun](https://github.com/jacobheun)
16
+
17
+ ## Table of Contents <!-- omit in toc -->
18
+
19
+ - [Background](#background)
20
+ - [What is `multistream-select`?](#what-is-multistream-select)
21
+ - [Select a protocol flow](#select-a-protocol-flow)
22
+ - [Install](#install)
23
+ - [Usage](#usage)
24
+ - [Dialer](#dialer)
25
+ - [Listener](#listener)
26
+ - [API](#api)
27
+ - [`new MSS.Dialer(duplex)`](#new-mssdialerduplex)
28
+ - [Parameters](#parameters)
29
+ - [Returns](#returns)
30
+ - [Examples](#examples)
31
+ - [`dialer.select(protocols, [options])`](#dialerselectprotocols-options)
32
+ - [Parameters](#parameters-1)
33
+ - [Returns](#returns-1)
34
+ - [Examples](#examples-1)
35
+ - [`dialer.ls([options])`](#dialerlsoptions)
36
+ - [Parameters](#parameters-2)
37
+ - [Returns](#returns-2)
38
+ - [Examples](#examples-2)
39
+ - [`new MSS.Listener(duplex)`](#new-msslistenerduplex)
40
+ - [Parameters](#parameters-3)
41
+ - [Returns](#returns-3)
42
+ - [Examples](#examples-3)
43
+ - [`listener.handle(protocols, [options])`](#listenerhandleprotocols-options)
44
+ - [Parameters](#parameters-4)
45
+ - [Returns](#returns-4)
46
+ - [Examples](#examples-4)
47
+ - [Contribute](#contribute)
48
+ - [License](#license)
49
+
50
+ ## Background
51
+
52
+ ### What is `multistream-select`?
53
+
54
+ TLDR; multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select)
55
+
56
+ #### Select a protocol flow
57
+
58
+ The caller will send "interactive" messages, expecting for some acknowledgement from the callee, which will "select" the handler for the desired and supported protocol:
59
+
60
+ ```console
61
+ < /multistream-select/0.3.0 # i speak multistream-select/0.3.0
62
+ > /multistream-select/0.3.0 # ok, let's speak multistream-select/0.3.0
63
+ > /ipfs-dht/0.2.3 # i want to speak ipfs-dht/0.2.3
64
+ < na # ipfs-dht/0.2.3 is not available
65
+ > /ipfs-dht/0.1.9 # What about ipfs-dht/0.1.9 ?
66
+ < /ipfs-dht/0.1.9 # ok let's speak ipfs-dht/0.1.9 -- in a sense acts as an ACK
67
+ > <dht-message>
68
+ > <dht-message>
69
+ > <dht-message>
70
+ ```
71
+
72
+ This mode also packs a `ls` option, so that the callee can list the protocols it currently supports
73
+
74
+ ## Install
75
+
76
+ ```sh
77
+ npm i multistream-select
78
+ ```
79
+
80
+ ## Usage
81
+
82
+ ```js
83
+ const MSS = require('multistream-select')
84
+ // You can now use
85
+ // MSS.Dialer - actively select a protocol with a remote
86
+ // MSS.Listener - handle a protocol with a remote
87
+ ```
88
+
89
+ ### Dialer
90
+
91
+ ```js
92
+ import { pipe } from 'it-pipe'
93
+ const MSS = require('multistream-select')
94
+ const Mplex = require('libp2p-mplex')
95
+
96
+ const muxer = new Mplex()
97
+ const muxedStream = muxer.newStream()
98
+
99
+ const mss = new MSS.Dialer(muxedStream)
100
+
101
+ // mss.select(protocol(s))
102
+ // Select from one of the passed protocols (in priority order)
103
+ // Returns selected stream and protocol
104
+ const { stream: dhtStream, protocol } = await mss.select([
105
+ // This might just be different versions of DHT, but could be different impls
106
+ '/ipfs-dht/2.0.0', // Most of the time this will probably just be one item.
107
+ '/ipfs-dht/1.0.0'
108
+ ])
109
+
110
+ // Typically this stream will be passed back to the caller of libp2p.dialProtocol
111
+ //
112
+ // ...it might then do something like this:
113
+ // try {
114
+ // await pipe(
115
+ // [uint8ArrayFromString('Some DHT data')]
116
+ // dhtStream,
117
+ // async source => {
118
+ // for await (const chunk of source)
119
+ // // DHT response data
120
+ // }
121
+ // )
122
+ // } catch (err) {
123
+ // // Error in stream
124
+ // }
125
+ ```
126
+
127
+ ### Listener
128
+
129
+ ```js
130
+ import { pipe } from 'it-pipe'
131
+ const MSS = require('multistream-select')
132
+ const Mplex = require('libp2p-mplex')
133
+
134
+ const muxer = new Mplex({
135
+ async onStream (muxedStream) {
136
+ const mss = new MSS.Listener(muxedStream)
137
+
138
+ // mss.handle(handledProtocols)
139
+ // Returns selected stream and protocol
140
+ const { stream, protocol } = await mss.handle([
141
+ '/ipfs-dht/1.0.0',
142
+ '/ipfs-bitswap/1.0.0'
143
+ ])
144
+
145
+ // Typically here we'd call the handler function that was registered in
146
+ // libp2p for the given protocol:
147
+ // e.g. handlers[protocol].handler(stream)
148
+ //
149
+ // If protocol was /ipfs-dht/1.0.0 it might do something like this:
150
+ // try {
151
+ // await pipe(
152
+ // dhtStream,
153
+ // source => (async function * () {
154
+ // for await (const chunk of source)
155
+ // // Incoming DHT data -> process and yield to respond
156
+ // })(),
157
+ // dhtStream
158
+ // )
159
+ // } catch (err) {
160
+ // // Error in stream
161
+ // }
162
+ }
163
+ })
164
+ ```
165
+
166
+ ## API
167
+
168
+ ### `new MSS.Dialer(duplex)`
169
+
170
+ 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.
171
+
172
+ #### Parameters
173
+
174
+ * `duplex` (`Object`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to dial on.
175
+
176
+ #### Returns
177
+
178
+ A new multistream select dialer instance.
179
+
180
+ #### Examples
181
+
182
+ ```js
183
+ const dialer = new MSS.Dialer(duplex)
184
+ ```
185
+
186
+ ### `dialer.select(protocols, [options])`
187
+
188
+ Negotiate a protocol to use from a list of protocols.
189
+
190
+ #### Parameters
191
+
192
+ * `protocols` (`String[]`/`String`) - A list of protocols (or single protocol) to negotiate with. Protocols are attempted in order until a match is made.
193
+ * `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal
194
+
195
+ #### Returns
196
+
197
+ `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`.
198
+
199
+ Note that after a protocol is selected `dialer` can no longer be used.
200
+
201
+ #### Examples
202
+
203
+ ```js
204
+ const { stream, protocol } = await dialer.select([
205
+ // This might just be different versions of DHT, but could be different impls
206
+ '/ipfs-dht/2.0.0', // Most of the time this will probably just be one item.
207
+ '/ipfs-dht/1.0.0'
208
+ ])
209
+ // Now talk `protocol` on `stream`
210
+ ```
211
+
212
+ ### `dialer.ls([options])`
213
+
214
+ List protocols that the remote supports.
215
+
216
+ #### Parameters
217
+
218
+ * `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal
219
+
220
+ #### Returns
221
+
222
+ `String[]` - A list of all the protocols the remote supports.
223
+
224
+ #### Examples
225
+
226
+ ```js
227
+ const protocols = await dialer.ls()
228
+ const wantedProto = '/ipfs-dht/2.0.0'
229
+
230
+ if (!protocols.includes(wantedProto)) {
231
+ throw new Error('remote does not support ' + wantedProto)
232
+ }
233
+
234
+ // Now use dialer.select to use wantedProto, safe in the knowledge it is supported
235
+ ```
236
+
237
+ ### `new MSS.Listener(duplex)`
238
+
239
+ Construct a new multistream select "listener" instance which can be used to handle multistream protocol selections for particular protocols.
240
+
241
+ #### Parameters
242
+
243
+ * `duplex` (`Object`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to listen on.
244
+
245
+ #### Returns
246
+
247
+ A new multistream select listener instance.
248
+
249
+ #### Examples
250
+
251
+ ```js
252
+ const listener = new MSS.Listener(duplex)
253
+ ```
254
+
255
+ ### `listener.handle(protocols, [options])`
256
+
257
+ Handle multistream protocol selections for the given list of protocols.
258
+
259
+ #### Parameters
260
+
261
+ * `protocols` (`String[]`/`String`) - A list of protocols (or single protocol) that this listener is able to speak.
262
+ * `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal
263
+
264
+ #### Returns
265
+
266
+ `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`.
267
+
268
+ Note that after a protocol is handled `listener` can no longer be used.
269
+
270
+ #### Examples
271
+
272
+ ```js
273
+ const { stream, protocol } = await listener.handle([
274
+ '/ipfs-dht/1.0.0',
275
+ '/ipfs-bitswap/1.0.0'
276
+ ])
277
+ // Remote wants to speak `protocol`
278
+ ```
279
+
280
+ ## Contribute
281
+
282
+ Contributions welcome. Please check out [the issues](https://github.com/multiformats/js-multistream-select/issues).
283
+
284
+ Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
285
+
286
+ Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
287
+
288
+ ## License
289
+
290
+ [MIT](LICENSE)
@@ -0,0 +1,2 @@
1
+ export declare const PROTOCOL_ID = "/multistream/1.0.0";
2
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,WAAW,uBAAuB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export const PROTOCOL_ID = '/multistream/1.0.0';
2
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAAA"}
@@ -0,0 +1,7 @@
1
+ import type { AbortOptions } from '@libp2p/interfaces';
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
+ }>;
7
+ //# sourceMappingURL=handle.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,35 @@
1
+ import { logger } from '@libp2p/logger';
2
+ import * as multistream from './multistream.js';
3
+ import { handshake } from 'it-handshake';
4
+ import { PROTOCOL_ID } from './constants.js';
5
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
6
+ import { Uint8ArrayList } from 'uint8arraylist';
7
+ const log = logger('libp2p:mss:handle');
8
+ export async function handle(stream, protocols, options) {
9
+ protocols = Array.isArray(protocols) ? protocols : [protocols];
10
+ const { writer, reader, rest, stream: shakeStream } = handshake(stream);
11
+ while (true) {
12
+ const protocol = await multistream.readString(reader, options);
13
+ log('read "%s"', protocol);
14
+ if (protocol === PROTOCOL_ID) {
15
+ log('respond with "%s" for "%s"', PROTOCOL_ID, protocol);
16
+ multistream.write(writer, uint8ArrayFromString(PROTOCOL_ID));
17
+ continue;
18
+ }
19
+ if (protocols.includes(protocol)) {
20
+ multistream.write(writer, uint8ArrayFromString(protocol));
21
+ log('respond with "%s" for "%s"', protocol, protocol);
22
+ rest();
23
+ return { stream: shakeStream, protocol };
24
+ }
25
+ if (protocol === 'ls') {
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)))));
28
+ log('respond with "%s" for %s', protocols, protocol);
29
+ continue;
30
+ }
31
+ multistream.write(writer, uint8ArrayFromString('na'));
32
+ log('respond with "na" for "%s"', protocol);
33
+ }
34
+ }
35
+ //# sourceMappingURL=handle.js.map
@@ -0,0 +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"}
@@ -0,0 +1,27 @@
1
+ import { PROTOCOL_ID } from './constants.js';
2
+ import type { Duplex } from 'it-stream-types';
3
+ import type { AbortOptions } from '@libp2p/interfaces';
4
+ export { PROTOCOL_ID };
5
+ export interface ProtocolStream {
6
+ stream: Duplex<Uint8Array>;
7
+ protocol: string;
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>;
19
+ }
20
+ export declare class Dialer extends MultistreamSelect {
21
+ select(protocols: string | string[], options?: AbortOptions): Promise<ProtocolStream>;
22
+ ls(options?: AbortOptions): Promise<string[]>;
23
+ }
24
+ export declare class Listener extends MultistreamSelect {
25
+ handle(protocols: string | string[], options?: AbortOptions): Promise<ProtocolStream>;
26
+ }
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,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;IAItF,EAAE,CAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAOrD;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"}
@@ -0,0 +1,42 @@
1
+ import { select } from './select.js';
2
+ import { handle } from './handle.js';
3
+ import { ls } from './ls.js';
4
+ import { PROTOCOL_ID } from './constants.js';
5
+ export { PROTOCOL_ID };
6
+ class MultistreamSelect {
7
+ constructor(stream) {
8
+ this.stream = stream;
9
+ this.shaken = false;
10
+ }
11
+ /**
12
+ * Perform the multistream-select handshake
13
+ *
14
+ * @param {AbortOptions} [options]
15
+ */
16
+ async _handshake(options) {
17
+ if (this.shaken) {
18
+ return;
19
+ }
20
+ const { stream } = await select(this.stream, PROTOCOL_ID, undefined, options);
21
+ this.stream = stream;
22
+ this.shaken = true;
23
+ }
24
+ }
25
+ export class Dialer extends MultistreamSelect {
26
+ async select(protocols, options) {
27
+ return await select(this.stream, protocols, this.shaken ? undefined : PROTOCOL_ID, options);
28
+ }
29
+ async ls(options) {
30
+ await this._handshake(options);
31
+ const res = await ls(this.stream, options);
32
+ const { stream, protocols } = res;
33
+ this.stream = stream;
34
+ return protocols;
35
+ }
36
+ }
37
+ export class Listener extends MultistreamSelect {
38
+ async handle(protocols, options) {
39
+ return await handle(this.stream, protocols, options);
40
+ }
41
+ }
42
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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,EAAE,EAAE,MAAM,SAAS,CAAA;AAC5B,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;IAED,KAAK,CAAC,EAAE,CAAE,OAAsB;QAC9B,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAC9B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC1C,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,CAAA;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,OAAO,SAAS,CAAA;IAClB,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"}
@@ -0,0 +1,7 @@
1
+ import type { Duplex } from 'it-stream-types';
2
+ import type { AbortOptions } from '@libp2p/interfaces';
3
+ export declare function ls(stream: Duplex<Uint8Array>, options?: AbortOptions): Promise<{
4
+ stream: Duplex<Uint8Array>;
5
+ protocols: string[];
6
+ }>;
7
+ //# sourceMappingURL=ls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../src/ls.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAItD,wBAAsB,EAAE,CAAE,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA+B1I"}
package/dist/src/ls.js ADDED
@@ -0,0 +1,32 @@
1
+ import { reader as createReader } from 'it-reader';
2
+ import { logger } from '@libp2p/logger';
3
+ import * as multistream from './multistream.js';
4
+ import { handshake } from 'it-handshake';
5
+ import * as lp from 'it-length-prefixed';
6
+ import { pipe } from 'it-pipe';
7
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
8
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
9
+ const log = logger('libp2p:mss:ls');
10
+ export async function ls(stream, options) {
11
+ const { reader, writer, rest, stream: shakeStream } = handshake(stream);
12
+ log('write "ls"');
13
+ multistream.write(writer, uint8ArrayFromString('ls'));
14
+ rest();
15
+ // Next message from remote will be (e.g. for 2 protocols):
16
+ // <varint-msg-len><varint-proto-name-len><proto-name>\n<varint-proto-name-len><proto-name>\n
17
+ const res = await multistream.read(reader, options);
18
+ // After reading response we have:
19
+ // <varint-proto-name-len><proto-name>\n<varint-proto-name-len><proto-name>\n
20
+ const protocolsReader = createReader([res]);
21
+ const protocols = [];
22
+ // Decode each of the protocols from the reader
23
+ await pipe(protocolsReader, lp.decode(), async (source) => {
24
+ for await (const protocol of source) {
25
+ // Remove the newline
26
+ protocols.push(uint8ArrayToString(protocol.slice(0, -1)));
27
+ }
28
+ });
29
+ const output = { stream: shakeStream, protocols };
30
+ return output;
31
+ }
32
+ //# sourceMappingURL=ls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.js","sourceRoot":"","sources":["../../src/ls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,WAAW,CAAA;AAClD,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,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAI5E,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,CAAA;AAEnC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAE,MAA0B,EAAE,OAAsB;IAC1E,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAEvE,GAAG,CAAC,YAAY,CAAC,CAAA;IACjB,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAA;IACrD,IAAI,EAAE,CAAA;IAEN,2DAA2D;IAC3D,6FAA6F;IAC7F,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAEnD,kCAAkC;IAClC,6EAA6E;IAC7E,MAAM,eAAe,GAAG,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC3C,MAAM,SAAS,GAAa,EAAE,CAAA;IAE9B,+CAA+C;IAC/C,MAAM,IAAI,CACR,eAAe,EACf,EAAE,CAAC,MAAM,EAAE,EACX,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,MAAM,EAAE;YACnC,qBAAqB;YACrB,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;SAC1D;IACH,CAAC,CACF,CAAA;IAED,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,CAAA;IAEjD,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { Uint8ArrayList } from 'uint8arraylist';
2
+ import type { Pushable } from 'it-pushable';
3
+ import type { AbortOptions } from '@libp2p/interfaces';
4
+ import type { Reader } from 'it-reader';
5
+ export declare function encode(buffer: Uint8Array | Uint8ArrayList): Uint8Array;
6
+ /**
7
+ * `write` encodes and writes a single buffer
8
+ */
9
+ export declare function write(writer: Pushable<Uint8Array>, buffer: Uint8Array | Uint8ArrayList): void;
10
+ /**
11
+ * `writeAll` behaves like `write`, except it encodes an array of items as a single write
12
+ */
13
+ export declare function writeAll(writer: Pushable<Uint8Array>, buffers: Uint8Array[]): void;
14
+ export declare function read(reader: Reader, options?: AbortOptions): Promise<Uint8Array>;
15
+ export declare function readString(reader: Reader, options?: AbortOptions): Promise<string>;
16
+ //# sourceMappingURL=multistream.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,57 @@
1
+ import { Uint8ArrayList } from 'uint8arraylist';
2
+ import * as lp from 'it-length-prefixed';
3
+ import { pipe } from 'it-pipe';
4
+ import errCode from 'err-code';
5
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
6
+ import first from 'it-first';
7
+ import { abortableSource } from 'abortable-iterator';
8
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
9
+ const NewLine = uint8ArrayFromString('\n');
10
+ export function encode(buffer) {
11
+ const list = new Uint8ArrayList(buffer, NewLine);
12
+ return lp.encode.single(list).slice();
13
+ }
14
+ /**
15
+ * `write` encodes and writes a single buffer
16
+ */
17
+ export function write(writer, buffer) {
18
+ writer.push(encode(buffer).slice());
19
+ }
20
+ /**
21
+ * `writeAll` behaves like `write`, except it encodes an array of items as a single write
22
+ */
23
+ export function writeAll(writer, buffers) {
24
+ const list = new Uint8ArrayList();
25
+ for (const buf of buffers) {
26
+ list.append(encode(buf));
27
+ }
28
+ writer.push(list.slice());
29
+ }
30
+ export async function read(reader, options) {
31
+ let byteLength = 1; // Read single byte chunks until the length is known
32
+ const varByteSource = {
33
+ [Symbol.asyncIterator]: () => varByteSource,
34
+ next: async () => await reader.next(byteLength)
35
+ };
36
+ let input = varByteSource;
37
+ // If we have been passed an abort signal, wrap the input source in an abortable
38
+ // iterator that will throw if the operation is aborted
39
+ if (options?.signal != null) {
40
+ input = abortableSource(varByteSource, options.signal);
41
+ }
42
+ // Once the length has been parsed, read chunk for that length
43
+ const onLength = (l) => { byteLength = l; };
44
+ const buf = await pipe(input, lp.decode({ onLength }), async (source) => await first(source));
45
+ if (buf == null) {
46
+ throw errCode(new Error('no buffer returned'), 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE');
47
+ }
48
+ if (buf[buf.length - 1] !== NewLine[0]) {
49
+ throw errCode(new Error('missing newline'), 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE');
50
+ }
51
+ return buf.slice(0, -1); // Remove newline
52
+ }
53
+ export async function readString(reader, options) {
54
+ const buf = await read(reader, options);
55
+ return uint8ArrayToString(buf);
56
+ }
57
+ //# sourceMappingURL=multistream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multistream.js","sourceRoot":"","sources":["../../src/multistream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AbortOptions } from '@libp2p/interfaces';
2
+ 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
+ }>;
7
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,48 @@
1
+ import { logger } from '@libp2p/logger';
2
+ import errCode from 'err-code';
3
+ import * as multistream from './multistream.js';
4
+ import { handshake } from 'it-handshake';
5
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
6
+ const log = logger('libp2p:mss:select');
7
+ export async function select(stream, protocols, protocolId, options) {
8
+ protocols = Array.isArray(protocols) ? [...protocols] : [protocols];
9
+ const { reader, writer, rest, stream: shakeStream } = handshake(stream);
10
+ const protocol = protocols.shift();
11
+ if (protocol == null) {
12
+ throw new Error('At least one protocol must be specified');
13
+ }
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
+ }
22
+ let response = await multistream.readString(reader, options);
23
+ log('select: read "%s"', response);
24
+ // Read the protocol response if we got the protocolId in return
25
+ if (response === protocolId) {
26
+ response = await multistream.readString(reader, options);
27
+ log('select: read "%s"', response);
28
+ }
29
+ // We're done
30
+ if (response === protocol) {
31
+ rest();
32
+ return { stream: shakeStream, protocol };
33
+ }
34
+ // We haven't gotten a valid ack, try the other protocols
35
+ for (const protocol of protocols) {
36
+ log('select: write "%s"', protocol);
37
+ multistream.write(writer, uint8ArrayFromString(protocol));
38
+ const response = await multistream.readString(reader, options);
39
+ log('select: read "%s" for "%s"', response, protocol);
40
+ if (response === protocol) {
41
+ rest(); // End our writer so others can start writing to stream
42
+ return { stream: shakeStream, protocol };
43
+ }
44
+ }
45
+ rest();
46
+ throw errCode(new Error('protocol selection failed'), 'ERR_UNSUPPORTED_PROTOCOL');
47
+ }
48
+ //# sourceMappingURL=select.js.map
@@ -0,0 +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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dialer.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialer.spec.d.ts","sourceRoot":"","sources":["../../test/dialer.spec.ts"],"names":[],"mappings":""}