JSPM

  • Created
  • Published
  • Downloads 48
  • Score
    100M100P100Q76398F
  • License ISC

node json rpc

Package Exports

  • renraku
  • renraku/dist/client/create-api-client.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (renraku) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

連絡
れんらく
R·E·N·R·A·K·U

node api library
   featuring seamless calling

RENRAKU creates seamless node api's

traditionally, to call an api, you'd do something like this:

// old and not cool
const userDetails = await api.apiCall("user.getDetails", [userId])

introducing RENRAKU!

// the future
const userDetails = await user.getDetails(userId)

RENRAKU features:

  • natural syntax with no more string literals to maintain
  • interchangable client object and server implementation (great for testing)
  • typings provide intellisense hints
  • typescript devs see errors in realtime (errors like a client/server api signature mismatch)

RENRAKU terminology:

  • api contains topics
  • topic contains functions
  • shape is json describing topic signature

RENRAKU leads by example

server.js — on your node server, expose some functionality

import {createApiServer} from "renraku"

const server = createApiServer({
  exposures: [
    {
      allowed: /^http\:\/\/localhost\:8\d{3}$/i,
      forbidden: /\:8989$/i,
      exposed: {
        reactor: {
          async generatePower(a, b) { return a + b },
          async radioactiveMeltdown(): Promise<void> {
            throw new Error("meltdown error")
          }
        }
      }
    }
  ]
})

server.start(8001)
  • topic objects must only have async functions
  • you can pass multiple exposures to expose different topics to different origins

client.js — call your functions from node or a browser

import {createApiClient} from "renraku"

async function main() {

  // create the renraku client
  const {reactor} = await createApiClient({
    url: "http://localhost:8001",
    shape: {
      reactor: {
        generatePower: true,
        radioactiveMeltdown: true
      }
    }
  })

  // ergonomic usage
  const result1 = await reactor.generatePower(1, 2)
  console.log(result1)
   //> 3

  const result2 = await reactor.radioactiveMeltdown()
   //> Error: meltdown error
}
  • you have to describe the shape of the api to the client.
    this allows RENRAKU to generate callable topic functions.
    if you use typescript, it will enforce that the shape is correctly maintained

RENRAKU is good for typescript devs

to use RENRAKU, the javascript examples above are all you need

additionally however, typescript devs can benefit by receiving compile-time errors, for example whenever a clientside shape object doesn't match a serverside implementation

to achieve this, carefully follow the examples below, and pay special attention to the usage of AbstractApiTopic on the serverside

common.ts

import {Api, Topic} from "renraku"

// topic interface, shared between server and client
export interface ReactorTopic extends Topic {
  generatePower(a: number): Promise<number>
  radioactiveMeltdown(a: number, b: number): Promise<number>
}

// api interface, shared between server and client
export interface NuclearApi extends Api {
  reactor: ReactorTopic
}

server.ts

import {createApiServer, AbstractTopic} from "renraku"
import {NuclearApi, ReactorTopic} from "./common"

class Reactor extends AbstractTopic implements ReactorTopic {
  async generatePower(a: number, b: number) { return a + b },
  async radioactiveMeltdown() { throw new Error("meltdown error") }
}

const server = createApiServer<NuclearApi>({
  exposures: [
    {
      allowed: /^http\:\/\/localhost\:8\d{3}$/i,
      forbidden: /\:8989$/i,
      exposed: {
        reactor: new Reactor()
      }
    }
  ]
)

client.ts

import {createApiClient} from "renraku"
import {NuclearApi, nuclearApiShape} from "./common"

const nuclearApiShape: ApiShape<NuclearApi> = {
  reactor: {
    generatePower: true,
    radioactiveMeltdown: true
  }
}

async function main() {
  const {reactor} = await createApiClient<NuclearApi>({
    url: "http://localhost:8001",
    shape: nuclearApiShape
  })

  const result = await reactor.generatePower(1, 2)
  console.log(result)
   //> 3
}

— RENRAKU means 'contact' —