@superblocksteam/sabs-client 0.258.0 → 0.260.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/dist/errors.d.ts +18 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/errors.test.d.ts +2 -0
- package/dist/errors.test.d.ts.map +1 -0
- package/dist/errors.test.js +272 -0
- package/dist/errors.test.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/sabs.d.ts +110 -0
- package/dist/sabs.d.ts.map +1 -1
- package/dist/sabs.js +159 -29
- package/dist/sabs.js.map +1 -1
- package/dist/sabs.test.js +245 -4
- package/dist/sabs.test.js.map +1 -1
- package/package.json +3 -2
- package/src/errors.test.ts +341 -0
- package/src/errors.ts +60 -0
- package/src/index.ts +1 -0
- package/src/sabs.test.ts +284 -5
- package/src/sabs.ts +159 -30
- package/tsconfig.tsbuildinfo +1 -1
package/dist/sabs.js
CHANGED
|
@@ -6,29 +6,53 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.SabsClient = void 0;
|
|
7
7
|
const sabs_types_1 = require("@superblocksteam/sabs-types");
|
|
8
8
|
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
const errors_1 = require("./errors");
|
|
10
|
+
/**
|
|
11
|
+
* SABS (Superblocks Application Build System) TypeScript Client
|
|
12
|
+
*
|
|
13
|
+
* Provides methods to interact with the SABS API for building and managing applications.
|
|
14
|
+
*
|
|
15
|
+
* All error types inherit from the standard `HttpError` class that extends the standard `Error` class,
|
|
16
|
+
* ensuring backward compatibility with existing error handling code that catches generic `Error` instances
|
|
17
|
+
* used in earlier versions of the client library.
|
|
18
|
+
*/
|
|
9
19
|
class SabsClient {
|
|
10
20
|
baseUrl;
|
|
11
21
|
constructor(baseUrl) {
|
|
12
22
|
this.baseUrl = baseUrl;
|
|
13
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Start a new build for an application
|
|
26
|
+
*
|
|
27
|
+
* @param params - Build parameters
|
|
28
|
+
* @param params.directoryHash - Hash of the application directory to build
|
|
29
|
+
* @param params.meta - Application metadata (ID and organization ID)
|
|
30
|
+
* @param params.buildKey - Secret build key for authentication
|
|
31
|
+
* @param params.accessToken - JWT access token for authorization
|
|
32
|
+
* @returns Promise resolving to build information including build ID
|
|
33
|
+
* @throws BadRequestError if the directory hash, application metadata, application ID, organization ID, build key, or access token are empty or invalid
|
|
34
|
+
* @throws ForbiddenError if the access token is invalid or missing the required scopes
|
|
35
|
+
* @throws InternalServerError if the service has an unexpected error while performing this request
|
|
36
|
+
* @throws HttpError if the request fails for an unknown reason
|
|
37
|
+
*/
|
|
14
38
|
async build({ directoryHash, meta, buildKey, accessToken }) {
|
|
15
39
|
if (!directoryHash || directoryHash.length === 0) {
|
|
16
|
-
throw
|
|
40
|
+
throw (0, errors_1.createClientError)('Directory hash is required');
|
|
17
41
|
}
|
|
18
42
|
if (!meta) {
|
|
19
|
-
throw
|
|
43
|
+
throw (0, errors_1.createClientError)('Application metadata is required');
|
|
20
44
|
}
|
|
21
45
|
if (!meta.id || meta.id.length === 0) {
|
|
22
|
-
throw
|
|
46
|
+
throw (0, errors_1.createClientError)('Application ID is required');
|
|
23
47
|
}
|
|
24
48
|
if (!meta.organizationId || meta.organizationId.length === 0) {
|
|
25
|
-
throw
|
|
49
|
+
throw (0, errors_1.createClientError)('Organization ID is required');
|
|
26
50
|
}
|
|
27
51
|
if (!buildKey || buildKey.length === 0) {
|
|
28
|
-
throw
|
|
52
|
+
throw (0, errors_1.createClientError)('Build key is required');
|
|
29
53
|
}
|
|
30
54
|
if (!accessToken || accessToken.length === 0) {
|
|
31
|
-
throw
|
|
55
|
+
throw (0, errors_1.createClientError)('Access token is required');
|
|
32
56
|
}
|
|
33
57
|
const data = new sabs_types_1.BuildRequest({
|
|
34
58
|
directoryHash: directoryHash,
|
|
@@ -41,30 +65,58 @@ class SabsClient {
|
|
|
41
65
|
data
|
|
42
66
|
}, accessToken);
|
|
43
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Get the status of a build
|
|
70
|
+
*
|
|
71
|
+
* @param params - Status query parameters
|
|
72
|
+
* @param params.buildId - ID of the build to check
|
|
73
|
+
* @param params.accessToken - JWT access token for authorization
|
|
74
|
+
* @returns Promise resolving to build status information
|
|
75
|
+
* @throws BadRequestError if the build ID or access token is empty or invalid
|
|
76
|
+
* @throws UnauthorizedError if the access token is invalid or missing the required scopes
|
|
77
|
+
* @throws NotFoundError if the build ID is invalid
|
|
78
|
+
* @throws InternalServerError if the service has an unexpected error while performing this request
|
|
79
|
+
* @throws HttpError if the request fails for an unknown reason
|
|
80
|
+
*/
|
|
44
81
|
async status({ buildId, accessToken }) {
|
|
45
82
|
if (!buildId || buildId.length === 0) {
|
|
46
|
-
throw
|
|
83
|
+
throw (0, errors_1.createClientError)('Build ID is required');
|
|
47
84
|
}
|
|
48
85
|
if (!accessToken || accessToken.length === 0) {
|
|
49
|
-
throw
|
|
86
|
+
throw (0, errors_1.createClientError)('Access token is required');
|
|
50
87
|
}
|
|
51
88
|
return this.executeRequest({
|
|
52
89
|
method: 'GET',
|
|
53
90
|
url: `${this.baseUrl}/v1/builds/${buildId}`
|
|
54
91
|
}, accessToken);
|
|
55
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Get the status of multiple builds at once
|
|
95
|
+
*
|
|
96
|
+
* @param params - Bulk status query parameters
|
|
97
|
+
* @param params.organizationId - Organization ID
|
|
98
|
+
* @param params.applicationId - Application ID
|
|
99
|
+
* @param params.directoryHashes - Array of directory hashes to check
|
|
100
|
+
* @param params.accessToken - JWT access token for authorization
|
|
101
|
+
* @returns Promise resolving to multiple build status information
|
|
102
|
+
* @throws BadRequestError if the organization ID, application ID, directory hashes, or access token are empty or invalid
|
|
103
|
+
* @throws UnauthorizedError if the access token is invalid or missing the required scopes
|
|
104
|
+
* @throws NotFoundError if the organization ID or application ID is invalid
|
|
105
|
+
* @throws InternalServerError if the service has an unexpected error while performing this request
|
|
106
|
+
* @throws HttpError if the request fails for an unknown reason
|
|
107
|
+
*/
|
|
56
108
|
async bulkStatus({ organizationId, applicationId, directoryHashes, accessToken }) {
|
|
57
109
|
if (!organizationId || organizationId.length === 0) {
|
|
58
|
-
throw
|
|
110
|
+
throw (0, errors_1.createClientError)('Organization ID is required');
|
|
59
111
|
}
|
|
60
112
|
if (!applicationId || applicationId.length === 0) {
|
|
61
|
-
throw
|
|
113
|
+
throw (0, errors_1.createClientError)('Application ID is required');
|
|
62
114
|
}
|
|
63
115
|
if (!directoryHashes || directoryHashes.length === 0) {
|
|
64
|
-
throw
|
|
116
|
+
throw (0, errors_1.createClientError)('Directory hashes are required');
|
|
65
117
|
}
|
|
66
118
|
if (!accessToken || accessToken.length === 0) {
|
|
67
|
-
throw
|
|
119
|
+
throw (0, errors_1.createClientError)('Access token is required');
|
|
68
120
|
}
|
|
69
121
|
const data = new sabs_types_1.BulkStatusRequest({
|
|
70
122
|
organizationId,
|
|
@@ -77,18 +129,33 @@ class SabsClient {
|
|
|
77
129
|
data
|
|
78
130
|
}, accessToken);
|
|
79
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* List all builds for a specific application and directory
|
|
134
|
+
*
|
|
135
|
+
* @param params - List query parameters
|
|
136
|
+
* @param params.organizationId - Organization ID
|
|
137
|
+
* @param params.applicationId - Application ID
|
|
138
|
+
* @param params.directoryHash - Hash of the application directory
|
|
139
|
+
* @param params.accessToken - JWT access token for authorization
|
|
140
|
+
* @returns Promise resolving to list of builds
|
|
141
|
+
* @throws BadRequestError if the organization ID, application ID, directory hash, or access token are empty or invalid
|
|
142
|
+
* @throws UnauthorizedError if the access token is invalid or missing the required scopes
|
|
143
|
+
* @throws NotFoundError if the organization ID or application ID is invalid
|
|
144
|
+
* @throws InternalServerError if the service has an unexpected error while performing this request
|
|
145
|
+
* @throws HttpError if the request fails for an unknown reason
|
|
146
|
+
*/
|
|
80
147
|
async list({ organizationId, applicationId, directoryHash, accessToken }) {
|
|
81
148
|
if (!organizationId || organizationId.length === 0) {
|
|
82
|
-
throw
|
|
149
|
+
throw (0, errors_1.createClientError)('Organization ID is required');
|
|
83
150
|
}
|
|
84
151
|
if (!applicationId || applicationId.length === 0) {
|
|
85
|
-
throw
|
|
152
|
+
throw (0, errors_1.createClientError)('Application ID is required');
|
|
86
153
|
}
|
|
87
154
|
if (!directoryHash || directoryHash.length === 0) {
|
|
88
|
-
throw
|
|
155
|
+
throw (0, errors_1.createClientError)('Directory hash is required');
|
|
89
156
|
}
|
|
90
157
|
if (!accessToken || accessToken.length === 0) {
|
|
91
|
-
throw
|
|
158
|
+
throw (0, errors_1.createClientError)('Access token is required');
|
|
92
159
|
}
|
|
93
160
|
const data = new sabs_types_1.ListRequest({
|
|
94
161
|
organizationId,
|
|
@@ -101,18 +168,34 @@ class SabsClient {
|
|
|
101
168
|
params: data
|
|
102
169
|
}, accessToken);
|
|
103
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Terminate a running build with a final status
|
|
173
|
+
*
|
|
174
|
+
* @param params - Termination parameters
|
|
175
|
+
* @param params.buildId - ID of the build to terminate
|
|
176
|
+
* @param params.status - Final status of the build
|
|
177
|
+
* @param params.buildKey - Secret build key for authentication
|
|
178
|
+
* @param params.error - Optional error message if build failed
|
|
179
|
+
* @param params.accessToken - JWT access token for authorization
|
|
180
|
+
* @returns Promise resolving to termination confirmation
|
|
181
|
+
* @throws BadRequestError if the build ID, build status, build key, or access token are empty or invalid
|
|
182
|
+
* @throws UnauthorizedError if the access token is invalid or missing the required scopes
|
|
183
|
+
* @throws NotFoundError if the build ID is invalid
|
|
184
|
+
* @throws InternalServerError if the service has an unexpected error while performing this request
|
|
185
|
+
* @throws HttpError if the request fails for an unknown reason
|
|
186
|
+
*/
|
|
104
187
|
async terminate({ buildId, status, buildKey, error, accessToken }) {
|
|
105
188
|
if (!buildId || buildId.length === 0) {
|
|
106
|
-
throw
|
|
189
|
+
throw (0, errors_1.createClientError)('Build ID is required');
|
|
107
190
|
}
|
|
108
191
|
if (!status) {
|
|
109
|
-
throw
|
|
192
|
+
throw (0, errors_1.createClientError)('Build status is required');
|
|
110
193
|
}
|
|
111
194
|
if (!buildKey || buildKey.length === 0) {
|
|
112
|
-
throw
|
|
195
|
+
throw (0, errors_1.createClientError)('Build key is required');
|
|
113
196
|
}
|
|
114
197
|
if (!accessToken || accessToken.length === 0) {
|
|
115
|
-
throw
|
|
198
|
+
throw (0, errors_1.createClientError)('Access token is required');
|
|
116
199
|
}
|
|
117
200
|
const data = new sabs_types_1.TerminateRequest({
|
|
118
201
|
buildId,
|
|
@@ -126,18 +209,36 @@ class SabsClient {
|
|
|
126
209
|
data
|
|
127
210
|
}, accessToken);
|
|
128
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Create a new live edit session for real-time development
|
|
214
|
+
*
|
|
215
|
+
* @param params - Live edit creation parameters
|
|
216
|
+
* @param params.applicationId - Application ID
|
|
217
|
+
* @param params.organizationId - Organization ID
|
|
218
|
+
* @param params.branch - Git branch name
|
|
219
|
+
* @param params.expiresIn - Session duration in seconds
|
|
220
|
+
* @param params.accessToken - JWT access token for authorization
|
|
221
|
+
* @returns Promise resolving to live edit session information
|
|
222
|
+
* @throws BadRequestError if the application ID, organization ID, branch, or access token are empty or invalid, or expiresIn is not greater than 0
|
|
223
|
+
* @throws UnauthorizedError if the access token is invalid or missing the required scopes
|
|
224
|
+
* @throws InternalServerError if the service has an unexpected error while performing this request
|
|
225
|
+
* @throws HttpError if the request fails for an unknown reason
|
|
226
|
+
*/
|
|
129
227
|
async createLiveEdit({ applicationId, organizationId, branch, expiresIn, accessToken }) {
|
|
130
228
|
if (!applicationId || applicationId.length === 0) {
|
|
131
|
-
throw
|
|
229
|
+
throw (0, errors_1.createClientError)('Application ID is required');
|
|
132
230
|
}
|
|
133
231
|
if (!organizationId || organizationId.length === 0) {
|
|
134
|
-
throw
|
|
232
|
+
throw (0, errors_1.createClientError)('Organization ID is required');
|
|
135
233
|
}
|
|
136
234
|
if (!branch || branch.length === 0) {
|
|
137
|
-
throw
|
|
235
|
+
throw (0, errors_1.createClientError)('Branch is required');
|
|
138
236
|
}
|
|
139
237
|
if (!accessToken || accessToken.length === 0) {
|
|
140
|
-
throw
|
|
238
|
+
throw (0, errors_1.createClientError)('Access token is required');
|
|
239
|
+
}
|
|
240
|
+
if (!expiresIn || expiresIn <= 0) {
|
|
241
|
+
throw (0, errors_1.createClientError)('Expires in is required and must be greater than 0');
|
|
141
242
|
}
|
|
142
243
|
const data = new sabs_types_1.CreateLiveEditRequest({
|
|
143
244
|
application: {
|
|
@@ -154,12 +255,25 @@ class SabsClient {
|
|
|
154
255
|
data
|
|
155
256
|
}, accessToken);
|
|
156
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* Terminate an active live edit session
|
|
260
|
+
*
|
|
261
|
+
* @param params - Live edit termination parameters
|
|
262
|
+
* @param params.liveEditId - ID of the live edit session to terminate
|
|
263
|
+
* @param params.accessToken - JWT access token for authorization
|
|
264
|
+
* @returns Promise resolving to termination confirmation
|
|
265
|
+
* @throws BadRequestError if the live edit ID or access token are empty or invalid
|
|
266
|
+
* @throws UnauthorizedError if the access token is invalid or missing the required scopes
|
|
267
|
+
* @throws NotFoundError if the live edit ID is invalid
|
|
268
|
+
* @throws InternalServerError if the service has an unexpected error while performing this request
|
|
269
|
+
* @throws HttpError if the request fails for an unknown reason
|
|
270
|
+
*/
|
|
157
271
|
async terminateLiveEdit({ liveEditId, accessToken }) {
|
|
158
272
|
if (!liveEditId || liveEditId.length === 0) {
|
|
159
|
-
throw
|
|
273
|
+
throw (0, errors_1.createClientError)('Live edit ID is required');
|
|
160
274
|
}
|
|
161
275
|
if (!accessToken || accessToken.length === 0) {
|
|
162
|
-
throw
|
|
276
|
+
throw (0, errors_1.createClientError)('Access token is required');
|
|
163
277
|
}
|
|
164
278
|
const data = new sabs_types_1.TerminateLiveEditRequest({
|
|
165
279
|
liveEditId
|
|
@@ -186,11 +300,27 @@ class SabsClient {
|
|
|
186
300
|
return response.data;
|
|
187
301
|
}
|
|
188
302
|
catch (error) {
|
|
189
|
-
let errMsg = `sabs service request failed: ${error.message}`;
|
|
190
303
|
if (axios_1.default.isAxiosError(error)) {
|
|
191
|
-
|
|
304
|
+
const statusCode = error.response?.status ?? 500;
|
|
305
|
+
const statusText = error.response?.statusText ?? 'Unknown Error';
|
|
306
|
+
const responseData = error.response?.data;
|
|
307
|
+
let message;
|
|
308
|
+
if (responseData && typeof responseData === 'object' && responseData.message) {
|
|
309
|
+
message = responseData.message;
|
|
310
|
+
}
|
|
311
|
+
else if (responseData && typeof responseData === 'string') {
|
|
312
|
+
message = responseData;
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
message = `${statusText} (${statusCode})`;
|
|
316
|
+
}
|
|
317
|
+
throw (0, errors_1.createErrorFromStatusCode)(statusCode, message);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
// Network error or other non-HTTP error
|
|
321
|
+
const message = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
322
|
+
throw (0, errors_1.createNetworkError)(message, error instanceof Error ? error : undefined);
|
|
192
323
|
}
|
|
193
|
-
throw new Error(errMsg);
|
|
194
324
|
}
|
|
195
325
|
}
|
|
196
326
|
}
|
package/dist/sabs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sabs.js","sourceRoot":"","sources":["../src/sabs.ts"],"names":[],"mappings":";;;;;;AAAA,4DAgBqC;AACrC,kDAA0E;AAE1E,MAAa,UAAU;IACJ,OAAO,CAAS;IAEjC,YAAmB,OAAe;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;
|
|
1
|
+
{"version":3,"file":"sabs.js","sourceRoot":"","sources":["../src/sabs.ts"],"names":[],"mappings":";;;;;;AAAA,4DAgBqC;AACrC,kDAA0E;AAE1E,qCAA4F;AAE5F;;;;;;;;GAQG;AACH,MAAa,UAAU;IACJ,OAAO,CAAS;IAEjC,YAAmB,OAAe;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACI,KAAK,CAAC,KAAK,CAAC,EACjB,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,WAAW,EAMZ;QACC,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,IAAA,0BAAiB,EAAC,4BAA4B,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAA,0BAAiB,EAAC,kCAAkC,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAA,0BAAiB,EAAC,4BAA4B,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAA,0BAAiB,EAAC,6BAA6B,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,IAAA,0BAAiB,EAAC,uBAAuB,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,yBAAY,CAAC;YAC5B,aAAa,EAAE,aAAa;YAC5B,mBAAmB,EAAE,IAAI;YACzB,QAAQ;SACT,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,cAAc,CACxB;YACE,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,YAAY;YAChC,IAAI;SACL,EACD,WAAW,CACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,WAAW,EAA6C;QACrF,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAA,0BAAiB,EAAC,sBAAsB,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,IAAI,CAAC,cAAc,CACxB;YACE,MAAM,EAAE,KAAK;YACb,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,cAAc,OAAO,EAAE;SAC5C,EACD,WAAW,CACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACI,KAAK,CAAC,UAAU,CAAC,EACtB,cAAc,EACd,aAAa,EACb,eAAe,EACf,WAAW,EAMZ;QACC,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnD,MAAM,IAAA,0BAAiB,EAAC,6BAA6B,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,IAAA,0BAAiB,EAAC,4BAA4B,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrD,MAAM,IAAA,0BAAiB,EAAC,+BAA+B,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,8BAAiB,CAAC;YACjC,cAAc;YACd,aAAa;YACb,eAAe;SAChB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,cAAc,CACxB;YACE,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,cAAc,cAAc,IAAI,aAAa,cAAc;YAC/E,IAAI;SACL,EACD,WAAW,CACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACI,KAAK,CAAC,IAAI,CAAC,EAChB,cAAc,EACd,aAAa,EACb,aAAa,EACb,WAAW,EAMZ;QACC,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnD,MAAM,IAAA,0BAAiB,EAAC,6BAA6B,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,IAAA,0BAAiB,EAAC,4BAA4B,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,IAAA,0BAAiB,EAAC,4BAA4B,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,wBAAW,CAAC;YAC3B,cAAc;YACd,aAAa;YACb,aAAa;SACd,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,cAAc,CACxB;YACE,MAAM,EAAE,KAAK;YACb,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,WAAW;YAC/B,MAAM,EAAE,IAAI;SACb,EACD,WAAW,CACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACI,KAAK,CAAC,SAAS,CAAC,EACrB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,KAAK,EACL,WAAW,EAOZ;QACC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAA,0BAAiB,EAAC,sBAAsB,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,IAAA,0BAAiB,EAAC,uBAAuB,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,6BAAgB,CAAC;YAChC,OAAO;YACP,MAAM;YACN,KAAK;YACL,QAAQ;SACT,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,cAAc,CACxB;YACE,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,cAAc,OAAO,YAAY;YACrD,IAAI;SACL,EACD,WAAW,CACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACI,KAAK,CAAC,cAAc,CAAC,EAC1B,aAAa,EACb,cAAc,EACd,MAAM,EACN,SAAS,EACT,WAAW,EAOZ;QACC,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,IAAA,0BAAiB,EAAC,4BAA4B,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnD,MAAM,IAAA,0BAAiB,EAAC,6BAA6B,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,MAAM,IAAA,0BAAiB,EAAC,oBAAoB,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,SAAS,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,IAAA,0BAAiB,EAAC,mDAAmD,CAAC,CAAC;QAC/E,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,kCAAqB,CAAC;YACrC,WAAW,EAAE;gBACX,aAAa;gBACb,cAAc,EAAE,cAAc;gBAC9B,MAAM,EAAE,MAAM;aACf;YACD,UAAU,EAAE,WAAW;YACvB,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC;SAC7B,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,cAAc,CACxB;YACE,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,eAAe;YACnC,IAAI;SACL,EACD,WAAW,CACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,KAAK,CAAC,iBAAiB,CAAC,EAC7B,UAAU,EACV,WAAW,EAIZ;QACC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAA,0BAAiB,EAAC,0BAA0B,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,qCAAwB,CAAC;YACxC,UAAU;SACX,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,cAAc,CACxB;YACE,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,iBAAiB,UAAU,YAAY;YAC3D,IAAI;SACL,EACD,WAAW,CACZ,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,cAAc,CAAI,MAA0B,EAAE,WAAoB;QAC9E,IAAI,OAA2C,CAAC;QAChD,IAAI,WAAW,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAClC,OAAO,GAAG;gBACR,GAAG,MAAM,CAAC,OAAO;gBACjB,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC,UAAU,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;aACjE,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,OAAO,CAAI;gBACtC,GAAG,MAAM;gBACT,OAAO;aACR,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,eAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC;gBACjD,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,EAAE,UAAU,IAAI,eAAe,CAAC;gBACjE,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC;gBAE1C,IAAI,OAAe,CAAC;gBACpB,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;oBAC7E,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC;gBACjC,CAAC;qBAAM,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;oBAC5D,OAAO,GAAG,YAAY,CAAC;gBACzB,CAAC;qBAAM,CAAC;oBACN,OAAO,GAAG,GAAG,UAAU,KAAK,UAAU,GAAG,CAAC;gBAC5C,CAAC;gBAED,MAAM,IAAA,kCAAyB,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,wCAAwC;gBACxC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;gBAClF,MAAM,IAAA,2BAAkB,EAAC,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAChF,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAzZD,gCAyZC"}
|
package/dist/sabs.test.js
CHANGED
|
@@ -695,17 +695,258 @@ describe('sabs service', () => {
|
|
|
695
695
|
data: 'failed to process request'
|
|
696
696
|
}));
|
|
697
697
|
const anyBuildId = 'anyBuildId';
|
|
698
|
-
const expectedError = 'sabs service request failed: request failed\n[500] internal server error: "failed to process request"';
|
|
699
698
|
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
700
|
-
await expect(sabs.status({ buildId: anyBuildId, accessToken: anyAccessToken })).rejects.toThrow(
|
|
699
|
+
await expect(sabs.status({ buildId: anyBuildId, accessToken: anyAccessToken })).rejects.toThrow();
|
|
701
700
|
});
|
|
702
701
|
test('re-raises error when error is not axios error', async () => {
|
|
703
702
|
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
704
703
|
mockAxios.mockRejectedValue(new Error('unexpected error'));
|
|
705
704
|
const anyBuildId = 'anyBuildId';
|
|
706
|
-
const expectedError = 'sabs service request failed: unexpected error';
|
|
707
705
|
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
708
|
-
await expect(sabs.status({ buildId: anyBuildId, accessToken: anyAccessToken })).rejects.toThrow(
|
|
706
|
+
await expect(sabs.status({ buildId: anyBuildId, accessToken: anyAccessToken })).rejects.toThrow();
|
|
707
|
+
});
|
|
708
|
+
});
|
|
709
|
+
describe('backward compatibility', () => {
|
|
710
|
+
test('errors can be caught as generic Error instances (backward compatibility)', async () => {
|
|
711
|
+
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
712
|
+
mockAxios.mockRejectedValue(new axios_1.AxiosError('Service unavailable', 'ECONNREFUSED', undefined, undefined, {
|
|
713
|
+
headers: {},
|
|
714
|
+
config: {
|
|
715
|
+
headers: new axios_1.AxiosHeaders()
|
|
716
|
+
},
|
|
717
|
+
status: 503,
|
|
718
|
+
statusText: 'Service Unavailable',
|
|
719
|
+
data: { message: 'Server temporarily unavailable' }
|
|
720
|
+
}));
|
|
721
|
+
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
722
|
+
const applicationId = 'test-app';
|
|
723
|
+
const organizationId = 'test-org';
|
|
724
|
+
const directoryHash = 'abc123';
|
|
725
|
+
// This simulates how existing applications might handle errors
|
|
726
|
+
try {
|
|
727
|
+
const result = await sabs.build({
|
|
728
|
+
directoryHash,
|
|
729
|
+
meta: new sabs_types_1.ApplicationMetadata({
|
|
730
|
+
id: applicationId,
|
|
731
|
+
organizationId
|
|
732
|
+
}),
|
|
733
|
+
buildKey: anyBuildKey,
|
|
734
|
+
accessToken: anyAccessToken
|
|
735
|
+
});
|
|
736
|
+
// Should not reach here
|
|
737
|
+
expect(result).toBeUndefined();
|
|
738
|
+
}
|
|
739
|
+
catch (error) {
|
|
740
|
+
// Legacy error handling - should still work with new error types
|
|
741
|
+
expect(error).toBeInstanceOf(Error);
|
|
742
|
+
expect(error.message).toContain('SABS API Error (503)');
|
|
743
|
+
// Verify we can still access basic Error properties
|
|
744
|
+
expect(typeof error.message).toBe('string');
|
|
745
|
+
expect(error.name).toBeDefined();
|
|
746
|
+
// This is how existing code might log and re-throw
|
|
747
|
+
const loggedError = {
|
|
748
|
+
error,
|
|
749
|
+
applicationId,
|
|
750
|
+
organizationId,
|
|
751
|
+
directoryHash,
|
|
752
|
+
message: error.message
|
|
753
|
+
};
|
|
754
|
+
expect(loggedError.error).toBe(error);
|
|
755
|
+
expect(loggedError.message).toBe(error.message);
|
|
756
|
+
// Re-throwing as generic Error should work
|
|
757
|
+
expect(() => {
|
|
758
|
+
throw new Error('Unable to launch build');
|
|
759
|
+
}).toThrow('Unable to launch build');
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
test('new error types provide additional functionality when accessed', async () => {
|
|
763
|
+
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
764
|
+
mockAxios.mockRejectedValue(new axios_1.AxiosError('Unauthorized', 'UNAUTHORIZED', undefined, undefined, {
|
|
765
|
+
headers: {},
|
|
766
|
+
config: {
|
|
767
|
+
headers: new axios_1.AxiosHeaders()
|
|
768
|
+
},
|
|
769
|
+
status: 401,
|
|
770
|
+
statusText: 'Unauthorized',
|
|
771
|
+
data: { message: 'Invalid token' }
|
|
772
|
+
}));
|
|
773
|
+
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
774
|
+
try {
|
|
775
|
+
await sabs.status({ buildId: 'test-build', accessToken: 'invalid-token' });
|
|
776
|
+
}
|
|
777
|
+
catch (error) {
|
|
778
|
+
// Backward compatible - can still catch as Error
|
|
779
|
+
expect(error).toBeInstanceOf(Error);
|
|
780
|
+
// But applications can now also check for specific error types
|
|
781
|
+
const { UnauthorizedError } = await Promise.resolve().then(() => __importStar(require('./errors')));
|
|
782
|
+
expect(error).toBeInstanceOf(UnauthorizedError);
|
|
783
|
+
// And access the status code if needed
|
|
784
|
+
if ('status' in error) {
|
|
785
|
+
expect(error.status).toBe(401);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
});
|
|
789
|
+
describe('response data handling', () => {
|
|
790
|
+
test('handles responseData with message property', async () => {
|
|
791
|
+
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
792
|
+
mockAxios.mockRejectedValue(new axios_1.AxiosError('Bad Request', 'BAD_REQUEST', undefined, undefined, {
|
|
793
|
+
headers: {},
|
|
794
|
+
config: {
|
|
795
|
+
headers: new axios_1.AxiosHeaders()
|
|
796
|
+
},
|
|
797
|
+
status: 400,
|
|
798
|
+
statusText: 'Bad Request',
|
|
799
|
+
data: { message: 'Directory hash is required' }
|
|
800
|
+
}));
|
|
801
|
+
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
802
|
+
try {
|
|
803
|
+
await sabs.build({
|
|
804
|
+
directoryHash: 'test', // Use non-empty value to avoid client-side validation
|
|
805
|
+
meta: new sabs_types_1.ApplicationMetadata({ id: 'test', organizationId: 'test' }),
|
|
806
|
+
buildKey: 'test',
|
|
807
|
+
accessToken: 'test'
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
catch (error) {
|
|
811
|
+
expect(error).toBeInstanceOf(Error);
|
|
812
|
+
expect(error.message).toBe('SABS API Error (400): Directory hash is required');
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
test('handles responseData as string', async () => {
|
|
816
|
+
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
817
|
+
mockAxios.mockRejectedValue(new axios_1.AxiosError('Internal Server Error', 'INTERNAL_SERVER_ERROR', undefined, undefined, {
|
|
818
|
+
headers: {},
|
|
819
|
+
config: {
|
|
820
|
+
headers: new axios_1.AxiosHeaders()
|
|
821
|
+
},
|
|
822
|
+
status: 500,
|
|
823
|
+
statusText: 'Internal Server Error',
|
|
824
|
+
data: 'Database connection failed'
|
|
825
|
+
}));
|
|
826
|
+
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
827
|
+
try {
|
|
828
|
+
await sabs.build({
|
|
829
|
+
directoryHash: 'test',
|
|
830
|
+
meta: new sabs_types_1.ApplicationMetadata({ id: 'test', organizationId: 'test' }),
|
|
831
|
+
buildKey: 'test',
|
|
832
|
+
accessToken: 'test'
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
catch (error) {
|
|
836
|
+
expect(error).toBeInstanceOf(Error);
|
|
837
|
+
expect(error.message).toBe('SABS API Error (500): Database connection failed');
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
test('handles null responseData', async () => {
|
|
841
|
+
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
842
|
+
mockAxios.mockRejectedValue(new axios_1.AxiosError('Service Unavailable', 'SERVICE_UNAVAILABLE', undefined, undefined, {
|
|
843
|
+
headers: {},
|
|
844
|
+
config: {
|
|
845
|
+
headers: new axios_1.AxiosHeaders()
|
|
846
|
+
},
|
|
847
|
+
status: 503,
|
|
848
|
+
statusText: 'Service Unavailable',
|
|
849
|
+
data: null
|
|
850
|
+
}));
|
|
851
|
+
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
852
|
+
try {
|
|
853
|
+
await sabs.build({
|
|
854
|
+
directoryHash: 'test',
|
|
855
|
+
meta: new sabs_types_1.ApplicationMetadata({ id: 'test', organizationId: 'test' }),
|
|
856
|
+
buildKey: 'test',
|
|
857
|
+
accessToken: 'test'
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
catch (error) {
|
|
861
|
+
expect(error).toBeInstanceOf(Error);
|
|
862
|
+
expect(error.message).toBe('SABS API Error (503): Service Unavailable (503)');
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
test('handles undefined responseData', async () => {
|
|
866
|
+
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
867
|
+
mockAxios.mockRejectedValue(new axios_1.AxiosError('Gateway Timeout', 'GATEWAY_TIMEOUT', undefined, undefined, {
|
|
868
|
+
headers: {},
|
|
869
|
+
config: {
|
|
870
|
+
headers: new axios_1.AxiosHeaders()
|
|
871
|
+
},
|
|
872
|
+
status: 504,
|
|
873
|
+
statusText: 'Gateway Timeout',
|
|
874
|
+
data: undefined
|
|
875
|
+
}));
|
|
876
|
+
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
877
|
+
try {
|
|
878
|
+
await sabs.build({
|
|
879
|
+
directoryHash: 'test',
|
|
880
|
+
meta: new sabs_types_1.ApplicationMetadata({ id: 'test', organizationId: 'test' }),
|
|
881
|
+
buildKey: 'test',
|
|
882
|
+
accessToken: 'test'
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
catch (error) {
|
|
886
|
+
expect(error).toBeInstanceOf(Error);
|
|
887
|
+
expect(error.message).toBe('SABS API Error (504): Gateway Timeout (504)');
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
test('handles responseData object without message property', async () => {
|
|
891
|
+
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
892
|
+
mockAxios.mockRejectedValue(new axios_1.AxiosError('Bad Request', 'BAD_REQUEST', undefined, undefined, {
|
|
893
|
+
headers: {},
|
|
894
|
+
config: {
|
|
895
|
+
headers: new axios_1.AxiosHeaders()
|
|
896
|
+
},
|
|
897
|
+
status: 400,
|
|
898
|
+
statusText: 'Bad Request',
|
|
899
|
+
data: { error: 'validation_failed', details: ['field is required'] }
|
|
900
|
+
}));
|
|
901
|
+
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
902
|
+
try {
|
|
903
|
+
await sabs.build({
|
|
904
|
+
directoryHash: 'test',
|
|
905
|
+
meta: new sabs_types_1.ApplicationMetadata({ id: 'test', organizationId: 'test' }),
|
|
906
|
+
buildKey: 'test',
|
|
907
|
+
accessToken: 'test'
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
catch (error) {
|
|
911
|
+
expect(error).toBeInstanceOf(Error);
|
|
912
|
+
expect(error.message).toBe('SABS API Error (400): Bad Request (400)');
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
test('all errors have consistent HttpError interface', async () => {
|
|
916
|
+
const responseData = { code: 'TIMEOUT', retryAfter: 30 };
|
|
917
|
+
const mockAxios = jest.spyOn(axios_1.default, 'request');
|
|
918
|
+
mockAxios.mockRejectedValue(new axios_1.AxiosError('Request timeout', 'TIMEOUT', undefined, undefined, {
|
|
919
|
+
headers: {},
|
|
920
|
+
config: {
|
|
921
|
+
headers: new axios_1.AxiosHeaders()
|
|
922
|
+
},
|
|
923
|
+
status: 500,
|
|
924
|
+
statusText: 'Internal Server Error',
|
|
925
|
+
data: responseData
|
|
926
|
+
}));
|
|
927
|
+
const sabs = new sabs_1.SabsClient('http://localhost:3000');
|
|
928
|
+
try {
|
|
929
|
+
await sabs.build({
|
|
930
|
+
directoryHash: 'test',
|
|
931
|
+
meta: new sabs_types_1.ApplicationMetadata({ id: 'test', organizationId: 'test' }),
|
|
932
|
+
buildKey: 'test',
|
|
933
|
+
accessToken: 'test'
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
catch (error) {
|
|
937
|
+
expect(error).toBeInstanceOf(Error);
|
|
938
|
+
expect(error.message).toBe('SABS API Error (500): Internal Server Error (500)');
|
|
939
|
+
// All error types now have consistent HttpError interface
|
|
940
|
+
expect('status' in error).toBe(true);
|
|
941
|
+
expect('title' in error).toBe(true);
|
|
942
|
+
if ('status' in error) {
|
|
943
|
+
expect(error.status).toBe(500);
|
|
944
|
+
}
|
|
945
|
+
if ('title' in error) {
|
|
946
|
+
expect(error.title).toBe('Internal server error');
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
});
|
|
709
950
|
});
|
|
710
951
|
});
|
|
711
952
|
});
|