@scalekit-sdk/node 2.0.0 → 2.1.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/jest.config.js +15 -0
- package/lib/core.d.ts +1 -1
- package/lib/core.js +31 -31
- package/lib/core.js.map +1 -1
- package/lib/errors/base-exception.d.ts +32 -0
- package/lib/errors/base-exception.js +238 -0
- package/lib/errors/base-exception.js.map +1 -0
- package/lib/errors/index.d.ts +2 -0
- package/lib/errors/index.js +20 -0
- package/lib/errors/index.js.map +1 -0
- package/lib/errors/specific-exceptions.d.ts +39 -0
- package/lib/errors/specific-exceptions.js +90 -0
- package/lib/errors/specific-exceptions.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.d.ts +34 -87
- package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.js +31 -120
- package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.d.ts +19 -10
- package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.js +18 -9
- package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.d.ts +209 -6
- package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.js +272 -5
- package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.d.ts +29 -0
- package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.js +40 -1
- package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.d.ts +25 -0
- package/lib/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.js +38 -1
- package/lib/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.d.ts +21 -1
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.js +20 -0
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.d.ts +110 -5
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.js +164 -5
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/users/users_connect.d.ts +48 -1
- package/lib/pkg/grpc/scalekit/v1/users/users_connect.js +47 -0
- package/lib/pkg/grpc/scalekit/v1/users/users_connect.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/users/users_pb.d.ts +280 -4
- package/lib/pkg/grpc/scalekit/v1/users/users_pb.js +449 -11
- package/lib/pkg/grpc/scalekit/v1/users/users_pb.js.map +1 -1
- package/lib/scalekit.d.ts +29 -8
- package/lib/scalekit.js +78 -28
- package/lib/scalekit.js.map +1 -1
- package/lib/types/scalekit.d.ts +5 -0
- package/lib/types/user.d.ts +1 -1
- package/lib/user.d.ts +10 -3
- package/lib/user.js +26 -5
- package/lib/user.js.map +1 -1
- package/package.json +6 -2
- package/src/core.ts +31 -32
- package/src/errors/base-exception.ts +262 -0
- package/src/errors/index.ts +3 -0
- package/src/errors/specific-exceptions.ts +88 -0
- package/src/index.ts +3 -1
- package/src/pkg/grpc/scalekit/v1/commons/commons_pb.ts +49 -129
- package/src/pkg/grpc/scalekit/v1/connections/connections_connect.ts +19 -10
- package/src/pkg/grpc/scalekit/v1/connections/connections_pb.ts +377 -8
- package/src/pkg/grpc/scalekit/v1/domains/domains_pb.ts +44 -0
- package/src/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.ts +49 -0
- package/src/pkg/grpc/scalekit/v1/organizations/organizations_connect.ts +21 -1
- package/src/pkg/grpc/scalekit/v1/organizations/organizations_pb.ts +218 -5
- package/src/pkg/grpc/scalekit/v1/users/users_connect.ts +48 -1
- package/src/pkg/grpc/scalekit/v1/users/users_pb.ts +558 -6
- package/src/scalekit.ts +95 -30
- package/src/types/scalekit.ts +6 -0
- package/src/types/user.ts +1 -1
- package/src/user.ts +34 -7
- package/tests/README.md +25 -0
- package/tests/connection.test.ts +42 -0
- package/tests/directory.test.ts +46 -0
- package/tests/organization.test.ts +65 -0
- package/tests/passwordless.test.ts +108 -0
- package/tests/scalekit.test.ts +104 -0
- package/tests/setup.ts +34 -0
- package/tests/users.test.ts +168 -0
- package/tests/utils/test-data.ts +248 -0
package/lib/user.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.js","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":";;;;;;;;;;;AAIA,8EAAyE;AACzE,
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.1.0",
|
|
3
3
|
"name": "@scalekit-sdk/node",
|
|
4
4
|
"description": "Official Scalekit Node SDK",
|
|
5
5
|
"main": "lib/index.js",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"generate": "npx buf generate $npm_config_src",
|
|
13
13
|
"build": "rm -rf lib && tsc",
|
|
14
|
-
"test": "
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"test:watch": "jest --watch"
|
|
15
16
|
},
|
|
16
17
|
"keywords": [
|
|
17
18
|
"sso",
|
|
@@ -34,9 +35,12 @@
|
|
|
34
35
|
"@bufbuild/buf": "^1.36.0",
|
|
35
36
|
"@bufbuild/protoc-gen-es": "^1.10.0",
|
|
36
37
|
"@connectrpc/protoc-gen-connect-es": "^1.4.0",
|
|
38
|
+
"@types/jest": "^29.5.14",
|
|
37
39
|
"@types/node": "^20.14.10",
|
|
38
40
|
"@types/qs": "^6.9.15",
|
|
39
41
|
"dotenv": "^16.4.7",
|
|
42
|
+
"jest": "^29.7.0",
|
|
43
|
+
"ts-jest": "^29.4.0",
|
|
40
44
|
"ts-node": "^10.9.2",
|
|
41
45
|
"typescript": "^5.5.3"
|
|
42
46
|
},
|
package/src/core.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { JWK } from 'jose';
|
|
|
4
4
|
import os from "os";
|
|
5
5
|
import QueryString from "qs";
|
|
6
6
|
import { GrantType } from './types/scalekit';
|
|
7
|
-
import { ErrorInfo } from './pkg/grpc/scalekit/v1/errdetails/errdetails_pb';
|
|
8
7
|
import { TokenResponse } from './types/auth';
|
|
8
|
+
import { ScalekitException, ScalekitServerException } from './errors/base-exception';
|
|
9
9
|
|
|
10
10
|
export const headers = {
|
|
11
11
|
"user-agent": "user-agent",
|
|
@@ -20,8 +20,8 @@ export default class CoreClient {
|
|
|
20
20
|
public keys: JWK[] = [];
|
|
21
21
|
public accessToken: string | null = null;
|
|
22
22
|
public axios: Axios;
|
|
23
|
-
public sdkVersion = `Scalekit-Node/2.
|
|
24
|
-
public apiVersion = "
|
|
23
|
+
public sdkVersion = `Scalekit-Node/2.1.0`;
|
|
24
|
+
public apiVersion = "20250815";
|
|
25
25
|
public userAgent = `${this.sdkVersion} Node/${process.version} (${process.platform}; ${os.arch()})`;
|
|
26
26
|
constructor(
|
|
27
27
|
readonly envUrl: string,
|
|
@@ -81,7 +81,7 @@ export default class CoreClient {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
84
|
+
* Execute a function with error handling and retry logic
|
|
85
85
|
* @param fn Function to execute
|
|
86
86
|
* @param data Data to pass to the function
|
|
87
87
|
* @param retryLeft Number of retries left
|
|
@@ -96,39 +96,38 @@ export default class CoreClient {
|
|
|
96
96
|
const res = await fn(data);
|
|
97
97
|
return res;
|
|
98
98
|
} catch (error) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
99
|
+
// Handle gRPC Connect errors
|
|
100
|
+
if (error instanceof ConnectError) {
|
|
101
|
+
if (retryLeft > 0) {
|
|
102
|
+
const serverException = new ScalekitServerException(error);
|
|
103
|
+
if (serverException.httpStatus === 401) {
|
|
104
|
+
await this.authenticateClient();
|
|
105
|
+
return this.connectExec(fn, data, retryLeft - 1);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
})
|
|
120
|
-
}
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
throw new Error(messages.join("\n"));
|
|
108
|
+
throw ScalekitServerException.promote(error);
|
|
109
|
+
}
|
|
110
|
+
// Handle HTTP/Axios errors
|
|
111
|
+
if (error instanceof AxiosError) {
|
|
112
|
+
if (error.response) {
|
|
113
|
+
if (retryLeft > 0) {
|
|
114
|
+
const serverException = new ScalekitServerException(error.response);
|
|
115
|
+
if (serverException.httpStatus === 401) {
|
|
116
|
+
await this.authenticateClient();
|
|
117
|
+
return this.connectExec(fn, data, retryLeft - 1);
|
|
118
|
+
}
|
|
124
119
|
}
|
|
120
|
+
throw ScalekitServerException.promote(error.response);
|
|
121
|
+
} else {
|
|
122
|
+
throw new ScalekitException(error);
|
|
125
123
|
}
|
|
126
|
-
if (isUnAuthenticatedError) {
|
|
127
|
-
await this.authenticateClient();
|
|
128
|
-
return this.connectExec(fn, data, retryLeft - 1);
|
|
129
|
-
}
|
|
130
124
|
}
|
|
131
|
-
|
|
125
|
+
// Handle existing ScalekitException instances
|
|
126
|
+
if (error instanceof ScalekitException) {
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
// Handle generic errors
|
|
130
|
+
throw new ScalekitException(error);
|
|
132
131
|
}
|
|
133
132
|
}
|
|
134
133
|
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { ConnectError, Code } from '@connectrpc/connect';
|
|
2
|
+
import { AxiosResponse } from 'axios';
|
|
3
|
+
import { ErrorInfo } from '../pkg/grpc/scalekit/v1/errdetails/errdetails_pb';
|
|
4
|
+
|
|
5
|
+
// gRPC to HTTP status mapping
|
|
6
|
+
const GRPC_TO_HTTP: Record<number, number> = {
|
|
7
|
+
[Code.InvalidArgument]: 400,
|
|
8
|
+
[Code.FailedPrecondition]: 400,
|
|
9
|
+
[Code.OutOfRange]: 400,
|
|
10
|
+
[Code.Unauthenticated]: 401,
|
|
11
|
+
[Code.PermissionDenied]: 403,
|
|
12
|
+
[Code.NotFound]: 404,
|
|
13
|
+
[Code.AlreadyExists]: 409,
|
|
14
|
+
[Code.Aborted]: 409,
|
|
15
|
+
[Code.ResourceExhausted]: 429,
|
|
16
|
+
[Code.Canceled]: 499,
|
|
17
|
+
[Code.DataLoss]: 500,
|
|
18
|
+
[Code.Unknown]: 500,
|
|
19
|
+
[Code.Internal]: 500,
|
|
20
|
+
[Code.Unimplemented]: 501,
|
|
21
|
+
[Code.Unavailable]: 503,
|
|
22
|
+
[Code.DeadlineExceeded]: 504,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// HTTP to gRPC status mapping
|
|
26
|
+
const HTTP_TO_GRPC: Record<number, number> = {
|
|
27
|
+
200: Code.Unknown, // No direct mapping for 200
|
|
28
|
+
400: Code.InvalidArgument,
|
|
29
|
+
401: Code.Unauthenticated,
|
|
30
|
+
403: Code.PermissionDenied,
|
|
31
|
+
404: Code.NotFound,
|
|
32
|
+
409: Code.AlreadyExists,
|
|
33
|
+
429: Code.ResourceExhausted,
|
|
34
|
+
500: Code.Internal,
|
|
35
|
+
501: Code.Unimplemented,
|
|
36
|
+
503: Code.Unavailable,
|
|
37
|
+
504: Code.DeadlineExceeded,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// HTTP status constants
|
|
41
|
+
const HTTP_STATUS = {
|
|
42
|
+
'OK': 200,
|
|
43
|
+
'BAD_REQUEST': 400,
|
|
44
|
+
'UNAUTHORIZED': 401,
|
|
45
|
+
'FORBIDDEN': 403,
|
|
46
|
+
'NOT_FOUND': 404,
|
|
47
|
+
'CONFLICT': 409,
|
|
48
|
+
'TOO_MANY_REQUESTS': 429,
|
|
49
|
+
'INTERNAL_SERVER_ERROR': 500,
|
|
50
|
+
'NOT_IMPLEMENTED': 501,
|
|
51
|
+
'SERVICE_UNAVAILABLE': 503,
|
|
52
|
+
'GATEWAY_TIMEOUT': 504,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Base exception class
|
|
56
|
+
export class ScalekitException extends Error {
|
|
57
|
+
constructor(error: any) {
|
|
58
|
+
super(error?.message || error?.toString() || 'Unknown error');
|
|
59
|
+
this.name = 'ScalekitException';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Webhook verification error
|
|
64
|
+
export class WebhookVerificationError extends ScalekitException {
|
|
65
|
+
constructor(error: any) {
|
|
66
|
+
super(error);
|
|
67
|
+
this.name = 'WebhookVerificationError';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Token validation failure exception
|
|
72
|
+
export class ScalekitValidateTokenFailureException extends ScalekitException {
|
|
73
|
+
constructor(error: any) {
|
|
74
|
+
super(error);
|
|
75
|
+
this.name = 'ScalekitValidateTokenFailureException';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Base server exception
|
|
80
|
+
export class ScalekitServerException extends ScalekitException {
|
|
81
|
+
private _grpcStatus: Code;
|
|
82
|
+
private _httpStatus: number;
|
|
83
|
+
private _message: string | null;
|
|
84
|
+
private _errDetails: any;
|
|
85
|
+
private _errorCode: string | null;
|
|
86
|
+
private _unpackedDetails: ErrorInfo[];
|
|
87
|
+
|
|
88
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
89
|
+
super(error);
|
|
90
|
+
|
|
91
|
+
this._unpackedDetails = [];
|
|
92
|
+
|
|
93
|
+
if (this.isAxiosResponse(error)) {
|
|
94
|
+
// Handle HTTP Response errors
|
|
95
|
+
if (error.statusText && typeof error.statusText === 'string') {
|
|
96
|
+
this._httpStatus = HTTP_STATUS[error.statusText.toUpperCase() as keyof typeof HTTP_STATUS] || HTTP_STATUS.INTERNAL_SERVER_ERROR;
|
|
97
|
+
} else {
|
|
98
|
+
this._httpStatus = HTTP_STATUS.INTERNAL_SERVER_ERROR;
|
|
99
|
+
}
|
|
100
|
+
this._grpcStatus = HTTP_TO_GRPC[error.status] || Code.Unknown;
|
|
101
|
+
this._errorCode = error.statusText;
|
|
102
|
+
this._errDetails = error.data;
|
|
103
|
+
this._message = null;
|
|
104
|
+
} else {
|
|
105
|
+
// Handle gRPC ConnectError
|
|
106
|
+
this._grpcStatus = error.code;
|
|
107
|
+
this._httpStatus = GRPC_TO_HTTP[error.code] || 500;
|
|
108
|
+
this._message = error.message;
|
|
109
|
+
this._errDetails = error.findDetails(ErrorInfo);
|
|
110
|
+
this._errorCode = null;
|
|
111
|
+
|
|
112
|
+
// Unpack error details
|
|
113
|
+
for (const detail of this._errDetails) {
|
|
114
|
+
this._unpackedDetails.push(detail);
|
|
115
|
+
if (!this._errorCode) {
|
|
116
|
+
this._errorCode = detail.errorCode;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.name = 'ScalekitServerException';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private isAxiosResponse(error: any): error is AxiosResponse {
|
|
125
|
+
return error && typeof error.status === 'number' && typeof error.statusText === 'string';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// String representation
|
|
129
|
+
toString(): string {
|
|
130
|
+
const border = '='.repeat(40);
|
|
131
|
+
|
|
132
|
+
if (this._unpackedDetails.length > 0) {
|
|
133
|
+
let detailsStr = JSON.stringify(this._unpackedDetails, null, 2);
|
|
134
|
+
|
|
135
|
+
// Format the JSON string for better readability
|
|
136
|
+
|
|
137
|
+
if (detailsStr.startsWith("[") && detailsStr.includes("\n")) {
|
|
138
|
+
detailsStr = "[\n" + detailsStr.substring(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return `\n${border}\n` +
|
|
142
|
+
`Error Code: ${this._errorCode}\n` +
|
|
143
|
+
`GRPC: (${this.getGrpcStatusName()}: ${this._grpcStatus})\n` +
|
|
144
|
+
`HTTP: (${this.getHttpStatusName()}: ${this._httpStatus})\n` +
|
|
145
|
+
`Error Details:\n` +
|
|
146
|
+
`${this._message}: ${detailsStr}\n${border}\n`;
|
|
147
|
+
} else {
|
|
148
|
+
return `\n${border}\n` +
|
|
149
|
+
`Error Code: ${this._errorCode}\n` +
|
|
150
|
+
`GRPC: (${this.getGrpcStatusName()}: ${this._grpcStatus})\n` +
|
|
151
|
+
`HTTP: (${this.getHttpStatusName()}: ${this._httpStatus})\n` +
|
|
152
|
+
`Error Details: ${this._errDetails}\n${border}\n`;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Helper method to get gRPC status name
|
|
157
|
+
private getGrpcStatusName(): string {
|
|
158
|
+
switch (this._grpcStatus) {
|
|
159
|
+
case Code.InvalidArgument: return 'INVALID_ARGUMENT';
|
|
160
|
+
case Code.FailedPrecondition: return 'FAILED_PRECONDITION';
|
|
161
|
+
case Code.OutOfRange: return 'OUT_OF_RANGE';
|
|
162
|
+
case Code.Unauthenticated: return 'UNAUTHENTICATED';
|
|
163
|
+
case Code.PermissionDenied: return 'PERMISSION_DENIED';
|
|
164
|
+
case Code.NotFound: return 'NOT_FOUND';
|
|
165
|
+
case Code.AlreadyExists: return 'ALREADY_EXISTS';
|
|
166
|
+
case Code.Aborted: return 'ABORTED';
|
|
167
|
+
case Code.ResourceExhausted: return 'RESOURCE_EXHAUSTED';
|
|
168
|
+
case Code.Canceled: return 'CANCELED';
|
|
169
|
+
case Code.DataLoss: return 'DATA_LOSS';
|
|
170
|
+
case Code.Unknown: return 'UNKNOWN';
|
|
171
|
+
case Code.Internal: return 'INTERNAL';
|
|
172
|
+
case Code.Unimplemented: return 'UNIMPLEMENTED';
|
|
173
|
+
case Code.Unavailable: return 'UNAVAILABLE';
|
|
174
|
+
case Code.DeadlineExceeded: return 'DEADLINE_EXCEEDED';
|
|
175
|
+
default: return 'UNKNOWN';
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Helper method to get HTTP status name
|
|
180
|
+
private getHttpStatusName(): string {
|
|
181
|
+
switch (this._httpStatus) {
|
|
182
|
+
case 200: return 'OK';
|
|
183
|
+
case 400: return 'BAD_REQUEST';
|
|
184
|
+
case 401: return 'UNAUTHORIZED';
|
|
185
|
+
case 403: return 'FORBIDDEN';
|
|
186
|
+
case 404: return 'NOT_FOUND';
|
|
187
|
+
case 409: return 'CONFLICT';
|
|
188
|
+
case 429: return 'TOO_MANY_REQUESTS';
|
|
189
|
+
case 500: return 'INTERNAL_SERVER_ERROR';
|
|
190
|
+
case 501: return 'NOT_IMPLEMENTED';
|
|
191
|
+
case 503: return 'SERVICE_UNAVAILABLE';
|
|
192
|
+
case 504: return 'GATEWAY_TIMEOUT';
|
|
193
|
+
default: return 'INTERNAL_SERVER_ERROR';
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Getters
|
|
198
|
+
get grpcStatus(): Code {
|
|
199
|
+
return this._grpcStatus;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
get httpStatus(): number {
|
|
203
|
+
return this._httpStatus;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
get errorCode(): string | null {
|
|
207
|
+
return this._errorCode;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
get message(): string {
|
|
211
|
+
return this._message || super.message;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
get errDetails(): any {
|
|
215
|
+
return this._errDetails;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
get unpackedDetails(): ErrorInfo[] {
|
|
219
|
+
return this._unpackedDetails;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static promote(error: AxiosResponse | ConnectError): ScalekitServerException {
|
|
223
|
+
// Use dynamic import to avoid circular dependency
|
|
224
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
225
|
+
const specific = require('./specific-exceptions');
|
|
226
|
+
const grpcStatus = error instanceof ConnectError
|
|
227
|
+
? error.code
|
|
228
|
+
: HTTP_TO_GRPC[error.status] || Code.Unknown;
|
|
229
|
+
|
|
230
|
+
switch (grpcStatus) {
|
|
231
|
+
case Code.InvalidArgument:
|
|
232
|
+
case Code.FailedPrecondition:
|
|
233
|
+
case Code.OutOfRange:
|
|
234
|
+
return new specific.ScalekitBadRequestException(error);
|
|
235
|
+
case Code.Unauthenticated:
|
|
236
|
+
return new specific.ScalekitUnauthorizedException(error);
|
|
237
|
+
case Code.PermissionDenied:
|
|
238
|
+
return new specific.ScalekitForbiddenException(error);
|
|
239
|
+
case Code.NotFound:
|
|
240
|
+
return new specific.ScalekitNotFoundException(error);
|
|
241
|
+
case Code.AlreadyExists:
|
|
242
|
+
case Code.Aborted:
|
|
243
|
+
return new specific.ScalekitConflictException(error);
|
|
244
|
+
case Code.ResourceExhausted:
|
|
245
|
+
return new specific.ScalekitTooManyRequestsException(error);
|
|
246
|
+
case Code.Canceled:
|
|
247
|
+
return new specific.ScalekitCancelledException(error);
|
|
248
|
+
case Code.DataLoss:
|
|
249
|
+
case Code.Unknown:
|
|
250
|
+
case Code.Internal:
|
|
251
|
+
return new specific.ScalekitInternalServerException(error);
|
|
252
|
+
case Code.Unimplemented:
|
|
253
|
+
return new specific.ScalekitNotImplementedException(error);
|
|
254
|
+
case Code.Unavailable:
|
|
255
|
+
return new specific.ScalekitServiceUnavailableException(error);
|
|
256
|
+
case Code.DeadlineExceeded:
|
|
257
|
+
return new specific.ScalekitGatewayTimeoutException(error);
|
|
258
|
+
default:
|
|
259
|
+
return new specific.ScalekitUnknownException(error);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { ConnectError } from '@connectrpc/connect';
|
|
2
|
+
import { AxiosResponse } from 'axios';
|
|
3
|
+
import { ScalekitServerException } from './base-exception';
|
|
4
|
+
|
|
5
|
+
// Specific exception classes
|
|
6
|
+
export class ScalekitBadRequestException extends ScalekitServerException {
|
|
7
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
8
|
+
super(error);
|
|
9
|
+
this.name = 'ScalekitBadRequestException';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class ScalekitUnauthorizedException extends ScalekitServerException {
|
|
14
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
15
|
+
super(error);
|
|
16
|
+
this.name = 'ScalekitUnauthorizedException';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class ScalekitForbiddenException extends ScalekitServerException {
|
|
21
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
22
|
+
super(error);
|
|
23
|
+
this.name = 'ScalekitForbiddenException';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class ScalekitNotFoundException extends ScalekitServerException {
|
|
28
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
29
|
+
super(error);
|
|
30
|
+
this.name = 'ScalekitNotFoundException';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class ScalekitConflictException extends ScalekitServerException {
|
|
35
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
36
|
+
super(error);
|
|
37
|
+
this.name = 'ScalekitConflictException';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class ScalekitTooManyRequestsException extends ScalekitServerException {
|
|
42
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
43
|
+
super(error);
|
|
44
|
+
this.name = 'ScalekitTooManyRequestsException';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class ScalekitInternalServerException extends ScalekitServerException {
|
|
49
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
50
|
+
super(error);
|
|
51
|
+
this.name = 'ScalekitInternalServerException';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class ScalekitNotImplementedException extends ScalekitServerException {
|
|
56
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
57
|
+
super(error);
|
|
58
|
+
this.name = 'ScalekitNotImplementedException';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class ScalekitServiceUnavailableException extends ScalekitServerException {
|
|
63
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
64
|
+
super(error);
|
|
65
|
+
this.name = 'ScalekitServiceUnavailableException';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export class ScalekitGatewayTimeoutException extends ScalekitServerException {
|
|
70
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
71
|
+
super(error);
|
|
72
|
+
this.name = 'ScalekitGatewayTimeoutException';
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export class ScalekitCancelledException extends ScalekitServerException {
|
|
77
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
78
|
+
super(error);
|
|
79
|
+
this.name = 'ScalekitCancelledException';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class ScalekitUnknownException extends ScalekitServerException {
|
|
84
|
+
constructor(error: AxiosResponse | ConnectError) {
|
|
85
|
+
super(error);
|
|
86
|
+
this.name = 'ScalekitUnknownException';
|
|
87
|
+
}
|
|
88
|
+
}
|