-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: refactor clientjs to support err handling
and notifications Clientjs needed a refactor, because error states from failed transports and notifications would silently fail or would require exceptional handling. Additionally the refactor adds support for timeout, and eventual implementation of request strategies for choosing which transport to use in a request. This refactor exposes notifications handler, and error handler as well as a timeout handler for timing out request. The refactor also moves request resolution to be handle by the transport, and transport selection and batching start and stopping to be handled by the request manager freeing multiple transports to potentially be used at the same time.
- Loading branch information
Showing
23 changed files
with
1,041 additions
and
341 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { convertJSONToRPCError, JSONRPCError } from "./Error"; | ||
import { generateMockErrorResponse } from "./__mocks__/requestData"; | ||
|
||
describe("Error test", () => { | ||
|
||
it("should convert payload to JSONRPC error ", () => { | ||
|
||
let err = convertJSONToRPCError("message"); | ||
expect(err instanceof Error).toBe(true); | ||
err = convertJSONToRPCError(generateMockErrorResponse(1, "somedata")); | ||
expect(err instanceof Error).toBe(true); | ||
}); | ||
|
||
it("should construct JSONRPCError", () => { | ||
const err = new JSONRPCError("test", 9999); | ||
const err2 = new JSONRPCError("test", 9999, "testdata"); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
export const ERR_TIMEOUT = 7777; | ||
export const ERR_MISSIING_ID = 7878; | ||
export const ERR_UNKNOWN = 7979; | ||
|
||
export class JSONRPCError extends Error { | ||
public message: string; | ||
public code: number; | ||
public data: any; | ||
constructor(message: string, code: number, data?: any) { | ||
super(message); | ||
this.message = message; | ||
this.code = code; | ||
this.data = data; | ||
} | ||
} | ||
|
||
export const convertJSONToRPCError = (payload: any): JSONRPCError => { | ||
if (payload.error) { | ||
const { message, code, data } = payload.error; | ||
return new JSONRPCError(message, code, data); | ||
} | ||
return new JSONRPCError("Unknown error", ERR_UNKNOWN, payload); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
|
||
export type JSONRPCRequestData = IJSONRPCData | IBatchRequest[] ; | ||
|
||
export interface IJSONRPCData { | ||
internalID: string | number; | ||
request: IJSONRPCRequest | IJSONRPCNotification; | ||
} | ||
|
||
export interface IBatchRequest { | ||
resolve: (data: any) => void; | ||
reject: (data: any) => void; | ||
request: IJSONRPCData; // IJSONRPCNotification | IJSONRPCRequest; | ||
} | ||
|
||
export interface IJSONRPCRequest { | ||
jsonrpc: "2.0"; | ||
id: string | number; | ||
method: string; | ||
params: any[] | object; | ||
} | ||
|
||
export interface IJSONRPCError { | ||
code: number; | ||
message: string; | ||
data: any; | ||
} | ||
|
||
export interface IJSONRPCResponse { | ||
jsonrpc: "2.0"; | ||
id: string | number; // can also be null | ||
result?: any; | ||
error?: IJSONRPCError; | ||
} | ||
|
||
export interface IJSONRPCNotificationResponse { | ||
jsonrpc: "2.0"; | ||
id?: null | undefined; | ||
result?: any; | ||
error?: IJSONRPCError; | ||
} | ||
|
||
export interface IJSONRPCNotification { | ||
jsonrpc: "2.0"; | ||
id?: null | undefined; | ||
method: string; | ||
params: any[] | object; | ||
} | ||
|
||
interface IRPCRequest { | ||
method: string; | ||
params: any[]; | ||
type: "single"; | ||
} | ||
|
||
interface IBatchRPCRequest { | ||
type: "batch"; | ||
batch: IJSONRPCRequest[]; | ||
} | ||
|
||
export type Request = IRPCRequest | IBatchRPCRequest; | ||
|
||
export const isNotification = (data: IJSONRPCData): boolean => { | ||
return (data.request.id === undefined || data.request.id === null); | ||
}; | ||
|
||
export const getBatchRequests = (data: JSONRPCRequestData): IJSONRPCData[] => { | ||
if (data instanceof Array) { | ||
return data.filter((datum) => { | ||
const id = datum.request.request.id; | ||
return id !== null && id !== undefined; | ||
}).map((batchRequest: IBatchRequest) => { | ||
return batchRequest.request; | ||
}); | ||
} | ||
return []; | ||
}; | ||
export const getNotifications = (data: JSONRPCRequestData): IJSONRPCData[] => { | ||
if (data instanceof Array) { | ||
return data.filter((datum) => { | ||
return isNotification(datum.request); | ||
}).map((batchRequest: IBatchRequest) => { | ||
return batchRequest.request; | ||
}); | ||
} | ||
if (isNotification(data)) { | ||
return [data]; | ||
} | ||
return []; | ||
}; |
Oops, something went wrong.