@superblocksteam/sabs-client 0.127.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/.prettierignore +3 -0
- package/.prettierrc +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/sabs.d.ts +43 -0
- package/dist/sabs.d.ts.map +1 -0
- package/dist/sabs.js +110 -0
- package/dist/sabs.js.map +1 -0
- package/dist/sabs.test.d.ts +2 -0
- package/dist/sabs.test.d.ts.map +1 -0
- package/dist/sabs.test.js +404 -0
- package/dist/sabs.test.js.map +1 -0
- package/eslint.config.mjs +261 -0
- package/jest.config.js +13 -0
- package/package.json +59 -0
- package/src/index.ts +1 -0
- package/src/sabs.test.ts +423 -0
- package/src/sabs.ts +203 -0
- package/tsconfig.json +24 -0
- package/tsconfig.test.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
package/src/sabs.test.ts
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import { ApplicationMetadata, BuildStatus } from '@superblocksteam/sabs-types';
|
|
2
|
+
import axios, { AxiosError, AxiosHeaders } from 'axios';
|
|
3
|
+
|
|
4
|
+
import { SabsClient } from './sabs';
|
|
5
|
+
|
|
6
|
+
describe('sabs service', () => {
|
|
7
|
+
let anyBuildKey: string;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
anyBuildKey = 'any-secret-build-key';
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
jest.restoreAllMocks();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('build', () => {
|
|
18
|
+
test.each([
|
|
19
|
+
{ accessToken: 'anyScopedJwt', expectedHeaders: { Authorization: 'Bearer anyScopedJwt' } },
|
|
20
|
+
{ accessToken: undefined, expectedHeaders: undefined }
|
|
21
|
+
])('returns expected response with accessToken=$accessToken', async ({ accessToken, expectedHeaders }) => {
|
|
22
|
+
const expectedBuildId = 'expectedBuildId';
|
|
23
|
+
const expectedCreated = new Date();
|
|
24
|
+
const expectedUpdated = new Date();
|
|
25
|
+
|
|
26
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
27
|
+
mockAxios.mockResolvedValue({
|
|
28
|
+
data: {
|
|
29
|
+
buildId: expectedBuildId,
|
|
30
|
+
created: expectedCreated,
|
|
31
|
+
updated: expectedUpdated
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const anyDirectoryHash = 'anyDirectoryHash';
|
|
36
|
+
const anyApplicationMetadata = new ApplicationMetadata({
|
|
37
|
+
id: 'anyApplicationId',
|
|
38
|
+
organizationId: 'anyOrganizationId'
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
42
|
+
const result = await sabs.build({
|
|
43
|
+
directoryHash: anyDirectoryHash,
|
|
44
|
+
meta: anyApplicationMetadata,
|
|
45
|
+
buildKey: anyBuildKey,
|
|
46
|
+
accessToken
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
expect(result).toEqual({
|
|
50
|
+
buildId: expectedBuildId,
|
|
51
|
+
created: expectedCreated,
|
|
52
|
+
updated: expectedUpdated
|
|
53
|
+
});
|
|
54
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
55
|
+
method: 'POST',
|
|
56
|
+
url: 'http://localhost:3000/v1/builds',
|
|
57
|
+
headers: expectedHeaders,
|
|
58
|
+
data: {
|
|
59
|
+
directoryHash: anyDirectoryHash,
|
|
60
|
+
applicationMetadata: anyApplicationMetadata,
|
|
61
|
+
buildKey: anyBuildKey
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('raises error when request fails', async () => {
|
|
67
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
68
|
+
mockAxios.mockRejectedValue(new Error('any error'));
|
|
69
|
+
|
|
70
|
+
const anyDirectoryHash = 'anyDirectoryHash';
|
|
71
|
+
const anyApplicationMetadata = new ApplicationMetadata({
|
|
72
|
+
id: 'anyApplicationId',
|
|
73
|
+
organizationId: 'anyOrganizationId'
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
77
|
+
await expect(sabs.build({ directoryHash: anyDirectoryHash, meta: anyApplicationMetadata, buildKey: anyBuildKey })).rejects.toThrow();
|
|
78
|
+
|
|
79
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
80
|
+
method: 'POST',
|
|
81
|
+
url: 'http://localhost:3000/v1/builds',
|
|
82
|
+
data: {
|
|
83
|
+
directoryHash: anyDirectoryHash,
|
|
84
|
+
applicationMetadata: anyApplicationMetadata,
|
|
85
|
+
buildKey: anyBuildKey
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('status', () => {
|
|
92
|
+
test.each([
|
|
93
|
+
{ accessToken: 'anyScopedJwt', expectedHeaders: { Authorization: 'Bearer anyScopedJwt' } },
|
|
94
|
+
{ accessToken: undefined, expectedHeaders: undefined }
|
|
95
|
+
])('returns expected response with accessToken=$accessToken', async ({ accessToken, expectedHeaders }) => {
|
|
96
|
+
const expectedBuildId = 'expectedBuildId';
|
|
97
|
+
const expectedStatus = BuildStatus.SUCCESS;
|
|
98
|
+
const expectedCreated = new Date();
|
|
99
|
+
const expectedUpdated = new Date();
|
|
100
|
+
|
|
101
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
102
|
+
mockAxios.mockResolvedValue({
|
|
103
|
+
data: {
|
|
104
|
+
buildId: expectedBuildId,
|
|
105
|
+
status: expectedStatus,
|
|
106
|
+
created: expectedCreated,
|
|
107
|
+
updated: expectedUpdated
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const anyBuildId = 'anyBuildId';
|
|
112
|
+
|
|
113
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
114
|
+
const result = await sabs.status({ buildId: anyBuildId, accessToken });
|
|
115
|
+
|
|
116
|
+
expect(result).toEqual({
|
|
117
|
+
buildId: expectedBuildId,
|
|
118
|
+
status: expectedStatus,
|
|
119
|
+
created: expectedCreated,
|
|
120
|
+
updated: expectedUpdated
|
|
121
|
+
});
|
|
122
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
123
|
+
method: 'GET',
|
|
124
|
+
url: `http://localhost:3000/v1/builds/${anyBuildId}`,
|
|
125
|
+
headers: expectedHeaders
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('raises error when request fails', async () => {
|
|
130
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
131
|
+
mockAxios.mockRejectedValue(new Error('any error'));
|
|
132
|
+
|
|
133
|
+
const anyBuildId = 'anyBuildId';
|
|
134
|
+
|
|
135
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
136
|
+
await expect(sabs.status({ buildId: anyBuildId })).rejects.toThrow();
|
|
137
|
+
|
|
138
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
139
|
+
method: 'GET',
|
|
140
|
+
url: `http://localhost:3000/v1/builds/${anyBuildId}`
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe('list', () => {
|
|
146
|
+
test.each([
|
|
147
|
+
{ accessToken: 'anyScopedJwt', expectedHeaders: { Authorization: 'Bearer anyScopedJwt' } },
|
|
148
|
+
{ accessToken: undefined, expectedHeaders: undefined }
|
|
149
|
+
])('returns expected response with accessToken=$accessToken', async ({ accessToken, expectedHeaders }) => {
|
|
150
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
151
|
+
mockAxios.mockResolvedValue({
|
|
152
|
+
data: {
|
|
153
|
+
builds: [
|
|
154
|
+
{
|
|
155
|
+
buildId: 'id1',
|
|
156
|
+
status: BuildStatus.SUCCESS,
|
|
157
|
+
created: new Date('2023-01-01'),
|
|
158
|
+
updated: new Date('2023-01-02')
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
buildId: 'id2',
|
|
162
|
+
status: BuildStatus.RUNNING,
|
|
163
|
+
created: new Date('2023-01-03'),
|
|
164
|
+
updated: new Date('2023-01-04')
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
buildId: 'id3',
|
|
168
|
+
status: BuildStatus.FAILED,
|
|
169
|
+
error: 'Build failed',
|
|
170
|
+
created: new Date('2023-01-05'),
|
|
171
|
+
updated: new Date('2023-01-06')
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const anyOrganizationId = 'anyOrganizationId';
|
|
178
|
+
const anyApplicationId = 'anyApplicationId';
|
|
179
|
+
const anyDirectoryHash = 'anyDirectoryHash';
|
|
180
|
+
|
|
181
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
182
|
+
const result = await sabs.list({
|
|
183
|
+
organizationId: anyOrganizationId,
|
|
184
|
+
applicationId: anyApplicationId,
|
|
185
|
+
directoryHash: anyDirectoryHash,
|
|
186
|
+
accessToken
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
expect(result).toEqual({
|
|
190
|
+
builds: [
|
|
191
|
+
{
|
|
192
|
+
buildId: 'id1',
|
|
193
|
+
status: BuildStatus.SUCCESS,
|
|
194
|
+
created: new Date('2023-01-01'),
|
|
195
|
+
updated: new Date('2023-01-02')
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
buildId: 'id2',
|
|
199
|
+
status: BuildStatus.RUNNING,
|
|
200
|
+
created: new Date('2023-01-03'),
|
|
201
|
+
updated: new Date('2023-01-04')
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
buildId: 'id3',
|
|
205
|
+
status: BuildStatus.FAILED,
|
|
206
|
+
error: 'Build failed',
|
|
207
|
+
created: new Date('2023-01-05'),
|
|
208
|
+
updated: new Date('2023-01-06')
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
});
|
|
212
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
213
|
+
method: 'GET',
|
|
214
|
+
url: `http://localhost:3000/v1/build`,
|
|
215
|
+
headers: expectedHeaders,
|
|
216
|
+
params: {
|
|
217
|
+
organizationId: anyOrganizationId,
|
|
218
|
+
applicationId: anyApplicationId,
|
|
219
|
+
directoryHash: anyDirectoryHash
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test('raises error when request fails', async () => {
|
|
225
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
226
|
+
mockAxios.mockRejectedValue(new Error('any error'));
|
|
227
|
+
|
|
228
|
+
const anyOrganizationId = 'anyOrganizationId';
|
|
229
|
+
const anyApplicationId = 'anyApplicationId';
|
|
230
|
+
const anyDirectoryHash = 'anyDirectoryHash';
|
|
231
|
+
|
|
232
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
233
|
+
await expect(
|
|
234
|
+
sabs.list({
|
|
235
|
+
organizationId: anyOrganizationId,
|
|
236
|
+
applicationId: anyApplicationId,
|
|
237
|
+
directoryHash: anyDirectoryHash
|
|
238
|
+
})
|
|
239
|
+
).rejects.toThrow();
|
|
240
|
+
|
|
241
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
242
|
+
method: 'GET',
|
|
243
|
+
url: `http://localhost:3000/v1/build`,
|
|
244
|
+
headers: undefined,
|
|
245
|
+
params: {
|
|
246
|
+
organizationId: anyOrganizationId,
|
|
247
|
+
applicationId: anyApplicationId,
|
|
248
|
+
directoryHash: anyDirectoryHash
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
describe('terminate', () => {
|
|
255
|
+
test.each([
|
|
256
|
+
{ accessToken: 'anyScopedJwt', expectedHeaders: { Authorization: 'Bearer anyScopedJwt' } },
|
|
257
|
+
{ accessToken: undefined, expectedHeaders: undefined }
|
|
258
|
+
])('returns expected response with accessToken=$accessToken', async ({ accessToken, expectedHeaders }) => {
|
|
259
|
+
const expectedBuildId = 'expectedBuildId';
|
|
260
|
+
const expectedStatus = BuildStatus.TIMED_OUT;
|
|
261
|
+
const expectedError = 'build timed out';
|
|
262
|
+
const expectedCreated = new Date();
|
|
263
|
+
const expectedUpdated = new Date();
|
|
264
|
+
|
|
265
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
266
|
+
mockAxios.mockResolvedValue({
|
|
267
|
+
data: {
|
|
268
|
+
buildId: expectedBuildId,
|
|
269
|
+
status: expectedStatus,
|
|
270
|
+
error: expectedError,
|
|
271
|
+
created: expectedCreated,
|
|
272
|
+
updated: expectedUpdated
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const anyBuildId = 'anyBuildId';
|
|
277
|
+
const anyStatus = BuildStatus.TIMED_OUT;
|
|
278
|
+
const anyError = 'build timed out';
|
|
279
|
+
|
|
280
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
281
|
+
const result = await sabs.terminate({ buildId: anyBuildId, status: anyStatus, buildKey: anyBuildKey, error: anyError, accessToken });
|
|
282
|
+
|
|
283
|
+
expect(result).toEqual({
|
|
284
|
+
buildId: expectedBuildId,
|
|
285
|
+
status: expectedStatus,
|
|
286
|
+
error: expectedError,
|
|
287
|
+
created: expectedCreated,
|
|
288
|
+
updated: expectedUpdated
|
|
289
|
+
});
|
|
290
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
291
|
+
method: 'POST',
|
|
292
|
+
url: `http://localhost:3000/v1/builds/${anyBuildId}/terminate`,
|
|
293
|
+
headers: expectedHeaders,
|
|
294
|
+
data: {
|
|
295
|
+
buildId: anyBuildId,
|
|
296
|
+
status: anyStatus,
|
|
297
|
+
error: anyError,
|
|
298
|
+
buildKey: anyBuildKey
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test('raises error when request fails', async () => {
|
|
304
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
305
|
+
mockAxios.mockRejectedValue(new Error('any error'));
|
|
306
|
+
|
|
307
|
+
const anyBuildId = 'anyBuildId';
|
|
308
|
+
const anyStatus = BuildStatus.TIMED_OUT;
|
|
309
|
+
const anyError = 'build timed out';
|
|
310
|
+
|
|
311
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
312
|
+
await expect(sabs.terminate({ buildId: anyBuildId, status: anyStatus, buildKey: anyBuildKey, error: anyError })).rejects.toThrow();
|
|
313
|
+
|
|
314
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
315
|
+
method: 'POST',
|
|
316
|
+
url: `http://localhost:3000/v1/builds/${anyBuildId}/terminate`,
|
|
317
|
+
data: {
|
|
318
|
+
buildId: anyBuildId,
|
|
319
|
+
status: anyStatus,
|
|
320
|
+
error: anyError,
|
|
321
|
+
buildKey: anyBuildKey
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
describe('bulkStatus', () => {
|
|
328
|
+
test('returns expected response', async () => {
|
|
329
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
330
|
+
mockAxios.mockResolvedValue({
|
|
331
|
+
data: {
|
|
332
|
+
builds: [
|
|
333
|
+
{
|
|
334
|
+
buildId: 'build1',
|
|
335
|
+
status: BuildStatus.SUCCESS,
|
|
336
|
+
created: new Date('2023-01-01'),
|
|
337
|
+
updated: new Date('2023-01-02')
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
buildId: 'build2',
|
|
341
|
+
status: BuildStatus.RUNNING,
|
|
342
|
+
created: new Date('2023-01-03'),
|
|
343
|
+
updated: new Date('2023-01-04')
|
|
344
|
+
}
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
const anyOrganizationId = 'anyOrganizationId';
|
|
350
|
+
const anyApplicationId = 'anyApplicationId';
|
|
351
|
+
const anyDirectoryHashes = ['hash1', 'hash2'];
|
|
352
|
+
|
|
353
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
354
|
+
const result = await sabs.bulkStatus({
|
|
355
|
+
organizationId: anyOrganizationId,
|
|
356
|
+
applicationId: anyApplicationId,
|
|
357
|
+
directoryHashes: anyDirectoryHashes
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
expect(result).toEqual({
|
|
361
|
+
builds: [
|
|
362
|
+
{
|
|
363
|
+
buildId: 'build1',
|
|
364
|
+
status: BuildStatus.SUCCESS,
|
|
365
|
+
created: new Date('2023-01-01'),
|
|
366
|
+
updated: new Date('2023-01-02')
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
buildId: 'build2',
|
|
370
|
+
status: BuildStatus.RUNNING,
|
|
371
|
+
created: new Date('2023-01-03'),
|
|
372
|
+
updated: new Date('2023-01-04')
|
|
373
|
+
}
|
|
374
|
+
]
|
|
375
|
+
});
|
|
376
|
+
expect(mockAxios).toHaveBeenCalledWith({
|
|
377
|
+
method: 'POST',
|
|
378
|
+
url: `http://localhost:3000/v1/builds/${anyOrganizationId}/${anyApplicationId}/bulk-status`,
|
|
379
|
+
data: {
|
|
380
|
+
organizationId: anyOrganizationId,
|
|
381
|
+
applicationId: anyApplicationId,
|
|
382
|
+
directoryHashes: anyDirectoryHashes
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
describe('executeRequest', () => {
|
|
389
|
+
test('raies expected error when error is axios error', async () => {
|
|
390
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
391
|
+
mockAxios.mockRejectedValue(
|
|
392
|
+
new AxiosError('request failed', 'internal', undefined, undefined, {
|
|
393
|
+
headers: {},
|
|
394
|
+
config: {
|
|
395
|
+
headers: new AxiosHeaders()
|
|
396
|
+
},
|
|
397
|
+
status: 500,
|
|
398
|
+
statusText: 'internal server error',
|
|
399
|
+
data: 'failed to process request'
|
|
400
|
+
})
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
const anyBuildId = 'anyBuildId';
|
|
404
|
+
|
|
405
|
+
const expectedError = 'sabs service request failed: request failed\n[500] internal server error: "failed to process request"';
|
|
406
|
+
|
|
407
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
408
|
+
await expect(sabs.status({ buildId: anyBuildId })).rejects.toThrow(expectedError);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test('re-raises error when error is not axios error', async () => {
|
|
412
|
+
const mockAxios = jest.spyOn(axios, 'request');
|
|
413
|
+
mockAxios.mockRejectedValue(new Error('unexpected error'));
|
|
414
|
+
|
|
415
|
+
const anyBuildId = 'anyBuildId';
|
|
416
|
+
|
|
417
|
+
const expectedError = 'sabs service request failed: unexpected error';
|
|
418
|
+
|
|
419
|
+
const sabs = new SabsClient('http://localhost:3000');
|
|
420
|
+
await expect(sabs.status({ buildId: anyBuildId })).rejects.toThrow(expectedError);
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
});
|
package/src/sabs.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApplicationMetadata,
|
|
3
|
+
BuildRequest,
|
|
4
|
+
BuildResponse,
|
|
5
|
+
BuildStatus,
|
|
6
|
+
ListRequest,
|
|
7
|
+
ListResponse,
|
|
8
|
+
StatusResponse,
|
|
9
|
+
TerminateRequest,
|
|
10
|
+
TerminateResponse,
|
|
11
|
+
BulkStatusRequest,
|
|
12
|
+
BulkStatusResponse,
|
|
13
|
+
CreateLiveEditRequest,
|
|
14
|
+
CreateLiveEditResponse
|
|
15
|
+
} from '@superblocksteam/sabs-types';
|
|
16
|
+
import axios, { AxiosRequestConfig, RawAxiosRequestHeaders } from 'axios';
|
|
17
|
+
|
|
18
|
+
export class SabsClient {
|
|
19
|
+
private readonly baseUrl: string;
|
|
20
|
+
|
|
21
|
+
public constructor(baseUrl: string) {
|
|
22
|
+
this.baseUrl = baseUrl;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public async build({
|
|
26
|
+
directoryHash,
|
|
27
|
+
meta,
|
|
28
|
+
buildKey,
|
|
29
|
+
accessToken
|
|
30
|
+
}: {
|
|
31
|
+
directoryHash: string;
|
|
32
|
+
meta: ApplicationMetadata;
|
|
33
|
+
buildKey: string;
|
|
34
|
+
accessToken?: string;
|
|
35
|
+
}): Promise<BuildResponse> {
|
|
36
|
+
const data = new BuildRequest({
|
|
37
|
+
directoryHash: directoryHash,
|
|
38
|
+
applicationMetadata: meta,
|
|
39
|
+
buildKey
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return this.executeRequest<BuildResponse>(
|
|
43
|
+
{
|
|
44
|
+
method: 'POST',
|
|
45
|
+
url: `${this.baseUrl}/v1/builds`,
|
|
46
|
+
data
|
|
47
|
+
},
|
|
48
|
+
accessToken
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public async status({ buildId, accessToken }: { buildId: string; accessToken?: string }): Promise<StatusResponse> {
|
|
53
|
+
return this.executeRequest<StatusResponse>(
|
|
54
|
+
{
|
|
55
|
+
method: 'GET',
|
|
56
|
+
url: `${this.baseUrl}/v1/builds/${buildId}`
|
|
57
|
+
},
|
|
58
|
+
accessToken
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public async bulkStatus({
|
|
63
|
+
organizationId,
|
|
64
|
+
applicationId,
|
|
65
|
+
directoryHashes,
|
|
66
|
+
accessToken
|
|
67
|
+
}: {
|
|
68
|
+
organizationId: string;
|
|
69
|
+
applicationId: string;
|
|
70
|
+
directoryHashes: string[];
|
|
71
|
+
accessToken?: string;
|
|
72
|
+
}): Promise<BulkStatusResponse> {
|
|
73
|
+
const data = new BulkStatusRequest({
|
|
74
|
+
organizationId,
|
|
75
|
+
applicationId,
|
|
76
|
+
directoryHashes
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return this.executeRequest<BulkStatusResponse>(
|
|
80
|
+
{
|
|
81
|
+
method: 'POST',
|
|
82
|
+
url: `${this.baseUrl}/v1/builds/${organizationId}/${applicationId}/bulk-status`,
|
|
83
|
+
data
|
|
84
|
+
},
|
|
85
|
+
accessToken
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public async list({
|
|
90
|
+
organizationId,
|
|
91
|
+
applicationId,
|
|
92
|
+
directoryHash,
|
|
93
|
+
accessToken
|
|
94
|
+
}: {
|
|
95
|
+
organizationId: string;
|
|
96
|
+
applicationId: string;
|
|
97
|
+
directoryHash: string;
|
|
98
|
+
accessToken?: string;
|
|
99
|
+
}): Promise<ListResponse> {
|
|
100
|
+
const data = new ListRequest({
|
|
101
|
+
organizationId,
|
|
102
|
+
applicationId,
|
|
103
|
+
directoryHash
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return this.executeRequest<ListResponse>(
|
|
107
|
+
{
|
|
108
|
+
method: 'GET',
|
|
109
|
+
url: `${this.baseUrl}/v1/build`,
|
|
110
|
+
params: data
|
|
111
|
+
},
|
|
112
|
+
accessToken
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public async terminate({
|
|
117
|
+
buildId,
|
|
118
|
+
status,
|
|
119
|
+
buildKey,
|
|
120
|
+
error,
|
|
121
|
+
accessToken
|
|
122
|
+
}: {
|
|
123
|
+
buildId: string;
|
|
124
|
+
status: BuildStatus;
|
|
125
|
+
buildKey?: string;
|
|
126
|
+
error?: string;
|
|
127
|
+
accessToken?: string;
|
|
128
|
+
}): Promise<TerminateResponse> {
|
|
129
|
+
const data = new TerminateRequest({
|
|
130
|
+
buildId,
|
|
131
|
+
status,
|
|
132
|
+
error,
|
|
133
|
+
buildKey
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return this.executeRequest<TerminateResponse>(
|
|
137
|
+
{
|
|
138
|
+
method: 'POST',
|
|
139
|
+
url: `${this.baseUrl}/v1/builds/${buildId}/terminate`,
|
|
140
|
+
data
|
|
141
|
+
},
|
|
142
|
+
accessToken
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
public async createLiveEdit({
|
|
147
|
+
applicationId,
|
|
148
|
+
organizationId,
|
|
149
|
+
branch,
|
|
150
|
+
expiresIn,
|
|
151
|
+
accessToken
|
|
152
|
+
}: {
|
|
153
|
+
applicationId: string;
|
|
154
|
+
organizationId: string;
|
|
155
|
+
branch: string;
|
|
156
|
+
expiresIn: number;
|
|
157
|
+
accessToken: string;
|
|
158
|
+
}): Promise<CreateLiveEditResponse> {
|
|
159
|
+
const data = new CreateLiveEditRequest({
|
|
160
|
+
application: {
|
|
161
|
+
applicationId,
|
|
162
|
+
organizationId: organizationId,
|
|
163
|
+
branch: branch
|
|
164
|
+
},
|
|
165
|
+
sessionJwt: accessToken,
|
|
166
|
+
expiresIn: BigInt(expiresIn)
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
return this.executeRequest<CreateLiveEditResponse>(
|
|
170
|
+
{
|
|
171
|
+
method: 'POST',
|
|
172
|
+
url: `${this.baseUrl}/v1/live-edit`,
|
|
173
|
+
data
|
|
174
|
+
},
|
|
175
|
+
accessToken
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private async executeRequest<T>(config: AxiosRequestConfig, accessToken?: string): Promise<T> {
|
|
180
|
+
let headers: RawAxiosRequestHeaders | undefined;
|
|
181
|
+
if (accessToken || config.headers) {
|
|
182
|
+
headers = {
|
|
183
|
+
...config.headers,
|
|
184
|
+
Authorization: accessToken ? `Bearer ${accessToken}` : undefined
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
const response = await axios.request<T>({
|
|
190
|
+
...config,
|
|
191
|
+
headers
|
|
192
|
+
});
|
|
193
|
+
return response.data;
|
|
194
|
+
} catch (error) {
|
|
195
|
+
let errMsg = `sabs service request failed: ${error.message}`;
|
|
196
|
+
if (axios.isAxiosError(error)) {
|
|
197
|
+
errMsg += `\n[${error.response?.status}] ${error.response?.statusText}: ${JSON.stringify(error.response?.data)}`;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
throw new Error(errMsg);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "esnext",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"composite": true,
|
|
6
|
+
"incremental": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"moduleResolution": "node",
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"rootDir": "./src",
|
|
14
|
+
"outDir": "./dist",
|
|
15
|
+
"allowSyntheticDefaultImports": true,
|
|
16
|
+
"forceConsistentCasingInFileNames": true,
|
|
17
|
+
"resolveJsonModule": true,
|
|
18
|
+
"strictNullChecks": true,
|
|
19
|
+
"allowJs": false,
|
|
20
|
+
"skipLibCheck": true
|
|
21
|
+
},
|
|
22
|
+
"exclude": ["./dist", "./node_modules"],
|
|
23
|
+
"include": ["./**/*.ts"]
|
|
24
|
+
}
|