diff --git a/packages/common/src/ILogger.ts b/packages/common/src/ILogger.ts new file mode 100644 index 0000000..132b1a6 --- /dev/null +++ b/packages/common/src/ILogger.ts @@ -0,0 +1,9 @@ +type ILogFunction = (message: string, ...meta: any[]) => void + +export interface ILogger { + error: ILogFunction + warn: ILogFunction + info: ILogFunction + debug: ILogFunction + verbose: ILogFunction +} diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 79af98e..70b71ae 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,5 +1,6 @@ export * from './IAPIDef' export * from './ICredentials' +export * from './ILogger' export * from './INewUser' export * from './IRequestParams' export * from './IRole' diff --git a/packages/jsonrpc/src/express.test.ts b/packages/jsonrpc/src/express.test.ts index d0a717d..0a8583c 100644 --- a/packages/jsonrpc/src/express.test.ts +++ b/packages/jsonrpc/src/express.test.ts @@ -3,6 +3,7 @@ import express from 'express' import request from 'supertest' import {createClient} from './supertest' import {jsonrpc} from './express' +import {noopLogger} from './test-utils' describe('jsonrpc', () => { @@ -55,15 +56,17 @@ describe('jsonrpc', () => { function createApp() { const app = express() app.use(bodyParser.json()) - app.use('/myService', jsonrpc(req => ({userId: 1000})) + app.use('/myService', + jsonrpc(req => ({userId: 1000}), noopLogger) .addService(new Service(5), [ - 'add', - 'delay', - 'syncError', - 'asyncError', - 'httpError', - 'addWithContext', - ])) + 'add', + 'delay', + 'syncError', + 'asyncError', + 'httpError', + 'addWithContext', + ]), + ) return app } diff --git a/packages/jsonrpc/src/express.ts b/packages/jsonrpc/src/express.ts index 7d76bba..15cbff8 100644 --- a/packages/jsonrpc/src/express.ts +++ b/packages/jsonrpc/src/express.ts @@ -2,6 +2,7 @@ import express, {ErrorRequestHandler} from 'express' import {FunctionPropertyNames} from './types' import {IDEMPOTENT_METHOD_REGEX} from './idempotent' import {IErrorResponse} from './jsonrpc' +import {ILogger} from '@rondo/common' import {ISuccessResponse} from './jsonrpc' import {NextFunction, Request, Response, Router} from 'express' import {createError, isJSONRPCError, IJSONRPCError, IError} from './error' @@ -11,8 +12,36 @@ export type TGetContext = (req: Request) => Context export function jsonrpc( getContext: TGetContext, + logger: ILogger, idempotentMethodRegex = IDEMPOTENT_METHOD_REGEX, ) { + + const handleError: ErrorRequestHandler = (err, req, res, next) => { + logger.error('JSON-RPC Error: %s', err.stack) + // TODO log error + + if (isJSONRPCError(err)) { + res.status(err.statusCode) + res.json(err.response) + return + } + + const id = getRequestId(req) + const statusCode: number = err.statusCode || 500 + const errorResponse: IErrorResponse = { + jsonrpc: '2.0', + id, + result: null, + error: { + code: ERROR_SERVER.code, + message: statusCode >= 500 ? ERROR_SERVER.message : err.message, + data: 'errors' in err ? err.errors : null, + }, + } + res.status(statusCode) + res.json(errorResponse) + } + return { /** * Adds middleware for handling JSON RPC requests. Expects JSON middleware to @@ -65,30 +94,6 @@ export function jsonrpc( }, } - const handleError: ErrorRequestHandler = (err, req, res, next) => { - // TODO log error - - if (isJSONRPCError(err)) { - res.status(err.statusCode) - res.json(err.response) - return - } - - const id = getRequestId(req) - const statusCode: number = err.statusCode || 500 - const errorResponse: IErrorResponse = { - jsonrpc: '2.0', - id, - result: null, - error: { - code: ERROR_SERVER.code, - message: statusCode >= 500 ? ERROR_SERVER.message : err.message, - data: 'errors' in err ? err.errors : null, - }, - } - res.status(statusCode) - res.json(errorResponse) - } } function getRequestId(req: express.Request) { diff --git a/packages/jsonrpc/src/redux.test.ts b/packages/jsonrpc/src/redux.test.ts index fa6c761..f3b4ace 100644 --- a/packages/jsonrpc/src/redux.test.ts +++ b/packages/jsonrpc/src/redux.test.ts @@ -13,6 +13,7 @@ import {createRemoteClient} from './remote' import {createStore} from '@rondo/client' import {jsonrpc} from './express' import {keys} from 'ts-transformer-keys' +import {noopLogger} from './test-utils' describe('createActions', () => { @@ -54,10 +55,11 @@ describe('createActions', () => { const app = express() app.use(bodyParser.json()) - app.use('/service', jsonrpc(() => ({userId: 1000})).addService( - new Service(), - keys(), - )) + app.use('/service', jsonrpc(() => ({userId: 1000}), noopLogger) + .addService( + new Service(), + keys(), + )) let baseUrl: string let server: Server diff --git a/packages/jsonrpc/src/remote.test.ts b/packages/jsonrpc/src/remote.test.ts index 7e2a56c..6d5958d 100644 --- a/packages/jsonrpc/src/remote.test.ts +++ b/packages/jsonrpc/src/remote.test.ts @@ -9,6 +9,7 @@ import {Server} from 'http' import {createRemoteClient} from './remote' import {jsonrpc} from './express' import {keys} from 'ts-transformer-keys' +import {noopLogger} from './test-utils' describe('remote', () => { @@ -28,7 +29,8 @@ describe('remote', () => { function createApp() { const a = express() a.use(bodyParser.json()) - a.use('/myService', jsonrpc(() => ({})).addService(service, IServiceKeys)) + a.use('/myService', jsonrpc(() => ({}), noopLogger) + .addService(service, IServiceKeys)) return a } diff --git a/packages/jsonrpc/src/test-utils.ts b/packages/jsonrpc/src/test-utils.ts new file mode 100644 index 0000000..51ee267 --- /dev/null +++ b/packages/jsonrpc/src/test-utils.ts @@ -0,0 +1,11 @@ +import {ILogger} from '@rondo/common' + +const noop = () => undefined + +export const noopLogger: ILogger = { + error: noop, + warn: noop, + info: noop, + debug: noop, + verbose: noop, +} diff --git a/packages/server/src/logger/ILogger.ts b/packages/server/src/logger/ILogger.ts index 132b1a6..b9f77e0 100644 --- a/packages/server/src/logger/ILogger.ts +++ b/packages/server/src/logger/ILogger.ts @@ -1,9 +1 @@ -type ILogFunction = (message: string, ...meta: any[]) => void - -export interface ILogger { - error: ILogFunction - warn: ILogFunction - info: ILogFunction - debug: ILogFunction - verbose: ILogFunction -} +export {ILogger} from '@rondo/common'