diff --git a/packages/jsonrpc/src/express.test.ts b/packages/jsonrpc/src/express.test.ts index 951a647..69d2db2 100644 --- a/packages/jsonrpc/src/express.test.ts +++ b/packages/jsonrpc/src/express.test.ts @@ -1,10 +1,11 @@ import bodyParser from 'body-parser' import express from 'express' import request from 'supertest' +import {IRequest} from './jsonrpc' import {createClient} from './supertest' +import {ensure} from './ensure' import {jsonrpc} from './express' import {noopLogger} from './test-utils' -import {ensure} from './ensure' describe('jsonrpc', () => { @@ -240,6 +241,54 @@ describe('jsonrpc', () => { .get(`/myService?jsonrpc=2.0&id=1&method=add¶ms=${params}`) .expect(405) }) + + describe('wrapCall', () => { + + let requests: IRequest[] = [] + let results: any[] = [] + function create() { + requests = [] + results = [] + + userId = 1000 + const app = express() + const myService = new Service(5) + // console.log('service', myService, Object. + app.use(bodyParser.json()) + app.use('/', + jsonrpc( + req => ({userId}), + noopLogger, + async (path, req, makeRequest) => { + requests.push(req) + const result = await makeRequest() + results.push(result) + return result + }, + ) + .addService('/myService', myService) + .router(), + ) + return app + } + + it('should wrap POST rpc method call', async () => { + const req = { + jsonrpc: '2.0', + id: 1, + method: 'add', + params: [1, 2], + } + const response = await request(create()) + .post('/myService') + .send(req) + + expect(response.body.result).toEqual(3) + expect(requests).toEqual([ req ]) + expect(results).toEqual([ response.body ]) + }) + + }) }) }) diff --git a/packages/jsonrpc/src/express.ts b/packages/jsonrpc/src/express.ts index a4cca57..f7c3c99 100644 --- a/packages/jsonrpc/src/express.ts +++ b/packages/jsonrpc/src/express.ts @@ -8,6 +8,7 @@ import {NextFunction, Request, Response, Router} from 'express' import {createError, isJSONRPCError, IJSONRPCError, IError} from './error' import { createRpcService, ERROR_SERVER, ERROR_INVALID_PARAMS, ERROR_METHOD_NOT_FOUND, + IRequest, } from './jsonrpc' export type TGetContext = (req: Request) => Context @@ -21,9 +22,19 @@ export interface IJSONRPCReturnType { router(): Router } +async function wrap( + path: string, request: A, fn: () => Promise): Promise { + const result = await fn() + return result +} + export function jsonrpc( getContext: TGetContext, logger: ILogger, + wrapCall: ( + path: string, + request: A, + fn: (request?: A) => Promise) => Promise = wrap, idempotentMethodRegex = IDEMPOTENT_METHOD_REGEX, ): IJSONRPCReturnType { @@ -94,13 +105,15 @@ export function jsonrpc( method: req.query.method, params: JSON.parse(req.query.params), } - rpcService.invoke(request, getContext(req)) + wrapCall(path, request, + (body = request) => rpcService.invoke(body, getContext(req))) .then(response => handleResponse(response, res)) .catch(next) }) router.post(path, (req, res, next) => { - rpcService.invoke(req.body, getContext(req)) + wrapCall(path, req.body, + (body = req.body) => rpcService.invoke(body, getContext(req))) .then(response => handleResponse(response, res)) .catch(next) }) diff --git a/packages/jsonrpc/src/jsonrpc.ts b/packages/jsonrpc/src/jsonrpc.ts index 098a455..2916a91 100644 --- a/packages/jsonrpc/src/jsonrpc.ts +++ b/packages/jsonrpc/src/jsonrpc.ts @@ -45,6 +45,21 @@ export function pick>(t: T, keys: K[]) }, {} as Pick) } +export function getAllMethods(obj: T): Array> { + const props = new Set() + do { + const l = Object.getOwnPropertyNames(obj) + .filter((p, i, arr) => { + return typeof (obj as any)[p] === 'function' && + p !== 'constructor' + }) + .forEach(p => props.add(p)) + obj = Object.getPrototypeOf(obj) + } while (Object.getPrototypeOf(obj)) + + return Array.from(props) as unknown as Array> +} + export interface IRequest { jsonrpc: '2.0' id: TId | null @@ -104,7 +119,9 @@ export const createRpcService = >( service: T, methods?: M[], ) => { - const rpcService = methods ? pick(service, methods) : service + + const rpcService = methods ? pick(service, methods) : + pick(service, getAllMethods(service)) return { async invoke( req: IRequest>,