@superblocksteam/sdk 1.4.1 → 1.5.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/.eslintrc.json +3 -0
- package/dist/client.d.ts +21 -14
- package/dist/client.js +198 -79
- package/dist/flag.d.ts +2 -0
- package/dist/flag.js +8 -0
- package/dist/sdk.d.ts +8 -7
- package/dist/sdk.js +16 -8
- package/dist/socket/handlers.d.ts +105 -0
- package/dist/socket/handlers.js +85 -0
- package/dist/socket/index.d.ts +27 -0
- package/dist/socket/index.js +69 -0
- package/dist/socket/signing.d.ts +13 -0
- package/dist/socket/signing.js +81 -0
- package/dist/socket/socket.d.ts +16 -0
- package/dist/socket/socket.js +157 -0
- package/dist/types/common.d.ts +111 -0
- package/dist/types/common.js +33 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.js +7 -0
- package/dist/types/plugin.d.ts +2 -0
- package/dist/types/plugin.js +9 -0
- package/dist/types/signing.d.ts +51 -0
- package/dist/types/signing.js +2 -0
- package/dist/types/socket.d.ts +17 -0
- package/dist/types/socket.js +2 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +36 -0
- package/package.json +5 -3
- package/src/client.ts +258 -83
- package/src/flag.ts +5 -0
- package/src/sdk.ts +48 -14
- package/src/socket/handlers.ts +228 -0
- package/src/socket/index.ts +164 -0
- package/src/socket/signing.ts +113 -0
- package/src/socket/socket.ts +253 -0
- package/src/types/common.ts +138 -0
- package/src/types/index.ts +4 -0
- package/src/types/plugin.ts +7 -0
- package/src/types/signing.ts +61 -0
- package/src/types/socket.ts +48 -0
- package/src/utils.ts +45 -0
- package/tsconfig.json +3 -1
package/src/sdk.ts
CHANGED
|
@@ -7,18 +7,18 @@ import {
|
|
|
7
7
|
fetchApi,
|
|
8
8
|
fetchApis,
|
|
9
9
|
fetchApplication,
|
|
10
|
-
|
|
10
|
+
fetchApplicationBranches,
|
|
11
11
|
fetchApplications,
|
|
12
|
-
|
|
13
|
-
uploadComponents,
|
|
12
|
+
fetchApplicationWithComponents,
|
|
14
13
|
fetchCurrentUser,
|
|
15
|
-
|
|
14
|
+
pushApi,
|
|
15
|
+
PushApiWithCommitConfig,
|
|
16
16
|
pushApplication,
|
|
17
17
|
PushApplicationWithCommitConfig,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
pushApi,
|
|
18
|
+
registerComponents,
|
|
19
|
+
uploadComponents,
|
|
21
20
|
validateGitSetup,
|
|
21
|
+
ViewMode,
|
|
22
22
|
} from "./client";
|
|
23
23
|
|
|
24
24
|
// Exporting here instead of index.ts because only sdk.ts is exposed outside in package.json
|
|
@@ -27,10 +27,16 @@ export * from "./errors";
|
|
|
27
27
|
export class SuperblocksSdk {
|
|
28
28
|
token = "";
|
|
29
29
|
superblocksBaseUrl = "";
|
|
30
|
+
cliVersion = "";
|
|
30
31
|
|
|
31
|
-
constructor(
|
|
32
|
+
constructor(
|
|
33
|
+
accessToken: string,
|
|
34
|
+
superblocksBaseUrl: string,
|
|
35
|
+
cliVersion: string
|
|
36
|
+
) {
|
|
32
37
|
this.token = accessToken;
|
|
33
38
|
this.superblocksBaseUrl = superblocksBaseUrl;
|
|
39
|
+
this.cliVersion = cliVersion;
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
async fetchApplication({
|
|
@@ -45,6 +51,7 @@ export class SuperblocksSdk {
|
|
|
45
51
|
viewMode?: ViewMode;
|
|
46
52
|
}) {
|
|
47
53
|
return fetchApplication({
|
|
54
|
+
cliVersion: this.cliVersion,
|
|
48
55
|
applicationId,
|
|
49
56
|
branch,
|
|
50
57
|
token: this.token,
|
|
@@ -56,6 +63,7 @@ export class SuperblocksSdk {
|
|
|
56
63
|
|
|
57
64
|
async fetchApplicationBranches(applicationId: string, headers = {}) {
|
|
58
65
|
return fetchApplicationBranches({
|
|
66
|
+
cliVersion: this.cliVersion,
|
|
59
67
|
applicationId,
|
|
60
68
|
token: this.token,
|
|
61
69
|
superblocksBaseUrl: this.superblocksBaseUrl,
|
|
@@ -75,6 +83,7 @@ export class SuperblocksSdk {
|
|
|
75
83
|
viewMode?: ViewMode;
|
|
76
84
|
}) {
|
|
77
85
|
return fetchApplicationWithComponents({
|
|
86
|
+
cliVersion: this.cliVersion,
|
|
78
87
|
applicationId,
|
|
79
88
|
branch,
|
|
80
89
|
token: this.token,
|
|
@@ -85,15 +94,31 @@ export class SuperblocksSdk {
|
|
|
85
94
|
}
|
|
86
95
|
|
|
87
96
|
async fetchApplications(headers?: Record<string, string>) {
|
|
88
|
-
return fetchApplications(
|
|
97
|
+
return fetchApplications(
|
|
98
|
+
this.cliVersion,
|
|
99
|
+
this.token,
|
|
100
|
+
this.superblocksBaseUrl,
|
|
101
|
+
headers
|
|
102
|
+
);
|
|
89
103
|
}
|
|
90
104
|
|
|
91
|
-
async fetchApi(
|
|
92
|
-
|
|
105
|
+
async fetchApi(
|
|
106
|
+
apiId: string,
|
|
107
|
+
viewMode: ViewMode = "export-live",
|
|
108
|
+
branch?: string
|
|
109
|
+
) {
|
|
110
|
+
return fetchApi(
|
|
111
|
+
this.cliVersion,
|
|
112
|
+
apiId,
|
|
113
|
+
this.token,
|
|
114
|
+
this.superblocksBaseUrl,
|
|
115
|
+
viewMode,
|
|
116
|
+
branch
|
|
117
|
+
);
|
|
93
118
|
}
|
|
94
119
|
|
|
95
120
|
async fetchApis() {
|
|
96
|
-
return fetchApis(this.token, this.superblocksBaseUrl);
|
|
121
|
+
return fetchApis(this.cliVersion, this.token, this.superblocksBaseUrl);
|
|
97
122
|
}
|
|
98
123
|
|
|
99
124
|
async validateGitSetup(
|
|
@@ -104,6 +129,7 @@ export class SuperblocksSdk {
|
|
|
104
129
|
injectedHeaders?: Record<string, string>
|
|
105
130
|
) {
|
|
106
131
|
return validateGitSetup(
|
|
132
|
+
this.cliVersion,
|
|
107
133
|
resourceId,
|
|
108
134
|
resourceType,
|
|
109
135
|
event,
|
|
@@ -118,9 +144,10 @@ export class SuperblocksSdk {
|
|
|
118
144
|
applicationId: string,
|
|
119
145
|
componentConfigs: Record<string, any>,
|
|
120
146
|
branch: string | null,
|
|
121
|
-
injectedHeaders
|
|
147
|
+
injectedHeaders: Record<string, string>
|
|
122
148
|
) {
|
|
123
149
|
return registerComponents(
|
|
150
|
+
this.cliVersion,
|
|
124
151
|
applicationId,
|
|
125
152
|
componentConfigs,
|
|
126
153
|
this.token,
|
|
@@ -137,6 +164,7 @@ export class SuperblocksSdk {
|
|
|
137
164
|
branch: string | null
|
|
138
165
|
) {
|
|
139
166
|
return uploadComponents({
|
|
167
|
+
cliVersion: this.cliVersion,
|
|
140
168
|
applicationId,
|
|
141
169
|
componentConfigs,
|
|
142
170
|
files,
|
|
@@ -147,7 +175,11 @@ export class SuperblocksSdk {
|
|
|
147
175
|
}
|
|
148
176
|
|
|
149
177
|
async fetchCurrentUser() {
|
|
150
|
-
return fetchCurrentUser(
|
|
178
|
+
return fetchCurrentUser(
|
|
179
|
+
this.cliVersion,
|
|
180
|
+
this.token,
|
|
181
|
+
this.superblocksBaseUrl
|
|
182
|
+
);
|
|
151
183
|
}
|
|
152
184
|
|
|
153
185
|
async pushApplication({
|
|
@@ -162,6 +194,7 @@ export class SuperblocksSdk {
|
|
|
162
194
|
headers?: Record<string, string>;
|
|
163
195
|
}) {
|
|
164
196
|
return pushApplication({
|
|
197
|
+
cliVersion: this.cliVersion,
|
|
165
198
|
applicationId,
|
|
166
199
|
token: this.token,
|
|
167
200
|
superblocksBaseUrl: this.superblocksBaseUrl,
|
|
@@ -182,6 +215,7 @@ export class SuperblocksSdk {
|
|
|
182
215
|
headers?: Record<string, string>;
|
|
183
216
|
}) {
|
|
184
217
|
return pushApi({
|
|
218
|
+
cliVersion: this.cliVersion,
|
|
185
219
|
apiId,
|
|
186
220
|
apiConfig,
|
|
187
221
|
token: this.token,
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApiToSign,
|
|
3
|
+
ApiToVerify,
|
|
4
|
+
AppToSign,
|
|
5
|
+
AppToVerify,
|
|
6
|
+
MethodHandlers,
|
|
7
|
+
RemoteCommitDto,
|
|
8
|
+
Signature,
|
|
9
|
+
} from "../types";
|
|
10
|
+
import { signResource, verifyResources } from "./signing";
|
|
11
|
+
|
|
12
|
+
type MethodSchema<Params, Response> = (params: Params) => Promise<Response>;
|
|
13
|
+
|
|
14
|
+
export interface ClientMethods {
|
|
15
|
+
v1: {
|
|
16
|
+
signing: {
|
|
17
|
+
signApplication: MethodSchema<
|
|
18
|
+
{ branchName: string; toSign: AppToSign },
|
|
19
|
+
{ signature: Signature }
|
|
20
|
+
>;
|
|
21
|
+
signApis: MethodSchema<
|
|
22
|
+
{ branchName: string; toSign: ApiToSign[] },
|
|
23
|
+
{ signatures: Signature[] }
|
|
24
|
+
>;
|
|
25
|
+
verifyApplication: MethodSchema<
|
|
26
|
+
{ branchName: string; toVerify: AppToVerify },
|
|
27
|
+
{ ok: boolean }
|
|
28
|
+
>;
|
|
29
|
+
verifyApi: MethodSchema<
|
|
30
|
+
{ branchName: string; toVerify: ApiToVerify[] },
|
|
31
|
+
{ ok: boolean }
|
|
32
|
+
>;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type ServerMethodSchema<Params, Response> = MethodSchema<
|
|
38
|
+
Params,
|
|
39
|
+
ResponseDto<Response>
|
|
40
|
+
>;
|
|
41
|
+
|
|
42
|
+
// This file contains the definition of the protocol used for communication between the SB server and clients
|
|
43
|
+
|
|
44
|
+
type ResponseDto<T> = {
|
|
45
|
+
responseMeta: ResponseMeta;
|
|
46
|
+
data: T;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type ResponseMeta = {
|
|
50
|
+
status: number;
|
|
51
|
+
success: boolean;
|
|
52
|
+
error?: APIResponseError;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
type APIResponseError = {
|
|
56
|
+
code: number;
|
|
57
|
+
message: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export interface ServerMethods {
|
|
61
|
+
v1: {
|
|
62
|
+
echo: MethodSchema<{ message: string }, { message: string }>;
|
|
63
|
+
public: {
|
|
64
|
+
application: {
|
|
65
|
+
component: {
|
|
66
|
+
register: ServerMethodSchema<
|
|
67
|
+
{
|
|
68
|
+
applicationId: string;
|
|
69
|
+
branchName: string;
|
|
70
|
+
cliVersion: string;
|
|
71
|
+
componentEvent: string;
|
|
72
|
+
components: Record<string, unknown>;
|
|
73
|
+
},
|
|
74
|
+
{ success: boolean }
|
|
75
|
+
>;
|
|
76
|
+
update: ServerMethodSchema<
|
|
77
|
+
{
|
|
78
|
+
applicationId: string;
|
|
79
|
+
branchName?: string;
|
|
80
|
+
srcFiles: string[];
|
|
81
|
+
buildFiles: string[];
|
|
82
|
+
registeredComponents: Record<string, unknown>;
|
|
83
|
+
cliVersion: string | undefined;
|
|
84
|
+
componentBaseUrl: string;
|
|
85
|
+
signingRequired: boolean;
|
|
86
|
+
},
|
|
87
|
+
{ success: boolean }
|
|
88
|
+
>;
|
|
89
|
+
};
|
|
90
|
+
pushCommit: ServerMethodSchema<
|
|
91
|
+
{
|
|
92
|
+
applicationId: string;
|
|
93
|
+
branchName: string;
|
|
94
|
+
commitId: string;
|
|
95
|
+
commitMessage: string;
|
|
96
|
+
application: Record<string, unknown>;
|
|
97
|
+
page: Record<string, unknown>;
|
|
98
|
+
apis: Record<string, unknown>[];
|
|
99
|
+
},
|
|
100
|
+
RemoteCommitDto
|
|
101
|
+
>;
|
|
102
|
+
};
|
|
103
|
+
api: {
|
|
104
|
+
pushCommit: ServerMethodSchema<
|
|
105
|
+
{
|
|
106
|
+
apiId: string;
|
|
107
|
+
branchName: string;
|
|
108
|
+
commitId: string;
|
|
109
|
+
commitMessage: string;
|
|
110
|
+
apiPb: Record<string, unknown>;
|
|
111
|
+
},
|
|
112
|
+
RemoteCommitDto
|
|
113
|
+
>;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function createRequestHandlers({
|
|
120
|
+
agentUrls,
|
|
121
|
+
token,
|
|
122
|
+
}: {
|
|
123
|
+
token: string;
|
|
124
|
+
agentUrls: string[];
|
|
125
|
+
}) {
|
|
126
|
+
const requestHandlers: MethodHandlers<ClientMethods, ServerMethods, unknown> =
|
|
127
|
+
{
|
|
128
|
+
v1: {
|
|
129
|
+
signing: {
|
|
130
|
+
signApplication: [
|
|
131
|
+
async ({
|
|
132
|
+
branchName,
|
|
133
|
+
toSign,
|
|
134
|
+
}: {
|
|
135
|
+
branchName: string;
|
|
136
|
+
toSign: AppToSign;
|
|
137
|
+
}) => {
|
|
138
|
+
const signature = await signResource({
|
|
139
|
+
agentUrls,
|
|
140
|
+
token: token,
|
|
141
|
+
branchName,
|
|
142
|
+
resource: {
|
|
143
|
+
literal: {
|
|
144
|
+
data: toSign.rootHash,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
return { signature: signature };
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
signApis: [
|
|
152
|
+
async ({
|
|
153
|
+
branchName,
|
|
154
|
+
toSign,
|
|
155
|
+
}: {
|
|
156
|
+
branchName: string;
|
|
157
|
+
toSign: ApiToSign[];
|
|
158
|
+
}) => {
|
|
159
|
+
const signatures: Signature[] = [];
|
|
160
|
+
for (const { apiPb } of toSign) {
|
|
161
|
+
const signature = await signResource({
|
|
162
|
+
agentUrls,
|
|
163
|
+
token: token,
|
|
164
|
+
branchName,
|
|
165
|
+
resource: { api: apiPb },
|
|
166
|
+
});
|
|
167
|
+
signatures.push(signature);
|
|
168
|
+
}
|
|
169
|
+
return { signatures };
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
verifyApplication: [
|
|
173
|
+
async ({
|
|
174
|
+
branchName,
|
|
175
|
+
toVerify,
|
|
176
|
+
}: {
|
|
177
|
+
branchName: string;
|
|
178
|
+
toVerify: AppToVerify;
|
|
179
|
+
}) => {
|
|
180
|
+
try {
|
|
181
|
+
await verifyResources({
|
|
182
|
+
agentUrls,
|
|
183
|
+
token,
|
|
184
|
+
branchName,
|
|
185
|
+
resources: [
|
|
186
|
+
{
|
|
187
|
+
literal: {
|
|
188
|
+
data: toVerify.rootHash,
|
|
189
|
+
signature: toVerify.signature,
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
});
|
|
194
|
+
return { ok: true };
|
|
195
|
+
} catch {
|
|
196
|
+
return { ok: false };
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
|
|
201
|
+
verifyApi: [
|
|
202
|
+
async ({
|
|
203
|
+
branchName,
|
|
204
|
+
toVerify,
|
|
205
|
+
}: {
|
|
206
|
+
branchName: string;
|
|
207
|
+
toVerify: ApiToVerify[];
|
|
208
|
+
}) => {
|
|
209
|
+
try {
|
|
210
|
+
await verifyResources({
|
|
211
|
+
agentUrls,
|
|
212
|
+
token,
|
|
213
|
+
branchName,
|
|
214
|
+
resources: toVerify.map(({ apiPb }) => ({
|
|
215
|
+
api: apiPb,
|
|
216
|
+
})),
|
|
217
|
+
});
|
|
218
|
+
return { ok: true };
|
|
219
|
+
} catch {
|
|
220
|
+
return { ok: false };
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
return requestHandlers;
|
|
228
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import WebSocket from "isomorphic-ws";
|
|
2
|
+
import {
|
|
3
|
+
ClientMethods,
|
|
4
|
+
createRequestHandlers,
|
|
5
|
+
ServerMethods,
|
|
6
|
+
} from "./handlers";
|
|
7
|
+
import { createISocketClient, ISocket } from "./socket";
|
|
8
|
+
|
|
9
|
+
export type StdISocketRPCClient = ISocketClient<ServerMethods>;
|
|
10
|
+
|
|
11
|
+
export async function connectToISocketRPCServer({
|
|
12
|
+
superblocksBaseUrl,
|
|
13
|
+
agentUrls,
|
|
14
|
+
token,
|
|
15
|
+
}: {
|
|
16
|
+
superblocksBaseUrl: string;
|
|
17
|
+
agentUrls: string[];
|
|
18
|
+
token: string;
|
|
19
|
+
}): Promise<StdISocketRPCClient> {
|
|
20
|
+
const requestHandlers = createRequestHandlers({
|
|
21
|
+
agentUrls,
|
|
22
|
+
token,
|
|
23
|
+
});
|
|
24
|
+
const authorization = `Bearer ${token}`;
|
|
25
|
+
const wsUrl = new URL("api/v1/rpc-ws", superblocksBaseUrl);
|
|
26
|
+
if (wsUrl.protocol === "http:") {
|
|
27
|
+
wsUrl.protocol = "ws:";
|
|
28
|
+
} else if (wsUrl.protocol === "https:") {
|
|
29
|
+
wsUrl.protocol = "wss:";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (wsUrl.host === "localhost:3000") {
|
|
33
|
+
wsUrl.host = "127.0.0.1:8080";
|
|
34
|
+
} else if (wsUrl.hostname === "localhost") {
|
|
35
|
+
wsUrl.hostname = "127.0.0.1";
|
|
36
|
+
}
|
|
37
|
+
return await connectISocket<ServerMethods, ClientMethods, unknown>(
|
|
38
|
+
wsUrl.href,
|
|
39
|
+
authorization,
|
|
40
|
+
requestHandlers
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// a subclass of ISocket that sends an auth token on the first request
|
|
45
|
+
// this is useful for client-side sockets that need to authenticate
|
|
46
|
+
// TODO(george): if we start using this for long-lived connections, we should add a way to refresh the token
|
|
47
|
+
class ISocketWithClientAuth<
|
|
48
|
+
ImplementedMethods,
|
|
49
|
+
CallableMethods,
|
|
50
|
+
RequestContext = void
|
|
51
|
+
> extends ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
52
|
+
private readonly authorization?: string;
|
|
53
|
+
private hasSentAuth = false;
|
|
54
|
+
|
|
55
|
+
constructor(
|
|
56
|
+
ws: WebSocket,
|
|
57
|
+
authorization: string | undefined,
|
|
58
|
+
requestHandlers: MethodHandlers<
|
|
59
|
+
ImplementedMethods,
|
|
60
|
+
CallableMethods,
|
|
61
|
+
RequestContext
|
|
62
|
+
>
|
|
63
|
+
) {
|
|
64
|
+
super(ws, requestHandlers);
|
|
65
|
+
this.authorization = authorization;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// override `request` from the base class to send `authorization` when appropriate
|
|
69
|
+
async request<Params, Result>(
|
|
70
|
+
method: string,
|
|
71
|
+
params: Params
|
|
72
|
+
): Promise<Result> {
|
|
73
|
+
// only send `authorization` on the first request
|
|
74
|
+
const authorization = this.hasSentAuth ? undefined : this.authorization;
|
|
75
|
+
const result = await super.request<Params, Result>(
|
|
76
|
+
method,
|
|
77
|
+
params,
|
|
78
|
+
authorization
|
|
79
|
+
);
|
|
80
|
+
this.hasSentAuth = true;
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function connectISocket<
|
|
86
|
+
CallableMethods,
|
|
87
|
+
ImplementedMethods,
|
|
88
|
+
RequestContext = never
|
|
89
|
+
>(
|
|
90
|
+
wsUrl: string,
|
|
91
|
+
authorization: string | undefined,
|
|
92
|
+
requestHandlers: MethodHandlers<
|
|
93
|
+
ImplementedMethods,
|
|
94
|
+
CallableMethods,
|
|
95
|
+
RequestContext
|
|
96
|
+
>
|
|
97
|
+
): Promise<ISocketClient<CallableMethods>> {
|
|
98
|
+
const ws = await connectWebSocket(wsUrl);
|
|
99
|
+
const isocket = new ISocketWithClientAuth(ws, authorization, requestHandlers);
|
|
100
|
+
return createISocketClient(isocket);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function connectWebSocket(wsUrl: string): Promise<WebSocket> {
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const ws = new WebSocket(wsUrl);
|
|
106
|
+
|
|
107
|
+
ws.addEventListener("open", () => {
|
|
108
|
+
// Resolve the promise with the WebSocket instance when the connection is open
|
|
109
|
+
resolve(ws);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
ws.addEventListener("error", (error: Error) => {
|
|
115
|
+
// Reject the promise if there's an error
|
|
116
|
+
reject(error);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
type MethodHandler<Params, Result, PeerMethods, RequestContext> = (
|
|
122
|
+
params: Params,
|
|
123
|
+
peer: ISocketClient<PeerMethods>,
|
|
124
|
+
ctx: RequestContext
|
|
125
|
+
) => Promise<Result>;
|
|
126
|
+
|
|
127
|
+
type MiddlewareHandler<Params, PeerMethods, RequestContext> = (
|
|
128
|
+
params: Params,
|
|
129
|
+
peerAuthorization: string | undefined,
|
|
130
|
+
peer: ISocketClient<PeerMethods>,
|
|
131
|
+
ctx: RequestContext
|
|
132
|
+
) => Promise<void>;
|
|
133
|
+
|
|
134
|
+
type MethodHandlers<Methods, PeerMethods, RequestContext> = {
|
|
135
|
+
[Key in keyof Methods]: Methods[Key] extends (
|
|
136
|
+
params: infer Params
|
|
137
|
+
) => Promise<infer Result>
|
|
138
|
+
? [
|
|
139
|
+
...middlewareHandlers: MiddlewareHandler<
|
|
140
|
+
Params,
|
|
141
|
+
PeerMethods,
|
|
142
|
+
RequestContext
|
|
143
|
+
>[],
|
|
144
|
+
handler: MethodHandler<Params, Result, PeerMethods, RequestContext>
|
|
145
|
+
]
|
|
146
|
+
: Methods[Key] extends Record<string, unknown>
|
|
147
|
+
? MethodHandlers<Methods[Key], PeerMethods, RequestContext>
|
|
148
|
+
: never;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
type ISocketClientMethodCall<Methods> = {
|
|
152
|
+
[Key in keyof Methods]: Methods[Key] extends (
|
|
153
|
+
params: infer P
|
|
154
|
+
) => Promise<infer R>
|
|
155
|
+
? (params: P) => Promise<R>
|
|
156
|
+
: Methods[Key] extends Record<string, unknown>
|
|
157
|
+
? ISocketClientMethodCall<Methods[Key]>
|
|
158
|
+
: never;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
type ISocketClient<Methods> = {
|
|
162
|
+
close: () => void;
|
|
163
|
+
call: ISocketClientMethodCall<Methods>;
|
|
164
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import axios, { AxiosRequestConfig, Method } from "axios";
|
|
2
|
+
import {
|
|
3
|
+
ApiResource,
|
|
4
|
+
GenericResource,
|
|
5
|
+
Signature,
|
|
6
|
+
SignatureResponse,
|
|
7
|
+
} from "../types";
|
|
8
|
+
import { getSanitizedApi } from "../utils";
|
|
9
|
+
|
|
10
|
+
export async function signResource({
|
|
11
|
+
token,
|
|
12
|
+
branchName,
|
|
13
|
+
resource,
|
|
14
|
+
agentUrls,
|
|
15
|
+
}: {
|
|
16
|
+
token: string;
|
|
17
|
+
branchName: string;
|
|
18
|
+
resource: ApiResource | GenericResource;
|
|
19
|
+
agentUrls: string[];
|
|
20
|
+
}): Promise<Signature> {
|
|
21
|
+
const requestResource: Record<string, any> = {
|
|
22
|
+
branchName: branchName ?? "main",
|
|
23
|
+
};
|
|
24
|
+
if ((resource as ApiResource).api) {
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
26
|
+
requestResource.api = getSanitizedApi((resource as ApiResource).api);
|
|
27
|
+
} else {
|
|
28
|
+
requestResource.literal = (resource as GenericResource).literal;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const resp = await callAgentFallBack<SignatureResponse>({
|
|
33
|
+
baseUrls: agentUrls,
|
|
34
|
+
path: "v1/signature/sign",
|
|
35
|
+
method: "post",
|
|
36
|
+
token: token,
|
|
37
|
+
data: { resource: requestResource },
|
|
38
|
+
});
|
|
39
|
+
return resp.signature;
|
|
40
|
+
} catch (e) {
|
|
41
|
+
throw new Error("No agents available to sign the resource");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function verifyResources({
|
|
46
|
+
agentUrls,
|
|
47
|
+
token,
|
|
48
|
+
branchName,
|
|
49
|
+
resources,
|
|
50
|
+
}: {
|
|
51
|
+
resources: Array<GenericResource | ApiResource>;
|
|
52
|
+
token: string;
|
|
53
|
+
branchName: string;
|
|
54
|
+
agentUrls: string[];
|
|
55
|
+
}): Promise<void> {
|
|
56
|
+
try {
|
|
57
|
+
await callAgentFallBack<{ keyId: string }>({
|
|
58
|
+
baseUrls: agentUrls,
|
|
59
|
+
path: "v1/signature/verify",
|
|
60
|
+
method: "post",
|
|
61
|
+
token: token,
|
|
62
|
+
data: {
|
|
63
|
+
resources: resources.map((res) => {
|
|
64
|
+
if ((res as ApiResource).api) {
|
|
65
|
+
return {
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
67
|
+
api: getSanitizedApi((res as ApiResource).api),
|
|
68
|
+
branchName: branchName ?? "main",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
...res,
|
|
73
|
+
branchName: branchName ?? "main",
|
|
74
|
+
};
|
|
75
|
+
}),
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
} catch (e) {
|
|
79
|
+
throw new Error("No agents available to verify the resource");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function callAgentFallBack<T>({
|
|
84
|
+
baseUrls,
|
|
85
|
+
path,
|
|
86
|
+
method,
|
|
87
|
+
token,
|
|
88
|
+
data,
|
|
89
|
+
}: {
|
|
90
|
+
baseUrls: string[];
|
|
91
|
+
path: string;
|
|
92
|
+
method: Method;
|
|
93
|
+
token: string;
|
|
94
|
+
data: any;
|
|
95
|
+
}): Promise<T> {
|
|
96
|
+
for (const baseUrl of baseUrls) {
|
|
97
|
+
try {
|
|
98
|
+
const url = new URL(path, baseUrl);
|
|
99
|
+
const config: AxiosRequestConfig = {
|
|
100
|
+
url: url.toString(),
|
|
101
|
+
method: method,
|
|
102
|
+
headers: {
|
|
103
|
+
Authorization: "Bearer " + token,
|
|
104
|
+
},
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
106
|
+
data: data,
|
|
107
|
+
};
|
|
108
|
+
const resp = await axios<T>(config);
|
|
109
|
+
return resp.data;
|
|
110
|
+
} catch (e) {}
|
|
111
|
+
}
|
|
112
|
+
throw new Error("Failed to request ");
|
|
113
|
+
}
|