Détail du package

it-ws

alanshaw105.7kApache-2.0 OR MIT6.1.5

Simple async iterables for websocket client connections

async, iterable, iterator, websocket

readme

it-ws

codecov CI

Simple async iterables for websocket client connections

Table of contents

Install

$ npm i it-ws

Browser <script> tag

Loading this module through a script tag will make it's exports available as ItWs in the global namespace.

<script src="https://unpkg.com/it-ws/dist/index.min.js"></script>

Usage

Example - client

import { connect } from 'it-ws/client'
import { pipe } from 'it-pipe'

const stream = connect(WS_URL)

await stream.connected() // Wait for websocket to be connected (optional)

pipe(source, stream, sink)

Example - server

import { createServer } from 'it-ws/server'
import { pipe } from 'it-pipe'

const server = createServer(stream => {
  //pipe the stream somewhere.
  //eg, echo server
  pipe(stream, stream)
})

await server.listen(PORT)

API

import { connect } from 'it-ws/client'

connect(url, { binary: boolean })

Create a websocket client connection. Set binary: true to get a stream of arrayBuffers (on the browser). Defaults to true on node, but to strings on the browser. This may cause a problems if your application assumes binary.

For adding options to the WebSocket instance, as websockets/ws/blob/master/doc/ws.md#new-websocketaddress-protocols-options, you can provide an object with the websocket property into the connect options.

const stream = connect(url)
// stream is duplex and is both a `source` and `sink`.
// See this for more information:
// https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it

import { createServer } from 'it-ws/server'

Create async iterable websocket servers.

createServer(options?, onConnection)

options takes the same server options as ws module

onConnection(stream) is called every time a connection is received.

Example

One duplex service you may want to use this with is muxrpc

import { createServer } from 'it-ws/server'
import { connect } from 'it-ws/client'
import { pipe } from 'it-pipe'

createServer({
  onConnection: (stream) => {
    // pipe duplex style to your service
    pipe(stream, service.createStream(), stream)
  }
})
.listen(9999)

const stream = client.createStream()

await pipe(
  stream,
  connect('ws://localhost:9999'),
  stream
)

if the connection fails, the stream will throw

try {
  await pipe(
    stream,
    connect('ws://localhost:9999'),
    stream
  )
} catch (err) {
  // handle err
}

To run the server over TLS:

createServer({
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
  // other options
})
.listen(9999)

To add client-authentication to the server, you can set verifyClient. Documentation here.

function verifyClient (info) {
  return info.secure == true
}
createServer({
  verifyClient: verifyClient
  // other options
})

use with an http server

if you have an http server that you also need to serve stuff over, and want to use a single port, use the server option.

import http from 'http'

const server = http.createServer(function(req, res){...}).listen(....)

createServer({
  server: server
  // other options
})

core, websocket wrapping functions

these modules are used internally, to wrap a websocket. you probably won't need to touch these, but they are documented anyway.

import duplex from 'it-ws/duplex'

turn a websocket into a duplex stream. If provided, opts is passed to sink(socket, opts).

WebSockets do not support half open mode. see allowHalfOpen option in net module

If you have a protocol that assumes halfOpen connections, but are using a networking protocol like websockets that does not support it, I suggest using it-goodbye with your protocol.

The duplex stream will also contain a copy of the properties from the http request that became the websocket. they are method, url, headers and upgrade.

also exposed at: import { duplex } from 'it-ws'

import sink from 'it-ws/sink'

Create a Sink that will write data to the socket. opts may be {closeOnEnd: true, onClose: onClose}. onClose will be called when the sink ends. If closeOnEnd=false the stream will not close, it will just stop emitting data. (by default closeOnEnd is true)

If opts is a function, then onClose = opts; opts.closeOnEnd = true.

import sink from 'it-ws/sink'
import { pipe } from 'it-pipe'
import each from 'it-foreach'
import delay from 'delay'

// connect to the echo endpoint for test/server.js
var socket = new WebSocket('wss://echo.websocket.org')

// write values to the socket
pipe(
  async function * () {
    while (true) {
      yield 'hello @ ' + Date.now()
    }
  }(),
  // throttle so it doesn't go nuts
  (source) => each(source, () => delay(100))
  sink(socket)
);

socket.addEventListener('message', function(evt) {
  console.log('received: ' + evt.data);
});

also exposed at import { sink } from 'it-ws'

import source from 'it-ws/source'

Create a Source that will read data from the socket.

import { pipe } from 'it-pipe'
import source from 'it-ws/source'
import { toString } from 'uint8arrays/to-string'

pipe(
  // connect to the test/server.js endpoint
  source(new WebSocket('ws://localhost:3000/read')),
  async (source) => {
    for await (const buf of source) {
      console.info(toString(buf))
    }
  }
);

also exposed at import { source } from 'it-ws'

License

Licensed under either of

Contribution

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.

changelog

6.1.5 (2024-07-30)

Bug Fixes

6.1.4 (2024-07-29)

Bug Fixes

6.1.3 (2024-07-24)

Dependencies

  • dev: bump aegir from 40.0.13 to 44.0.1 (#117) (2fd31de)

6.1.2 (2024-07-22)

Bug Fixes

  • export web-socket (#99) (9687a51)
  • it-goodbye expects the source to be an async generator (#115) (d00509c)

6.1.1 (2023-12-11)

Dependencies

  • bump uint8arrays from 4.0.10 to 5.0.0 (#96) (df1e824)

6.1.0 (2023-12-10)

Features

Trivial Changes

  • add or force update .github/workflows/js-test-and-release.yml (#77) (96f4c7b)
  • delete templates [skip ci] (#76) (e8b6c1f)

6.0.5 (2023-08-10)

Dependencies

  • add @types/ws to dependencies to ensure types for the version of ws are compatible (#71) (80092e8)

6.0.4 (2023-08-10)

Dependencies

  • dev: bump delay from 5.0.0 to 6.0.0 (#69) (a5b1437)

6.0.3 (2023-08-10)

Dependencies

  • dev: bump aegir from 38.1.8 to 40.0.0 (#74) (7749816)

6.0.2 (2023-08-10)

Bug Fixes

  • only send data if the socket is open (#75) (f63265e)

6.0.1 (2023-04-18)

Bug Fixes

6.0.0 (2023-04-18)

⚠ BREAKING CHANGES

  • the type of the source/sink properties have changed

Bug Fixes

Dependencies

5.0.6 (2022-12-08)

Bug Fixes

5.0.5 (2022-12-07)

Dependencies

  • update it-drain, it-ndjson and it-foreach (#35) (5c65441)

5.0.4 (2022-12-07)

Dependencies

  • dev: bump it-all from 1.0.6 to 2.0.0 (#27) (003752d)
  • dev: bump it-map from 1.0.6 to 2.0.0 (#28) (8cde19c)

5.0.3 (2022-10-13)

Bug Fixes

Trivial Changes

Dependencies

  • bump uint8arrays from 3.1.1 to 4.0.2 (#26) (3dea637)
  • dev: bump wherearewe from 1.0.2 to 2.0.1 (#22) (8a3635a)

5.0.2 (2022-05-20)

Bug Fixes

5.0.1 (2022-03-04)

Bug Fixes

5.0.0 (2022-01-29)

⚠ BREAKING CHANGES

  • switch to named exports, ESM only

Features