Skip to content

YieldRay/json-rpc-ts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

json-rpc-ts

deno.land/x JSR npm codecov ci

A strictly typed json-rpc(2.0) implementation, zero dependency, minimal abstraction, with a simple API.

Specification https://www.jsonrpc.org/specification

Installation

For Node.js

npx jsr add @yieldray/json-rpc-ts # recommended
# or
npm install @yieldray/json-rpc-ts

For Deno

deno add jsr:@yieldray/json-rpc-ts

Examples

Example to use the client:

import { JSONRPCClient } from '@yieldray/json-rpc-ts'

const requestForResponse = (json: string) =>
    fetch('http://localhost:6800/jsonrpc', {
        method: 'POST',
        body: json,
    }).then((res) => res.text())

const client = new JSONRPCClient<{
    'aria2.addUri': (
        urls: string[],
        options?: object,
        position?: number,
    ) => string
    'aria2.remove': (gid: string) => string
    'system.listMethods': () => string[]
}>(requestForResponse)

const resultGid: string = await client.request('aria2.addUri', [
    ['https://example.net/index.html'],
    {},
    0,
])

Example to use the server:

import { JSONRPCServer } from '@yieldray/json-rpc-ts'

const server = new JSONRPCServer({
    upper: (str: string) => str.toUpperCase(),
    lower: (str: string) => str.toLowerCase(),
    plus: ([a, b]: [number, number]) => a + b,
    minus: ([a, b]: [number, number]) => a - b,
})

// or:
server.setMethod('trim', (str: string) => str.trim())
server.setMethod('trimStart', (str: string) => str.trimStart())
server.setMethod('trimEnd', (str: string) => str.trimEnd())

const handler = async (request: Request): Promise<Response> => {
    // server.handleRequest() accept string and returns Promise<string>
    const jsonString = await server.handleRequest(await request.text())

    return new Response(jsonString, {
        headers: { 'content-type': 'application/json' },
    })
}

const httpServer = Deno.serve(handler)

When a server function fails, the server does not throw an exception but instead sends a JSONRPCError to the client, making the error unobservable by default. To handle server errors, you can wrap the server function as follows:

import {
    JSONRPCInvalidParamsError,
    type JSONRPCMethod,
    type JSONRPCMethods,
    JSONRPCServer,
} from '@yieldray/json-rpc-ts'

function wrapMethod<T, U>(fn: JSONRPCMethod<T, U>): JSONRPCMethod<T, U> {
    return async (arg) => {
        try {
            console.log('Request', arg, fn)
            const result = await fn(arg)
            console.log('Response', result)
            return result
        } catch (e) {
            console.error('Error', e)
            throw e
        }
    }
}

function wrapMethods(methods: JSONRPCMethods): JSONRPCMethods {
    return Object.fromEntries(
        Object.entries(methods).map(([name, fn]) => [
            name,
            typeof fn === 'function' ? wrapMethod(fn.bind(methods)) : fn,
        ]),
    )
}

const methods: JSONRPCMethods = {
    upper: (str: string) => {
        if (typeof str !== 'string') {
            throw new JSONRPCInvalidParamsError(
                'Invalid argument type, expected string',
            )
        }
        // if not JSONRPCxxxError, the client will receive an Internal Error
        return str.toUpperCase()
    },
    lower: (str: string) => str.toLowerCase(),
    plus: ([a, b]: [number, number]) => a + b,
    minus: ([a, b]: [number, number]) => a - b,
}

const server = new JSONRPCServer(wrapMethods(methods))

// or:
const setMethod = <T, U>(name: string, method: JSONRPCMethod<T, U>) =>
    server.setMethod(name, wrapMethod(method))

setMethod('trim', (str: string) => str.trim())
setMethod('trimStart', (str: string) => str.trimStart())
setMethod('trimEnd', (str: string) => str.trimEnd())

About

A strictly typed json-rpc(2.0) implementation, zero dependency, minimal abstraction, with simple api

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published