@dcl/mini-rpc
This package can be used to create clients and servers over an abstract transport, and it includes some transport implementations.
Installation
npm i @dcl/mini-rpc
Usage
You need to define the methods, and optionally you can also add events
enum Method {
GET = 'get',
SET = 'set',
HAS = 'has',
DELETE = 'delete'
}
type Params = {
[Method.GET]: { key: string }
[Method.SET]: { key: string; value: string }
[Method.HAS]: { key: string }
[Method.DELETE]: { key: string }
}
type Result = {
[Method.GET]: string
[Method.SET]: void
[Method.HAS]: boolean
[Method.DELETE]: void
}
// optionally you can have events emitted by the server or the client
enum EventType {
HELLO = 'hello'
}
type EventData = {
[EventType.HELLO]: { name: string }
}
Then you can implement the client by extending the RPC
class and using the internal request
method
//client.ts
import { RPC } from '@dcl/mini-rpc'
import { Method, Params, Result, EventType, EventData } from './types'
export class Client extends RPC<Method, Params, Result, EventType, EventData> {
constructor(transport: RPC.Transport) {
super("my-rpc", transport)
}
get(key: string) {
return this.request('get', { key })
}
set(key: string, value: string) {
return this.request('set', { key, value })
}
has(key: string) {
return this.request('has', { key })
}
delete(key: string) {
return this.request('delete', { key })
}
}
NOTE: You will need to pass an id to the
RPC
super constructor, in this case"my-rpc"
you will need to use the same name for the server implementation. This is so multiples clients and servers can work over the same single transport.
To implement the server you do the same thing but use the internal handle
to implement the methods
// server.ts
import { RPC } from '@dcl/mini-rpc'
import { Method, Params, Result , EventType, EventData } from './types'
export class Server extends RPC<Method, Params, Result, EventType, EventData> {
constructor(transport: RPC.Transport) {
super("my-rpc", transport)
this.handle('get', async ({ key }) => {
return localStorage.getItem(key)
})
this.handle('set', async ({ key, value }) => {
return localStorage.setItem(key, value)
})
this.handle('has', async ({ key }) => {
return localStorage.getItem(key) !== null
})
this.handle('delete', async ({ path }) => {
return localStorage.removeItem(key)
})
}
}
Now you can create a transport and use the client like this
// webapp.ts
import { MessageTransport } from '@dcl/mini-rpc'
import { Client } from './client'
const iframe = document.getElementById('my-iframe')
const transport = new MessageTransport(window, iframe.contentWindow, 'https://iframe.com')
const client = new Client(transport)
// you can use any method on the client and it will be relayer to the server, and it will resolve/reject to the result/error
await client.set('some-key', 'some-value')
console.log(await client.get('some-key')) // 'some-value'
// you can also listen to events from the server
client.on('hello', ({ name }) => console.log(`hello ${name}`))
And the server like this
// iframe.ts
import { MessageTransport } from '@dcl/mini-rpc'
import { Server } from './server'
const transport = new MessageTransport(window, window.parent, 'https://parent.com')
const server = new Server(transport)
// you can emit events if needed for the client to listen to
server.emit('hello', { name: 'world' })
Test
npm test
Or with coverage reports
npm run test:coverage
Build
npm run build
Release
To release a new version of this package create a new release via GitHub