@scalekit-sdk/node 2.2.0 → 2.2.2

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.
Files changed (62) hide show
  1. package/{reference.md → REFERENCE.md} +530 -77
  2. package/lib/core.js +1 -1
  3. package/package.json +9 -3
  4. package/.github/dependabot.yml +0 -10
  5. package/.nvmrc +0 -1
  6. package/buf.gen.yaml +0 -20
  7. package/jest.config.js +0 -15
  8. package/src/auth.ts +0 -99
  9. package/src/connect.ts +0 -32
  10. package/src/connection.ts +0 -267
  11. package/src/constants/user.ts +0 -22
  12. package/src/core.ts +0 -139
  13. package/src/directory.ts +0 -431
  14. package/src/domain.ts +0 -273
  15. package/src/errors/base-exception.ts +0 -263
  16. package/src/errors/index.ts +0 -3
  17. package/src/errors/specific-exceptions.ts +0 -88
  18. package/src/index.ts +0 -10
  19. package/src/organization.ts +0 -571
  20. package/src/passwordless.ts +0 -139
  21. package/src/permission.ts +0 -310
  22. package/src/pkg/grpc/buf/validate/validate_pb.ts +0 -28
  23. package/src/pkg/grpc/google/api/annotations_pb.ts +0 -28
  24. package/src/pkg/grpc/google/api/field_behavior_pb.ts +0 -28
  25. package/src/pkg/grpc/google/api/visibility_pb.ts +0 -28
  26. package/src/pkg/grpc/protoc-gen-openapiv2/options/annotations_pb.ts +0 -28
  27. package/src/pkg/grpc/scalekit/v1/auditlogs/auditlogs_pb.ts +0 -257
  28. package/src/pkg/grpc/scalekit/v1/auth/auth_pb.ts +0 -836
  29. package/src/pkg/grpc/scalekit/v1/auth/passwordless_pb.ts +0 -264
  30. package/src/pkg/grpc/scalekit/v1/auth/webauthn_pb.ts +0 -794
  31. package/src/pkg/grpc/scalekit/v1/commons/commons_pb.ts +0 -452
  32. package/src/pkg/grpc/scalekit/v1/connections/connections_pb.ts +0 -2645
  33. package/src/pkg/grpc/scalekit/v1/directories/directories_pb.ts +0 -1393
  34. package/src/pkg/grpc/scalekit/v1/domains/domains_pb.ts +0 -599
  35. package/src/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.ts +0 -311
  36. package/src/pkg/grpc/scalekit/v1/options/options_pb.ts +0 -200
  37. package/src/pkg/grpc/scalekit/v1/organizations/organizations_pb.ts +0 -1141
  38. package/src/pkg/grpc/scalekit/v1/roles/roles_pb.ts +0 -1491
  39. package/src/pkg/grpc/scalekit/v1/sessions/sessions_pb.ts +0 -497
  40. package/src/pkg/grpc/scalekit/v1/users/users_pb.ts +0 -1404
  41. package/src/role.ts +0 -463
  42. package/src/scalekit.ts +0 -800
  43. package/src/session.ts +0 -323
  44. package/src/types/auth.ts +0 -73
  45. package/src/types/organization.ts +0 -12
  46. package/src/types/scalekit.ts +0 -50
  47. package/src/types/user.ts +0 -21
  48. package/src/user.ts +0 -829
  49. package/src/webauthn.ts +0 -99
  50. package/tests/README.md +0 -25
  51. package/tests/connection.test.ts +0 -42
  52. package/tests/directory.test.ts +0 -46
  53. package/tests/domain.test.ts +0 -293
  54. package/tests/organization.test.ts +0 -81
  55. package/tests/passwordless.test.ts +0 -108
  56. package/tests/permission.test.ts +0 -399
  57. package/tests/role.test.ts +0 -323
  58. package/tests/scalekit.test.ts +0 -104
  59. package/tests/setup.ts +0 -34
  60. package/tests/users.test.ts +0 -168
  61. package/tests/utils/test-data.ts +0 -490
  62. package/tsconfig.json +0 -19
package/lib/core.js CHANGED
@@ -67,7 +67,7 @@ class CoreClient {
67
67
  this.clientSecret = clientSecret;
68
68
  this.keys = [];
69
69
  this.accessToken = null;
70
- this.sdkVersion = `Scalekit-Node/2.2.0`;
70
+ this.sdkVersion = `Scalekit-Node/2.2.2`;
71
71
  this.apiVersion = "20260202";
72
72
  this.userAgent = `${this.sdkVersion} Node/${process.version} (${process.platform}; ${os_1.default.arch()})`;
73
73
  this.axios = axios_1.default.create({ baseURL: envUrl });
package/package.json CHANGED
@@ -1,9 +1,15 @@
1
1
  {
2
- "version": "2.2.0",
2
+ "version": "2.2.2",
3
3
  "name": "@scalekit-sdk/node",
4
4
  "description": "Official Scalekit Node SDK",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
+ "files": [
8
+ "lib",
9
+ "README.md",
10
+ "REFERENCE.md",
11
+ "LICENSE"
12
+ ],
7
13
  "repository": {
8
14
  "type": "git",
9
15
  "url": "git+https://github.com/scalekit-inc/scalekit-sdk-node.git"
@@ -27,9 +33,9 @@
27
33
  "@bufbuild/protobuf": "^2.7.0",
28
34
  "@connectrpc/connect": "^2.1.1",
29
35
  "@connectrpc/connect-node": "^2.1.1",
30
- "axios": "^1.10.0",
36
+ "axios": "^1.13.5",
31
37
  "jose": "^5.6.3",
32
- "qs": "^6.14.1"
38
+ "qs": "^6.14.2"
33
39
  },
34
40
  "devDependencies": {
35
41
  "@bufbuild/buf": "^1.36.0",
@@ -1,10 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: "npm"
4
- directory: "/"
5
- schedule:
6
- interval: "weekly"
7
- time: "06:00"
8
- timezone: "Asia/Kolkata"
9
- reviewers:
10
- - "dhawani"
package/.nvmrc DELETED
@@ -1 +0,0 @@
1
- 20.0.0
package/buf.gen.yaml DELETED
@@ -1,20 +0,0 @@
1
- version: v1
2
- plugins:
3
- - plugin: es
4
- path: node_modules/.bin/protoc-gen-es
5
- opt: target=ts
6
- out: src/pkg/grpc
7
- types:
8
- include:
9
- - scalekit.v1.errdetails
10
- - scalekit.v1.connections
11
- - scalekit.v1.domains
12
- - scalekit.v1.organizations
13
- - scalekit.v1.directories
14
- - scalekit.v1.users
15
- - scalekit.v1.auth.passwordless
16
- - scalekit.v1.auditlogs
17
- - scalekit.v1.sessions
18
- - scalekit.v1.roles
19
- - scalekit.v1.auth
20
- - scalekit.v1.auth.webauthn
package/jest.config.js DELETED
@@ -1,15 +0,0 @@
1
- module.exports = {
2
- verbose: true,
3
- testEnvironment: 'node',
4
- testPathIgnorePatterns: ['/node_modules/', '/lib/'],
5
- roots: ['<rootDir>/tests'],
6
- setupFilesAfterEnv: ['./tests/setup.ts'],
7
- transform: {
8
- '^.+\\.ts?$': 'ts-jest',
9
- },
10
- moduleNameMapper: {
11
- '^jose': require.resolve('jose'),
12
- '^(\\.{1,2}/.*)\\.js$': '$1',
13
- },
14
- testTimeout: 10000,
15
- };
package/src/auth.ts DELETED
@@ -1,99 +0,0 @@
1
- import type { JsonObject } from "@bufbuild/protobuf";
2
- import { create } from "@bufbuild/protobuf";
3
- import type { MessageShape } from "@bufbuild/protobuf";
4
- import { EmptySchema } from "@bufbuild/protobuf/wkt";
5
- import CoreClient from "./core";
6
- import type { Client } from "@connectrpc/connect";
7
- import GrpcConnect from "./connect";
8
- import {
9
- AuthService,
10
- UpdateLoginUserDetailsRequestSchema,
11
- UserSchema,
12
- type User,
13
- } from "./pkg/grpc/scalekit/v1/auth/auth_pb";
14
-
15
- /** User input for updateLoginUserDetails; customAttributes is a plain object (proto Struct → JsonObject in v2). */
16
- type UserInput = Partial<User> & {
17
- customAttributes?: JsonObject;
18
- };
19
-
20
- /**
21
- * If you are using Auth for MCP solution of Scalekit in "Bring your own Auth" mode, this client helps updating Scalekit with the currently logged in user details for the ongoing authentication request.
22
- *
23
- *
24
- * @example
25
- * const scalekitClient = new ScalekitClient(envUrl, clientId, clientSecret);
26
- * const authClient = scalekitClient.auth;
27
- *
28
- * @see {@link https://docs.scalekit.com/apis/#tag/api%20auth | Authentication API Documentation}
29
- */
30
- export default class AuthClient {
31
- private readonly client: Client<typeof AuthService>;
32
-
33
- constructor(
34
- private readonly grpcConnect: GrpcConnect,
35
- private readonly coreClient: CoreClient
36
- ) {
37
- this.client = this.grpcConnect.createClient(AuthService);
38
- }
39
-
40
- /**
41
- * Updates user details for an ongoing authentication request.
42
- *
43
- *
44
- * @param {string} connectionId - The SSO connection ID being used for authentication
45
- * @param {string} loginRequestId - The unique login request identifier from the auth flow
46
- * @param {UserInput} user - User details to update or associate with the login request
47
- * @param {string} [user.email] - User's email address
48
- * @param {string} [user.sub] - Unique user identifier (subject)
49
- *
50
- * @returns {Promise<MessageShape<EmptySchema>>} Empty response on successful update
51
- *
52
- * @throws {Error} When connectionId is missing or invalid
53
- * @throws {Error} When loginRequestId is missing or invalid
54
- * @throws {Error} When user object is invalid
55
- *
56
- * @example
57
- * await scalekitClient.auth.updateLoginUserDetails(
58
- * 'conn_abc123',
59
- * 'login_xyz789',
60
- * {
61
- * email: 'john.doe@company.com',
62
- * sub: 'unique_user_id_456',
63
- * }
64
- * );
65
- *
66
- *
67
- * @see {@link https://docs.scalekit.com/apis/#tag/api%20auth | Update Login User Details API}
68
- */
69
- async updateLoginUserDetails(
70
- connectionId: string,
71
- loginRequestId: string,
72
- user: UserInput
73
- ): Promise<MessageShape<typeof EmptySchema>> {
74
- if (!connectionId || typeof connectionId !== "string") {
75
- throw new Error("connectionId must be a non-empty string");
76
- }
77
-
78
- if (!loginRequestId || typeof loginRequestId !== "string") {
79
- throw new Error("loginRequestId must be a non-empty string");
80
- }
81
-
82
- if (!user || typeof user !== "object") {
83
- throw new Error("user must be a valid object");
84
- }
85
-
86
- const userMessage = create(UserSchema, user as Parameters<typeof create<typeof UserSchema>>[1]);
87
-
88
- const request = create(UpdateLoginUserDetailsRequestSchema, {
89
- connectionId,
90
- loginRequestId,
91
- user: userMessage,
92
- });
93
-
94
- return this.coreClient.connectExec(
95
- this.client.updateLoginUserDetails,
96
- request
97
- );
98
- }
99
- }
package/src/connect.ts DELETED
@@ -1,32 +0,0 @@
1
- import type { DescService } from '@bufbuild/protobuf';
2
- import { type Client, type Transport, createClient } from '@connectrpc/connect';
3
- import { createGrpcTransport } from '@connectrpc/connect-node';
4
- import CoreClient, { headers } from './core';
5
-
6
- export default class GrpcConnect {
7
- private transport: Transport;
8
- constructor(
9
- private readonly coreClient: CoreClient
10
- ) {
11
- this.transport = createGrpcTransport({
12
- baseUrl: this.coreClient.envUrl,
13
- interceptors: [
14
- (next) => {
15
- return (req) => {
16
- req.header.set(headers['user-agent'], this.coreClient.userAgent)
17
- req.header.set(headers['x-sdk-version'], this.coreClient.sdkVersion)
18
- req.header.set(headers['x-api-version'], this.coreClient.apiVersion)
19
- if (this.coreClient.accessToken) {
20
- req.header.set(headers.authorization, `Bearer ${this.coreClient.accessToken}`)
21
- }
22
- return next(req)
23
- }
24
- }
25
- ],
26
- });
27
- }
28
-
29
- createClient<T extends DescService>(service: T): Client<T> {
30
- return createClient(service, this.transport);
31
- }
32
- }
package/src/connection.ts DELETED
@@ -1,267 +0,0 @@
1
- import type { Client } from "@connectrpc/connect";
2
- import GrpcConnect from "./connect";
3
- import CoreClient from "./core";
4
- import { ConnectionService } from "./pkg/grpc/scalekit/v1/connections/connections_pb";
5
- import {
6
- GetConnectionResponse,
7
- ToggleConnectionResponse,
8
- ListConnectionsResponse,
9
- } from "./pkg/grpc/scalekit/v1/connections/connections_pb";
10
-
11
- /**
12
- * Client for managing enterprise SSO connections for organizations.
13
- *
14
- * Connections represent the SSO integration between an organization and their identity provider (IdP).
15
- * Each organization can have an enterprise connection supporting different protocols (SAML, OIDC) and
16
- * providers (Okta, Azure AD, Google Workspace, etc.). Use this client to retrieve connection details,
17
- * list connections, and enable/disable them.
18
- *
19
- * @example
20
- * const scalekitClient = new ScalekitClient(envUrl, clientId, clientSecret);
21
- * const connectionClient = scalekitClient.connection;
22
- *
23
- * @see {@link https://docs.scalekit.com/apis/#tag/connections | Connection API Documentation}
24
- */
25
- export default class ConnectionClient {
26
- private client: Client<typeof ConnectionService>;
27
- constructor(
28
- private readonly grpcConnect: GrpcConnect,
29
- private readonly coreClient: CoreClient
30
- ) {
31
- this.client = this.grpcConnect.createClient(ConnectionService);
32
- }
33
-
34
- /**
35
- * Retrieves complete configuration and status details for a specific SSO connection.
36
- *
37
- * Use this method to fetch comprehensive information about an organization's SSO connection,
38
- * including provider settings, protocol details (SAML/OIDC), enabled status, and configuration
39
- * metadata. This is useful for verifying connection setup, auditing configurations, checking
40
- * connection health before authentication flows, or displaying connection details to administrators.
41
- *
42
- * @param {string} organizationId - The organization ID that owns the connection (format: "org_...")
43
- * @param {string} id - The connection identifier to retrieve (format: "conn_...")
44
- *
45
- * @returns {Promise<GetConnectionResponse>} Response containing:
46
- * - connection: Complete connection object with:
47
- * - id: Unique connection identifier
48
- * - organizationId: Parent organization ID
49
- * - provider: Identity provider name (e.g., "okta", "azure_ad", "google")
50
- * - type: Protocol type ("saml", "oidc")
51
- * - enabled: Whether the connection is active
52
- * - status: Configuration status
53
- * - domains: Associated email domains for this connection
54
- * - metadata: Provider-specific configuration details
55
- * - createTime: When the connection was created
56
- * - updateTime: When the connection was last modified
57
- *
58
- * @throws {Error} If the organization or connection is not found
59
- *
60
- * @example
61
- * // Get connection details
62
- * const response = await scalekitClient.connection.getConnection(
63
- * 'org_123456',
64
- * 'conn_abc123'
65
- * );
66
- *
67
- * const conn = response.connection;
68
- * console.log('Provider:', conn.provider);
69
- * console.log('Type:', conn.type);
70
- * console.log('Status:', conn.enabled ? 'Enabled' : 'Disabled');
71
- * console.log('Domains:', conn.domains);
72
- *
73
- * @example
74
- * // Verify connection is ready for authentication
75
- * const response = await scalekitClient.connection.getConnection(orgId, connId);
76
- *
77
- * if (response.connection.enabled && response.connection.status === 'active') {
78
- * console.log('Connection is ready for SSO authentication');
79
- * } else {
80
- * console.log('Connection not ready:', response.connection.status);
81
- * }
82
- *
83
- *
84
- * @see {@link https://docs.scalekit.com/apis/#tag/connections | Get Connection API}
85
- * @see {@link listConnections} - List all connections for an organization
86
- * @see {@link enableConnection} - Enable this connection
87
- * @see {@link disableConnection} - Disable this connection
88
- */
89
- async getConnection(
90
- organizationId: string,
91
- id: string
92
- ): Promise<GetConnectionResponse> {
93
- return this.coreClient.connectExec(this.client.getConnection, {
94
- id,
95
- organizationId,
96
- });
97
- }
98
-
99
- /**
100
- * Lists all SSO connections associated with a specific email domain.
101
- *
102
- * Use this method to discover which organizations have SSO configured for a particular
103
- * domain. This is useful for implementing domain-based SSO routing where users are
104
- * automatically directed to their organization's SSO based on their email domain.
105
- *
106
- * @param {string} domain - The email domain to search for (e.g., "acme.com")
107
- *
108
- * @returns {Promise<ListConnectionsResponse>} Response containing:
109
- * - connections: Array of connection objects for the domain
110
- *
111
- * @example
112
- * // Find SSO connections for a domain
113
- * const response = await scalekitClient.connection.listConnectionsByDomain('acme.com');
114
- *
115
- * if (response.connections.length > 0) {
116
- * console.log('SSO available for domain acme.com');
117
- * const connection = response.connections[0];
118
- * console.log('Organization:', connection.organizationId);
119
- * console.log('Provider:', connection.provider);
120
- * }
121
- *
122
- * @example
123
- * // Implement domain-based SSO routing
124
- * app.post('/auth/login', async (req, res) => {
125
- * const email = req.body.email;
126
- * const domain = email.split('@')[1];
127
- *
128
- * const response = await scalekitClient.connection.listConnectionsByDomain(domain);
129
- *
130
- * if (response.connections.length > 0) {
131
- * // Redirect to SSO
132
- * const authUrl = scalekitClient.getAuthorizationUrl(redirectUri, {
133
- * connectionId: response.connections[0].id,
134
- * loginHint: email
135
- * });
136
- * return res.redirect(authUrl);
137
- * } else {
138
- * // Use password-based login
139
- * return res.render('password-login');
140
- * }
141
- * });
142
- *
143
- * @see {@link https://docs.scalekit.com/apis/#tag/connections | List Connections API}
144
- * @see {@link listConnections} - List all connections for an organization
145
- */
146
- async listConnectionsByDomain(
147
- domain: string
148
- ): Promise<ListConnectionsResponse> {
149
- return this.coreClient.connectExec(this.client.listConnections, {
150
- domain,
151
- });
152
- }
153
-
154
- /**
155
- * Lists all SSO connections configured for an organization.
156
- *
157
- * Retrieves all enterprise SSO connections (SAML, OIDC) that have been configured for
158
- * the specified organization. Each connection includes details about the provider,
159
- * status, and configuration.
160
- *
161
- * @param {string} organizationId - The organization ID
162
- *
163
- * @returns {Promise<ListConnectionsResponse>} Response containing:
164
- * - connections: Array of connection objects with provider details and status
165
- *
166
- * @example
167
- * // List all SSO connections for an organization
168
- * const response = await scalekitClient.connection.listConnections('org_123456');
169
- *
170
- * console.log(`Found ${response.connections.length} connections`);
171
- * response.connections.forEach(conn => {
172
- * console.log(`- ${conn.provider} (${conn.type}): ${conn.enabled ? 'Enabled' : 'Disabled'}`);
173
- * });
174
- *
175
- * @example
176
- * // Check if organization has any enabled connections
177
- * const response = await scalekitClient.connection.listConnections('org_123456');
178
- * const hasEnabledSSO = response.connections.some(conn => conn.enabled);
179
- *
180
- * if (!hasEnabledSSO) {
181
- * console.log('No SSO connections enabled for this organization');
182
- * }
183
- *
184
- * @see {@link https://docs.scalekit.com/apis/#tag/connections | List Connections API}
185
- * @see {@link getConnection} - Get details of a specific connection
186
- * @see {@link enableConnection} - Enable a connection
187
- * @see {@link disableConnection} - Disable a connection
188
- */
189
- async listConnections(
190
- organizationId: string
191
- ): Promise<ListConnectionsResponse> {
192
- return this.coreClient.connectExec(this.client.listConnections, {
193
- organizationId,
194
- });
195
- }
196
-
197
- /**
198
- * Enables an SSO connection for an organization.
199
- *
200
- * Activates a previously disabled or newly configured SSO connection, allowing users
201
- * from the organization to authenticate using this identity provider. Once enabled,
202
- * users can immediately start using SSO to log in.
203
- *
204
- * @param {string} organizationId - The organization ID
205
- * @param {string} id - The connection ID to enable
206
- *
207
- * @returns {Promise<ToggleConnectionResponse>} Response with updated connection status
208
- *
209
- * @example
210
- * // Enable an SSO connection
211
- * const response = await scalekitClient.connection.enableConnection(
212
- * 'org_123456',
213
- * 'conn_abc123'
214
- * );
215
- *
216
- * console.log('Connection enabled:', response.connection.enabled); // true
217
- *
218
- *
219
- * @see {@link https://docs.scalekit.com/apis/#tag/connections | Enable Connection API}
220
- * @see {@link disableConnection} - Disable a connection
221
- * @see {@link listConnections} - List all connections
222
- */
223
- async enableConnection(
224
- organizationId: string,
225
- id: string
226
- ): Promise<ToggleConnectionResponse> {
227
- return this.coreClient.connectExec(this.client.enableConnection, {
228
- id,
229
- organizationId,
230
- });
231
- }
232
-
233
- /**
234
- * Disables an SSO connection for an organization.
235
- *
236
- * Deactivates an SSO connection, preventing users from authenticating via this identity
237
- * provider. This is useful for temporarily suspending SSO access, during maintenance,
238
- * or when migrating to a different provider. Existing user sessions remain valid.
239
- *
240
- * @param {string} organizationId - The organization ID
241
- * @param {string} id - The connection ID to disable
242
- *
243
- * @returns {Promise<ToggleConnectionResponse>} Response with updated connection status
244
- *
245
- * @example
246
- * // Disable an SSO connection
247
- * const response = await scalekitClient.connection.disableConnection(
248
- * 'org_123456',
249
- * 'conn_abc123'
250
- * );
251
- *
252
- * console.log('Connection disabled:', !response.connection.enabled); // true
253
- *
254
- * @see {@link https://docs.scalekit.com/apis/#tag/connections | Disable Connection API}
255
- * @see {@link enableConnection} - Enable a connection
256
- * @see {@link listConnections} - List all connections
257
- */
258
- async disableConnection(
259
- organizationId: string,
260
- id: string
261
- ): Promise<ToggleConnectionResponse> {
262
- return this.coreClient.connectExec(this.client.disableConnection, {
263
- id,
264
- organizationId,
265
- });
266
- }
267
- }
@@ -1,22 +0,0 @@
1
- import type { IdTokenClaim, User } from '../types/auth';
2
-
3
- export const IdTokenClaimToUserMap: { [k in keyof IdTokenClaim]: keyof User } = {
4
- "sub": "id",
5
- "name": "name",
6
- "preferred_username": "username",
7
- "given_name": "givenName",
8
- "family_name": "familyName",
9
- "email": "email",
10
- "email_verified": "emailVerified",
11
- "phone_number": "phoneNumber",
12
- "phone_number_verified": "phoneNumberVerified",
13
- "profile": 'profile',
14
- "picture": "picture",
15
- "gender": "gender",
16
- "birthdate": "birthDate",
17
- "zoneinfo": "zoneInfo",
18
- "locale": "locale",
19
- "updated_at": "updatedAt",
20
- "identities": "identities",
21
- "metadata": "metadata"
22
- }
package/src/core.ts DELETED
@@ -1,139 +0,0 @@
1
- import { Code, ConnectError } from "@connectrpc/connect";
2
- import axios, { Axios, AxiosError, AxiosResponse, HttpStatusCode } from "axios";
3
- import { JWK } from "jose";
4
- import os from "os";
5
- import QueryString from "qs";
6
- import { GrantType } from "./types/scalekit";
7
- import { TokenResponse } from "./types/auth";
8
- import {
9
- ScalekitException,
10
- ScalekitServerException,
11
- } from "./errors/base-exception";
12
-
13
- export const headers = {
14
- "user-agent": "user-agent",
15
- "x-sdk-version": "x-sdk-version",
16
- "x-api-version": "x-api-version",
17
- authorization: "authorization",
18
- };
19
-
20
- const tokenEndpoint = "oauth/token";
21
- const jwksEndpoint = "keys";
22
- export default class CoreClient {
23
- public keys: JWK[] = [];
24
- public accessToken: string | null = null;
25
- public axios: Axios;
26
- public sdkVersion = `Scalekit-Node/2.2.0`;
27
- public apiVersion = "20260202";
28
- public userAgent = `${this.sdkVersion} Node/${process.version} (${
29
- process.platform
30
- }; ${os.arch()})`;
31
- constructor(
32
- readonly envUrl: string,
33
- readonly clientId: string,
34
- readonly clientSecret: string
35
- ) {
36
- this.axios = axios.create({ baseURL: envUrl });
37
- this.axios.interceptors.request.use((config) => {
38
- config.headers[headers["user-agent"]] = this.userAgent;
39
- config.headers[headers["x-sdk-version"]] = this.sdkVersion;
40
- config.headers[headers["x-api-version"]] = this.apiVersion;
41
- if (this.accessToken) {
42
- config.headers[headers.authorization] = `Bearer ${this.accessToken}`;
43
- }
44
-
45
- return config;
46
- });
47
- // removing token creation at the time of constructor and instead letting the retry functionality handle generating a token whenever required.
48
- //this.authenticateClient();
49
- }
50
-
51
- private async authenticateClient() {
52
- const res = await this.authenticate(
53
- QueryString.stringify({
54
- grant_type: GrantType.ClientCredentials,
55
- client_id: this.clientId,
56
- client_secret: this.clientSecret,
57
- })
58
- );
59
-
60
- this.accessToken = res.data.access_token;
61
- }
62
- /**
63
- * Authenticate with the code
64
- * @param {string} data Data to authenticate
65
- * @returns {Promise<AxiosResponse<TokenResponse>>} Returns access token and id token
66
- */
67
- async authenticate(data: string): Promise<AxiosResponse<TokenResponse, any>> {
68
- return this.axios.post<TokenResponse>(tokenEndpoint, data, {
69
- headers: {
70
- "Content-Type": "application/x-www-form-urlencoded",
71
- },
72
- });
73
- }
74
-
75
- /**
76
- * Get the JWKS from the server and store it in the client instance
77
- * @returns {Promise<void>} Returns nothing
78
- */
79
- async getJwks(): Promise<void> {
80
- if (this.keys.length) {
81
- return Promise.resolve();
82
- }
83
- const {
84
- data: { keys },
85
- } = await this.axios.get<{ keys: JWK[] }>(jwksEndpoint);
86
- this.keys = keys;
87
- }
88
-
89
- /**
90
- * Execute a function with error handling and retry logic
91
- * @param fn Function to execute
92
- * @param data Data to pass to the function
93
- * @param retryLeft Number of retries left
94
- * @returns {Promise<TResponse>} Returns the response
95
- */
96
- async connectExec<TRequest, TResponse>(
97
- fn: (request: TRequest) => Promise<TResponse>,
98
- data: TRequest,
99
- retryLeft: number = 1
100
- ): Promise<TResponse> {
101
- try {
102
- const res = await fn(data);
103
- return res;
104
- } catch (error) {
105
- // Handle gRPC Connect errors
106
- if (error instanceof ConnectError) {
107
- if (retryLeft > 0) {
108
- const serverException = new ScalekitServerException(error);
109
- if (serverException.httpStatus === 401) {
110
- await this.authenticateClient();
111
- return this.connectExec(fn, data, retryLeft - 1);
112
- }
113
- }
114
- throw ScalekitServerException.promote(error);
115
- }
116
- // Handle HTTP/Axios errors
117
- if (error instanceof AxiosError) {
118
- if (error.response) {
119
- if (retryLeft > 0) {
120
- const serverException = new ScalekitServerException(error.response);
121
- if (serverException.httpStatus === 401) {
122
- await this.authenticateClient();
123
- return this.connectExec(fn, data, retryLeft - 1);
124
- }
125
- }
126
- throw ScalekitServerException.promote(error.response);
127
- } else {
128
- throw new ScalekitException(error);
129
- }
130
- }
131
- // Handle existing ScalekitException instances
132
- if (error instanceof ScalekitException) {
133
- throw error;
134
- }
135
- // Handle generic errors
136
- throw new ScalekitException(error);
137
- }
138
- }
139
- }