-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathprocessor.ts
More file actions
83 lines (66 loc) · 2.45 KB
/
processor.ts
File metadata and controls
83 lines (66 loc) · 2.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import type { Contracts } from "@mainsail/contracts";
import Hapi from "@hapi/hapi";
import { Enums, Identifiers } from "@mainsail/constants";
import { inject, injectable } from "@mainsail/container";
import { RpcError } from "@mainsail/exceptions";
import { getRcpId, prepareRcpError } from "./utilities.js";
@injectable()
export class Processor implements Contracts.Api.RPC.Processor {
@inject(Identifiers.Cryptography.Validator)
private readonly validator!: Contracts.Crypto.Validator;
#actions: Map<string, Contracts.Api.RPC.Action> = new Map();
public registerAction(action: Contracts.Api.RPC.Action): void {
this.#actions.set(action.name, action);
this.validator.addSchema(action.schema);
}
async process(
request: Hapi.Request,
): Promise<
Contracts.Api.RPC.Response | Contracts.Api.RPC.Error | (Contracts.Api.RPC.Response | Contracts.Api.RPC.Error)[]
> {
if (!this.#validatePayload(request)) {
return prepareRcpError(getRcpId(request), Enums.Api.RcpErrorCode.InvalidRequest);
}
const payload = request.payload as Contracts.Api.RPC.Request<[]>;
if (Array.isArray(payload)) {
return Promise.all(payload.map(async (rcpRequest) => await this.#processSingle(rcpRequest)));
} else {
return this.#processSingle(payload);
}
}
async #processSingle(
rcpRequest: Contracts.Api.RPC.Request<[]>,
): Promise<Contracts.Api.RPC.Response | Contracts.Api.RPC.Error> {
const action = this.#actions.get(rcpRequest.method);
if (!action) {
return prepareRcpError(rcpRequest.id, Enums.Api.RcpErrorCode.MethodNotFound);
}
if (!this.#validateParams(rcpRequest.params, action)) {
return prepareRcpError(rcpRequest.id, Enums.Api.RcpErrorCode.InvalidParameters);
}
try {
return {
id: rcpRequest.id,
jsonrpc: "2.0",
result: await action.handle(rcpRequest.params),
};
} catch (error) {
if (error instanceof RpcError) {
return prepareRcpError(rcpRequest.id, error.code, error.message, error.data);
}
return prepareRcpError(rcpRequest.id, Enums.Api.RcpErrorCode.InternalError);
}
}
#validatePayload(request: Hapi.Request): boolean {
const payload = request.payload as Contracts.Types.JsonObject;
const { error } = this.validator.validate("jsonRpcPayload", payload);
return !error;
}
#validateParams(parameters: [], action: Contracts.Api.RPC.Action): boolean {
if (!action.schema.$id) {
return true;
}
const { error } = this.validator.validate(action.schema.$id, parameters ?? []);
return !error;
}
}