Comparing version 0.2.0 to 0.3.0
@@ -1,7 +0,7 @@ | ||
import { RPCConnection, RPCParams } from './types'; | ||
export declare class RPCClient { | ||
connection: RPCConnection; | ||
constructor(connection: RPCConnection); | ||
import type { RPCConnection, RPCMethods } from './types'; | ||
export declare class RPCClient<Methods extends RPCMethods> { | ||
connection: RPCConnection<Methods>; | ||
constructor(connection: RPCConnection<Methods>); | ||
createID(): string; | ||
request<M = string, P extends RPCParams | undefined = undefined, R = unknown, E = undefined>(method: M, params?: P): Promise<R>; | ||
request<MethodName extends keyof Methods>(method: MethodName, params: Methods[MethodName]['params']): Promise<Methods[MethodName]['result']>; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { RPCErrorObject } from './types'; | ||
import type { RPCErrorObject } from './types'; | ||
export declare enum ERROR_CODE { | ||
@@ -3,0 +3,0 @@ PARSE_ERROR = -32700, |
@@ -1054,4 +1054,5 @@ 'use strict'; | ||
console.warn('Unhandled notification', msg); | ||
} | ||
} // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types | ||
function createHandler(methods, options) { | ||
@@ -1058,0 +1059,0 @@ var _options$onHandlerErr, _options$onInvalidMes, _options$onNotificati; |
@@ -1052,4 +1052,5 @@ import { nanoid } from 'nanoid'; | ||
console.warn('Unhandled notification', msg); | ||
} | ||
} // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types | ||
function createHandler(methods, options) { | ||
@@ -1056,0 +1057,0 @@ var _options$onHandlerErr, _options$onInvalidMes, _options$onNotificati; |
@@ -1,14 +0,15 @@ | ||
import { RPCErrorResponse, RPCParams, RPCRequest, RPCResponse } from './types'; | ||
export declare type ErrorHandler<C = unknown, M = string> = <P extends RPCParams | undefined>(ctx: C, req: RPCRequest<M, P>, error: Error) => void; | ||
export declare type MethodHandler<C = unknown, P extends RPCParams | undefined = undefined, R = unknown> = (ctx: C, params?: P) => R | Promise<R>; | ||
export declare type NotificationHandler<C = unknown, M = string> = <P extends RPCParams | undefined>(ctx: C, req: RPCRequest<M, P>) => void; | ||
export declare type HandlerMethods<C = unknown> = Record<string, MethodHandler<C>>; | ||
export interface HandlerOptions<C = any> { | ||
onHandlerError?: ErrorHandler<C>; | ||
onInvalidMessage?: NotificationHandler<C>; | ||
onNotification?: NotificationHandler<C>; | ||
} | ||
export declare type RequestHandler<C = any, M = string> = <P extends RPCParams | undefined, R, E>(ctx: C, msg: RPCRequest<M, P | undefined>) => Promise<RPCResponse<R, E | undefined> | null>; | ||
import type { RPCErrorResponse, RPCMethods, RPCRequest, RPCResponse } from './types'; | ||
export declare type ErrorHandler<Context, Methods extends RPCMethods> = <K extends keyof Methods>(ctx: Context, req: RPCRequest<Methods, K>, error: Error) => void; | ||
export declare type MethodHandler<Context, Params, Result> = (ctx: Context, params?: Params) => Result | Promise<Result>; | ||
export declare type NotificationHandler<Context, Methods extends RPCMethods> = <K extends keyof Methods>(ctx: Context, req: RPCRequest<Methods, K>) => void; | ||
export declare type HandlerMethods<Context, Methods extends RPCMethods> = { | ||
[K in keyof Methods]: MethodHandler<Context, Methods[K]['params'], Methods[K]['result']>; | ||
}; | ||
export declare type HandlerOptions<Context, Methods extends RPCMethods> = { | ||
onHandlerError?: ErrorHandler<Context, Methods>; | ||
onInvalidMessage?: NotificationHandler<Context, Methods>; | ||
onNotification?: NotificationHandler<Context, Methods>; | ||
}; | ||
export declare function parseJSON<T = any>(input: string): T; | ||
export declare function createErrorResponse(id: number | string, code: number): RPCErrorResponse; | ||
export declare function createHandler<C = unknown>(methods: HandlerMethods<C>, options?: HandlerOptions<C>): RequestHandler<C, keyof typeof methods>; | ||
export declare function createHandler<Context, Methods extends RPCMethods>(methods: HandlerMethods<Context, Methods>, options?: HandlerOptions<Context, Methods>): <K extends keyof Methods>(ctx: Context, msg: RPCRequest<Methods, K>) => Promise<import("./types").RPCResultResponse<Methods[K]["result"]> | RPCErrorResponse<Methods[K]["error"]> | null>; |
export declare type RPCID = string | number | null; | ||
export declare type RPCParams = Record<string, unknown> | Array<unknown>; | ||
export declare type RPCRequest<M = string, P extends RPCParams | undefined = undefined> = { | ||
export declare type RPCMethodTypes = { | ||
params?: RPCParams; | ||
result?: unknown; | ||
error?: undefined; | ||
}; | ||
export declare type RPCMethods = Record<string, RPCMethodTypes>; | ||
export declare type RPCRequest<Methods extends RPCMethods, MethodName extends keyof Methods> = { | ||
jsonrpc: string; | ||
method: M; | ||
method: MethodName; | ||
params: Methods[MethodName]['params']; | ||
id?: RPCID; | ||
} & (P extends undefined ? { | ||
params?: any; | ||
} : { | ||
params: P; | ||
}); | ||
export declare type RPCErrorObject<D = undefined> = { | ||
}; | ||
export declare type RPCErrorObject<Data = undefined> = { | ||
code: number; | ||
data?: Data; | ||
message?: string; | ||
} & (D extends undefined ? { | ||
data?: undefined; | ||
} : { | ||
data: D; | ||
}); | ||
export declare type RPCErrorResponse<E = undefined> = { | ||
}; | ||
export declare type RPCErrorResponse<ErrorData = undefined> = { | ||
jsonrpc: string; | ||
id: RPCID; | ||
result?: never; | ||
error: RPCErrorObject<E>; | ||
error: RPCErrorObject<ErrorData>; | ||
}; | ||
export declare type RPCResultResponse<R = unknown> = { | ||
export declare type RPCResultResponse<Result = unknown> = { | ||
jsonrpc: string; | ||
id: RPCID; | ||
result: R; | ||
result: Result; | ||
error?: never; | ||
}; | ||
export declare type RPCResponse<R = unknown, E = undefined> = RPCResultResponse<R> | RPCErrorResponse<E>; | ||
export declare type SendRequestFunc = <M = string, P extends RPCParams | undefined = undefined, R = undefined, E = undefined>(request: RPCRequest<M, P>) => Promise<RPCResponse<R, E> | null>; | ||
export interface RPCConnection { | ||
send: SendRequestFunc; | ||
} | ||
export declare type RPCResponse<Methods extends RPCMethods, K extends keyof Methods> = RPCResultResponse<Methods[K]['result']> | RPCErrorResponse<Methods[K]['error']>; | ||
export declare type SendRequestFunc<Methods extends RPCMethods> = <K extends keyof Methods>(request: RPCRequest<Methods, K>) => Promise<RPCResponse<Methods, K> | null>; | ||
export declare type RPCConnection<Methods extends RPCMethods> = { | ||
send: SendRequestFunc<Methods>; | ||
}; |
{ | ||
"name": "rpc-utils", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"author": "Paul Le Cam <paul@3box.io>", | ||
@@ -26,13 +26,15 @@ "license": "(Apache-2.0 OR MIT)", | ||
"dependencies": { | ||
"nanoid": "^3.1.18" | ||
"nanoid": "^3.1.20" | ||
}, | ||
"devDependencies": { | ||
"@size-limit/preset-small-lib": "^4.9.0", | ||
"@size-limit/preset-small-lib": "^4.9.2", | ||
"@types/nanoid": "^2.1.0", | ||
"eslint": "^7.21.0", | ||
"eslint-config-3box": "^0.2.0", | ||
"husky": "^4.3.0", | ||
"size-limit": "^4.9.0", | ||
"husky": "^5.1.3", | ||
"prettier": "^2.2.1", | ||
"size-limit": "^4.9.2", | ||
"tsdx": "^0.14.1", | ||
"tslib": "^2.0.3", | ||
"typescript": "^4.1.2" | ||
"tslib": "^2.1.0", | ||
"typescript": "^4.2.2" | ||
}, | ||
@@ -39,0 +41,0 @@ "husky": { |
154
README.md
@@ -11,3 +11,3 @@ # RPC utils | ||
## Types and interfaces | ||
## Types | ||
@@ -26,10 +26,27 @@ ### RPCID | ||
### RPCMethodTypes | ||
```ts | ||
type RPCMethodTypes = { | ||
params?: RPCParams | ||
result?: unknown | ||
error?: undefined | ||
} | ||
``` | ||
### RPCMethods | ||
```ts | ||
type RPCMethods = Record<string, RPCMethodTypes> | ||
``` | ||
### RPCRequest | ||
```ts | ||
type RPCRequest<M = string, P extends RPCParams | undefined = undefined> = { | ||
type RPCRequest<Methods extends RPCMethods, MethodName extends keyof Methods> = { | ||
jsonrpc: string | ||
method: M | ||
method: MethodName | ||
params: Methods[MethodName]['params'] | ||
id?: RPCID | ||
} & (P extends undefined ? { params?: any } : { params: P }) | ||
} | ||
``` | ||
@@ -40,6 +57,7 @@ | ||
```ts | ||
type RPCErrorObject<D = undefined> = { | ||
type RPCErrorObject<Data = undefined> = { | ||
code: number | ||
data?: Data | ||
message?: string | ||
} & (D extends undefined ? { data?: undefined } : { data: D }) | ||
} | ||
``` | ||
@@ -50,7 +68,7 @@ | ||
```ts | ||
type RPCErrorResponse<E = undefined> = { | ||
type RPCErrorResponse<ErrorData = undefined> = { | ||
jsonrpc: string | ||
id: RPCID | ||
result?: never | ||
error: RPCErrorObject<E> | ||
error: RPCErrorObject<ErrorData> | ||
} | ||
@@ -62,6 +80,6 @@ ``` | ||
```ts | ||
type RPCResultResponse<R = unknown> = { | ||
type RPCResultResponse<Result = unknown> = { | ||
jsonrpc: string | ||
id: RPCID | ||
result: R | ||
result: Result | ||
error?: never | ||
@@ -74,3 +92,5 @@ } | ||
```ts | ||
type RPCResponse<R = unknown, E = undefined> = RPCResultResponse<R> | RPCErrorResponse<E> | ||
type RPCResponse<Methods extends RPCMethods, K extends keyof Methods> = | ||
| RPCResultResponse<Methods[K]['result']> | ||
| RPCErrorResponse<Methods[K]['error']> | ||
``` | ||
@@ -81,10 +101,5 @@ | ||
```ts | ||
type SendRequestFunc = < | ||
M = string, | ||
P extends RPCParams | undefined = undefined, | ||
R = undefined, | ||
E = undefined | ||
>( | ||
request: RPCRequest<M, P> | ||
) => Promise<RPCResponse<R, E> | null> | ||
type SendRequestFunc<Methods extends RPCMethods> = <K extends keyof Methods>( | ||
request: RPCRequest<Methods, K> | ||
) => Promise<RPCResponse<Methods, K> | null> | ||
``` | ||
@@ -95,4 +110,4 @@ | ||
```ts | ||
interface RPCConnection { | ||
send: SendRequestFunc | ||
type RPCConnection<Methods extends RPCMethods> = { | ||
send: SendRequestFunc<Methods> | ||
} | ||
@@ -104,5 +119,5 @@ ``` | ||
```ts | ||
type ErrorHandler<C = unknown, M = string> = <P extends RPCParams | undefined>( | ||
ctx: C, | ||
req: RPCRequest<M, P>, | ||
type ErrorHandler<Context, Methods extends RPCMethods> = <K extends keyof Methods>( | ||
ctx: Context, | ||
req: RPCRequest<Methods, K>, | ||
error: Error | ||
@@ -115,6 +130,6 @@ ) => void | ||
```ts | ||
type MethodHandler<C = unknown, P extends RPCParams | undefined = undefined, R = unknown> = ( | ||
ctx: C, | ||
params?: P | ||
) => R | Promise<R> | ||
type MethodHandler<Context, Params, Result> = ( | ||
ctx: Context, | ||
params?: Params | ||
) => Result | Promise<Result> | ||
``` | ||
@@ -125,5 +140,5 @@ | ||
```ts | ||
type NotificationHandler<C = unknown, M = string> = <P extends RPCParams | undefined>( | ||
ctx: C, | ||
req: RPCRequest<M, P> | ||
type NotificationHandler<Context, Methods extends RPCMethods> = <K extends keyof Methods>( | ||
ctx: Context, | ||
req: RPCRequest<Methods, K> | ||
) => void | ||
@@ -135,3 +150,5 @@ ``` | ||
```ts | ||
type HandlerMethods<C = any> = Record<string, MethodHandler<C>> | ||
type HandlerMethods<Context, Methods extends RPCMethods> = { | ||
[K in keyof Methods]: MethodHandler<Context, Methods[K]['params'], Methods[K]['result']> | ||
} | ||
``` | ||
@@ -142,18 +159,9 @@ | ||
```ts | ||
interface HandlerOptions<C = any> { | ||
onHandlerError?: ErrorHandler<C> | ||
onInvalidMessage?: NotificationHandler<C> | ||
onNotification?: NotificationHandler<C> | ||
type HandlerOptions<Context, Methods extends RPCMethods> = { | ||
onHandlerError?: ErrorHandler<Context, Methods> | ||
onInvalidMessage?: NotificationHandler<Context, Methods> | ||
onNotification?: NotificationHandler<Context, Methods> | ||
} | ||
``` | ||
### RequestHandler | ||
```ts | ||
type RequestHandler<C = any, M = string> = <P extends RPCParams | undefined, R, E>( | ||
ctx: C, | ||
msg: RPCRequest<M, P | undefined> | ||
) => Promise<RPCResponse<R, E | undefined> | null> | ||
``` | ||
## Error APIs | ||
@@ -183,3 +191,3 @@ | ||
1. `T = any`: the type of the `data` attached to the error | ||
1. `Data = any`: the type of the `data` attached to the error | ||
@@ -192,3 +200,3 @@ #### new RPCError() | ||
1. `message?: string | undefined`: if not set, will use `getErrorMessage()` | ||
1. `data?: T | undefined` | ||
1. `data?: Data | undefined` | ||
@@ -205,7 +213,7 @@ #### .code | ||
**Returns** `T | undefined` | ||
**Returns** `Data | undefined` | ||
#### .toObject() | ||
**Returns** `RPCErrorObject<T>` | ||
**Returns** `RPCErrorObject<Data>` | ||
@@ -216,9 +224,9 @@ #### RPCError.fromObject() | ||
1. `D = unknown`: the type of the `data` attached to the error | ||
1. `Data = unknown`: the type of the `data` attached to the error | ||
**Arguments** | ||
1. `error: RPCErrorObject<D>` | ||
1. `error: RPCErrorObject<Data>` | ||
**Returns** `RPCError<D>` | ||
**Returns** `RPCError<Data>` | ||
@@ -229,2 +237,6 @@ ## Client APIs | ||
**Type parameters** | ||
1. `Methods extends RPCMethods`: the methods supported by the RPC server | ||
#### new RPCClient() | ||
@@ -234,3 +246,3 @@ | ||
1. `connection: RPCConnection` | ||
1. `connection: RPCConnection<Methods>` | ||
@@ -241,12 +253,9 @@ #### .send() | ||
1. `M = string`: the request `method` | ||
1. `P extends RPCParams | undefined = undefined`: the request `params` | ||
1. `R = unknown`: the response `result` | ||
1. `E = undefined`: the response error `data` | ||
1. `MethodName extends keyof Methods`: the request `method` | ||
**Arguments** | ||
1. `request: RPCRequest<M, P>` | ||
1. `request: RPCRequest<Methods, MethodName>` | ||
**Returns** `Promise<RPCResponse<R, E | undefined> | null>` | ||
**Returns** `Promise<RPCResponse<Methods, MethodName> | null>` | ||
@@ -257,13 +266,10 @@ #### .request() | ||
1. `M = string`: the request `method` | ||
1. `P extends RPCParams | undefined = undefined`: the request `params` | ||
1. `R = unknown`: the response `result` | ||
1. `E = undefined`: the response error `data` | ||
1. `MethodName extends keyof Methods`: the request `method` | ||
**Arguments** | ||
1. `method: M` | ||
1. `params: P` | ||
1. `method: MethodName` | ||
1. `params: Methods[MethodName]['params']` | ||
**Returns** `Promise<R>` or throws a `RPCError` instance if the request fails | ||
**Returns** `Promise<Methods[MethodName]['result']>` or throws a `RPCError` instance if the request fails | ||
@@ -288,17 +294,17 @@ ## Server APIs | ||
1. `C = unknown`: the context type | ||
1. `M = string`: the `methods` keys | ||
1. `Context`: the context type | ||
1. `Methods extends RPCMethods`: the methods and APIs types | ||
**Arguments** | ||
1. `methods: HandlerMethods<C>` | ||
1. `options: HandlerOptions<C> = {}` | ||
1. `methods: HandlerMethods<Context, Methods>` | ||
1. `options: HandlerOptions<Context, Methods> = {}` | ||
**Returns** `RequestHandler<C, M>` | ||
**Returns** `<K extends keyof Methods>(ctx: Context, msg: RPCRequest<Methods, K>): Promise<RPCResponse<Methods, K> | null>` request handler function | ||
**Options** | ||
- `onHandlerError: ErrorHandler<C>`: callback used when a method handler throws an `Error` other than `RPCError`. | ||
- `onInvalidMessage: NotificationHandler<C, M>`: callback used when receiving an invalid message, such as not having the `jsonrpc` field as `2.0` or missing the `method`. | ||
- `onNotification: NotificationHandler<C, M>`: callback used when receiving a JSON-RPC notification (no `id` present). | ||
- `onHandlerError: ErrorHandler<Context, Methods>`: callback used when a method handler throws an `Error` other than `RPCError`. | ||
- `onInvalidMessage: NotificationHandler<Context, Methods>`: callback used when receiving an invalid message, such as not having the `jsonrpc` field as `2.0` or missing the `method`. | ||
- `onNotification: NotificationHandler<Context, Methods>`: callback used when receiving a JSON-RPC notification (no `id` present). | ||
@@ -305,0 +311,0 @@ When these options are not provided, fallbacks using `console.warn` will be called instead. |
import { nanoid } from 'nanoid' | ||
import { RPCError } from './error' | ||
import { RPCConnection, RPCParams } from './types' | ||
import type { RPCConnection, RPCMethods } from './types' | ||
export class RPCClient { | ||
public connection: RPCConnection | ||
export class RPCClient<Methods extends RPCMethods> { | ||
connection: RPCConnection<Methods> | ||
constructor(connection: RPCConnection) { | ||
constructor(connection: RPCConnection<Methods>) { | ||
this.connection = connection | ||
} | ||
public createID(): string { | ||
createID(): string { | ||
return nanoid() | ||
} | ||
public async request< | ||
M = string, | ||
P extends RPCParams | undefined = undefined, | ||
R = unknown, | ||
E = undefined | ||
>(method: M, params?: P): Promise<R> { | ||
const res = await this.connection.send<M, P | undefined, R, E>({ | ||
async request<MethodName extends keyof Methods>( | ||
method: MethodName, | ||
params: Methods[MethodName]['params'] | ||
): Promise<Methods[MethodName]['result']> { | ||
const res = await this.connection.send({ | ||
jsonrpc: '2.0', | ||
id: this.createID(), | ||
method, | ||
params | ||
params, | ||
}) | ||
@@ -33,6 +31,6 @@ if (res == null) { | ||
if (res.error != null) { | ||
throw RPCError.fromObject<E>(res.error) | ||
throw RPCError.fromObject<Methods[MethodName]['error']>(res.error) | ||
} | ||
return res.result as R | ||
return res.result | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import { RPCErrorObject } from './types' | ||
import type { RPCErrorObject } from './types' | ||
@@ -8,3 +8,3 @@ export enum ERROR_CODE { | ||
INVALID_PARAMS = -32602, | ||
INTERNAL_ERROR = -32603 | ||
INTERNAL_ERROR = -32603, | ||
} | ||
@@ -17,3 +17,3 @@ | ||
[ERROR_CODE.INVALID_PARAMS]: 'Invalid params', | ||
[ERROR_CODE.INTERNAL_ERROR]: 'Internal error' | ||
[ERROR_CODE.INTERNAL_ERROR]: 'Internal error', | ||
} | ||
@@ -32,11 +32,11 @@ | ||
export class RPCError<T = undefined> extends Error { | ||
public static fromObject<D = any>(err: RPCErrorObject<D>): RPCError<D> { | ||
static fromObject<D = any>(err: RPCErrorObject<D>): RPCError<D> { | ||
return new RPCError<D>(err.code, err.message, err.data) | ||
} | ||
public code: number | ||
public data: T | undefined | ||
public message: string | ||
code: number | ||
data: T | undefined | ||
message: string | ||
public constructor(code: number, message?: string, data?: T) { | ||
constructor(code: number, message?: string, data?: T) { | ||
super() | ||
@@ -50,7 +50,7 @@ Object.setPrototypeOf(this, RPCError.prototype) | ||
public toObject<U = T>(): RPCErrorObject<U | undefined> { | ||
toObject<U = T>(): RPCErrorObject<U | undefined> { | ||
return { | ||
code: this.code, | ||
data: this.data, | ||
message: this.message | ||
message: this.message, | ||
} as RPCErrorObject<U | undefined> | ||
@@ -57,0 +57,0 @@ } |
import { ERROR_CODE, RPCError, createParseError, getErrorMessage } from './error' | ||
import { RPCErrorResponse, RPCParams, RPCRequest, RPCResponse } from './types' | ||
import type { RPCErrorResponse, RPCMethods, RPCRequest, RPCResponse } from './types' | ||
export type ErrorHandler<C = unknown, M = string> = <P extends RPCParams | undefined>( | ||
ctx: C, | ||
req: RPCRequest<M, P>, | ||
export type ErrorHandler<Context, Methods extends RPCMethods> = <K extends keyof Methods>( | ||
ctx: Context, | ||
req: RPCRequest<Methods, K>, | ||
error: Error | ||
) => void | ||
export type MethodHandler<C = unknown, P extends RPCParams | undefined = undefined, R = unknown> = ( | ||
ctx: C, | ||
params?: P | ||
) => R | Promise<R> | ||
export type MethodHandler<Context, Params, Result> = ( | ||
ctx: Context, | ||
params?: Params | ||
) => Result | Promise<Result> | ||
export type NotificationHandler<C = unknown, M = string> = <P extends RPCParams | undefined>( | ||
ctx: C, | ||
req: RPCRequest<M, P> | ||
export type NotificationHandler<Context, Methods extends RPCMethods> = <K extends keyof Methods>( | ||
ctx: Context, | ||
req: RPCRequest<Methods, K> | ||
) => void | ||
export type HandlerMethods<C = unknown> = Record<string, MethodHandler<C>> | ||
export type HandlerMethods<Context, Methods extends RPCMethods> = { | ||
[K in keyof Methods]: MethodHandler<Context, Methods[K]['params'], Methods[K]['result']> | ||
} | ||
export interface HandlerOptions<C = any> { | ||
onHandlerError?: ErrorHandler<C> | ||
onInvalidMessage?: NotificationHandler<C> | ||
onNotification?: NotificationHandler<C> | ||
export type HandlerOptions<Context, Methods extends RPCMethods> = { | ||
onHandlerError?: ErrorHandler<Context, Methods> | ||
onInvalidMessage?: NotificationHandler<Context, Methods> | ||
onNotification?: NotificationHandler<Context, Methods> | ||
} | ||
export type RequestHandler<C = any, M = string> = <P extends RPCParams | undefined, R, E>( | ||
ctx: C, | ||
msg: RPCRequest<M, P | undefined> | ||
) => Promise<RPCResponse<R, E | undefined> | null> | ||
export function parseJSON<T = any>(input: string): T { | ||
@@ -45,11 +42,11 @@ try { | ||
id, | ||
error: { code, message: getErrorMessage(code) } | ||
error: { code, message: getErrorMessage(code) }, | ||
} | ||
} | ||
function fallbackOnHandlerError< | ||
C = unknown, | ||
M = string, | ||
P extends RPCParams | undefined = undefined | ||
>(_ctx: C, msg: RPCRequest<M, P>, error: Error): void { | ||
function fallbackOnHandlerError<Context, Methods extends RPCMethods, K extends keyof Methods>( | ||
_ctx: Context, | ||
msg: RPCRequest<Methods, K>, | ||
error: Error | ||
): void { | ||
// eslint-disable-next-line no-console | ||
@@ -59,7 +56,6 @@ console.warn('Unhandled handler error', msg, error) | ||
function fallbackOnInvalidMessage< | ||
C = unknown, | ||
M = string, | ||
P extends RPCParams | undefined = undefined | ||
>(_ctx: C, msg: RPCRequest<M, P>): void { | ||
function fallbackOnInvalidMessage<Context, Methods extends RPCMethods, K extends keyof Methods>( | ||
_ctx: Context, | ||
msg: RPCRequest<Methods, K> | ||
): void { | ||
// eslint-disable-next-line no-console | ||
@@ -69,7 +65,6 @@ console.warn('Unhandled invalid message', msg) | ||
function fallbackOnNotification< | ||
C = unknown, | ||
M = string, | ||
P extends RPCParams | undefined = undefined | ||
>(_ctx: C, msg: RPCRequest<M, P>): void { | ||
function fallbackOnNotification<Context, Methods extends RPCMethods, K extends keyof Methods>( | ||
_ctx: Context, | ||
msg: RPCRequest<Methods, K> | ||
): void { | ||
// eslint-disable-next-line no-console | ||
@@ -79,6 +74,7 @@ console.warn('Unhandled notification', msg) | ||
export function createHandler<C = unknown>( | ||
methods: HandlerMethods<C>, | ||
options: HandlerOptions<C> = {} | ||
): RequestHandler<C, keyof typeof methods> { | ||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types | ||
export function createHandler<Context, Methods extends RPCMethods>( | ||
methods: HandlerMethods<Context, Methods>, | ||
options: HandlerOptions<Context, Methods> = {} | ||
) { | ||
const onHandlerError = options.onHandlerError ?? fallbackOnHandlerError | ||
@@ -88,6 +84,6 @@ const onInvalidMessage = options.onInvalidMessage ?? fallbackOnInvalidMessage | ||
return async function handleRequest<P extends RPCParams | undefined, R, E>( | ||
ctx: C, | ||
msg: RPCRequest<keyof typeof methods, P> | ||
): Promise<RPCResponse<R, E | undefined> | null> { | ||
return async function handleRequest<K extends keyof Methods>( | ||
ctx: Context, | ||
msg: RPCRequest<Methods, K> | ||
): Promise<RPCResponse<Methods, K> | null> { | ||
const id = msg.id | ||
@@ -110,9 +106,12 @@ if (msg.jsonrpc !== '2.0' || msg.method == null) { | ||
try { | ||
const handled = handler(ctx, msg.params) as R | Promise<R> | ||
const result = typeof (handled as Promise<R>).then === 'function' ? await handled : handled | ||
return { jsonrpc: '2.0', id, result } as RPCResponse<R> | ||
const handled = handler(ctx, msg.params) | ||
const result = | ||
typeof (handled as Promise<Methods[K]['result']>).then === 'function' | ||
? await handled | ||
: handled | ||
return { jsonrpc: '2.0', id, result } | ||
} catch (err) { | ||
let error | ||
if (err instanceof RPCError) { | ||
error = err.toObject<E>() | ||
error = err.toObject() | ||
} else { | ||
@@ -119,0 +118,0 @@ onHandlerError(ctx, msg, err) |
@@ -5,40 +5,46 @@ export type RPCID = string | number | null | ||
export type RPCRequest<M = string, P extends RPCParams | undefined = undefined> = { | ||
export type RPCMethodTypes = { | ||
params?: RPCParams | ||
result?: unknown | ||
error?: undefined | ||
} | ||
export type RPCMethods = Record<string, RPCMethodTypes> | ||
export type RPCRequest<Methods extends RPCMethods, MethodName extends keyof Methods> = { | ||
jsonrpc: string | ||
method: M | ||
method: MethodName | ||
params: Methods[MethodName]['params'] | ||
id?: RPCID | ||
} & (P extends undefined ? { params?: any } : { params: P }) | ||
} | ||
export type RPCErrorObject<D = undefined> = { | ||
export type RPCErrorObject<Data = undefined> = { | ||
code: number | ||
data?: Data | ||
message?: string | ||
} & (D extends undefined ? { data?: undefined } : { data: D }) | ||
} | ||
export type RPCErrorResponse<E = undefined> = { | ||
export type RPCErrorResponse<ErrorData = undefined> = { | ||
jsonrpc: string | ||
id: RPCID | ||
result?: never | ||
error: RPCErrorObject<E> | ||
error: RPCErrorObject<ErrorData> | ||
} | ||
export type RPCResultResponse<R = unknown> = { | ||
export type RPCResultResponse<Result = unknown> = { | ||
jsonrpc: string | ||
id: RPCID | ||
result: R | ||
result: Result | ||
error?: never | ||
} | ||
export type RPCResponse<R = unknown, E = undefined> = RPCResultResponse<R> | RPCErrorResponse<E> | ||
export type RPCResponse<Methods extends RPCMethods, K extends keyof Methods> = | ||
| RPCResultResponse<Methods[K]['result']> | ||
| RPCErrorResponse<Methods[K]['error']> | ||
export type SendRequestFunc = < | ||
M = string, | ||
P extends RPCParams | undefined = undefined, | ||
R = undefined, | ||
E = undefined | ||
>( | ||
request: RPCRequest<M, P> | ||
) => Promise<RPCResponse<R, E> | null> | ||
export type SendRequestFunc<Methods extends RPCMethods> = <K extends keyof Methods>( | ||
request: RPCRequest<Methods, K> | ||
) => Promise<RPCResponse<Methods, K> | null> | ||
export interface RPCConnection { | ||
send: SendRequestFunc | ||
export type RPCConnection<Methods extends RPCMethods> = { | ||
send: SendRequestFunc<Methods> | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
266971
2348
294
3
10
Updatednanoid@^3.1.20