Compare commits

..

3 Commits

2 changed files with 113 additions and 28 deletions

View File

@@ -11,15 +11,13 @@ export interface BaseHookCtx {
export interface CallOutgoingBeforeCtx extends BaseHookCtx {
session: RPCSession;
options: {
fnPath: string;
args: any[];
};
options: unknown;
setOptions: (opt: unknown) => void;
}
export interface CallOutgoingCtx extends CallOutgoingBeforeCtx {
result: any;
setResult: (data: any) => void;
result: unknown;
setResult: (res: unknown) => void;
}
export interface CallIncomingBeforeCtx extends BaseHookCtx {
@@ -51,8 +49,8 @@ export interface RPCPlugin extends RPCPluginHooks {
}
export abstract class AbstractRPCPlugin implements RPCPlugin {
abstract onInit?(): void;
abstract onDestroy?(): void;
// abstract onInit?(): void;
// abstract onDestroy?(): void;
abstract onCallOutgoingBefore?(ctx: CallOutgoingBeforeCtx): NormalMethodReturn;
abstract onCallOutgoing?(ctx: CallOutgoingCtx): NormalMethodReturn;
abstract onCallIncomingBefore?(ctx: CallIncomingBeforeCtx): NormalMethodReturn;

View File

@@ -1,4 +1,4 @@
import { isPublicMethod, ToDeepPromise } from "@/utils/utils";
import { isArray, isObject, isPublicMethod, ToDeepPromise } from "@/utils/utils";
import { RPCConnection } from "./RPCConnection";
import { RPCHandler } from "./RPCHandler";
import { RPCProvider } from "./RPCProvider";
@@ -8,6 +8,7 @@ import { RPCError, RPCErrorCode } from "./RPCError";
import { makeCallPacket, makeCallResponsePacket, parseCallPacket, parseCallResponsePacket } from "./RPCCommon";
import { RPCPacket } from "./RPCPacket";
import { EventEmitter } from "@/utils/EventEmitter";
import { createHookRunner } from "./RPCPlugin";
function getProviderFunction(provider: RPCProvider, fnPath: string):
[(...args: any[]) => Promise<any>, object] | null {
@@ -111,6 +112,45 @@ export class RPCSession {
});
}
function setOptions(opt: unknown) {
if (!isObject(opt)) {
return;
}
if ('fnPath' in opt && 'args' in opt && 'timeout' in opt) {
const { fnPath, args, timeout } = opt;
if (typeof fnPath !== 'string') {
return;
}
if (!isArray(args)) {
return;
}
if (typeof timeout !== 'number') {
return;
}
options = {
...options,
fnPath,
args,
timeout,
}
}
}
const hookRunner = createHookRunner(this.rpcHandler.getPlugins(), 'onCallOutgoingBefore');
await hookRunner({
session: this,
options: { ...options },
setOptions,
});
/** due to `await hookRunner` */
if (this.connection.closed) {
throw new RPCError({
errorCode: RPCErrorCode.CONNECTION_DISCONNECTED,
});
}
const { fnPath, args } = options;
const packet = makeCallPacket({
fnPath,
@@ -135,28 +175,75 @@ export class RPCSession {
})();
const handleCallResponsePacket = (packet: RPCPacket) => {
const result = parseCallResponsePacket(packet);
if (result === null) {
return reject(new RPCError({
let result = parseCallResponsePacket(packet);
function setResult(res: unknown) {
if (!isObject(res)) {
return;
}
const { success, error } = res;
if (typeof success === 'object' && typeof error === 'object') {
if (success && !error) {
if ('data' in success) {
result = {
success: { data: success.data },
error: null,
}
}
} else if (!success && error) {
const { errorCode, reason } = error;
if (typeof errorCode === 'number' && typeof reason === 'string') {
result = {
success: null,
error: {
errorCode,
reason,
},
}
}
}
}
}
const hookRunner = createHookRunner(this.rpcHandler.getPlugins(), 'onCallOutgoing');
hookRunner({
session: this,
options: { ...options },
setOptions,
result,
setResult,
}).then(() => {
if (result === null) {
return reject(new RPCError({
errorCode: RPCErrorCode.UNKNOWN_ERROR,
}));;
}
const { success, error } = result;
if (success) {
return resolve(success.data);
}
if (error) {
return reject(new RPCError({
errorCode: error.errorCode,
reason: error.reason
}));
}
reject(new RPCError({
errorCode: RPCErrorCode.UNKNOWN_ERROR,
}));;
}
}).catch((e) => {
if (e instanceof RPCError) {
return reject(e);
}
const { success, error } = result;
if (success) {
return resolve(success.data);
}
if (error) {
return reject(new RPCError({
errorCode: error.errorCode,
reason: error.reason
}));
}
return reject(new RPCError({
errorCode: RPCErrorCode.UNKNOWN_ERROR,
}));;
reject(new RPCError({
errorCode: RPCErrorCode.UNKNOWN_ERROR,
}))
})
}
this.callResponseEmitter.once(packet.id, handleCallResponsePacket);