@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/src/client.ts CHANGED
@@ -12,34 +12,35 @@ import {
12
12
  } from "@superblocksteam/util";
13
13
  import axios, { AxiosError, AxiosRequestConfig } from "axios";
14
14
  import FormData from "form-data";
15
- import { isEmpty } from "lodash";
15
+ import { isEqual, isEmpty } from "lodash";
16
16
  import {
17
17
  BranchNotCheckedOutError,
18
18
  CommitAlreadyExistsError,
19
19
  ValidateGitSetupError,
20
20
  } from "./errors";
21
21
  import { signingEnabled } from "./flag";
22
- import { connectToISocketRPCServer } from "./socket";
22
+ import { connectToISocketRPCServer, StdISocketRPCClient } from "./socket";
23
23
  import {
24
24
  AgentType,
25
25
  ApiWithPb,
26
26
  Page,
27
27
  RemoteCommitDto,
28
28
  UserMeDto,
29
+ ViewMode,
29
30
  } from "./types";
30
31
  import { getAgentUrl } from "./utils";
31
32
 
32
33
  const BASE_BUCKETEER_URL = "api";
33
34
  const BASE_SERVER_PUBLIC_API_URL_V1 = "api/v1/public";
34
35
  const BASE_SERVER_PUBLIC_API_URL_v2 = "api/v2/public";
36
+ const BASE_SERVER_API_URL_V2 = "api/v2";
37
+ const BASE_SERVER_API_URL_V3 = "api/v3";
35
38
 
36
39
  const SUPERBLOCKS_MAX_FILE_SIZE_MB = 10;
37
40
 
38
41
  const CLI_VERSION_HEADER = "x-superblocks-cli-version";
39
42
  const SUPERBLOCKS_URL_HEADER = "x-superblocks-url";
40
43
 
41
- export type ViewMode = "export-deployed" | "export-latest" | "export-live";
42
-
43
44
  export interface UploadFile {
44
45
  name: string;
45
46
  filename: string;
@@ -58,17 +59,12 @@ export interface MultiPageApplicationWrapper {
58
59
  apis: Record<string, any>[];
59
60
  }
60
61
 
61
- export type PushApplicationWithCommitConfig = ApplicationWrapper & {
62
- commitId: string;
63
- commitMessage: string;
64
- gitState: LocalGitRepoState;
65
- };
66
-
67
62
  export type PushMultiPageApplicationWithCommitConfig =
68
63
  MultiPageApplicationWrapper & {
69
- commitId: string;
70
- commitMessage: string;
64
+ commitId?: string;
65
+ commitMessage?: string;
71
66
  gitState: LocalGitRepoState;
67
+ skipCommit: boolean;
72
68
  };
73
69
 
74
70
  export interface ApiWrapper {
@@ -78,9 +74,10 @@ export interface ApiWrapper {
78
74
 
79
75
  export type PushApiWithCommitConfig = {
80
76
  apiPb: Record<string, any>;
81
- commitId: string;
82
- commitMessage: string;
77
+ commitId?: string;
78
+ commitMessage?: string;
83
79
  gitState: LocalGitRepoState;
80
+ skipCommit: boolean;
84
81
  };
85
82
 
86
83
  export type Branches = {
@@ -94,6 +91,26 @@ export type Branch = {
94
91
 
95
92
  type ResponseWithMeta<T> = { responseMeta: unknown; data: T };
96
93
 
94
+ export interface CommitDto {
95
+ commitMessage: string;
96
+ committer: {
97
+ name?: string;
98
+ email: string;
99
+ };
100
+ commitId: string;
101
+ commitDate: number;
102
+ branch?: string;
103
+ autosave?: boolean;
104
+ tag: string;
105
+ externalCommitId?: string | null;
106
+ externalCommitDate?: number | null;
107
+ }
108
+
109
+ export interface GetCommitsResponseBody {
110
+ autosaves: CommitDto[];
111
+ commits: CommitDto[];
112
+ }
113
+
97
114
  export async function fetchApplication({
98
115
  cliVersion,
99
116
  applicationId,
@@ -101,8 +118,9 @@ export async function fetchApplication({
101
118
  token,
102
119
  superblocksBaseUrl,
103
120
  viewMode,
121
+ commitId,
122
+ skipSigningVerification = false,
104
123
  injectedHeaders = {},
105
- fetchSinglePageApplication,
106
124
  }: {
107
125
  cliVersion: string;
108
126
  applicationId: string;
@@ -110,24 +128,51 @@ export async function fetchApplication({
110
128
  token: string;
111
129
  superblocksBaseUrl: string;
112
130
  viewMode: ViewMode;
131
+ commitId?: string;
132
+ skipSigningVerification?: boolean;
113
133
  injectedHeaders: Record<string, string>;
114
- fetchSinglePageApplication: boolean;
115
- }): Promise<ApplicationWrapper | MultiPageApplicationWrapper | undefined> {
134
+ }): Promise<MultiPageApplicationWrapper | undefined> {
135
+ if (commitId && viewMode !== "export-commit") {
136
+ throw new Error(
137
+ `If commitId ${commitId} is provided, viewMode cannot be ${viewMode}`
138
+ );
139
+ }
116
140
  try {
117
- const baseServerUrl = fetchSinglePageApplication
118
- ? BASE_SERVER_PUBLIC_API_URL_V1
119
- : BASE_SERVER_PUBLIC_API_URL_v2;
120
141
  const serverURL = branch
121
142
  ? new URL(
122
- `${baseServerUrl}/applications/${applicationId}/branches/${encodeURIComponent(
143
+ `${BASE_SERVER_PUBLIC_API_URL_v2}/applications/${applicationId}/branches/${encodeURIComponent(
123
144
  branch
124
- )}?viewMode=${viewMode}`,
145
+ )}`,
125
146
  superblocksBaseUrl
126
147
  )
127
148
  : new URL(
128
- `${baseServerUrl}/applications/${applicationId}?viewMode=${viewMode}`,
149
+ `${BASE_SERVER_PUBLIC_API_URL_v2}/applications/${applicationId}`,
129
150
  superblocksBaseUrl
130
151
  );
152
+ serverURL.search = new URLSearchParams({
153
+ viewMode,
154
+ ...(commitId ? { commitId } : {}),
155
+ }).toString();
156
+ const socket = !skipSigningVerification
157
+ ? await createSocketConnectionIfNeeded(
158
+ cliVersion,
159
+ token,
160
+ superblocksBaseUrl
161
+ )
162
+ : undefined;
163
+ if (socket) {
164
+ try {
165
+ const resp = await socket.call.v2.public.application.get({
166
+ applicationId,
167
+ viewMode,
168
+ branchName: branch,
169
+ commitId,
170
+ });
171
+ return resp.data;
172
+ } finally {
173
+ socket.close();
174
+ }
175
+ }
131
176
  const config: AxiosRequestConfig = {
132
177
  method: "get",
133
178
  url: serverURL.toString(),
@@ -138,7 +183,7 @@ export async function fetchApplication({
138
183
  },
139
184
  };
140
185
  const serverResponse = await axios<
141
- ResponseWithMeta<ApplicationWrapper | MultiPageApplicationWrapper>
186
+ ResponseWithMeta<MultiPageApplicationWrapper>
142
187
  >(config);
143
188
  const data = serverResponse?.data?.data;
144
189
  return data;
@@ -146,7 +191,11 @@ export async function fetchApplication({
146
191
  if (axios.isAxiosError(e) && e.response?.status === 404) {
147
192
  throw new NotFoundError(`Application ${applicationId} was not found`);
148
193
  }
149
- throw new Error("Could not fetch application");
194
+ throw new Error(
195
+ `Could not fetch application: ${
196
+ typeof e === "object" && e && "message" in e ? e.message : e
197
+ }`
198
+ );
150
199
  }
151
200
  }
152
201
 
@@ -197,8 +246,9 @@ export async function fetchApplicationWithComponents({
197
246
  token,
198
247
  superblocksBaseUrl,
199
248
  viewMode,
249
+ commitId,
250
+ skipSigningVerification = false,
200
251
  injectedHeaders = {},
201
- fetchSinglePageApplication = false,
202
252
  }: {
203
253
  cliVersion: string;
204
254
  applicationId: string;
@@ -206,10 +256,11 @@ export async function fetchApplicationWithComponents({
206
256
  token: string;
207
257
  superblocksBaseUrl: string;
208
258
  viewMode: ViewMode;
259
+ commitId?: string;
260
+ skipSigningVerification?: boolean;
209
261
  injectedHeaders: Record<string, string>;
210
- fetchSinglePageApplication?: boolean;
211
262
  }): Promise<
212
- | ((ApplicationWrapper | MultiPageApplicationWrapper) & {
263
+ | (MultiPageApplicationWrapper & {
213
264
  componentFiles: any;
214
265
  })
215
266
  | undefined
@@ -221,8 +272,9 @@ export async function fetchApplicationWithComponents({
221
272
  token,
222
273
  superblocksBaseUrl,
223
274
  viewMode,
275
+ commitId,
276
+ skipSigningVerification,
224
277
  injectedHeaders,
225
- fetchSinglePageApplication,
226
278
  });
227
279
 
228
280
  if (isEmpty(applicationWrapper)) {
@@ -236,18 +288,14 @@ export async function fetchApplicationWithComponents({
236
288
  componentFiles: null,
237
289
  };
238
290
  }
239
-
240
- // TODO(jason) update this with commit ID once we enable fetching by commit
241
- const commitId = "latest";
242
291
  superblocksBaseUrl = superblocksBaseUrl.replace(/\/$/, "");
243
292
  const bucketeerBaseUrl =
244
293
  getBucketeerUrlFromSuperblocksUrl(superblocksBaseUrl);
245
294
 
246
- const multiPage = fetchSinglePageApplication ? "false" : "true";
247
295
  // fetch files from bucketeer
248
296
  const branchPath = branch ? `/branches/${encodeURIComponent(branch)}` : "";
249
297
  const componentFileURL = new URL(
250
- `${BASE_BUCKETEER_URL}/v1/components/${applicationId}${branchPath}?commit=${commitId}&viewMode=${viewMode}&multiPage=${multiPage}`,
298
+ `${BASE_BUCKETEER_URL}/v1/components/${applicationId}${branchPath}?commit=${commitId}&viewMode=${viewMode}&multiPage=true`,
251
299
  bucketeerBaseUrl
252
300
  ).toString();
253
301
 
@@ -261,8 +309,23 @@ export async function fetchApplicationWithComponents({
261
309
  ...injectedHeaders,
262
310
  },
263
311
  };
264
- const response = await axios(config);
265
- return response.data;
312
+ const bucketeerApp = (await axios(config))
313
+ .data as MultiPageApplicationWrapper & {
314
+ componentFiles: any;
315
+ };
316
+
317
+ if (
318
+ !isEqual(
319
+ applicationWrapper.application.settings,
320
+ bucketeerApp.application.settings
321
+ )
322
+ ) {
323
+ throw new Error(
324
+ "Application settings fetched from bucketeer do not match the settings fetched from the server"
325
+ );
326
+ }
327
+
328
+ return bucketeerApp;
266
329
  } catch (e) {
267
330
  if (axios.isAxiosError(e) && e.response?.status === 404) {
268
331
  throw new NotFoundError(`Application ${applicationId} was not found`);
@@ -314,36 +377,66 @@ export async function fetchApi(
314
377
  token: string,
315
378
  superblocksBaseUrl: string,
316
379
  viewMode: ViewMode,
317
- branch?: string
380
+ branch?: string,
381
+ commitId?: string,
382
+ skipSigningVerification = false
318
383
  ) {
319
384
  try {
320
385
  const serverURL = branch
321
386
  ? new URL(
322
387
  `${BASE_SERVER_PUBLIC_API_URL_V1}/apis/${apiId}/branches/${encodeURIComponent(
323
388
  branch
324
- )}?viewMode=${viewMode}`,
389
+ )}`,
325
390
  superblocksBaseUrl
326
391
  )
327
392
  : new URL(
328
- `${BASE_SERVER_PUBLIC_API_URL_V1}/apis/${apiId}?viewMode=${viewMode}`,
393
+ `${BASE_SERVER_PUBLIC_API_URL_V1}/apis/${apiId}`,
329
394
  superblocksBaseUrl
330
395
  );
396
+ serverURL.search = new URLSearchParams({
397
+ viewMode,
398
+ ...(commitId ? { commitId } : {}),
399
+ }).toString();
400
+ const socket = !skipSigningVerification
401
+ ? await createSocketConnectionIfNeeded(
402
+ cliVersion,
403
+ token,
404
+ superblocksBaseUrl
405
+ )
406
+ : undefined;
331
407
 
332
- const config: AxiosRequestConfig = {
333
- method: "get",
334
- url: new URL(serverURL, superblocksBaseUrl).toString(),
335
- headers: {
336
- Authorization: "Bearer " + token,
337
- [CLI_VERSION_HEADER]: cliVersion,
338
- },
339
- };
340
- const response = await axios(config);
341
- return response.data.data;
408
+ if (socket) {
409
+ try {
410
+ const resp = await socket.call.v1.public.api.get({
411
+ apiId,
412
+ viewMode,
413
+ branchName: branch,
414
+ });
415
+ return resp.data;
416
+ } finally {
417
+ socket.close();
418
+ }
419
+ } else {
420
+ const config: AxiosRequestConfig = {
421
+ method: "get",
422
+ url: new URL(serverURL, superblocksBaseUrl).toString(),
423
+ headers: {
424
+ Authorization: "Bearer " + token,
425
+ [CLI_VERSION_HEADER]: cliVersion,
426
+ },
427
+ };
428
+ const response = await axios(config);
429
+ return response.data.data;
430
+ }
342
431
  } catch (e) {
343
432
  if (axios.isAxiosError(e) && e.response?.status === 404) {
344
433
  throw new NotFoundError(`Api ${apiId} was not found`);
345
434
  }
346
- throw new Error("Could not fetch api");
435
+ throw new Error(
436
+ `Could not fetch api: ${
437
+ typeof e === "object" && e && "message" in e ? e.message : e
438
+ }`
439
+ );
347
440
  }
348
441
  }
349
442
 
@@ -437,7 +530,7 @@ export async function validateGitSetup(
437
530
  message = `${e?.message ? e.message : e}`;
438
531
  }
439
532
 
440
- const errorMessage = `Could not validate your git setup against Superblocks for the ${resourceType.toLowerCase()} ${
533
+ const errorMessage = `Could not validate your git setup against Superblocks for ${resourceType.toLowerCase()} ${
441
534
  resourceName ?? resourceId
442
535
  }${message ? "\n" + message : ""}`;
443
536
 
@@ -462,27 +555,12 @@ export async function registerComponents(
462
555
  ) {
463
556
  try {
464
557
  const branchPath = branch ? `/branches/${encodeURIComponent(branch)}` : "";
465
- const userMe = await fetchCurrentUser(
558
+ const socket = await createSocketConnectionIfNeeded(
466
559
  cliVersion,
467
560
  token,
468
561
  superblocksBaseUrl
469
562
  );
470
- const organization = userMe.organizations[0];
471
- if (
472
- organization.agentType == AgentType.ONPREMISE &&
473
- signingEnabled(userMe.flagBootstrap)
474
- ) {
475
- const profile = process.env.SUPERBLOCKS_PROFILE;
476
- const agentUrl = await getAgentUrl(
477
- userMe.agents,
478
- organization.agentType,
479
- profile
480
- );
481
- const socket = await connectToISocketRPCServer({
482
- agentUrl,
483
- superblocksBaseUrl,
484
- token,
485
- });
563
+ if (socket) {
486
564
  const resp = await socket.call.v1.public.application.component.register({
487
565
  applicationId,
488
566
  branchName: branch || "",
@@ -614,24 +692,18 @@ You can reduce your component bundle size by uploading static assets to a separa
614
692
 
615
693
  const uploadResponse = await axios.post(postURL, formData, config);
616
694
 
617
- const userMe = await fetchCurrentUser(
695
+ const initialSocket = await createSocketConnectionIfNeeded(
618
696
  cliVersion,
619
697
  token,
620
698
  superblocksBaseUrl
621
699
  );
622
- const organization = userMe.organizations[0];
623
- let agentUrl: string | undefined;
624
- const signingRequired =
625
- organization.agentType == AgentType.ONPREMISE &&
626
- signingEnabled(userMe.flagBootstrap);
627
- if (signingRequired) {
628
- agentUrl = await getAgentUrl(userMe.agents, organization.agentType);
629
- }
630
- const socket = await connectToISocketRPCServer({
631
- agentUrl,
632
- superblocksBaseUrl,
633
- token,
634
- });
700
+ const socket =
701
+ initialSocket ??
702
+ (await connectToISocketRPCServer({
703
+ agentUrl: undefined,
704
+ superblocksBaseUrl,
705
+ token,
706
+ }));
635
707
  try {
636
708
  await socket.call.v1.public.application.component.update({
637
709
  applicationId,
@@ -641,7 +713,7 @@ You can reduce your component bundle size by uploading static assets to a separa
641
713
  registeredComponents: componentConfigs,
642
714
  cliVersion,
643
715
  componentBaseUrl: uploadResponse.data.componentBaseUrl,
644
- signingRequired,
716
+ signingRequired: !isEmpty(initialSocket),
645
717
  });
646
718
  } finally {
647
719
  socket.close();
@@ -704,6 +776,31 @@ export async function fetchCurrentUser(
704
776
  }
705
777
  }
706
778
 
779
+ export const createSocketConnectionIfNeeded = async (
780
+ cliVersion: string,
781
+ token: string,
782
+ superblocksBaseUrl: string
783
+ ): Promise<StdISocketRPCClient | undefined> => {
784
+ const userMe = await fetchCurrentUser(cliVersion, token, superblocksBaseUrl);
785
+ const organization = userMe.organizations[0];
786
+ if (
787
+ organization.agentType == AgentType.ONPREMISE &&
788
+ signingEnabled(userMe.flagBootstrap)
789
+ ) {
790
+ const profile = process.env.SUPERBLOCKS_PROFILE;
791
+ const agentUrl = await getAgentUrl(
792
+ userMe.agents,
793
+ organization.agentType,
794
+ profile
795
+ );
796
+ return await connectToISocketRPCServer({
797
+ agentUrl,
798
+ superblocksBaseUrl,
799
+ token,
800
+ });
801
+ }
802
+ };
803
+
707
804
  export async function pushApplication({
708
805
  cliVersion,
709
806
  applicationId,
@@ -712,7 +809,6 @@ export async function pushApplication({
712
809
  applicationConfig,
713
810
  branch,
714
811
  injectedHeaders = {},
715
- multiPage = false,
716
812
  }: {
717
813
  cliVersion: string;
718
814
  applicationId: string;
@@ -720,11 +816,8 @@ export async function pushApplication({
720
816
  superblocksBaseUrl: string;
721
817
  branch: string;
722
818
  injectedHeaders: Record<string, string>;
723
- applicationConfig:
724
- | PushApplicationWithCommitConfig
725
- | PushMultiPageApplicationWithCommitConfig;
726
- multiPage?: boolean;
727
- }): Promise<RemoteCommitDto | undefined> {
819
+ applicationConfig: PushMultiPageApplicationWithCommitConfig;
820
+ }): Promise<RemoteCommitDto | { updated: Date } | undefined> {
728
821
  const handleHttpError = (status: number) => {
729
822
  if (status === 405) {
730
823
  throw new BranchNotCheckedOutError(`Branch ${branch} is not checked out`);
@@ -735,52 +828,26 @@ export async function pushApplication({
735
828
  }
736
829
  };
737
830
  try {
738
- const userMe = await fetchCurrentUser(
831
+ const socket = await createSocketConnectionIfNeeded(
739
832
  cliVersion,
740
833
  token,
741
834
  superblocksBaseUrl
742
835
  );
743
- const organization = userMe.organizations[0];
744
- if (
745
- organization.agentType == AgentType.ONPREMISE &&
746
- signingEnabled(userMe.flagBootstrap)
747
- ) {
748
- const profile = process.env.SUPERBLOCKS_PROFILE;
749
- const agentUrl = await getAgentUrl(
750
- userMe.agents,
751
- organization.agentType,
752
- profile
753
- );
754
- const socket = await connectToISocketRPCServer({
755
- agentUrl,
756
- superblocksBaseUrl,
757
- token,
836
+
837
+ if (socket) {
838
+ const resp = await socket.call.v2.public.application.pushCommit({
839
+ applicationId,
840
+ apis: applicationConfig.apis,
841
+ application: applicationConfig.application,
842
+ branchName: branch,
843
+ commitId: applicationConfig.commitId,
844
+ commitMessage: applicationConfig.commitMessage,
845
+ pages: (
846
+ applicationConfig as unknown as PushMultiPageApplicationWithCommitConfig
847
+ ).pages,
848
+ gitState: applicationConfig.gitState,
849
+ skipCommit: applicationConfig.skipCommit,
758
850
  });
759
- const resp = multiPage
760
- ? await socket.call.v2.public.application.pushCommit({
761
- applicationId,
762
- apis: applicationConfig.apis,
763
- application: applicationConfig.application,
764
- branchName: branch,
765
- commitId: applicationConfig.commitId,
766
- commitMessage: applicationConfig.commitMessage,
767
- pages: (
768
- applicationConfig as unknown as PushMultiPageApplicationWithCommitConfig
769
- ).pages,
770
- gitState: applicationConfig.gitState,
771
- })
772
- : await socket.call.v1.public.application.pushCommit({
773
- applicationId,
774
- apis: applicationConfig.apis,
775
- application: applicationConfig.application,
776
- branchName: branch,
777
- commitId: applicationConfig.commitId,
778
- commitMessage: applicationConfig.commitMessage,
779
- page: (
780
- applicationConfig as unknown as PushApplicationWithCommitConfig
781
- ).page,
782
- gitState: applicationConfig.gitState,
783
- });
784
851
  socket.close();
785
852
  handleHttpError(resp.responseMeta.status);
786
853
  if (resp.responseMeta.status !== 200) {
@@ -791,12 +858,8 @@ export async function pushApplication({
791
858
  }
792
859
  return resp.data;
793
860
  } else {
794
- // v1 calls can be removed once all customers move to multi page
795
- const baseServerPublicApiUrl = multiPage
796
- ? BASE_SERVER_PUBLIC_API_URL_v2
797
- : BASE_SERVER_PUBLIC_API_URL_V1;
798
861
  const serverURL = new URL(
799
- `${baseServerPublicApiUrl}/applications/${applicationId}/branches/${encodeURIComponent(
862
+ `${BASE_SERVER_PUBLIC_API_URL_v2}/applications/${applicationId}/branches/${encodeURIComponent(
800
863
  branch
801
864
  )}/push`,
802
865
  superblocksBaseUrl
@@ -812,9 +875,9 @@ export async function pushApplication({
812
875
  data: applicationConfig,
813
876
  };
814
877
  try {
815
- const serverResponse = await axios<ResponseWithMeta<RemoteCommitDto>>(
816
- config
817
- );
878
+ const serverResponse = await axios<
879
+ ResponseWithMeta<RemoteCommitDto | { updated: Date }>
880
+ >(config);
818
881
  return serverResponse?.data?.data;
819
882
  } catch (e) {
820
883
  if (!axios.isAxiosError(e)) {
@@ -862,7 +925,7 @@ export async function pushApi({
862
925
  apiConfig: PushApiWithCommitConfig;
863
926
  branch: string;
864
927
  injectedHeaders: Record<string, string>;
865
- }): Promise<{ commitId: string } | undefined> {
928
+ }): Promise<{ commitId: string } | { updated: Date } | undefined> {
866
929
  const handleHttpError = (status: number) => {
867
930
  if (status === 405) {
868
931
  throw new BranchNotCheckedOutError(`Branch ${branch} is not checked out`);
@@ -879,22 +942,12 @@ export async function pushApi({
879
942
  superblocksBaseUrl
880
943
  );
881
944
  try {
882
- const userMe = await fetchCurrentUser(
945
+ const socket = await createSocketConnectionIfNeeded(
883
946
  cliVersion,
884
947
  token,
885
948
  superblocksBaseUrl
886
949
  );
887
- const organization = userMe.organizations[0];
888
- if (
889
- organization.agentType == AgentType.ONPREMISE &&
890
- signingEnabled(userMe.flagBootstrap)
891
- ) {
892
- const agentUrl = await getAgentUrl(userMe.agents, organization.agentType);
893
- const socket = await connectToISocketRPCServer({
894
- agentUrl,
895
- superblocksBaseUrl,
896
- token,
897
- });
950
+ if (socket) {
898
951
  const resp = await socket.call.v1.public.api.pushCommit({
899
952
  apiId,
900
953
  apiPb: apiConfig.apiPb,
@@ -902,6 +955,7 @@ export async function pushApi({
902
955
  commitId: apiConfig.commitId,
903
956
  commitMessage: apiConfig.commitMessage,
904
957
  gitState: apiConfig.gitState,
958
+ skipCommit: apiConfig.skipCommit,
905
959
  });
906
960
  socket.close();
907
961
  handleHttpError(resp.responseMeta.status);
@@ -925,7 +979,7 @@ export async function pushApi({
925
979
  };
926
980
  try {
927
981
  const serverResponse = await axios<
928
- ResponseWithMeta<{ commitId: string }>
982
+ ResponseWithMeta<{ commitId: string } | { updated: Date }>
929
983
  >(config);
930
984
  return serverResponse?.data?.data;
931
985
  } catch (e) {
@@ -955,3 +1009,117 @@ export async function pushApi({
955
1009
  );
956
1010
  }
957
1011
  }
1012
+
1013
+ export async function fetchApplicationCommits({
1014
+ cliVersion,
1015
+ applicationId,
1016
+ branch,
1017
+ token,
1018
+ superblocksBaseUrl,
1019
+ injectedHeaders = {},
1020
+ limit,
1021
+ offset,
1022
+ }: {
1023
+ cliVersion: string;
1024
+ applicationId: string;
1025
+ branch?: string;
1026
+ token: string;
1027
+ superblocksBaseUrl: string;
1028
+ injectedHeaders: Record<string, string>;
1029
+ limit?: number;
1030
+ offset?: number;
1031
+ }): Promise<GetCommitsResponseBody> {
1032
+ try {
1033
+ const serverURL = branch
1034
+ ? new URL(
1035
+ `${BASE_SERVER_API_URL_V2}/applications/${applicationId}/branches/${encodeURIComponent(
1036
+ branch
1037
+ )}/commits`,
1038
+ superblocksBaseUrl
1039
+ )
1040
+ : new URL(
1041
+ `${BASE_SERVER_API_URL_V2}/applications/${applicationId}/commits`,
1042
+ superblocksBaseUrl
1043
+ );
1044
+ serverURL.search = new URLSearchParams({
1045
+ commitType: "commit",
1046
+ ...(limit ? { limit: limit.toString() } : {}),
1047
+ ...(offset ? { offset: offset.toString() } : {}),
1048
+ }).toString();
1049
+ const config: AxiosRequestConfig = {
1050
+ method: "get",
1051
+ url: serverURL.toString(),
1052
+ headers: {
1053
+ Authorization: "Bearer " + token,
1054
+ [CLI_VERSION_HEADER]: cliVersion,
1055
+ ...injectedHeaders,
1056
+ },
1057
+ };
1058
+ const serverResponse = await axios<
1059
+ ResponseWithMeta<GetCommitsResponseBody>
1060
+ >(config);
1061
+ return serverResponse?.data?.data;
1062
+ } catch (e) {
1063
+ if (axios.isAxiosError(e) && e.response?.status === 404) {
1064
+ throw new NotFoundError(`Application ${applicationId} was not found`);
1065
+ }
1066
+ throw new Error("Could not fetch application");
1067
+ }
1068
+ }
1069
+
1070
+ export async function fetchApiCommits({
1071
+ cliVersion,
1072
+ applicationId,
1073
+ branch,
1074
+ token,
1075
+ superblocksBaseUrl,
1076
+ injectedHeaders = {},
1077
+ limit,
1078
+ offset,
1079
+ }: {
1080
+ cliVersion: string;
1081
+ applicationId: string;
1082
+ branch?: string;
1083
+ token: string;
1084
+ superblocksBaseUrl: string;
1085
+ injectedHeaders: Record<string, string>;
1086
+ limit?: number;
1087
+ offset?: number;
1088
+ }): Promise<GetCommitsResponseBody> {
1089
+ try {
1090
+ const serverURL = branch
1091
+ ? new URL(
1092
+ `${BASE_SERVER_API_URL_V3}/apis/${applicationId}/branches/${encodeURIComponent(
1093
+ branch
1094
+ )}/commits`,
1095
+ superblocksBaseUrl
1096
+ )
1097
+ : new URL(
1098
+ `${BASE_SERVER_API_URL_V3}/apis/${applicationId}/commits`,
1099
+ superblocksBaseUrl
1100
+ );
1101
+ serverURL.search = new URLSearchParams({
1102
+ commitType: "commit",
1103
+ ...(limit ? { limit: limit.toString() } : {}),
1104
+ ...(offset ? { offset: offset.toString() } : {}),
1105
+ }).toString();
1106
+ const config: AxiosRequestConfig = {
1107
+ method: "get",
1108
+ url: serverURL.toString(),
1109
+ headers: {
1110
+ Authorization: "Bearer " + token,
1111
+ [CLI_VERSION_HEADER]: cliVersion,
1112
+ ...injectedHeaders,
1113
+ },
1114
+ };
1115
+ const serverResponse = await axios<
1116
+ ResponseWithMeta<GetCommitsResponseBody>
1117
+ >(config);
1118
+ return serverResponse?.data?.data;
1119
+ } catch (e) {
1120
+ if (axios.isAxiosError(e) && e.response?.status === 404) {
1121
+ throw new NotFoundError(`Application ${applicationId} was not found`);
1122
+ }
1123
+ throw new Error("Could not fetch application");
1124
+ }
1125
+ }