@superblocksteam/sdk 1.9.3 → 1.11.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/src/sdk.ts CHANGED
@@ -21,7 +21,8 @@ import {
21
21
  uploadComponents,
22
22
  validateGitSetup,
23
23
  } from "./client";
24
- import { ViewMode } from "./types";
24
+ import { FeatureFlags } from "./flag";
25
+ import { UserMeDto, ViewMode } from "./types";
25
26
 
26
27
  // Exporting here instead of index.ts because only sdk.ts is exposed outside in package.json
27
28
  export * from "./errors";
@@ -34,13 +35,22 @@ export class SuperblocksSdk {
34
35
  constructor(
35
36
  accessToken: string,
36
37
  superblocksBaseUrl: string,
37
- cliVersion: string
38
+ cliVersion: string,
38
39
  ) {
39
40
  this.token = accessToken;
40
41
  this.superblocksBaseUrl = superblocksBaseUrl;
41
42
  this.cliVersion = cliVersion;
42
43
  }
43
44
 
45
+ async getFeatureFlagsForCurrentUser(): Promise<FeatureFlags> {
46
+ const user = await this.fetchCurrentUser();
47
+ return new FeatureFlags(user.flagBootstrap);
48
+ }
49
+
50
+ getFeatureFlagsForUser(user: UserMeDto): FeatureFlags {
51
+ return new FeatureFlags(user.flagBootstrap);
52
+ }
53
+
44
54
  async fetchApplication({
45
55
  applicationId,
46
56
  branch,
@@ -159,7 +169,7 @@ export class SuperblocksSdk {
159
169
  this.cliVersion,
160
170
  this.token,
161
171
  this.superblocksBaseUrl,
162
- headers
172
+ headers,
163
173
  );
164
174
  }
165
175
 
@@ -184,7 +194,7 @@ export class SuperblocksSdk {
184
194
  viewMode,
185
195
  branch,
186
196
  commitId,
187
- skipSigningVerification
197
+ skipSigningVerification,
188
198
  );
189
199
  }
190
200
 
@@ -197,7 +207,7 @@ export class SuperblocksSdk {
197
207
  resourceType: SuperblocksResourceType,
198
208
  event: ComponentEvent,
199
209
  localGitRepoState: LocalGitRepoState,
200
- injectedHeaders?: Record<string, string>
210
+ injectedHeaders?: Record<string, string>,
201
211
  ) {
202
212
  return validateGitSetup(
203
213
  this.cliVersion,
@@ -207,7 +217,7 @@ export class SuperblocksSdk {
207
217
  localGitRepoState,
208
218
  this.token,
209
219
  this.superblocksBaseUrl,
210
- injectedHeaders
220
+ injectedHeaders,
211
221
  );
212
222
  }
213
223
 
@@ -215,7 +225,7 @@ export class SuperblocksSdk {
215
225
  applicationId: string,
216
226
  componentConfigs: Record<string, any>,
217
227
  branch: string | null,
218
- injectedHeaders: Record<string, string>
228
+ injectedHeaders: Record<string, string>,
219
229
  ) {
220
230
  return registerComponents(
221
231
  this.cliVersion,
@@ -224,7 +234,7 @@ export class SuperblocksSdk {
224
234
  this.token,
225
235
  this.superblocksBaseUrl,
226
236
  branch,
227
- injectedHeaders
237
+ injectedHeaders,
228
238
  );
229
239
  }
230
240
 
@@ -232,7 +242,7 @@ export class SuperblocksSdk {
232
242
  applicationId: string,
233
243
  componentConfigs: Record<string, any>,
234
244
  files: string[],
235
- branch: string | null
245
+ branch: string | null,
236
246
  ) {
237
247
  return uploadComponents({
238
248
  cliVersion: this.cliVersion,
@@ -249,7 +259,7 @@ export class SuperblocksSdk {
249
259
  return fetchCurrentUser(
250
260
  this.cliVersion,
251
261
  this.token,
252
- this.superblocksBaseUrl
262
+ this.superblocksBaseUrl,
253
263
  );
254
264
  }
255
265
 
@@ -181,7 +181,7 @@ export function createRequestHandlers({
181
181
  }) => {
182
182
  if (!agentUrl) {
183
183
  throw new Error(
184
- "Agent url not specified. This shouldn't happen."
184
+ "Agent url not specified. This shouldn't happen.",
185
185
  );
186
186
  }
187
187
  const signature = await signResource({
@@ -209,7 +209,7 @@ export function createRequestHandlers({
209
209
  for (const { apiPb } of toSign) {
210
210
  if (!agentUrl) {
211
211
  throw new Error(
212
- "Agent url not specified. This shouldn't happen."
212
+ "Agent url not specified. This shouldn't happen.",
213
213
  );
214
214
  }
215
215
  const signature = await signResource({
@@ -234,7 +234,7 @@ export function createRequestHandlers({
234
234
  try {
235
235
  if (!agentUrl) {
236
236
  throw new Error(
237
- "Agent url not specified. This shouldn't happen."
237
+ "Agent url not specified. This shouldn't happen.",
238
238
  );
239
239
  }
240
240
  await verifyResources({
@@ -268,7 +268,7 @@ export function createRequestHandlers({
268
268
  try {
269
269
  if (!agentUrl) {
270
270
  throw new Error(
271
- "Agent url not specified. This shouldn't happen."
271
+ "Agent url not specified. This shouldn't happen.",
272
272
  );
273
273
  }
274
274
  await verifyResources({
@@ -50,7 +50,7 @@ export async function connectToISocketRPCServer({
50
50
  {
51
51
  connectionTimeoutInSeconds: 6 * 60, // 6 minutes
52
52
  noResponseTimeoutInSeconds: 5 * 60, // 5 minutes
53
- }
53
+ },
54
54
  );
55
55
  }
56
56
 
@@ -60,7 +60,7 @@ export async function connectToISocketRPCServer({
60
60
  export class ISocketWithClientAuth<
61
61
  ImplementedMethods,
62
62
  CallableMethods,
63
- RequestContext extends RequestContextBase
63
+ RequestContext extends RequestContextBase,
64
64
  > extends ISocket<ImplementedMethods, CallableMethods, RequestContext> {
65
65
  private readonly authorization?: string;
66
66
  private hasSentAuth = false;
@@ -74,7 +74,7 @@ export class ISocketWithClientAuth<
74
74
  RequestContext
75
75
  >,
76
76
  globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[],
77
- timeouts?: SocketTimeouts
77
+ timeouts?: SocketTimeouts,
78
78
  ) {
79
79
  super(ws, requestHandlers, globalMiddlewares, timeouts);
80
80
  this.authorization = authorization;
@@ -83,14 +83,14 @@ export class ISocketWithClientAuth<
83
83
  // override `request` from the base class to send `authorization` when appropriate
84
84
  async request<Params, Result>(
85
85
  method: string,
86
- params: Params
86
+ params: Params,
87
87
  ): Promise<Result> {
88
88
  // only send `authorization` on the first request
89
89
  const authorization = this.hasSentAuth ? undefined : this.authorization;
90
90
  const result = await super.request<Params, Result>(
91
91
  method,
92
92
  params,
93
- authorization
93
+ authorization,
94
94
  );
95
95
  this.hasSentAuth = true;
96
96
  return result;
@@ -100,7 +100,7 @@ export class ISocketWithClientAuth<
100
100
  export async function connectISocket<
101
101
  CallableMethods,
102
102
  ImplementedMethods,
103
- RequestContext extends RequestContextBase = RequestContextBase
103
+ RequestContext extends RequestContextBase = RequestContextBase,
104
104
  >(
105
105
  wsUrl: string,
106
106
  authorization: string | undefined,
@@ -110,7 +110,7 @@ export async function connectISocket<
110
110
  RequestContext
111
111
  >,
112
112
  globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[],
113
- timeouts?: SocketTimeouts
113
+ timeouts?: SocketTimeouts,
114
114
  ): Promise<ISocketClient<CallableMethods>> {
115
115
  const ws = await connectWebSocket(wsUrl);
116
116
  const isocket = new ISocketWithClientAuth(
@@ -118,7 +118,7 @@ export async function connectISocket<
118
118
  authorization,
119
119
  requestHandlers,
120
120
  globalMiddlewares,
121
- timeouts
121
+ timeouts,
122
122
  );
123
123
  return createISocketClient(isocket);
124
124
  }
@@ -25,7 +25,7 @@ interface SocketResponse<Payload = unknown> {
25
25
 
26
26
  export interface SocketMessage<
27
27
  RequestPayload = unknown,
28
- ResponsePayload = unknown
28
+ ResponsePayload = unknown,
29
29
  > {
30
30
  request?: SocketRequest<RequestPayload>;
31
31
  response?: SocketResponse<ResponsePayload>;
@@ -52,7 +52,7 @@ export interface SocketError {
52
52
  export class ISocket<
53
53
  ImplementedMethods,
54
54
  CallableMethods,
55
- RequestContext extends RequestContextBase
55
+ RequestContext extends RequestContextBase,
56
56
  > {
57
57
  private readonly ws: WebSocket;
58
58
  private readonly requestHandlers: MethodHandlers<
@@ -88,7 +88,7 @@ export class ISocket<
88
88
  >,
89
89
  globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[],
90
90
  timeouts?: SocketTimeouts,
91
- logger?: { error: (message?: string) => void }
91
+ logger?: { error: (message?: string) => void },
92
92
  ) {
93
93
  this.ws = ws;
94
94
  this.requestHandlers = requestHandlers;
@@ -103,9 +103,10 @@ export class ISocket<
103
103
  "message",
104
104
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
105
105
  async (event: WebSocket.MessageEvent) => {
106
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
106
107
  const eventData: SocketMessage = JSON.parse(event.data.toString());
107
108
  return this.handleMessage(eventData);
108
- }
109
+ },
109
110
  );
110
111
  }
111
112
 
@@ -153,7 +154,7 @@ export class ISocket<
153
154
  if (alreadyResponded) {
154
155
  throw new SocketErrorException(
155
156
  4,
156
- "next() was called after the response was sent"
157
+ "next() was called after the response was sent",
157
158
  );
158
159
  }
159
160
  const handler = (
@@ -164,13 +165,13 @@ export class ISocket<
164
165
  if (!handler) {
165
166
  throw new SocketErrorException(
166
167
  5,
167
- "cannot call past the last handler in the chain"
168
+ "cannot call past the last handler in the chain",
168
169
  );
169
170
  }
170
171
  if (wasCalled) {
171
172
  throw new SocketErrorException(
172
173
  6,
173
- "next() was called multiple times"
174
+ "next() was called multiple times",
174
175
  );
175
176
  }
176
177
  wasCalled = true;
@@ -179,7 +180,7 @@ export class ISocket<
179
180
  payload,
180
181
  reqCtx,
181
182
  client,
182
- generateNextFn(idx + 1)
183
+ generateNextFn(idx + 1),
183
184
  );
184
185
  };
185
186
  };
@@ -220,13 +221,13 @@ export class ISocket<
220
221
  Params,
221
222
  Result,
222
223
  CallableMethods,
223
- RequestContext extends RequestContextBase
224
+ RequestContext extends RequestContextBase,
224
225
  >(
225
226
  handler: MethodHandler<Params, Result, CallableMethods, RequestContext>,
226
227
  params: Params,
227
228
  ctx: RequestContext,
228
229
  client: ISocketClient<CallableMethods>,
229
- next: () => Promise<Result>
230
+ next: () => Promise<Result>,
230
231
  ): Promise<Result> {
231
232
  return handler(params, ctx, client, next);
232
233
  }
@@ -234,12 +235,13 @@ export class ISocket<
234
235
  public request<Params, Result>(
235
236
  method: string,
236
237
  params: Params,
237
- authorization?: string
238
+ authorization?: string,
238
239
  ): Promise<Result> {
239
240
  return new Promise<Result>((resolve, reject) => {
240
241
  const requestId = ++this.nxtRequestId;
241
242
  this.responseHandler.set(requestId, {
242
243
  resolve: (result) => resolve(result as Result),
244
+ // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
243
245
  reject: (error: SocketError) => reject(error),
244
246
  });
245
247
  const toSend: SocketMessage = {
@@ -287,14 +289,14 @@ export class ISocket<
287
289
  // Set a new timeout for the next message
288
290
  this.connectionTimeout = setTimeout(
289
291
  this.handleConnectionTimeout(),
290
- this.timeouts?.connectionTimeoutInSeconds * 1000
292
+ this.timeouts?.connectionTimeoutInSeconds * 1000,
291
293
  );
292
294
  }
293
295
 
294
296
  private handleConnectionTimeout() {
295
297
  return () => {
296
298
  this.logger.error(
297
- `Connection timed out after ${this.timeouts?.connectionTimeoutInSeconds} seconds`
299
+ `Connection timed out after ${this.timeouts?.connectionTimeoutInSeconds} seconds`,
298
300
  );
299
301
  this.close();
300
302
  };
@@ -316,7 +318,7 @@ export class ISocket<
316
318
  // Set a new timeout for the next message
317
319
  responseHandler.timeout = setTimeout(
318
320
  this.handleNoResponseTimeout(reject),
319
- this.timeouts?.noResponseTimeoutInSeconds * 1000
321
+ this.timeouts?.noResponseTimeoutInSeconds * 1000,
320
322
  );
321
323
  }
322
324
 
@@ -333,7 +335,7 @@ export class ISocket<
333
335
  this.responseHandler.forEach((handler, key) => {
334
336
  clearTimeout(handler.timeout);
335
337
  this.logger.error(
336
- `Rejecting pending requestId ${key} due to connection close`
338
+ `Rejecting pending requestId ${key} due to connection close`,
337
339
  );
338
340
  handler.reject({ code: 8, message: "Connection closed" });
339
341
  });
@@ -348,11 +350,11 @@ const proxyTarget = Object.freeze(() => {
348
350
  function createIsocketProxy<
349
351
  ImplementedMethods,
350
352
  CallableMethods,
351
- RequestContext extends RequestContextBase
353
+ RequestContext extends RequestContextBase,
352
354
  >(
353
355
  socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>,
354
356
  // if path is undefined, it means the current object is the root object
355
- path: string | undefined
357
+ path: string | undefined,
356
358
  ): unknown {
357
359
  return new Proxy(proxyTarget, {
358
360
  get(_target, prop: string) {
@@ -386,9 +388,9 @@ function createIsocketProxy<
386
388
  export function createISocketClient<
387
389
  CallableMethods,
388
390
  ImplementedMethods,
389
- RequestContext extends RequestContextBase
391
+ RequestContext extends RequestContextBase,
390
392
  >(
391
- socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>
393
+ socket: ISocket<ImplementedMethods, CallableMethods, RequestContext>,
392
394
  ): ISocketClient<CallableMethods> {
393
395
  return {
394
396
  close: () => socket.close(),
@@ -7,6 +7,9 @@ export interface UserMeDto {
7
7
 
8
8
  export interface FlagBootstrap {
9
9
  "ui.enable-resource-signing"?: boolean;
10
+ "superblocks.git.split.large.steps.enabled"?: boolean;
11
+ "superblocks.git.split.large.steps.new.enabled"?: boolean;
12
+ "superblocks.git.split.large.step.lines"?: number;
10
13
  }
11
14
 
12
15
  export type User = {
@@ -116,7 +119,7 @@ export type Api = {
116
119
  };
117
120
  folder?: string;
118
121
  };
119
- blocks?: any[];
122
+ blocks?: Block[];
120
123
  trigger: any;
121
124
  signature?: Signature;
122
125
  };
@@ -127,6 +130,95 @@ export type ApiWithPb = {
127
130
  apiPb: Api;
128
131
  };
129
132
 
133
+ export type Block = {
134
+ name: string;
135
+ step?: Step;
136
+ loop?: Loop;
137
+ tryCatch?: TryCatch;
138
+ conditional?: Conditional;
139
+ parallel?: Parallel;
140
+ stream?: Stream;
141
+ };
142
+
143
+ export type Step = {
144
+ integration: string;
145
+ javascript?: LanguageContent;
146
+ python?: LanguageContent;
147
+ };
148
+
149
+ export type Loop = {
150
+ blocks: Block[];
151
+ range: string;
152
+ type: LoopType;
153
+ variables?: Variables;
154
+ };
155
+
156
+ export enum LoopType {
157
+ FOR = "TYPE_FOR",
158
+ FOR_EACH = "TYPE_FOREACH",
159
+ WHILE = "TYPE_WHILE",
160
+ UNSPECIFIED = "TYPE_UNSPECIFIED",
161
+ }
162
+
163
+ export type TryCatch = {
164
+ try?: Blocks;
165
+ catch?: Blocks;
166
+ finally?: Blocks;
167
+ variables?: Variables;
168
+ };
169
+
170
+ export type Conditional = {
171
+ if?: ConditionalBlockWithCondition;
172
+ elseIf: ConditionalBlockWithCondition[];
173
+ else?: Blocks;
174
+ };
175
+
176
+ export type Blocks = {
177
+ blocks: Block[];
178
+ };
179
+
180
+ export type ConditionalBlockWithCondition = Blocks & {
181
+ condition?: string;
182
+ };
183
+
184
+ export type Parallel = {
185
+ static?: {
186
+ paths: Record<string, Blocks>;
187
+ };
188
+ dynamic?: {
189
+ blocks: Block[];
190
+ variables?: Variables;
191
+ paths?: string;
192
+ };
193
+ poolSize?: number;
194
+ wait?: WAIT_TYPE;
195
+ };
196
+
197
+ export type Stream = {
198
+ trigger?: StreamTrigger;
199
+ process?: Blocks;
200
+ variables?: Variables;
201
+ };
202
+
203
+ export type StreamTrigger = {
204
+ name: string;
205
+ step?: Step;
206
+ };
207
+
208
+ export enum WAIT_TYPE {
209
+ ALL = "WAIT_ALL",
210
+ ANY = "WAIT_NONE",
211
+ UNSPECIFIED = "WAIT_UNSPECIFIED",
212
+ }
213
+
214
+ export type Variables = Record<string, string>;
215
+
216
+ export type LanguageContent = {
217
+ body: Body;
218
+ };
219
+
220
+ export type Body = string | { path: string };
221
+
130
222
  export type Page = {
131
223
  id: string;
132
224
  applicationId: string;
@@ -8,7 +8,7 @@ export type MethodHandler<Params, Result, PeerMethods, RequestContext> = (
8
8
  params: Params,
9
9
  ctx: RequestContext,
10
10
  peer: ISocketClient<PeerMethods>,
11
- next: () => Promise<Result>
11
+ next: () => Promise<Result>,
12
12
  ) => Promise<Result>;
13
13
 
14
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
@@ -24,22 +24,22 @@ export type NonEmptyArray<T> = [...T[], T];
24
24
 
25
25
  export type MethodHandlers<Methods, PeerMethods, RequestContext> = {
26
26
  [Key in keyof Methods]: Methods[Key] extends (
27
- params: infer Params
27
+ params: infer Params,
28
28
  ) => Promise<infer Result>
29
29
  ? NonEmptyArray<MethodHandler<Params, Result, PeerMethods, RequestContext>>
30
30
  : Methods[Key] extends Record<string, unknown>
31
- ? MethodHandlers<Methods[Key], PeerMethods, RequestContext>
32
- : never;
31
+ ? MethodHandlers<Methods[Key], PeerMethods, RequestContext>
32
+ : never;
33
33
  };
34
34
 
35
35
  type ISocketClientMethodCall<Methods> = {
36
36
  [Key in keyof Methods]: Methods[Key] extends (
37
- params: infer P
37
+ params: infer P,
38
38
  ) => Promise<infer R>
39
39
  ? (params: P) => Promise<R>
40
40
  : Methods[Key] extends Record<string, unknown>
41
- ? ISocketClientMethodCall<Methods[Key]>
42
- : never;
41
+ ? ISocketClientMethodCall<Methods[Key]>
42
+ : never;
43
43
  };
44
44
 
45
45
  export type ISocketClient<Methods> = {
@@ -48,7 +48,7 @@ export type ISocketClient<Methods> = {
48
48
  };
49
49
 
50
50
  export type MethodSchema<Params, Response> = (
51
- params: Params
51
+ params: Params,
52
52
  ) => Promise<Response>;
53
53
 
54
54
  /** The exception type can be thrown to cause the default error handler to write a raw error response to the socket */
package/src/utils.ts CHANGED
@@ -12,16 +12,16 @@ export async function getAgentUrl(
12
12
  agents: Agent[],
13
13
  agentType: AgentType,
14
14
  profile?: string,
15
- healthCheck = true
15
+ healthCheck = true,
16
16
  ): Promise<string> {
17
17
  let filtered = agents.filter(
18
- (a) => a.type === agentType && a.status === AgentStatus.ACTIVE
18
+ (a) => a.type === agentType && a.status === AgentStatus.ACTIVE,
19
19
  );
20
20
  if (profile) {
21
21
  filtered = agents.filter(
22
22
  (a) =>
23
23
  a.tags.profile &&
24
- (a.tags.profile.includes("*") || a.tags.profile.includes(profile))
24
+ (a.tags.profile.includes("*") || a.tags.profile.includes(profile)),
25
25
  );
26
26
  }
27
27
  if (healthCheck) {
@@ -41,7 +41,7 @@ export async function getAgentUrl(
41
41
  }
42
42
  try {
43
43
  return await Promise.any(coroutines);
44
- } catch (e) {
44
+ } catch {
45
45
  throw new Error("No available agents");
46
46
  }
47
47
  } else {
@@ -51,7 +51,7 @@ export async function getAgentUrl(
51
51
  }
52
52
 
53
53
  export const sanitizeV2RequestBody = (
54
- apiBody: Record<string, unknown>
54
+ apiBody: Record<string, unknown>,
55
55
  ): Record<string, unknown> => {
56
56
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
57
  const traverseJSON = (obj: any) => {
@@ -72,7 +72,7 @@ export const sanitizeV2RequestBody = (
72
72
 
73
73
  export const getSanitizedApi = (api: Api): any => {
74
74
  const sanitizedBlocks = (api.blocks ?? [])?.map(
75
- (block: Record<string, unknown>) => sanitizeV2RequestBody(block)
75
+ (block: Record<string, unknown>) => sanitizeV2RequestBody(block),
76
76
  );
77
77
  return {
78
78
  ...api,
package/tsconfig.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "outDir": "dist",
7
7
  "rootDir": "src",
8
8
  "strict": true,
9
- "target": "es2021",
9
+ "target": "es2022",
10
10
  "esModuleInterop": true,
11
11
  "skipLibCheck": true
12
12
  },
@@ -0,0 +1 @@
1
+ {"root":["./src/client.ts","./src/errors.ts","./src/flag.ts","./src/index.ts","./src/sdk.ts","./src/utils.ts","./src/socket/handlers.ts","./src/socket/index.ts","./src/socket/signing.ts","./src/socket/socket.ts","./src/types/common.ts","./src/types/index.ts","./src/types/plugin.ts","./src/types/signing.ts","./src/types/socket.ts"],"version":"5.7.3"}