Skip to content
This repository was archived by the owner on Nov 9, 2023. It is now read-only.

Commit bd9c430

Browse files
committed
Refactor to use a notification handler function
1 parent 3ff7755 commit bd9c430

File tree

2 files changed

+29
-102
lines changed

2 files changed

+29
-102
lines changed

src/JsonRpcEngine.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ describe('JsonRpcEngine', () => {
2828

2929
it('handle: returns error for invalid request method', async () => {
3030
const engine = new JsonRpcEngine();
31-
let response: any = await engine.handle({ method: null } as any);
31+
let response: any = await engine.handle({ id: 1, method: null } as any);
3232
expect(response.error.code).toStrictEqual(-32600);
3333
expect(response.result).toBeUndefined();
3434

35+
// No response if duck-typed as a notification
3536
response = await engine.handle({ method: true } as any);
36-
expect(response.error.code).toStrictEqual(-32600);
37-
expect(response.result).toBeUndefined();
37+
expect(response).toBeUndefined();
3838
});
3939

4040
it('handle: basic middleware test 1', async () => {

src/JsonRpcEngine.ts

Lines changed: 26 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import SafeEventEmitter from '@metamask/safe-event-emitter';
22
import { errorCodes, EthereumRpcError, serializeError } from 'eth-rpc-errors';
3-
import { isJsonRpcNotification, isJsonRpcRequest } from './utils';
3+
import { isJsonRpcRequest } from './utils';
44

55
type Maybe<T> = Partial<T> | null | undefined;
66

@@ -86,58 +86,32 @@ export type JsonRpcMiddleware<T, U> = (
8686
end: JsonRpcEngineEndCallback,
8787
) => void;
8888

89-
export type JsonRpcNotificationMiddleware<T> = (
90-
req: JsonRpcNotification<T>,
91-
) => Promise<void>;
89+
export type JsonRpcNotificationHandler<T> = (
90+
notification: JsonRpcNotification<T>,
91+
) => void | Promise<void>;
9292

9393
/**
9494
* A JSON-RPC request and response processor.
9595
* Give it a stack of middleware, pass it requests, and get back responses.
9696
*/
9797
export class JsonRpcEngine extends SafeEventEmitter {
98-
private _requestMiddleware: JsonRpcMiddleware<unknown, unknown>[];
98+
private _middleware: JsonRpcMiddleware<unknown, unknown>[];
9999

100-
private _notificationMiddleware: JsonRpcNotificationMiddleware<unknown>[];
100+
private readonly _notificationHandler?: JsonRpcNotificationHandler<unknown>;
101101

102-
constructor() {
102+
constructor(notificationHandler?: JsonRpcNotificationHandler<unknown>) {
103103
super();
104-
this._requestMiddleware = [];
105-
this._notificationMiddleware = [];
104+
this._middleware = [];
105+
this._notificationHandler = notificationHandler;
106106
}
107107

108108
/**
109109
* Add a middleware function to the engine's request middleware stack.
110110
*
111111
* @param middleware - The middleware function to add.
112112
*/
113-
pushRequestMiddleware<T, U>(middleware: JsonRpcMiddleware<T, U>): void {
114-
this._requestMiddleware.push(
115-
middleware as JsonRpcMiddleware<unknown, unknown>,
116-
);
117-
}
118-
119-
/**
120-
* Alias for `pushRequestMiddleware`, for backwards compatibility.
121-
*
122-
* @param middleware - The request middleware function to add.
123-
*/
124113
push<T, U>(middleware: JsonRpcMiddleware<T, U>): void {
125-
this.pushRequestMiddleware(
126-
middleware as JsonRpcMiddleware<unknown, unknown>,
127-
);
128-
}
129-
130-
/**
131-
* Adds a middleware function to the engine's notification middleware stack.
132-
*
133-
* @param middleware - The notification middleware function to add.
134-
*/
135-
pushNotificationMiddleware<T>(
136-
middleware: JsonRpcNotificationMiddleware<T>,
137-
): void {
138-
this._requestMiddleware.push(
139-
middleware as JsonRpcNotificationMiddleware<unknown>,
140-
);
114+
this._middleware.push(middleware as JsonRpcMiddleware<unknown, unknown>);
141115
}
142116

143117
/**
@@ -158,7 +132,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
158132
* @param callback - An error-first callback that will receive a `void` response.
159133
*/
160134
handle<T>(
161-
request: JsonRpcNotification<T>,
135+
notification: JsonRpcNotification<T>,
162136
callback: (error: unknown, response: void) => void,
163137
): void;
164138

@@ -228,21 +202,8 @@ export class JsonRpcEngine extends SafeEventEmitter {
228202
asMiddleware(): JsonRpcMiddleware<unknown, unknown> {
229203
return async (req, res, next, end) => {
230204
try {
231-
if (isJsonRpcNotification(req)) {
232-
// This will invoke the end callback.
233-
return await JsonRpcEngine._processNotification(
234-
req,
235-
this._notificationMiddleware,
236-
() => end(),
237-
);
238-
}
239-
240205
const [middlewareError, isComplete, returnHandlers] =
241-
await JsonRpcEngine._runAllRequestMiddleware(
242-
req,
243-
res,
244-
this._requestMiddleware,
245-
);
206+
await JsonRpcEngine._runAllMiddleware(req, res, this._middleware);
246207

247208
if (isComplete) {
248209
await JsonRpcEngine._runReturnHandlers(returnHandlers);
@@ -367,7 +328,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
367328

368329
if (isJsonRpcRequest(callerReq)) {
369330
return callback(error, {
370-
id: (callerReq as any).id ?? null,
331+
id: callerReq.id ?? null,
371332
jsonrpc: '2.0',
372333
error,
373334
});
@@ -380,12 +341,8 @@ export class JsonRpcEngine extends SafeEventEmitter {
380341
// We can't use isJsonRpcNotification here because that narrows callerReq to
381342
// "never" after the if clause for unknown reasons.
382343
if (!isJsonRpcRequest(callerReq)) {
383-
// This will invoke the callback.
384-
return await JsonRpcEngine._processNotification(
385-
{ ...callerReq },
386-
this._notificationMiddleware,
387-
callback,
388-
);
344+
await this._notificationHandler?.(callerReq);
345+
return callback(null);
389346
}
390347

391348
let error: JsonRpcEngineCallbackError = null;
@@ -398,7 +355,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
398355
};
399356

400357
try {
401-
await JsonRpcEngine._processRequest(req, res, this._requestMiddleware);
358+
await JsonRpcEngine._processRequest(req, res, this._middleware);
402359
} catch (_error) {
403360
// A request handler error, a re-thrown middleware error, or something
404361
// unexpected.
@@ -416,52 +373,22 @@ export class JsonRpcEngine extends SafeEventEmitter {
416373
return callback(error, res as JsonRpcResponse<unknown>);
417374
}
418375

419-
/**
420-
* Runs all notification middleware on the specified notification.
421-
* Does not throw.
422-
*
423-
* @param notification - The notification object to process.
424-
* @param notificationMiddlewares - The stack of notification middleware
425-
* functions.
426-
* @param callback - Callback from {@link JsonRpcEngine._handle} or
427-
* {@link JsonRpcEngineEndCallback}. Will always be invoked with nothing,
428-
* because notifications must not be responded to.
429-
*/
430-
private static async _processNotification(
431-
notification: JsonRpcNotification<unknown>,
432-
notificationMiddlewares: JsonRpcNotificationMiddleware<unknown>[],
433-
callback: (error?: unknown, response?: JsonRpcResponse<unknown>) => void,
434-
): Promise<void> {
435-
try {
436-
for (const middleware of notificationMiddlewares) {
437-
await middleware(notification);
438-
}
439-
} catch (middlewareError) {
440-
console.error(middlewareError);
441-
}
442-
callback(null);
443-
}
444-
445376
/**
446377
* For the given request and response, runs all middleware and their return
447378
* handlers, if any, and ensures that internal request processing semantics
448379
* are satisfied.
449380
*
450381
* @param req - The request object.
451382
* @param res - The response object.
452-
* @param requestMiddlewares - The stack of request middleware functions.
383+
* @param middlewares - The stack of request middleware functions.
453384
*/
454385
private static async _processRequest(
455386
req: JsonRpcRequest<unknown>,
456387
res: PendingJsonRpcResponse<unknown>,
457-
requestMiddlewares: JsonRpcMiddleware<unknown, unknown>[],
388+
middlewares: JsonRpcMiddleware<unknown, unknown>[],
458389
): Promise<void> {
459390
const [error, isComplete, returnHandlers] =
460-
await JsonRpcEngine._runAllRequestMiddleware(
461-
req,
462-
res,
463-
requestMiddlewares,
464-
);
391+
await JsonRpcEngine._runAllMiddleware(req, res, middlewares);
465392

466393
// Throw if "end" was not called, or if the response has neither a result
467394
// nor an error.
@@ -483,15 +410,15 @@ export class JsonRpcEngine extends SafeEventEmitter {
483410
*
484411
* @param req - The request object.
485412
* @param res - The response object.
486-
* @param requestMiddlewares - The stack of middleware functions to execute.
413+
* @param middlewares - The stack of middleware functions to execute.
487414
* @returns An array of any error encountered during middleware execution,
488415
* a boolean indicating whether the request was completed, and an array of
489416
* middleware-defined return handlers.
490417
*/
491-
private static async _runAllRequestMiddleware(
418+
private static async _runAllMiddleware(
492419
req: JsonRpcRequest<unknown>,
493420
res: PendingJsonRpcResponse<unknown>,
494-
requestMiddlewares: JsonRpcMiddleware<unknown, unknown>[],
421+
middlewares: JsonRpcMiddleware<unknown, unknown>[],
495422
): Promise<
496423
[
497424
unknown, // error
@@ -504,8 +431,8 @@ export class JsonRpcEngine extends SafeEventEmitter {
504431
let isComplete = false;
505432

506433
// Go down stack of middleware, call and collect optional returnHandlers
507-
for (const middleware of requestMiddlewares) {
508-
[error, isComplete] = await JsonRpcEngine._runRequestMiddleware(
434+
for (const middleware of middlewares) {
435+
[error, isComplete] = await JsonRpcEngine._runMiddleware(
509436
req,
510437
res,
511438
middleware,
@@ -529,7 +456,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
529456
* @returns An array of any error encountered during middleware exection,
530457
* and a boolean indicating whether the request should end.
531458
*/
532-
private static _runRequestMiddleware(
459+
private static _runMiddleware(
533460
req: JsonRpcRequest<unknown>,
534461
res: PendingJsonRpcResponse<unknown>,
535462
middleware: JsonRpcMiddleware<unknown, unknown>,
@@ -602,7 +529,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
602529
*
603530
* @param req - The request object.
604531
* @param res - The response object.
605-
* @param isComplete - Boolean from {@link JsonRpcEngine._runAllRequestMiddleware}
532+
* @param isComplete - Boolean from {@link JsonRpcEngine._runAllMiddleware}
606533
* indicating whether a middleware ended the request.
607534
*/
608535
private static _checkForCompletion(

0 commit comments

Comments
 (0)