diff --git a/.gitignore b/.gitignore
index db79d1f189..910f6339ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,8 @@
node_modules
-coverage
-.nyc_output
+build
+dist
+.docs
+.coverage
+node_modules
package-lock.json
yarn.lock
-docs
-dist
diff --git a/README.md b/README.md
index 3559f75116..9014aa4a0c 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,20 @@
# @libp2p/multistream-select
[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
-[![IRC](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p)
[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io)
[![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)
-[![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)
+[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-multistream-select/js-test-and-release.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p-multistream-select/actions/workflows/js-test-and-release.yml?query=branch%3Amaster)
> JavaScript implementation of multistream-select
## Table of contents
- [Install](#install)
+ - [Browser `
+```
+
## Background
### What is `multistream-select`?
TLDR; multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select)
-#### Select a protocol flow
+### Select a protocol flow
The caller will send "interactive" messages, expecting for some acknowledgement from the callee, which will "select" the handler for the desired and supported protocol:
-```console
+```
< /multistream-select/0.3.0 # i speak multistream-select/0.3.0
> /multistream-select/0.3.0 # ok, let's speak multistream-select/0.3.0
> /ipfs-dht/0.2.3 # i want to speak ipfs-dht/0.2.3
@@ -57,142 +54,9 @@ The caller will send "interactive" messages, expecting for some acknowledgement
>
```
-## Usage
-
-```js
-import { select, handle } from '@libp2p/multistream-select'
-// You can now use
-// select - actively select a protocol with a remote
-// handle - handle a protocol with a remote
-```
-
-### Dialer
-
-```js
-import { pipe } from 'it-pipe'
-import * as mss from '@libp2p/multistream-select'
-import { Mplex } from '@libp2p/mplex'
-
-const muxer = new Mplex()
-const muxedStream = muxer.newStream()
-
-// mss.select(protocol(s))
-// Select from one of the passed protocols (in priority order)
-// Returns selected stream and protocol
-const { stream: dhtStream, protocol } = await mss.select(muxedStream, [
- // This might just be different versions of DHT, but could be different impls
- '/ipfs-dht/2.0.0', // Most of the time this will probably just be one item.
- '/ipfs-dht/1.0.0'
-])
-
-// Typically this stream will be passed back to the caller of libp2p.dialProtocol
-//
-// ...it might then do something like this:
-// try {
-// await pipe(
-// [uint8ArrayFromString('Some DHT data')]
-// dhtStream,
-// async source => {
-// for await (const chunk of source)
-// // DHT response data
-// }
-// )
-// } catch (err) {
-// // Error in stream
-// }
-```
-
-### Listener
-
-```js
-import { pipe } from 'it-pipe'
-import * as mss from '@libp2p/multistream-select'
-import { Mplex } from '@libp2p/mplex'
-
-const muxer = new Mplex({
- async onStream (muxedStream) {
- // mss.handle(handledProtocols)
- // Returns selected stream and protocol
- const { stream, protocol } = await mss.handle(muxedStream, [
- '/ipfs-dht/1.0.0',
- '/ipfs-bitswap/1.0.0'
- ])
-
- // Typically here we'd call the handler function that was registered in
- // libp2p for the given protocol:
- // e.g. handlers[protocol].handler(stream)
- //
- // If protocol was /ipfs-dht/1.0.0 it might do something like this:
- // try {
- // await pipe(
- // dhtStream,
- // source => (async function * () {
- // for await (const chunk of source)
- // // Incoming DHT data -> process and yield to respond
- // })(),
- // dhtStream
- // )
- // } catch (err) {
- // // Error in stream
- // }
- }
-})
-```
-
-## API
-
-### `mss.select(dulpex, protocols, [options])`
-
-Negotiate a protocol to use from a list of protocols.
-
-#### Parameters
-
-- `duplex` (`Duplex`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to dial on.
-- `protocols` (`string[]`/`string`) - A list of protocols (or single protocol) to negotiate with. Protocols are attempted in order until a match is made.
-- `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
-
-#### Returns
-
-`Promise<{ stream, protocol }>` - A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`.
-
-Note that after a protocol is selected `dialer` can no longer be used.
-
-#### Examples
-
-```js
-const { stream, protocol } = await dialer.select([
- // This might just be different versions of DHT, but could be different impls
- '/ipfs-dht/2.0.0', // Most of the time this will probably just be one item.
- '/ipfs-dht/1.0.0'
-])
-// Now talk `protocol` on `stream`
-```
-
-### `mss.handle(duplex, protocols, [options])`
+## API Docs
-Handle multistream protocol selections for the given list of protocols.
-
-#### Parameters
-
-- `duplex` (`Duplex`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to listen on.
-- `protocols` (`String[]`/`String`) - A list of protocols (or single protocol) that this listener is able to speak.
-- `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
-
-#### Returns
-
-`Promise<{ stream, protocol }>` - A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`.
-
-Note that after a protocol is handled `listener` can no longer be used.
-
-#### Examples
-
-```js
-const { stream, protocol } = await mss.handle(duplex, [
- '/ipfs-dht/1.0.0',
- '/ipfs-bitswap/1.0.0'
-])
-// Remote wants to speak `protocol`
-```
+-
## License
diff --git a/package.json b/package.json
index 34832092b6..3bb2cfa699 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"types": "./dist/src/index.d.ts",
"files": [
"src",
- "dist/src",
+ "dist",
"!dist/test",
"!**/*.tsbuildinfo"
],
@@ -139,7 +139,8 @@
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
"test:node": "aegir test -t node --cov",
"test:electron-main": "aegir test -t electron-main",
- "release": "aegir release"
+ "release": "aegir release",
+ "docs": "aegir docs"
},
"dependencies": {
"@libp2p/interfaces": "^3.0.2",
diff --git a/src/handle.ts b/src/handle.ts
index 6c38d77645..a5d160698d 100644
--- a/src/handle.ts
+++ b/src/handle.ts
@@ -9,6 +9,52 @@ import type { ByteArrayInit, ByteListInit, MultistreamSelectInit, ProtocolStream
const log = logger('libp2p:mss:handle')
+/**
+ * Handle multistream protocol selections for the given list of protocols.
+ *
+ * Note that after a protocol is handled `listener` can no longer be used.
+ *
+ * @param stream - A duplex iterable stream to listen on
+ * @param protocols - A list of protocols (or single protocol) that this listener is able to speak.
+ * @param options - 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
+ * @returns A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`
+ * @example
+ *
+ * ```js
+ * import { pipe } from 'it-pipe'
+ * import * as mss from '@libp2p/multistream-select'
+ * import { Mplex } from '@libp2p/mplex'
+ *
+ * const muxer = new Mplex({
+ * async onStream (muxedStream) {
+ * // mss.handle(handledProtocols)
+ * // Returns selected stream and protocol
+ * const { stream, protocol } = await mss.handle(muxedStream, [
+ * '/ipfs-dht/1.0.0',
+ * '/ipfs-bitswap/1.0.0'
+ * ])
+ *
+ * // Typically here we'd call the handler function that was registered in
+ * // libp2p for the given protocol:
+ * // e.g. handlers[protocol].handler(stream)
+ * //
+ * // If protocol was /ipfs-dht/1.0.0 it might do something like this:
+ * // try {
+ * // await pipe(
+ * // dhtStream,
+ * // source => (async function * () {
+ * // for await (const chunk of source)
+ * // // Incoming DHT data -> process and yield to respond
+ * // })(),
+ * // dhtStream
+ * // )
+ * // } catch (err) {
+ * // // Error in stream
+ * // }
+ * }
+ * })
+ * ```
+ */
export async function handle (stream: Duplex, protocols: string | string[], options: ByteArrayInit): Promise>
export async function handle (stream: Duplex, protocols: string | string[], options?: ByteListInit): Promise>
export async function handle (stream: Duplex, protocols: string | string[], options?: MultistreamSelectInit): Promise> {
diff --git a/src/select.ts b/src/select.ts
index a0478535ea..702e5ce983 100644
--- a/src/select.ts
+++ b/src/select.ts
@@ -13,6 +13,49 @@ import type { ByteArrayInit, ByteListInit, MultistreamSelectInit, ProtocolStream
const log = logger('libp2p:mss:select')
+/**
+ * Negotiate a protocol to use from a list of protocols.
+ *
+ * @param stream - A duplex iterable stream to dial on
+ * @param protocols - A list of protocols (or single protocol) to negotiate with. Protocols are attempted in order until a match is made.
+ * @param options - 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
+ * @returns A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`.
+ * @example
+ *
+ * ```js
+ * import { pipe } from 'it-pipe'
+ * import * as mss from '@libp2p/multistream-select'
+ * import { Mplex } from '@libp2p/mplex'
+ *
+ * const muxer = new Mplex()
+ * const muxedStream = muxer.newStream()
+ *
+ * // mss.select(protocol(s))
+ * // Select from one of the passed protocols (in priority order)
+ * // Returns selected stream and protocol
+ * const { stream: dhtStream, protocol } = await mss.select(muxedStream, [
+ * // This might just be different versions of DHT, but could be different impls
+ * '/ipfs-dht/2.0.0', // Most of the time this will probably just be one item.
+ * '/ipfs-dht/1.0.0'
+ * ])
+ *
+ * // Typically this stream will be passed back to the caller of libp2p.dialProtocol
+ * //
+ * // ...it might then do something like this:
+ * // try {
+ * // await pipe(
+ * // [uint8ArrayFromString('Some DHT data')]
+ * // dhtStream,
+ * // async source => {
+ * // for await (const chunk of source)
+ * // // DHT response data
+ * // }
+ * // )
+ * // } catch (err) {
+ * // // Error in stream
+ * // }
+ * ```
+ */
export async function select (stream: Duplex, protocols: string | string[], options: ByteArrayInit): Promise>
export async function select (stream: Duplex, protocols: string | string[], options?: ByteListInit): Promise>
export async function select (stream: Duplex, protocols: string | string[], options: MultistreamSelectInit = {}): Promise> {