Skip to content

Commit 7dfd00c

Browse files
committed
add README guide to handle server error
1 parent 0ed5ed7 commit 7dfd00c

File tree

1 file changed

+74
-11
lines changed

1 file changed

+74
-11
lines changed

README.md

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![codecov](https://codecov.io/gh/YieldRay/json-rpc-ts/graph/badge.svg?token=BabjRkI8jk)](https://codecov.io/gh/YieldRay/json-rpc-ts)
77
[![ci](https://github.com/yieldray/json-rpc-ts/actions/workflows/ci.yml/badge.svg)](https://github.com/yieldray/json-rpc-ts/actions/workflows/ci.yml)
88

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

1111
> Specification <https://www.jsonrpc.org/specification>
1212
@@ -28,9 +28,11 @@ deno add jsr:@yieldray/json-rpc-ts
2828

2929
# Examples
3030

31-
Example to use the client
31+
Example to use the client:
3232

3333
```ts
34+
import { JSONRPCClient } from '@yieldray/json-rpc-ts'
35+
3436
const requestForResponse = (json: string) =>
3537
fetch('http://localhost:6800/jsonrpc', {
3638
method: 'POST',
@@ -54,9 +56,11 @@ const resultGid: string = await client.request('aria2.addUri', [
5456
])
5557
```
5658

57-
Example to use the server
59+
Example to use the server:
5860

5961
```ts
62+
import { JSONRPCServer } from '@yieldray/json-rpc-ts'
63+
6064
const server = new JSONRPCServer({
6165
upper: (str: string) => str.toUpperCase(),
6266
lower: (str: string) => str.toLowerCase(),
@@ -69,14 +73,73 @@ server.setMethod('trim', (str: string) => str.trim())
6973
server.setMethod('trimStart', (str: string) => str.trimStart())
7074
server.setMethod('trimEnd', (str: string) => str.trimEnd())
7175

72-
const httpServer = Deno.serve(
73-
async (request) => {
74-
// server.handleRequest() accept string and returns Promise<string>
75-
const jsonString = await server.handleRequest(await request.text())
76+
const handler = async (request: Request): Promise<Response> => {
77+
// server.handleRequest() accept string and returns Promise<string>
78+
const jsonString = await server.handleRequest(await request.text())
7679

77-
return new Response(jsonString, {
78-
headers: { 'content-type': 'application/json' },
79-
})
80+
return new Response(jsonString, {
81+
headers: { 'content-type': 'application/json' },
82+
})
83+
}
84+
85+
const httpServer = Deno.serve(handler)
86+
```
87+
88+
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:
89+
90+
```ts
91+
import {
92+
JSONRPCInvalidParamsError,
93+
type JSONRPCMethod,
94+
type JSONRPCMethods,
95+
JSONRPCServer,
96+
} from '@yieldray/json-rpc-ts'
97+
98+
function wrapMethod<T, U>(fn: JSONRPCMethod<T, U>): JSONRPCMethod<T, U> {
99+
return async (arg) => {
100+
try {
101+
console.log('Request', arg, fn)
102+
const result = await fn(arg)
103+
console.log('Response', result)
104+
return result
105+
} catch (e) {
106+
console.error('Error', e)
107+
throw e
108+
}
109+
}
110+
}
111+
112+
function wrapMethods(methods: JSONRPCMethods): JSONRPCMethods {
113+
return Object.fromEntries(
114+
Object.entries(methods).map(([name, fn]) => [
115+
name,
116+
typeof fn === 'function' ? wrapMethod(fn.bind(methods)) : fn,
117+
]),
118+
)
119+
}
120+
121+
const methods: JSONRPCMethods = {
122+
upper: (str: string) => {
123+
if (typeof str !== 'string') {
124+
throw new JSONRPCInvalidParamsError(
125+
'Invalid argument type, expected string',
126+
)
127+
}
128+
// if not JSONRPCxxxError, the client will receive an Internal Error
129+
return str.toUpperCase()
80130
},
81-
)
131+
lower: (str: string) => str.toLowerCase(),
132+
plus: ([a, b]: [number, number]) => a + b,
133+
minus: ([a, b]: [number, number]) => a - b,
134+
}
135+
136+
const server = new JSONRPCServer(wrapMethods(methods))
137+
138+
// or:
139+
const setMethod = <T, U>(name: string, method: JSONRPCMethod<T, U>) =>
140+
server.setMethod(name, wrapMethod(method))
141+
142+
setMethod('trim', (str: string) => str.trim())
143+
setMethod('trimStart', (str: string) => str.trimStart())
144+
setMethod('trimEnd', (str: string) => str.trimEnd())
82145
```

0 commit comments

Comments
 (0)