@superblocksteam/sdk 1.8.2 → 1.9.1
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 +179 -102
- 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 +9 -17
- package/dist/socket/index.js +10 -6
- package/dist/socket/socket.d.ts +52 -8
- 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 +2 -2
- package/src/client.ts +319 -151
- package/src/sdk.ts +79 -20
- package/src/socket/handlers.ts +27 -6
- package/src/socket/index.ts +32 -54
- package/src/socket/socket.ts +217 -69
- package/src/types/common.ts +6 -2
- package/src/types/socket.ts +36 -15
package/dist/sdk.js
CHANGED
|
@@ -14,7 +14,7 @@ class SuperblocksSdk {
|
|
|
14
14
|
this.superblocksBaseUrl = superblocksBaseUrl;
|
|
15
15
|
this.cliVersion = cliVersion;
|
|
16
16
|
}
|
|
17
|
-
async fetchApplication({ applicationId, branch, headers = {}, viewMode = "export-live",
|
|
17
|
+
async fetchApplication({ applicationId, branch, headers = {}, viewMode = "export-live", skipSigningVerification = false, }) {
|
|
18
18
|
return (0, client_1.fetchApplication)({
|
|
19
19
|
cliVersion: this.cliVersion,
|
|
20
20
|
applicationId,
|
|
@@ -22,8 +22,8 @@ class SuperblocksSdk {
|
|
|
22
22
|
token: this.token,
|
|
23
23
|
superblocksBaseUrl: this.superblocksBaseUrl,
|
|
24
24
|
viewMode,
|
|
25
|
+
skipSigningVerification,
|
|
25
26
|
injectedHeaders: headers,
|
|
26
|
-
fetchSinglePageApplication,
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
async fetchApplicationBranches(applicationId, headers = {}) {
|
|
@@ -35,7 +35,7 @@ class SuperblocksSdk {
|
|
|
35
35
|
injectedHeaders: headers,
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
async fetchApplicationWithComponents({ applicationId, branch, headers = {}, viewMode = "export-live",
|
|
38
|
+
async fetchApplicationWithComponents({ applicationId, branch, headers = {}, viewMode = "export-live", commitId, skipSigningVerification = false, }) {
|
|
39
39
|
return (0, client_1.fetchApplicationWithComponents)({
|
|
40
40
|
cliVersion: this.cliVersion,
|
|
41
41
|
applicationId,
|
|
@@ -43,15 +43,40 @@ class SuperblocksSdk {
|
|
|
43
43
|
token: this.token,
|
|
44
44
|
superblocksBaseUrl: this.superblocksBaseUrl,
|
|
45
45
|
viewMode,
|
|
46
|
+
skipSigningVerification,
|
|
47
|
+
commitId,
|
|
46
48
|
injectedHeaders: headers,
|
|
47
|
-
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async fetchApplicationCommits({ applicationId, branch, headers = {}, limit, offset, }) {
|
|
52
|
+
return (0, client_1.fetchApplicationCommits)({
|
|
53
|
+
cliVersion: this.cliVersion,
|
|
54
|
+
applicationId,
|
|
55
|
+
branch,
|
|
56
|
+
token: this.token,
|
|
57
|
+
superblocksBaseUrl: this.superblocksBaseUrl,
|
|
58
|
+
injectedHeaders: headers,
|
|
59
|
+
limit,
|
|
60
|
+
offset,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async fetchApiCommits({ apiId, branch, headers = {}, limit, offset, }) {
|
|
64
|
+
return (0, client_1.fetchApiCommits)({
|
|
65
|
+
cliVersion: this.cliVersion,
|
|
66
|
+
applicationId: apiId,
|
|
67
|
+
branch,
|
|
68
|
+
token: this.token,
|
|
69
|
+
superblocksBaseUrl: this.superblocksBaseUrl,
|
|
70
|
+
injectedHeaders: headers,
|
|
71
|
+
limit,
|
|
72
|
+
offset,
|
|
48
73
|
});
|
|
49
74
|
}
|
|
50
75
|
async fetchApplications(headers) {
|
|
51
76
|
return (0, client_1.fetchApplications)(this.cliVersion, this.token, this.superblocksBaseUrl, headers);
|
|
52
77
|
}
|
|
53
|
-
async fetchApi(apiId, viewMode = "export-live",
|
|
54
|
-
return (0, client_1.fetchApi)(this.cliVersion, apiId, this.token, this.superblocksBaseUrl, viewMode, branch);
|
|
78
|
+
async fetchApi({ apiId, branch, viewMode = "export-live", commitId, skipSigningVerification = false, }) {
|
|
79
|
+
return (0, client_1.fetchApi)(this.cliVersion, apiId, this.token, this.superblocksBaseUrl, viewMode, branch, commitId, skipSigningVerification);
|
|
55
80
|
}
|
|
56
81
|
async fetchApis() {
|
|
57
82
|
return (0, client_1.fetchApis)(this.cliVersion, this.token, this.superblocksBaseUrl);
|
|
@@ -76,7 +101,7 @@ class SuperblocksSdk {
|
|
|
76
101
|
async fetchCurrentUser() {
|
|
77
102
|
return (0, client_1.fetchCurrentUser)(this.cliVersion, this.token, this.superblocksBaseUrl);
|
|
78
103
|
}
|
|
79
|
-
async pushApplication({ applicationId, applicationConfig, branch, headers = {},
|
|
104
|
+
async pushApplication({ applicationId, applicationConfig, branch, headers = {}, }) {
|
|
80
105
|
return (0, client_1.pushApplication)({
|
|
81
106
|
cliVersion: this.cliVersion,
|
|
82
107
|
applicationId,
|
|
@@ -85,7 +110,6 @@ class SuperblocksSdk {
|
|
|
85
110
|
branch,
|
|
86
111
|
injectedHeaders: headers,
|
|
87
112
|
applicationConfig,
|
|
88
|
-
multiPage,
|
|
89
113
|
});
|
|
90
114
|
}
|
|
91
115
|
async pushApi({ apiId, apiConfig, branch, headers = {}, }) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LocalGitRepoState } from "@superblocksteam/util";
|
|
2
|
-
import { ApiToSign, ApiToVerify, AppToSign, AppToVerify, MethodHandlers, RemoteCommitDto, Signature } from "../types";
|
|
2
|
+
import { ApiToSign, ApiToVerify, AppToSign, AppToVerify, MethodHandlers, RemoteCommitDto, Signature, ViewMode } from "../types";
|
|
3
3
|
type MethodSchema<Params, Response> = (params: Params) => Promise<Response>;
|
|
4
4
|
export interface ClientMethods {
|
|
5
5
|
v1: {
|
|
@@ -93,11 +93,20 @@ export interface ServerMethods {
|
|
|
93
93
|
pushCommit: ServerMethodSchema<{
|
|
94
94
|
apiId: string;
|
|
95
95
|
branchName: string;
|
|
96
|
-
commitId
|
|
97
|
-
commitMessage
|
|
96
|
+
commitId?: string;
|
|
97
|
+
commitMessage?: string;
|
|
98
98
|
apiPb: Record<string, unknown>;
|
|
99
99
|
gitState: LocalGitRepoState;
|
|
100
|
-
|
|
100
|
+
skipCommit: boolean;
|
|
101
|
+
}, RemoteCommitDto | {
|
|
102
|
+
updated: Date;
|
|
103
|
+
}>;
|
|
104
|
+
get: ServerMethodSchema<{
|
|
105
|
+
apiId: string;
|
|
106
|
+
branchName?: string;
|
|
107
|
+
viewMode: ViewMode;
|
|
108
|
+
commitId?: string;
|
|
109
|
+
}, any>;
|
|
101
110
|
};
|
|
102
111
|
};
|
|
103
112
|
};
|
|
@@ -107,13 +116,22 @@ export interface ServerMethods {
|
|
|
107
116
|
pushCommit: ServerMethodSchema<{
|
|
108
117
|
applicationId: string;
|
|
109
118
|
branchName: string;
|
|
110
|
-
commitId
|
|
111
|
-
commitMessage
|
|
119
|
+
commitId?: string;
|
|
120
|
+
commitMessage?: string;
|
|
112
121
|
application: Record<string, unknown>;
|
|
113
122
|
pages: Record<string, unknown>[];
|
|
114
123
|
apis: Record<string, unknown>[];
|
|
115
124
|
gitState: LocalGitRepoState;
|
|
116
|
-
|
|
125
|
+
skipCommit: boolean;
|
|
126
|
+
}, RemoteCommitDto | {
|
|
127
|
+
updated: Date;
|
|
128
|
+
}>;
|
|
129
|
+
get: ServerMethodSchema<{
|
|
130
|
+
applicationId: string;
|
|
131
|
+
viewMode: ViewMode;
|
|
132
|
+
branchName?: string;
|
|
133
|
+
commitId?: string;
|
|
134
|
+
}, any>;
|
|
117
135
|
};
|
|
118
136
|
};
|
|
119
137
|
};
|
package/dist/socket/index.d.ts
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
import WebSocket from "ws";
|
|
2
|
+
import { GenericMiddleware, ISocketClient, MethodHandlers, RequestContextBase, SocketTimeouts } from "../types";
|
|
2
3
|
import { ServerMethods } from "./handlers";
|
|
4
|
+
import { ISocket } from "./socket";
|
|
3
5
|
export type StdISocketRPCClient = ISocketClient<ServerMethods>;
|
|
4
6
|
export declare function connectToISocketRPCServer({ superblocksBaseUrl, agentUrl, token, }: {
|
|
5
7
|
superblocksBaseUrl: string;
|
|
6
8
|
token: string;
|
|
7
9
|
agentUrl?: string;
|
|
8
10
|
}): Promise<StdISocketRPCClient>;
|
|
9
|
-
export declare
|
|
11
|
+
export declare class ISocketWithClientAuth<ImplementedMethods, CallableMethods, RequestContext extends RequestContextBase> extends ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
12
|
+
private readonly authorization?;
|
|
13
|
+
private hasSentAuth;
|
|
14
|
+
constructor(ws: WebSocket, authorization: string | undefined, requestHandlers: MethodHandlers<ImplementedMethods, CallableMethods, RequestContext>, globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[], timeouts?: SocketTimeouts);
|
|
15
|
+
request<Params, Result>(method: string, params: Params): Promise<Result>;
|
|
16
|
+
}
|
|
17
|
+
export declare function connectISocket<CallableMethods, ImplementedMethods, RequestContext extends RequestContextBase = RequestContextBase>(wsUrl: string, authorization: string | undefined, requestHandlers: MethodHandlers<ImplementedMethods, CallableMethods, RequestContext>, globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[], timeouts?: SocketTimeouts): Promise<ISocketClient<CallableMethods>>;
|
|
10
18
|
export declare function connectWebSocket(wsUrl: string): Promise<WebSocket>;
|
|
11
|
-
type MethodHandler<Params, Result, PeerMethods, RequestContext> = (params: Params, peer: ISocketClient<PeerMethods>, ctx: RequestContext) => Promise<Result>;
|
|
12
|
-
type MiddlewareHandler<Params, PeerMethods, RequestContext> = (params: Params, peerAuthorization: string | undefined, peer: ISocketClient<PeerMethods>, ctx: RequestContext) => Promise<void>;
|
|
13
|
-
type MethodHandlers<Methods, PeerMethods, RequestContext> = {
|
|
14
|
-
[Key in keyof Methods]: Methods[Key] extends (params: infer Params) => Promise<infer Result> ? [
|
|
15
|
-
...middlewareHandlers: MiddlewareHandler<Params, PeerMethods, RequestContext>[],
|
|
16
|
-
handler: MethodHandler<Params, Result, PeerMethods, RequestContext>
|
|
17
|
-
] : Methods[Key] extends Record<string, unknown> ? MethodHandlers<Methods[Key], PeerMethods, RequestContext> : never;
|
|
18
|
-
};
|
|
19
|
-
type ISocketClientMethodCall<Methods> = {
|
|
20
|
-
[Key in keyof Methods]: Methods[Key] extends (params: infer P) => Promise<infer R> ? (params: P) => Promise<R> : Methods[Key] extends Record<string, unknown> ? ISocketClientMethodCall<Methods[Key]> : never;
|
|
21
|
-
};
|
|
22
|
-
type ISocketClient<Methods> = {
|
|
23
|
-
close: () => void;
|
|
24
|
-
call: ISocketClientMethodCall<Methods>;
|
|
25
|
-
};
|
|
26
|
-
export {};
|
package/dist/socket/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.connectWebSocket = exports.connectISocket = exports.connectToISocketRPCServer = void 0;
|
|
3
|
+
exports.connectWebSocket = exports.connectISocket = exports.ISocketWithClientAuth = exports.connectToISocketRPCServer = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const ws_1 = tslib_1.__importDefault(require("ws"));
|
|
6
6
|
const handlers_1 = require("./handlers");
|
|
@@ -24,15 +24,18 @@ async function connectToISocketRPCServer({ superblocksBaseUrl, agentUrl, token,
|
|
|
24
24
|
else if (wsUrl.hostname === "localhost") {
|
|
25
25
|
wsUrl.hostname = "127.0.0.1";
|
|
26
26
|
}
|
|
27
|
-
return await connectISocket(wsUrl.href, authorization, requestHandlers
|
|
27
|
+
return await connectISocket(wsUrl.href, authorization, requestHandlers, [], {
|
|
28
|
+
connectionTimeoutInSeconds: 6 * 60,
|
|
29
|
+
noResponseTimeoutInSeconds: 5 * 60, // 5 minutes
|
|
30
|
+
});
|
|
28
31
|
}
|
|
29
32
|
exports.connectToISocketRPCServer = connectToISocketRPCServer;
|
|
30
33
|
// a subclass of ISocket that sends an auth token on the first request
|
|
31
34
|
// this is useful for client-side sockets that need to authenticate
|
|
32
35
|
// TODO(george): if we start using this for long-lived connections, we should add a way to refresh the token
|
|
33
36
|
class ISocketWithClientAuth extends socket_1.ISocket {
|
|
34
|
-
constructor(ws, authorization, requestHandlers) {
|
|
35
|
-
super(ws, requestHandlers);
|
|
37
|
+
constructor(ws, authorization, requestHandlers, globalMiddlewares, timeouts) {
|
|
38
|
+
super(ws, requestHandlers, globalMiddlewares, timeouts);
|
|
36
39
|
this.hasSentAuth = false;
|
|
37
40
|
this.authorization = authorization;
|
|
38
41
|
}
|
|
@@ -45,9 +48,10 @@ class ISocketWithClientAuth extends socket_1.ISocket {
|
|
|
45
48
|
return result;
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
|
-
|
|
51
|
+
exports.ISocketWithClientAuth = ISocketWithClientAuth;
|
|
52
|
+
async function connectISocket(wsUrl, authorization, requestHandlers, globalMiddlewares, timeouts) {
|
|
49
53
|
const ws = await connectWebSocket(wsUrl);
|
|
50
|
-
const isocket = new ISocketWithClientAuth(ws, authorization, requestHandlers);
|
|
54
|
+
const isocket = new ISocketWithClientAuth(ws, authorization, requestHandlers, globalMiddlewares, timeouts);
|
|
51
55
|
return (0, socket_1.createISocketClient)(isocket);
|
|
52
56
|
}
|
|
53
57
|
exports.connectISocket = connectISocket;
|
package/dist/socket/socket.d.ts
CHANGED
|
@@ -1,16 +1,60 @@
|
|
|
1
1
|
import WebSocket from "ws";
|
|
2
|
-
import { ISocketClient, MethodHandlers } from "../types";
|
|
3
|
-
|
|
2
|
+
import { ISocketClient, MethodHandler, MethodHandlers, RequestContextBase, SocketTimeouts, GenericMiddleware } from "../types";
|
|
3
|
+
interface SocketRequest<Payload = unknown> {
|
|
4
|
+
method: string;
|
|
5
|
+
payload: Payload;
|
|
6
|
+
id: number;
|
|
7
|
+
setAuthorization?: string;
|
|
8
|
+
}
|
|
9
|
+
interface SocketResponse<Payload = unknown> {
|
|
10
|
+
id: number;
|
|
11
|
+
payload: Payload;
|
|
12
|
+
error: SocketError | null;
|
|
13
|
+
}
|
|
14
|
+
export interface SocketMessage<RequestPayload = unknown, ResponsePayload = unknown> {
|
|
15
|
+
request?: SocketRequest<RequestPayload>;
|
|
16
|
+
response?: SocketResponse<ResponsePayload>;
|
|
17
|
+
}
|
|
18
|
+
export interface SocketError {
|
|
19
|
+
message: string;
|
|
20
|
+
code: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* ISocket is a class that wraps a WebSocket connection and provides a simple interface for sending and receiving messages.
|
|
24
|
+
* ISocket is initialized by both server and client and request/response is called symmetrically.
|
|
25
|
+
*
|
|
26
|
+
* ISocket handles has two timeout actions:
|
|
27
|
+
* 1. Connection timeout: If the connection is not closed after a certain time, the connection is closed.
|
|
28
|
+
* - This is useful to prevent a connection from being open indefinitely. This is mainly used in the server side since
|
|
29
|
+
* the client side manages connection lifecycle manually.
|
|
30
|
+
* 2. No response timeout: If the response is not received after a certain time, the request is timed out.
|
|
31
|
+
* - This is mainly used by CLI to handle the case where the server is not responding.
|
|
32
|
+
*
|
|
33
|
+
* It is expected that timeouts should be relatively sorted in the order of connection timeout > request timeout > no response timeout.
|
|
34
|
+
*/
|
|
35
|
+
export declare class ISocket<ImplementedMethods, CallableMethods, RequestContext extends RequestContextBase> {
|
|
4
36
|
private readonly ws;
|
|
5
37
|
private readonly requestHandlers;
|
|
38
|
+
private readonly globalMiddlewares;
|
|
6
39
|
private readonly responseHandler;
|
|
7
40
|
private peerAuthorization?;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
private
|
|
41
|
+
protected nxtRequestId: number;
|
|
42
|
+
private connectionTimeout?;
|
|
43
|
+
private logger;
|
|
44
|
+
private timeouts?;
|
|
45
|
+
constructor(ws: WebSocket, requestHandlers: MethodHandlers<ImplementedMethods, CallableMethods, RequestContext>, globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[], timeouts?: SocketTimeouts, logger?: {
|
|
46
|
+
error: (message?: string) => void;
|
|
47
|
+
});
|
|
48
|
+
protected handleMessage(message: SocketMessage): Promise<void>;
|
|
49
|
+
protected callHandler<Params, Result, CallableMethods, RequestContext extends RequestContextBase>(handler: MethodHandler<Params, Result, CallableMethods, RequestContext>, params: Params, ctx: RequestContext, client: ISocketClient<CallableMethods>, next: () => Promise<Result>): Promise<Result>;
|
|
11
50
|
request<Params, Result>(method: string, params: Params, authorization?: string): Promise<Result>;
|
|
12
|
-
|
|
13
|
-
|
|
51
|
+
protected respond<Result>(requestId: number, result: Result): void;
|
|
52
|
+
protected respondError(requestId: number, error: SocketError): void;
|
|
53
|
+
private resetConnectionTimeout;
|
|
54
|
+
private handleConnectionTimeout;
|
|
55
|
+
private resetNoResponseTimeout;
|
|
56
|
+
private handleNoResponseTimeout;
|
|
14
57
|
close(): void;
|
|
15
58
|
}
|
|
16
|
-
export declare function createISocketClient<CallableMethods, ImplementedMethods, RequestContext>(socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>): ISocketClient<CallableMethods>;
|
|
59
|
+
export declare function createISocketClient<CallableMethods, ImplementedMethods, RequestContext extends RequestContextBase>(socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>): ISocketClient<CallableMethods>;
|
|
60
|
+
export {};
|
package/dist/socket/socket.js
CHANGED
|
@@ -1,72 +1,114 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createISocketClient = exports.ISocket = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/**
|
|
6
|
+
* ISocket is a class that wraps a WebSocket connection and provides a simple interface for sending and receiving messages.
|
|
7
|
+
* ISocket is initialized by both server and client and request/response is called symmetrically.
|
|
8
|
+
*
|
|
9
|
+
* ISocket handles has two timeout actions:
|
|
10
|
+
* 1. Connection timeout: If the connection is not closed after a certain time, the connection is closed.
|
|
11
|
+
* - This is useful to prevent a connection from being open indefinitely. This is mainly used in the server side since
|
|
12
|
+
* the client side manages connection lifecycle manually.
|
|
13
|
+
* 2. No response timeout: If the response is not received after a certain time, the request is timed out.
|
|
14
|
+
* - This is mainly used by CLI to handle the case where the server is not responding.
|
|
15
|
+
*
|
|
16
|
+
* It is expected that timeouts should be relatively sorted in the order of connection timeout > request timeout > no response timeout.
|
|
17
|
+
*/
|
|
4
18
|
class ISocket {
|
|
5
|
-
constructor(ws, requestHandlers) {
|
|
6
|
-
this.responseHandler =
|
|
19
|
+
constructor(ws, requestHandlers, globalMiddlewares, timeouts, logger) {
|
|
20
|
+
this.responseHandler = new Map();
|
|
7
21
|
this.ws = ws;
|
|
8
22
|
this.requestHandlers = requestHandlers;
|
|
23
|
+
this.globalMiddlewares = globalMiddlewares;
|
|
9
24
|
this.nxtRequestId = 0;
|
|
10
|
-
this.
|
|
25
|
+
this.logger = logger ?? { error: console.error };
|
|
26
|
+
this.timeouts = timeouts;
|
|
27
|
+
// reset connection timeout in each message received. It means connection still active
|
|
28
|
+
this.resetConnectionTimeout();
|
|
29
|
+
this.ws.addEventListener("message",
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
31
|
+
async (event) => {
|
|
11
32
|
const eventData = JSON.parse(event.data.toString());
|
|
12
|
-
|
|
33
|
+
return this.handleMessage(eventData);
|
|
13
34
|
});
|
|
14
35
|
}
|
|
15
|
-
async
|
|
16
|
-
|
|
36
|
+
async handleMessage(message) {
|
|
37
|
+
this.resetConnectionTimeout();
|
|
38
|
+
if (message.request) {
|
|
17
39
|
// Split the method string into parts
|
|
18
|
-
const parts =
|
|
40
|
+
const parts = message.request.method.split(".");
|
|
19
41
|
let handlers = this.requestHandlers;
|
|
20
42
|
for (const part of parts) {
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
22
|
-
// @ts-ignore
|
|
23
43
|
handlers = handlers[part];
|
|
24
44
|
if (!handlers) {
|
|
25
|
-
return this.respondError(
|
|
45
|
+
return this.respondError(message.request.id, {
|
|
26
46
|
code: 2,
|
|
27
|
-
message: `unknown method ${
|
|
47
|
+
message: `unknown method ${message.request.method}`,
|
|
28
48
|
});
|
|
29
49
|
}
|
|
30
50
|
}
|
|
31
51
|
if (!Array.isArray(handlers)) {
|
|
32
|
-
return this.respondError(
|
|
52
|
+
return this.respondError(message.request.id, {
|
|
33
53
|
code: 2,
|
|
34
54
|
message: "unknown method",
|
|
35
55
|
});
|
|
36
56
|
}
|
|
37
|
-
|
|
38
|
-
|
|
57
|
+
handlers = [...this.globalMiddlewares, ...handlers];
|
|
58
|
+
if (message.request.setAuthorization) {
|
|
59
|
+
this.peerAuthorization = message.request.setAuthorization;
|
|
39
60
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
const reqCtx = {
|
|
62
|
+
peerAuthorization: this.peerAuthorization,
|
|
63
|
+
method: message.request.method,
|
|
64
|
+
requestId: message.request.id,
|
|
65
|
+
};
|
|
45
66
|
const client = createISocketClient(this);
|
|
67
|
+
const payload = message.request.payload;
|
|
68
|
+
let alreadyResponded = false;
|
|
69
|
+
const generateNextFn = (idx) => {
|
|
70
|
+
let wasCalled = false;
|
|
71
|
+
return async () => {
|
|
72
|
+
if (alreadyResponded) {
|
|
73
|
+
throw new types_1.SocketErrorException(4, "next() was called after the response was sent");
|
|
74
|
+
}
|
|
75
|
+
const handler = handlers[idx];
|
|
76
|
+
if (!handler) {
|
|
77
|
+
throw new types_1.SocketErrorException(5, "cannot call past the last handler in the chain");
|
|
78
|
+
}
|
|
79
|
+
if (wasCalled) {
|
|
80
|
+
throw new types_1.SocketErrorException(6, "next() was called multiple times");
|
|
81
|
+
}
|
|
82
|
+
wasCalled = true;
|
|
83
|
+
return this.callHandler(handler, payload, reqCtx, client, generateNextFn(idx + 1));
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
let response;
|
|
46
87
|
try {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
response = await handler(eventData.request.payload, client, reqCtx);
|
|
88
|
+
// call the first handler in the chain
|
|
89
|
+
response = await generateNextFn(0)();
|
|
51
90
|
}
|
|
52
91
|
catch (error) {
|
|
53
|
-
|
|
54
|
-
code:
|
|
55
|
-
message: error.toString()
|
|
56
|
-
|
|
92
|
+
const socketError = error instanceof types_1.SocketErrorException
|
|
93
|
+
? { code: error.code, message: error.message }
|
|
94
|
+
: { code: 3, message: error.toString() };
|
|
95
|
+
return this.respondError(message.request.id, socketError);
|
|
57
96
|
}
|
|
58
|
-
this.respond(
|
|
97
|
+
this.respond(message.request.id, response);
|
|
98
|
+
alreadyResponded = true;
|
|
59
99
|
}
|
|
60
|
-
else if (
|
|
61
|
-
|
|
100
|
+
else if (message.response && message.response.id) {
|
|
101
|
+
const responseHandler = this.responseHandler.get(message.response.id);
|
|
102
|
+
if (!responseHandler) {
|
|
62
103
|
return;
|
|
63
104
|
}
|
|
64
|
-
if (
|
|
65
|
-
|
|
105
|
+
if (message.response.error) {
|
|
106
|
+
responseHandler.reject(message.response.error);
|
|
66
107
|
}
|
|
67
108
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
-
|
|
69
|
-
|
|
109
|
+
responseHandler.resolve(message.response.payload);
|
|
110
|
+
clearTimeout(responseHandler.timeout);
|
|
111
|
+
this.responseHandler.delete(message.response.id);
|
|
70
112
|
}
|
|
71
113
|
else {
|
|
72
114
|
return this.respondError(-1, {
|
|
@@ -75,13 +117,16 @@ class ISocket {
|
|
|
75
117
|
});
|
|
76
118
|
}
|
|
77
119
|
}
|
|
120
|
+
async callHandler(handler, params, ctx, client, next) {
|
|
121
|
+
return handler(params, ctx, client, next);
|
|
122
|
+
}
|
|
78
123
|
request(method, params, authorization) {
|
|
79
124
|
return new Promise((resolve, reject) => {
|
|
80
125
|
const requestId = ++this.nxtRequestId;
|
|
81
|
-
this.responseHandler
|
|
126
|
+
this.responseHandler.set(requestId, {
|
|
82
127
|
resolve: (result) => resolve(result),
|
|
83
128
|
reject: (error) => reject(error),
|
|
84
|
-
};
|
|
129
|
+
});
|
|
85
130
|
const toSend = {
|
|
86
131
|
request: {
|
|
87
132
|
method,
|
|
@@ -91,6 +136,7 @@ class ISocket {
|
|
|
91
136
|
},
|
|
92
137
|
};
|
|
93
138
|
this.ws.send(JSON.stringify(toSend));
|
|
139
|
+
this.resetNoResponseTimeout(requestId);
|
|
94
140
|
});
|
|
95
141
|
}
|
|
96
142
|
respond(requestId, result) {
|
|
@@ -113,7 +159,52 @@ class ISocket {
|
|
|
113
159
|
};
|
|
114
160
|
return this.ws.send(JSON.stringify(toSend));
|
|
115
161
|
}
|
|
162
|
+
resetConnectionTimeout() {
|
|
163
|
+
if (!this.timeouts?.connectionTimeoutInSeconds) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (this.connectionTimeout) {
|
|
167
|
+
clearTimeout(this.connectionTimeout);
|
|
168
|
+
}
|
|
169
|
+
// Set a new timeout for the next message
|
|
170
|
+
this.connectionTimeout = setTimeout(this.handleConnectionTimeout(), this.timeouts?.connectionTimeoutInSeconds * 1000);
|
|
171
|
+
}
|
|
172
|
+
handleConnectionTimeout() {
|
|
173
|
+
return () => {
|
|
174
|
+
this.logger.error(`Connection timed out after ${this.timeouts?.connectionTimeoutInSeconds} seconds`);
|
|
175
|
+
this.close();
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
resetNoResponseTimeout(requestId) {
|
|
179
|
+
if (!this.timeouts?.noResponseTimeoutInSeconds) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const responseHandler = this.responseHandler.get(requestId);
|
|
183
|
+
if (!responseHandler) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const noResponseTimeout = responseHandler.timeout;
|
|
187
|
+
const reject = responseHandler.reject;
|
|
188
|
+
if (responseHandler.timeout) {
|
|
189
|
+
clearTimeout(noResponseTimeout);
|
|
190
|
+
}
|
|
191
|
+
// Set a new timeout for the next message
|
|
192
|
+
responseHandler.timeout = setTimeout(this.handleNoResponseTimeout(reject), this.timeouts?.noResponseTimeoutInSeconds * 1000);
|
|
193
|
+
}
|
|
194
|
+
handleNoResponseTimeout(reject) {
|
|
195
|
+
return () => {
|
|
196
|
+
const message = `Request timed out after ${this.timeouts?.noResponseTimeoutInSeconds} seconds`;
|
|
197
|
+
this.logger.error(message);
|
|
198
|
+
reject({ code: 7, message });
|
|
199
|
+
};
|
|
200
|
+
}
|
|
116
201
|
close() {
|
|
202
|
+
clearTimeout(this.connectionTimeout);
|
|
203
|
+
this.responseHandler.forEach((handler, key) => {
|
|
204
|
+
clearTimeout(handler.timeout);
|
|
205
|
+
this.logger.error(`Rejecting pending requestId ${key} due to connection close`);
|
|
206
|
+
handler.reject({ code: 8, message: "Connection closed" });
|
|
207
|
+
});
|
|
117
208
|
this.ws.close();
|
|
118
209
|
}
|
|
119
210
|
}
|
|
@@ -152,7 +243,7 @@ path) {
|
|
|
152
243
|
function createISocketClient(socket) {
|
|
153
244
|
return {
|
|
154
245
|
close: () => socket.close(),
|
|
155
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
246
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
156
247
|
call: createIsocketProxy(socket, undefined),
|
|
157
248
|
};
|
|
158
249
|
}
|
package/dist/types/common.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ export interface UserMeDto {
|
|
|
6
6
|
}
|
|
7
7
|
export interface FlagBootstrap {
|
|
8
8
|
"ui.enable-resource-signing"?: boolean;
|
|
9
|
-
"ui.multi-page.enabled"?: boolean;
|
|
10
9
|
}
|
|
11
10
|
export type User = {
|
|
12
11
|
id: string;
|
|
@@ -123,3 +122,4 @@ export interface RemoteCommitDto {
|
|
|
123
122
|
branchName: string;
|
|
124
123
|
repositoryId: string;
|
|
125
124
|
}
|
|
125
|
+
export type ViewMode = "export-deployed" | "export-latest" | "export-live" | "export-commit";
|
package/dist/types/socket.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
1
|
+
export interface RequestContextBase {
|
|
2
|
+
peerAuthorization?: string;
|
|
3
|
+
method: string;
|
|
4
|
+
requestId: number;
|
|
5
|
+
}
|
|
6
|
+
export type MethodHandler<Params, Result, PeerMethods, RequestContext> = (params: Params, ctx: RequestContext, peer: ISocketClient<PeerMethods>, next: () => Promise<Result>) => Promise<Result>;
|
|
7
|
+
export type GenericMiddleware<PeerMethods, RequestContext> = MethodHandler<any, any, PeerMethods, RequestContext>;
|
|
8
|
+
export type NonEmptyArray<T> = [...T[], T];
|
|
3
9
|
export type MethodHandlers<Methods, PeerMethods, RequestContext> = {
|
|
4
|
-
[Key in keyof Methods]: Methods[Key] extends (params: infer Params) => Promise<infer Result> ? [
|
|
5
|
-
...middlewareHandlers: MiddlewareHandler<Params, PeerMethods, RequestContext>[],
|
|
6
|
-
handler: MethodHandler<Params, Result, PeerMethods, RequestContext>
|
|
7
|
-
] : Methods[Key] extends Record<string, unknown> ? MethodHandlers<Methods[Key], PeerMethods, RequestContext> : never;
|
|
10
|
+
[Key in keyof Methods]: Methods[Key] extends (params: infer Params) => Promise<infer Result> ? NonEmptyArray<MethodHandler<Params, Result, PeerMethods, RequestContext>> : Methods[Key] extends Record<string, unknown> ? MethodHandlers<Methods[Key], PeerMethods, RequestContext> : never;
|
|
8
11
|
};
|
|
9
12
|
type ISocketClientMethodCall<Methods> = {
|
|
10
13
|
[Key in keyof Methods]: Methods[Key] extends (params: infer P) => Promise<infer R> ? (params: P) => Promise<R> : Methods[Key] extends Record<string, unknown> ? ISocketClientMethodCall<Methods[Key]> : never;
|
|
@@ -14,4 +17,14 @@ export type ISocketClient<Methods> = {
|
|
|
14
17
|
call: ISocketClientMethodCall<Methods>;
|
|
15
18
|
};
|
|
16
19
|
export type MethodSchema<Params, Response> = (params: Params) => Promise<Response>;
|
|
20
|
+
/** The exception type can be thrown to cause the default error handler to write a raw error response to the socket */
|
|
21
|
+
export declare class SocketErrorException extends Error {
|
|
22
|
+
readonly code: number;
|
|
23
|
+
readonly message: string;
|
|
24
|
+
constructor(code: number, message: string);
|
|
25
|
+
}
|
|
26
|
+
export type SocketTimeouts = {
|
|
27
|
+
noResponseTimeoutInSeconds?: number;
|
|
28
|
+
connectionTimeoutInSeconds?: number;
|
|
29
|
+
};
|
|
17
30
|
export {};
|
package/dist/types/socket.js
CHANGED
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SocketErrorException = void 0;
|
|
4
|
+
/** The exception type can be thrown to cause the default error handler to write a raw error response to the socket */
|
|
5
|
+
class SocketErrorException extends Error {
|
|
6
|
+
constructor(code, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.message = message;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.SocketErrorException = SocketErrorException;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superblocksteam/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Superblocks JS SDK",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"typescript": "^5.1.3"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@superblocksteam/util": "1.
|
|
34
|
+
"@superblocksteam/util": "1.9.1",
|
|
35
35
|
"axios": "^1.3.5",
|
|
36
36
|
"ws": "^8.17.0"
|
|
37
37
|
},
|