@superblocksteam/sdk 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +63 -22
- package/dist/client.js +180 -103
- package/dist/sdk.d.ts +37 -12
- package/dist/sdk.js +32 -8
- package/dist/socket/handlers.d.ts +25 -7
- package/dist/socket/index.d.ts +10 -19
- package/dist/socket/index.js +12 -8
- package/dist/socket/socket.d.ts +53 -10
- package/dist/socket/socket.js +128 -37
- package/dist/types/common.d.ts +1 -1
- package/dist/types/socket.d.ts +19 -6
- package/dist/types/socket.js +10 -0
- package/package.json +3 -3
- package/src/client.ts +320 -152
- package/src/sdk.ts +79 -20
- package/src/socket/handlers.ts +27 -6
- package/src/socket/index.ts +33 -55
- package/src/socket/socket.ts +218 -70
- package/src/types/common.ts +6 -1
- package/src/types/socket.ts +36 -15
package/src/socket/socket.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import WebSocket from "
|
|
1
|
+
import WebSocket from "ws";
|
|
2
2
|
import {
|
|
3
3
|
ISocketClient,
|
|
4
4
|
MethodHandler,
|
|
5
5
|
MethodHandlers,
|
|
6
|
-
|
|
6
|
+
RequestContextBase,
|
|
7
|
+
SocketTimeouts,
|
|
8
|
+
SocketErrorException,
|
|
9
|
+
GenericMiddleware,
|
|
10
|
+
NonEmptyArray,
|
|
7
11
|
} from "../types";
|
|
8
12
|
|
|
9
13
|
interface SocketRequest<Payload = unknown> {
|
|
@@ -19,31 +23,61 @@ interface SocketResponse<Payload = unknown> {
|
|
|
19
23
|
error: SocketError | null;
|
|
20
24
|
}
|
|
21
25
|
|
|
22
|
-
interface SocketMessage<
|
|
26
|
+
export interface SocketMessage<
|
|
27
|
+
RequestPayload = unknown,
|
|
28
|
+
ResponsePayload = unknown
|
|
29
|
+
> {
|
|
23
30
|
request?: SocketRequest<RequestPayload>;
|
|
24
31
|
response?: SocketResponse<ResponsePayload>;
|
|
25
32
|
}
|
|
26
33
|
|
|
27
|
-
interface SocketError {
|
|
34
|
+
export interface SocketError {
|
|
28
35
|
message: string;
|
|
29
36
|
code: number;
|
|
30
37
|
}
|
|
31
38
|
|
|
32
|
-
|
|
39
|
+
/**
|
|
40
|
+
* ISocket is a class that wraps a WebSocket connection and provides a simple interface for sending and receiving messages.
|
|
41
|
+
* ISocket is initialized by both server and client and request/response is called symmetrically.
|
|
42
|
+
*
|
|
43
|
+
* ISocket handles has two timeout actions:
|
|
44
|
+
* 1. Connection timeout: If the connection is not closed after a certain time, the connection is closed.
|
|
45
|
+
* - This is useful to prevent a connection from being open indefinitely. This is mainly used in the server side since
|
|
46
|
+
* the client side manages connection lifecycle manually.
|
|
47
|
+
* 2. No response timeout: If the response is not received after a certain time, the request is timed out.
|
|
48
|
+
* - This is mainly used by CLI to handle the case where the server is not responding.
|
|
49
|
+
*
|
|
50
|
+
* It is expected that timeouts should be relatively sorted in the order of connection timeout > request timeout > no response timeout.
|
|
51
|
+
*/
|
|
52
|
+
export class ISocket<
|
|
53
|
+
ImplementedMethods,
|
|
54
|
+
CallableMethods,
|
|
55
|
+
RequestContext extends RequestContextBase
|
|
56
|
+
> {
|
|
33
57
|
private readonly ws: WebSocket;
|
|
34
58
|
private readonly requestHandlers: MethodHandlers<
|
|
35
59
|
ImplementedMethods,
|
|
36
60
|
CallableMethods,
|
|
37
61
|
RequestContext
|
|
38
62
|
>;
|
|
39
|
-
private readonly
|
|
40
|
-
|
|
63
|
+
private readonly globalMiddlewares: GenericMiddleware<
|
|
64
|
+
CallableMethods,
|
|
65
|
+
RequestContext
|
|
66
|
+
>[];
|
|
67
|
+
private readonly responseHandler = new Map<
|
|
68
|
+
number,
|
|
69
|
+
{
|
|
41
70
|
resolve: (data: unknown) => void;
|
|
42
71
|
reject: (error: SocketError) => void;
|
|
43
|
-
|
|
44
|
-
|
|
72
|
+
timeout?: NodeJS.Timeout;
|
|
73
|
+
}
|
|
74
|
+
>();
|
|
45
75
|
private peerAuthorization?: string;
|
|
46
|
-
|
|
76
|
+
protected nxtRequestId: number;
|
|
77
|
+
private connectionTimeout?: NodeJS.Timeout;
|
|
78
|
+
// pino library not available in shared
|
|
79
|
+
private logger: { error: (message?: string) => void };
|
|
80
|
+
private timeouts?: SocketTimeouts;
|
|
47
81
|
|
|
48
82
|
constructor(
|
|
49
83
|
ws: WebSocket,
|
|
@@ -51,90 +85,129 @@ export class ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
|
51
85
|
ImplementedMethods,
|
|
52
86
|
CallableMethods,
|
|
53
87
|
RequestContext
|
|
54
|
-
|
|
88
|
+
>,
|
|
89
|
+
globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[],
|
|
90
|
+
timeouts?: SocketTimeouts,
|
|
91
|
+
logger?: { error: (message?: string) => void }
|
|
55
92
|
) {
|
|
56
93
|
this.ws = ws;
|
|
57
94
|
this.requestHandlers = requestHandlers;
|
|
95
|
+
this.globalMiddlewares = globalMiddlewares;
|
|
58
96
|
this.nxtRequestId = 0;
|
|
97
|
+
this.logger = logger ?? { error: console.error };
|
|
98
|
+
this.timeouts = timeouts;
|
|
99
|
+
// reset connection timeout in each message received. It means connection still active
|
|
100
|
+
this.resetConnectionTimeout();
|
|
59
101
|
|
|
60
|
-
this.ws.addEventListener(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
102
|
+
this.ws.addEventListener(
|
|
103
|
+
"message",
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
105
|
+
async (event: WebSocket.MessageEvent) => {
|
|
106
|
+
const eventData: SocketMessage = JSON.parse(event.data.toString());
|
|
107
|
+
return this.handleMessage(eventData);
|
|
108
|
+
}
|
|
109
|
+
);
|
|
64
110
|
}
|
|
65
111
|
|
|
66
|
-
|
|
67
|
-
|
|
112
|
+
protected async handleMessage(message: SocketMessage): Promise<void> {
|
|
113
|
+
this.resetConnectionTimeout();
|
|
114
|
+
if (message.request) {
|
|
68
115
|
// Split the method string into parts
|
|
69
|
-
const parts =
|
|
70
|
-
let handlers = this.requestHandlers
|
|
116
|
+
const parts = message.request.method.split(".");
|
|
117
|
+
let handlers = this.requestHandlers as Record<string, unknown>;
|
|
71
118
|
for (const part of parts) {
|
|
72
|
-
|
|
73
|
-
// @ts-ignore
|
|
74
|
-
handlers = handlers[part];
|
|
119
|
+
handlers = handlers[part] as Record<string, unknown>;
|
|
75
120
|
if (!handlers) {
|
|
76
|
-
return this.respondError(
|
|
121
|
+
return this.respondError(message.request.id, {
|
|
77
122
|
code: 2,
|
|
78
|
-
message: `unknown method ${
|
|
123
|
+
message: `unknown method ${message.request.method}`,
|
|
79
124
|
});
|
|
80
125
|
}
|
|
81
126
|
}
|
|
82
127
|
|
|
83
128
|
if (!Array.isArray(handlers)) {
|
|
84
|
-
return this.respondError(
|
|
129
|
+
return this.respondError(message.request.id, {
|
|
85
130
|
code: 2,
|
|
86
131
|
message: "unknown method",
|
|
87
132
|
});
|
|
88
133
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
const middlewareHandlers = handlers.slice(0, -1) as MiddlewareHandler<
|
|
93
|
-
unknown,
|
|
94
|
-
CallableMethods,
|
|
95
|
-
RequestContext
|
|
96
|
-
>[];
|
|
97
|
-
const handler = handlers[handlers.length - 1] as MethodHandler<
|
|
98
|
-
unknown,
|
|
99
|
-
unknown,
|
|
134
|
+
handlers = [...this.globalMiddlewares, ...handlers] as MethodHandlers<
|
|
135
|
+
ImplementedMethods,
|
|
100
136
|
CallableMethods,
|
|
101
137
|
RequestContext
|
|
102
138
|
>;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
139
|
+
if (message.request.setAuthorization) {
|
|
140
|
+
this.peerAuthorization = message.request.setAuthorization;
|
|
141
|
+
}
|
|
142
|
+
const reqCtx = {
|
|
143
|
+
peerAuthorization: this.peerAuthorization,
|
|
144
|
+
method: message.request.method,
|
|
145
|
+
requestId: message.request.id,
|
|
146
|
+
} as RequestContext;
|
|
106
147
|
const client = createISocketClient(this);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
148
|
+
const payload = message.request.payload;
|
|
149
|
+
let alreadyResponded = false;
|
|
150
|
+
const generateNextFn = (idx: number): (() => Promise<unknown>) => {
|
|
151
|
+
let wasCalled = false;
|
|
152
|
+
return async () => {
|
|
153
|
+
if (alreadyResponded) {
|
|
154
|
+
throw new SocketErrorException(
|
|
155
|
+
4,
|
|
156
|
+
"next() was called after the response was sent"
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
const handler = (
|
|
160
|
+
handlers as unknown as NonEmptyArray<
|
|
161
|
+
MethodHandler<unknown, unknown, CallableMethods, RequestContext>
|
|
162
|
+
>
|
|
163
|
+
)[idx];
|
|
164
|
+
if (!handler) {
|
|
165
|
+
throw new SocketErrorException(
|
|
166
|
+
5,
|
|
167
|
+
"cannot call past the last handler in the chain"
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
if (wasCalled) {
|
|
171
|
+
throw new SocketErrorException(
|
|
172
|
+
6,
|
|
173
|
+
"next() was called multiple times"
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
wasCalled = true;
|
|
177
|
+
return this.callHandler(
|
|
178
|
+
handler,
|
|
179
|
+
payload,
|
|
180
|
+
reqCtx,
|
|
112
181
|
client,
|
|
113
|
-
|
|
182
|
+
generateNextFn(idx + 1)
|
|
114
183
|
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
let response: unknown;
|
|
187
|
+
try {
|
|
188
|
+
// call the first handler in the chain
|
|
189
|
+
response = await generateNextFn(0)();
|
|
190
|
+
} catch (error) {
|
|
191
|
+
const socketError =
|
|
192
|
+
error instanceof SocketErrorException
|
|
193
|
+
? { code: error.code, message: error.message }
|
|
194
|
+
: { code: 3, message: (error as Error).toString() };
|
|
195
|
+
return this.respondError(message.request.id, socketError);
|
|
122
196
|
}
|
|
123
|
-
this.respond(
|
|
124
|
-
|
|
125
|
-
|
|
197
|
+
this.respond(message.request.id, response);
|
|
198
|
+
alreadyResponded = true;
|
|
199
|
+
} else if (message.response && message.response.id) {
|
|
200
|
+
const responseHandler = this.responseHandler.get(message.response.id);
|
|
201
|
+
if (!responseHandler) {
|
|
126
202
|
return;
|
|
127
203
|
}
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
eventData.response.error
|
|
131
|
-
);
|
|
204
|
+
if (message.response.error) {
|
|
205
|
+
responseHandler.reject(message.response.error);
|
|
132
206
|
}
|
|
133
207
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
);
|
|
137
|
-
delete this.responseHandler[eventData.response.id];
|
|
208
|
+
responseHandler.resolve(message.response.payload as any);
|
|
209
|
+
clearTimeout(responseHandler.timeout);
|
|
210
|
+
this.responseHandler.delete(message.response.id);
|
|
138
211
|
} else {
|
|
139
212
|
return this.respondError(-1, {
|
|
140
213
|
code: 3,
|
|
@@ -143,6 +216,21 @@ export class ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
|
143
216
|
}
|
|
144
217
|
}
|
|
145
218
|
|
|
219
|
+
protected async callHandler<
|
|
220
|
+
Params,
|
|
221
|
+
Result,
|
|
222
|
+
CallableMethods,
|
|
223
|
+
RequestContext extends RequestContextBase
|
|
224
|
+
>(
|
|
225
|
+
handler: MethodHandler<Params, Result, CallableMethods, RequestContext>,
|
|
226
|
+
params: Params,
|
|
227
|
+
ctx: RequestContext,
|
|
228
|
+
client: ISocketClient<CallableMethods>,
|
|
229
|
+
next: () => Promise<Result>
|
|
230
|
+
): Promise<Result> {
|
|
231
|
+
return handler(params, ctx, client, next);
|
|
232
|
+
}
|
|
233
|
+
|
|
146
234
|
public request<Params, Result>(
|
|
147
235
|
method: string,
|
|
148
236
|
params: Params,
|
|
@@ -150,10 +238,10 @@ export class ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
|
150
238
|
): Promise<Result> {
|
|
151
239
|
return new Promise<Result>((resolve, reject) => {
|
|
152
240
|
const requestId = ++this.nxtRequestId;
|
|
153
|
-
this.responseHandler
|
|
241
|
+
this.responseHandler.set(requestId, {
|
|
154
242
|
resolve: (result) => resolve(result as Result),
|
|
155
243
|
reject: (error: SocketError) => reject(error),
|
|
156
|
-
};
|
|
244
|
+
});
|
|
157
245
|
const toSend: SocketMessage = {
|
|
158
246
|
request: {
|
|
159
247
|
method,
|
|
@@ -163,10 +251,11 @@ export class ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
|
163
251
|
},
|
|
164
252
|
};
|
|
165
253
|
this.ws.send(JSON.stringify(toSend));
|
|
254
|
+
this.resetNoResponseTimeout(requestId);
|
|
166
255
|
});
|
|
167
256
|
}
|
|
168
257
|
|
|
169
|
-
|
|
258
|
+
protected respond<Result>(requestId: number, result: Result): void {
|
|
170
259
|
const toSend: SocketMessage = {
|
|
171
260
|
response: {
|
|
172
261
|
payload: result,
|
|
@@ -177,7 +266,7 @@ export class ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
|
177
266
|
return this.ws.send(JSON.stringify(toSend));
|
|
178
267
|
}
|
|
179
268
|
|
|
180
|
-
|
|
269
|
+
protected respondError(requestId: number, error: SocketError): void {
|
|
181
270
|
const toSend: SocketMessage = {
|
|
182
271
|
response: {
|
|
183
272
|
payload: null,
|
|
@@ -188,7 +277,66 @@ export class ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
|
188
277
|
return this.ws.send(JSON.stringify(toSend));
|
|
189
278
|
}
|
|
190
279
|
|
|
280
|
+
private resetConnectionTimeout(): void {
|
|
281
|
+
if (!this.timeouts?.connectionTimeoutInSeconds) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (this.connectionTimeout) {
|
|
285
|
+
clearTimeout(this.connectionTimeout);
|
|
286
|
+
}
|
|
287
|
+
// Set a new timeout for the next message
|
|
288
|
+
this.connectionTimeout = setTimeout(
|
|
289
|
+
this.handleConnectionTimeout(),
|
|
290
|
+
this.timeouts?.connectionTimeoutInSeconds * 1000
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private handleConnectionTimeout() {
|
|
295
|
+
return () => {
|
|
296
|
+
this.logger.error(
|
|
297
|
+
`Connection timed out after ${this.timeouts?.connectionTimeoutInSeconds} seconds`
|
|
298
|
+
);
|
|
299
|
+
this.close();
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
private resetNoResponseTimeout(requestId: number): void {
|
|
304
|
+
if (!this.timeouts?.noResponseTimeoutInSeconds) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const responseHandler = this.responseHandler.get(requestId);
|
|
308
|
+
if (!responseHandler) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const noResponseTimeout = responseHandler.timeout;
|
|
312
|
+
const reject = responseHandler.reject;
|
|
313
|
+
if (responseHandler.timeout) {
|
|
314
|
+
clearTimeout(noResponseTimeout);
|
|
315
|
+
}
|
|
316
|
+
// Set a new timeout for the next message
|
|
317
|
+
responseHandler.timeout = setTimeout(
|
|
318
|
+
this.handleNoResponseTimeout(reject),
|
|
319
|
+
this.timeouts?.noResponseTimeoutInSeconds * 1000
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private handleNoResponseTimeout(reject: (error: SocketError) => void) {
|
|
324
|
+
return () => {
|
|
325
|
+
const message = `Request timed out after ${this.timeouts?.noResponseTimeoutInSeconds} seconds`;
|
|
326
|
+
this.logger.error(message);
|
|
327
|
+
reject({ code: 7, message });
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
191
331
|
public close(): void {
|
|
332
|
+
clearTimeout(this.connectionTimeout);
|
|
333
|
+
this.responseHandler.forEach((handler, key) => {
|
|
334
|
+
clearTimeout(handler.timeout);
|
|
335
|
+
this.logger.error(
|
|
336
|
+
`Rejecting pending requestId ${key} due to connection close`
|
|
337
|
+
);
|
|
338
|
+
handler.reject({ code: 8, message: "Connection closed" });
|
|
339
|
+
});
|
|
192
340
|
this.ws.close();
|
|
193
341
|
}
|
|
194
342
|
}
|
|
@@ -200,7 +348,7 @@ const proxyTarget = Object.freeze(() => {
|
|
|
200
348
|
function createIsocketProxy<
|
|
201
349
|
ImplementedMethods,
|
|
202
350
|
CallableMethods,
|
|
203
|
-
RequestContext
|
|
351
|
+
RequestContext extends RequestContextBase
|
|
204
352
|
>(
|
|
205
353
|
socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>,
|
|
206
354
|
// if path is undefined, it means the current object is the root object
|
|
@@ -238,13 +386,13 @@ function createIsocketProxy<
|
|
|
238
386
|
export function createISocketClient<
|
|
239
387
|
CallableMethods,
|
|
240
388
|
ImplementedMethods,
|
|
241
|
-
RequestContext
|
|
389
|
+
RequestContext extends RequestContextBase
|
|
242
390
|
>(
|
|
243
391
|
socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>
|
|
244
392
|
): ISocketClient<CallableMethods> {
|
|
245
393
|
return {
|
|
246
394
|
close: () => socket.close(),
|
|
247
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
395
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
248
396
|
call: createIsocketProxy(socket, undefined) as any,
|
|
249
397
|
};
|
|
250
398
|
}
|
package/src/types/common.ts
CHANGED
|
@@ -7,7 +7,6 @@ export interface UserMeDto {
|
|
|
7
7
|
|
|
8
8
|
export interface FlagBootstrap {
|
|
9
9
|
"ui.enable-resource-signing"?: boolean;
|
|
10
|
-
"server.multipage.enabled"?: boolean;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
export type User = {
|
|
@@ -152,3 +151,9 @@ export interface RemoteCommitDto {
|
|
|
152
151
|
branchName: string;
|
|
153
152
|
repositoryId: string;
|
|
154
153
|
}
|
|
154
|
+
|
|
155
|
+
export type ViewMode =
|
|
156
|
+
| "export-deployed"
|
|
157
|
+
| "export-latest"
|
|
158
|
+
| "export-live"
|
|
159
|
+
| "export-commit";
|
package/src/types/socket.ts
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
|
+
export interface RequestContextBase {
|
|
2
|
+
peerAuthorization?: string;
|
|
3
|
+
method: string;
|
|
4
|
+
requestId: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
1
7
|
export type MethodHandler<Params, Result, PeerMethods, RequestContext> = (
|
|
2
8
|
params: Params,
|
|
9
|
+
ctx: RequestContext,
|
|
3
10
|
peer: ISocketClient<PeerMethods>,
|
|
4
|
-
|
|
11
|
+
next: () => Promise<Result>
|
|
5
12
|
) => Promise<Result>;
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
// A generic middleware is a method handler that can be chained with any other method handler, so it uses `any` for the params and result types
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
export type GenericMiddleware<PeerMethods, RequestContext> = MethodHandler<
|
|
17
|
+
any,
|
|
18
|
+
any,
|
|
19
|
+
PeerMethods,
|
|
20
|
+
RequestContext
|
|
21
|
+
>;
|
|
22
|
+
|
|
23
|
+
export type NonEmptyArray<T> = [...T[], T];
|
|
13
24
|
|
|
14
25
|
export type MethodHandlers<Methods, PeerMethods, RequestContext> = {
|
|
15
26
|
[Key in keyof Methods]: Methods[Key] extends (
|
|
16
27
|
params: infer Params
|
|
17
28
|
) => Promise<infer Result>
|
|
18
|
-
?
|
|
19
|
-
...middlewareHandlers: MiddlewareHandler<
|
|
20
|
-
Params,
|
|
21
|
-
PeerMethods,
|
|
22
|
-
RequestContext
|
|
23
|
-
>[],
|
|
24
|
-
handler: MethodHandler<Params, Result, PeerMethods, RequestContext>
|
|
25
|
-
]
|
|
29
|
+
? NonEmptyArray<MethodHandler<Params, Result, PeerMethods, RequestContext>>
|
|
26
30
|
: Methods[Key] extends Record<string, unknown>
|
|
27
31
|
? MethodHandlers<Methods[Key], PeerMethods, RequestContext>
|
|
28
32
|
: never;
|
|
@@ -46,3 +50,20 @@ export type ISocketClient<Methods> = {
|
|
|
46
50
|
export type MethodSchema<Params, Response> = (
|
|
47
51
|
params: Params
|
|
48
52
|
) => Promise<Response>;
|
|
53
|
+
|
|
54
|
+
/** The exception type can be thrown to cause the default error handler to write a raw error response to the socket */
|
|
55
|
+
export class SocketErrorException extends Error {
|
|
56
|
+
readonly code: number;
|
|
57
|
+
readonly message: string;
|
|
58
|
+
|
|
59
|
+
constructor(code: number, message: string) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.code = code;
|
|
62
|
+
this.message = message;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type SocketTimeouts = {
|
|
67
|
+
noResponseTimeoutInSeconds?: number;
|
|
68
|
+
connectionTimeoutInSeconds?: number;
|
|
69
|
+
};
|