npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sidewinder/client

v0.14.0

Published

Sidewinder Client

Downloads

37

Readme

Overview

This package contains the WebClient and WebSocketClient client types to connect to WebService and WebSocketService services respectively. This package can be used in both Node and Browser environments. For consuming Sidewinder service in other languages see the Protocol section below.

Contents

Example

The following shows general usage of the Sidewinder WebClient.

import { Type } from '@sidewinder/contract'

export const Contract = Type.Contract({
  server: {
    add: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    sub: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    mul: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    div: Type.Function([Type.Number(), Type.Number()], Type.Number()),
  },
})
import { WebClient } from '@sidewinder/client'

const client = new WebClient(Contract, 'http://localhost:5000/')
const add = await client.call('add', 1, 2)
const sub = await client.call('sub', 1, 2)
const mul = await client.call('mul', 1, 2)
const div = await client.call('div', 1, 2)
console.log([add, sub, mul, div]) // [3, -1, 2, 0.5]

WebClient

The WebClient connects to WebService server implementations. This client type uses Http for the transport and only supports uni-directional request response calling patterns only. The WebClient provides two methods; call() and send(). The first argument is the name of the method to call, with subsequent arguments passed as parameters to the remote function.

import { Type } from '@sidewinder/contract'

export const Contract = Type.Contract({
  server: {
    add: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    sub: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    mul: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    div: Type.Function([Type.Number(), Type.Number()], Type.Number()),
  },
})
import { WebClient } from '@sidewinder/client'

const client = new WebClient(Contract, 'http://localhost:5000/')

/** Use the call() function to execute a remote service method and obtain a result. */
const result = client.call('add', 1, 2)

/** Use the send() function to execute a remote method and ignore the result. */
client.send('add', 1, 2)

WebSocketClient

The WebSocketClient connects to WebSocketService services. This client type provides the same functionality as the WebClient but offers additional support for bi-directional method calls as well as connection retry options.

const client = new WebSocketClient(Contract, 'ws://localhost:5000/', {
  /**
   * If true, this socket will attempt to automatically reconnect
   * to the remote service if the underlying WebSocket transport
   * closes.
   *
   * (Default is false)
   */
  autoReconnectEnabled: false,
  /**
   * If true, this socket will buffer any RPC method calls if calls
   * are made while the underlying WebSocket transport is in a
   * disconnected state. This option is only available if the
   * autoReconnectEnabled option is true.
   *
   * (Default is false)
   */
  autoReconnectBuffer: false,
  /**
   * The auto reconnection timeout. This is the period of time that
   * should elapse before a reconnection attempt is made in instances
   * the underlying WebSocket connection terminates. This option is
   * only available if the autoReconnectEnabled option is true.
   *
   * (Default is 4000)
   */
  autoReconnectTimeout: false,
})
import { Type } from '@sidewinder/contract'

export const Contract = Type.Contract({
  server: {
    task: Type.Function([], Type.Void()),
  },
  client: {
    log: Type.Function([Type.String()], Type.Void()),
  },
})
import { WebSocketService } from '@sidewinder/service'

const service = new WebSocketService(Contract)

service.method('task', async (context, request) => {
  await service.call(context, 'log', 'log message 1')
  await service.call(context, 'log', 'log message 2')
  await service.call(context, 'log', 'log message 3')
})
import { WebSocketClient } from '@sidewinder/client'

const client = new WebSocketClient(Contract, 'ws://localhost:5000')
client.method('log', (message) => console.log(message)) // 'log message 1'
// 'log message 2'
// 'log message 3'

client.call('task')

WebProxy

The WebProxy is a utility function that transforms either WebClient or WebServiceClient into a object where remote methods can be called as functions (vs passing string names for each function). This can be more ergonimic to use in some cases. Note the WebProxy function only transforms the call() function of the client. The following demonstrates its use.

import { Type } from '@sidewinder/contract'

export const Contract = Type.Contract({
  server: {
    add: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    sub: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    mul: Type.Function([Type.Number(), Type.Number()], Type.Number()),
    div: Type.Function([Type.Number(), Type.Number()], Type.Number()),
  },
})
import { WebClient, WebProxy } from '@sidewinder/client'

const client = WebProxy(new WebClient(Contract, 'http://localhost:5000/'))
const add = await client.add(1, 2)
const sub = await client.sub(1, 2)
const mul = await client.mul(1, 2)
const div = await client.div(1, 2)

Protocol

Sidewinder implements the JSON RPC 2.0 protocol specification over both Http and Web Sockets service types. The following section details how remote systems can communicate with Sidewinder services by using common JavaScript APIs.

Http

The following calls a WebService method using the JavaScript fetch(...) API. Note that the Content-Type must match the format described in the Contract (with is either json or msgpack). The appropriate Content Types are application/json or application/x-msgpack respectively.

const result = await fetch('http://localhost:5001/', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jsonrpc: '2.0',
    id: '1', // optional: omit if send()
    method: 'add',
    params: [1, 2],
  }),
}).then((res) => res.json())
// result = { jsonrpc: '2.0', id: '1', result: 3 }

WebSockets

The following calls a WebSocketService method using the JavaScript WebSocket API. Note Sidewinder transmits message using binary RFC6455 sockets only. You can use the JavaScript TextEncoder and TextDecoder to JSON to and from Uint8Array.

const encoder = new TextEncoder()
const decoder = new TextDecoder()
const socket  = new WebSocket('ws://localhost:5001/')
socket.binaryType = 'arraybuffer'

socket.onmessage = (event) => {
const result = JSON.parse(decoder.decode(event.data))
// result = { jsonrpc: '2.0', id: '1', result: 3 }
}
socket.onopen = () => {
socket.send(encoder.encode(JSON.stringify({
jsonrpc: '2.0',
id: '1', // optional: omit if send()
method: 'add',
params: [1, 2]
})))
}