@scalekit-sdk/node 2.2.0-beta.2 → 2.2.0-beta.3

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/reference.md CHANGED
@@ -5187,6 +5187,313 @@ await scalekitClient.auth.updateLoginUserDetails(
5187
5187
  </dl>
5188
5188
 
5189
5189
 
5190
+ </dd>
5191
+ </dl>
5192
+ </details>
5193
+
5194
+ ## Actions
5195
+
5196
+ <details><summary><code>client.actions.<a href="/src/actions.ts">executeTool</a>(params) -> Promise&lt;ExecuteToolResponse&gt;</code></summary>
5197
+ <dl>
5198
+ <dd>
5199
+
5200
+ #### 📝 Description
5201
+
5202
+ <dl>
5203
+ <dd>
5204
+
5205
+ <dl>
5206
+ <dd>
5207
+
5208
+ Executes a tool on behalf of a connected account using the high-level actions wrapper. This is a thin wrapper around `client.tools.executeTool` and is the primary entrypoint for agent-style tool execution in the Node SDK.
5209
+ </dd>
5210
+ </dl>
5211
+ </dd>
5212
+ </dl>
5213
+
5214
+ #### 🔌 Usage
5215
+
5216
+ <dl>
5217
+ <dd>
5218
+
5219
+ <dl>
5220
+ <dd>
5221
+
5222
+ ```typescript
5223
+ // Execute a tool with a connected account ID
5224
+ const executeResponse = await scalekitClient.actions.executeTool({
5225
+ toolName: 'gmail_send_email',
5226
+ toolInput: {
5227
+ to: 'user@example.com',
5228
+ subject: 'Hello',
5229
+ body: 'Hello from Scalekit Actions',
5230
+ },
5231
+ connectedAccountId: 'ca_123',
5232
+ });
5233
+
5234
+ // Execute a tool by resolving the connected account via identifier + connector
5235
+ const executeResponse2 = await scalekitClient.actions.executeTool({
5236
+ toolName: 'gmail_send_email',
5237
+ toolInput: {
5238
+ to: 'user@example.com',
5239
+ subject: 'Test',
5240
+ body: 'Body',
5241
+ },
5242
+ identifier: 'user@example.com',
5243
+ connector: 'google_workspace',
5244
+ organizationId: 'org_123',
5245
+ });
5246
+ ```
5247
+ </dd>
5248
+ </dl>
5249
+ </dd>
5250
+ </dl>
5251
+
5252
+ #### ⚙️ Parameters
5253
+
5254
+ <dl>
5255
+ <dd>
5256
+
5257
+ <dl>
5258
+ <dd>
5259
+
5260
+ **params:** `object`
5261
+ - `toolName: string` - Name of the tool to execute
5262
+ - `toolInput: Record<string, unknown>` - JSON payload passed as the tool's input parameters
5263
+ - `identifier?: string` - Connected account identifier (e.g., email, workspace ID)
5264
+ - `connectedAccountId?: string` - Direct ID of the connected account (`ca_...`)
5265
+ - `connector?: string` - Connector/provider name when using identifier-based lookup
5266
+ - `organizationId?: string` - Organization scope for identifier-based lookup
5267
+ - `userId?: string` - User scope for identifier-based lookup
5268
+
5269
+ </dd>
5270
+ </dl>
5271
+ </dd>
5272
+ </dl>
5273
+
5274
+
5275
+ </dd>
5276
+ </dl>
5277
+ </details>
5278
+
5279
+ <details><summary><code>client.actions.<a href="/src/actions.ts">getAuthorizationLink</a>(params) -> Promise&lt;GetMagicLinkForConnectedAccountResponse&gt;</code></summary>
5280
+ <dl>
5281
+ <dd>
5282
+
5283
+ #### 📝 Description
5284
+
5285
+ <dl>
5286
+ <dd>
5287
+
5288
+ <dl>
5289
+ <dd>
5290
+
5291
+ Generates a time-limited magic link to authorize or re-authorize a third-party account for a given connector and identifier, via the high-level actions wrapper.
5292
+ </dd>
5293
+ </dl>
5294
+ </dd>
5295
+ </dl>
5296
+
5297
+ #### 🔌 Usage
5298
+
5299
+ <dl>
5300
+ <dd>
5301
+
5302
+ <dl>
5303
+ <dd>
5304
+
5305
+ ```typescript
5306
+ const magicLinkResponse = await scalekitClient.actions.getAuthorizationLink({
5307
+ connectionName: 'notion',
5308
+ identifier: 'workspace_123',
5309
+ organizationId: 'org_123',
5310
+ });
5311
+
5312
+ // Redirect the user to magicLinkResponse.link before it expires
5313
+ console.log(magicLinkResponse.link, magicLinkResponse.expiry);
5314
+ ```
5315
+ </dd>
5316
+ </dl>
5317
+ </dd>
5318
+ </dl>
5319
+
5320
+ #### ⚙️ Parameters
5321
+
5322
+ <dl>
5323
+ <dd>
5324
+
5325
+ <dl>
5326
+ <dd>
5327
+
5328
+ **params:** `object`
5329
+ - `connectionName?: string` - Connector identifier (e.g., `notion`, `google_workspace`)
5330
+ - `identifier?: string` - Connected account identifier (e.g., workspace ID, email)
5331
+ - `connectedAccountId?: string` - Optional connected account ID (`ca_...`)
5332
+ - `organizationId?: string` - Optional organization scope
5333
+ - `userId?: string` - Optional user scope
5334
+
5335
+ </dd>
5336
+ </dl>
5337
+ </dd>
5338
+ </dl>
5339
+
5340
+
5341
+ </dd>
5342
+ </dl>
5343
+ </details>
5344
+
5345
+ <details><summary><code>client.actions.<a href="/src/actions.ts">getOrCreateConnectedAccount</a>(params) -> Promise&lt;CreateConnectedAccountResponse&gt;</code></summary>
5346
+ <dl>
5347
+ <dd>
5348
+
5349
+ #### 📝 Description
5350
+
5351
+ <dl>
5352
+ <dd>
5353
+
5354
+ <dl>
5355
+ <dd>
5356
+
5357
+ Retrieves an existing connected account for a connector + identifier or creates one if it does not exist. This mirrors the Python `ActionClient.get_or_create_connected_account` behavior.
5358
+ </dd>
5359
+ </dl>
5360
+ </dd>
5361
+ </dl>
5362
+
5363
+ #### 🔌 Usage
5364
+
5365
+ <dl>
5366
+ <dd>
5367
+
5368
+ <dl>
5369
+ <dd>
5370
+
5371
+ ```typescript
5372
+ import {
5373
+ AuthorizationDetails,
5374
+ OauthToken,
5375
+ } from '@scalekit-sdk/node';
5376
+
5377
+ const oauthToken = new OauthToken({
5378
+ accessToken: 'test_access_token',
5379
+ refreshToken: 'test_refresh_token',
5380
+ scopes: ['read', 'write'],
5381
+ });
5382
+
5383
+ const authorizationDetails = new AuthorizationDetails({
5384
+ details: {
5385
+ case: 'oauthToken',
5386
+ value: oauthToken,
5387
+ },
5388
+ });
5389
+
5390
+ const connectedAccountResponse = await scalekitClient.actions.getOrCreateConnectedAccount({
5391
+ connectionName: 'gmail',
5392
+ identifier: 'user@example.com',
5393
+ authorizationDetails,
5394
+ organizationId: 'org_123',
5395
+ });
5396
+
5397
+ console.log(connectedAccountResponse.connectedAccount?.id);
5398
+ ```
5399
+ </dd>
5400
+ </dl>
5401
+ </dd>
5402
+ </dl>
5403
+
5404
+ #### ⚙️ Parameters
5405
+
5406
+ <dl>
5407
+ <dd>
5408
+
5409
+ <dl>
5410
+ <dd>
5411
+
5412
+ **params:** `object`
5413
+ - `connectionName: string` - Connector identifier (e.g., `gmail`, `notion`)
5414
+ - `identifier: string` - Connected account identifier (e.g., email, workspace ID)
5415
+ - `authorizationDetails?: AuthorizationDetails` - Optional auth details used when creating a new account
5416
+ - `organizationId?: string` - Optional organization scope
5417
+ - `userId?: string` - Optional user scope
5418
+ - `apiConfig?: Record<string, unknown>` - Optional API configuration used when creating a new account
5419
+
5420
+ </dd>
5421
+ </dl>
5422
+ </dd>
5423
+ </dl>
5424
+
5425
+
5426
+ </dd>
5427
+ </dl>
5428
+ </details>
5429
+
5430
+ <details><summary><code>client.actions.<a href="/src/actions.ts">request</a>(params) -> Promise&lt;AxiosResponse&lt;any&gt;&gt;</code></summary>
5431
+ <dl>
5432
+ <dd>
5433
+
5434
+ #### 📝 Description
5435
+
5436
+ <dl>
5437
+ <dd>
5438
+
5439
+ <dl>
5440
+ <dd>
5441
+
5442
+ Makes a proxied REST API call through Scalekit on behalf of a connected account. This mirrors the Python `ActionClient.request` helper and is useful for direct HTTP calls to third-party APIs.
5443
+ </dd>
5444
+ </dl>
5445
+ </dd>
5446
+ </dl>
5447
+
5448
+ #### 🔌 Usage
5449
+
5450
+ <dl>
5451
+ <dd>
5452
+
5453
+ <dl>
5454
+ <dd>
5455
+
5456
+ ```typescript
5457
+ const response = await scalekitClient.actions.request({
5458
+ connectionName: 'microsoft_graph',
5459
+ identifier: 'user@example.com',
5460
+ path: '/v1.0/me/messages',
5461
+ method: 'GET',
5462
+ queryParams: { '$top': 10 },
5463
+ });
5464
+
5465
+ console.log(response.status, response.data);
5466
+ ```
5467
+ </dd>
5468
+ </dl>
5469
+ </dd>
5470
+ </dl>
5471
+
5472
+ #### ⚙️ Parameters
5473
+
5474
+ <dl>
5475
+ <dd>
5476
+
5477
+ <dl>
5478
+ <dd>
5479
+
5480
+ **params:** `object`
5481
+ - `connectionName: string` - Connector identifier to route the proxied call
5482
+ - `identifier: string` - Connected account identifier whose credentials are used
5483
+ - `path: string` - Target API path (e.g., `/v1.0/me/messages`)
5484
+ - `method?: string` - HTTP method (`GET`, `POST`, `PUT`, etc., default: `GET`)
5485
+ - `queryParams?: Record<string, unknown>` - URL query parameters
5486
+ - `body?: unknown` - JSON body payload
5487
+ - `formData?: Record<string, unknown>` - Form-encoded payload (alternative to `body`)
5488
+ - `headers?: Record<string, string>` - Additional HTTP headers to send
5489
+ - `timeoutMs?: number` - Optional request timeout in milliseconds
5490
+
5491
+ </dd>
5492
+ </dl>
5493
+ </dd>
5494
+ </dl>
5495
+
5496
+
5190
5497
  </dd>
5191
5498
  </dl>
5192
5499
  </details>
package/src/actions.ts ADDED
@@ -0,0 +1,349 @@
1
+ import { AxiosResponse } from "axios";
2
+ import CoreClient from "./core";
3
+ import ToolsClient from "./tools";
4
+ import ConnectedAccountsClient from "./connected-accounts";
5
+ import {
6
+ CreateConnectedAccount,
7
+ CreateConnectedAccountResponse,
8
+ DeleteConnectedAccountResponse,
9
+ GetConnectedAccountByIdentifierResponse,
10
+ GetMagicLinkForConnectedAccountResponse,
11
+ ListConnectedAccountsResponse,
12
+ UpdateConnectedAccount,
13
+ UpdateConnectedAccountResponse,
14
+ } from "./pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_pb";
15
+ import { ExecuteToolResponse } from "./pkg/grpc/scalekit/v1/tools/tools_pb";
16
+
17
+ /**
18
+ * This class is intended to be accessed via `ScalekitClient.actions`.
19
+ * It composes the existing ToolsClient and ConnectedAccountsClient
20
+ * without changing their behavior.
21
+ */
22
+ export default class ActionsClient {
23
+ constructor(
24
+ private readonly tools: ToolsClient,
25
+ private readonly connectedAccounts: ConnectedAccountsClient,
26
+ private readonly coreClient: CoreClient
27
+ ) {}
28
+
29
+ /**
30
+ * Execute a tool on behalf of a connected account.
31
+ *
32
+ * Thin wrapper around ToolsClient.executeTool, reserved for future
33
+ * pre/post modifier support.
34
+ */
35
+ async executeTool(params: {
36
+ toolName: string;
37
+ toolInput: Record<string, unknown>;
38
+ identifier?: string;
39
+ connectedAccountId?: string;
40
+ connector?: string;
41
+ organizationId?: string;
42
+ userId?: string;
43
+ }): Promise<ExecuteToolResponse> {
44
+ const {
45
+ toolName,
46
+ toolInput,
47
+ identifier,
48
+ connectedAccountId,
49
+ connector,
50
+ organizationId,
51
+ userId,
52
+ } = params;
53
+
54
+ if (!toolName?.trim()) {
55
+ throw new Error("toolName is required");
56
+ }
57
+
58
+ return this.tools.executeTool({
59
+ toolName,
60
+ identifier,
61
+ params: toolInput,
62
+ connectedAccountId,
63
+ connector,
64
+ organizationId,
65
+ userId,
66
+ });
67
+ }
68
+
69
+ /**
70
+ * Get an authorization magic link for a connected account.
71
+ */
72
+ async getAuthorizationLink(params: {
73
+ connectionName?: string;
74
+ identifier?: string;
75
+ connectedAccountId?: string;
76
+ organizationId?: string;
77
+ userId?: string;
78
+ }): Promise<GetMagicLinkForConnectedAccountResponse> {
79
+ const {
80
+ connectionName,
81
+ identifier,
82
+ connectedAccountId,
83
+ organizationId,
84
+ userId,
85
+ } = params;
86
+
87
+ return this.connectedAccounts.getMagicLinkForConnectedAccount({
88
+ connector: connectionName ?? "",
89
+ identifier: identifier ?? "",
90
+ organizationId,
91
+ userId,
92
+ connectedAccountId,
93
+ });
94
+ }
95
+
96
+ /**
97
+ * List connected accounts with optional filters.
98
+ */
99
+ async listConnectedAccounts(params?: {
100
+ connectionName?: string;
101
+ identifier?: string;
102
+ provider?: string;
103
+ organizationId?: string;
104
+ userId?: string;
105
+ pageSize?: number;
106
+ pageToken?: string;
107
+ query?: string;
108
+ }): Promise<ListConnectedAccountsResponse> {
109
+ return this.connectedAccounts.listConnectedAccounts({
110
+ organizationId: params?.organizationId,
111
+ userId: params?.userId,
112
+ connector: params?.connectionName,
113
+ identifier: params?.identifier,
114
+ provider: params?.provider,
115
+ pageSize: params?.pageSize,
116
+ pageToken: params?.pageToken,
117
+ query: params?.query,
118
+ });
119
+ }
120
+
121
+ /**
122
+ * Delete a connected account.
123
+ */
124
+ async deleteConnectedAccount(params: {
125
+ connectionName: string;
126
+ identifier: string;
127
+ connectedAccountId?: string;
128
+ organizationId?: string;
129
+ userId?: string;
130
+ }): Promise<DeleteConnectedAccountResponse> {
131
+ const {
132
+ connectionName,
133
+ identifier,
134
+ connectedAccountId,
135
+ organizationId,
136
+ userId,
137
+ } = params;
138
+
139
+ return this.connectedAccounts.deleteConnectedAccount({
140
+ connector: connectionName,
141
+ identifier,
142
+ organizationId,
143
+ userId,
144
+ connectedAccountId,
145
+ });
146
+ }
147
+
148
+ /**
149
+ * Get connected account authorization details.
150
+ */
151
+ async getConnectedAccount(params: {
152
+ connectionName: string;
153
+ identifier: string;
154
+ connectedAccountId?: string;
155
+ organizationId?: string;
156
+ userId?: string;
157
+ }): Promise<GetConnectedAccountByIdentifierResponse> {
158
+ const {
159
+ connectionName,
160
+ identifier,
161
+ connectedAccountId,
162
+ organizationId,
163
+ userId,
164
+ } = params;
165
+
166
+ return this.connectedAccounts.getConnectedAccountByIdentifier({
167
+ connector: connectionName,
168
+ identifier,
169
+ organizationId,
170
+ userId,
171
+ connectedAccountId,
172
+ });
173
+ }
174
+
175
+ /**
176
+ * Create a new connected account.
177
+ *
178
+ * This helper accepts a high-level payload and builds the
179
+ * underlying CreateConnectedAccount message.
180
+ */
181
+ async createConnectedAccount(params: {
182
+ connectionName: string;
183
+ identifier: string;
184
+ authorizationDetails: CreateConnectedAccount["authorizationDetails"];
185
+ organizationId?: string;
186
+ userId?: string;
187
+ apiConfig?: Record<string, unknown>;
188
+ }): Promise<CreateConnectedAccountResponse> {
189
+ const {
190
+ connectionName,
191
+ identifier,
192
+ authorizationDetails,
193
+ organizationId,
194
+ userId,
195
+ apiConfig,
196
+ } = params;
197
+
198
+ if (!connectionName?.trim()) {
199
+ throw new Error("connectionName is required");
200
+ }
201
+ if (!identifier?.trim()) {
202
+ throw new Error("identifier is required");
203
+ }
204
+
205
+ const connectedAccount = new CreateConnectedAccount({
206
+ authorizationDetails,
207
+ ...(apiConfig != null && {
208
+ apiConfig: apiConfig as unknown as CreateConnectedAccount["apiConfig"],
209
+ }),
210
+ });
211
+
212
+ return this.connectedAccounts.createConnectedAccount({
213
+ connector: connectionName,
214
+ identifier,
215
+ connectedAccount,
216
+ organizationId,
217
+ userId,
218
+ });
219
+ }
220
+
221
+ /**
222
+ * Get an existing connected account or create a new one if it doesn't exist.
223
+ */
224
+ async getOrCreateConnectedAccount(params: {
225
+ connectionName: string;
226
+ identifier: string;
227
+ authorizationDetails?: CreateConnectedAccount["authorizationDetails"];
228
+ organizationId?: string;
229
+ userId?: string;
230
+ apiConfig?: Record<string, unknown>;
231
+ }): Promise<CreateConnectedAccountResponse> {
232
+ const {
233
+ connectionName,
234
+ identifier,
235
+ authorizationDetails,
236
+ organizationId,
237
+ userId,
238
+ apiConfig,
239
+ } = params;
240
+
241
+ return this.connectedAccounts.getOrCreateConnectedAccount({
242
+ connector: connectionName,
243
+ identifier,
244
+ authorizationDetails,
245
+ organizationId,
246
+ userId,
247
+ apiConfig,
248
+ });
249
+ }
250
+
251
+ /**
252
+ * Update an existing connected account.
253
+ */
254
+ async updateConnectedAccount(params: {
255
+ connectionName: string;
256
+ identifier: string;
257
+ authorizationDetails?: UpdateConnectedAccount["authorizationDetails"];
258
+ organizationId?: string;
259
+ userId?: string;
260
+ connectedAccountId?: string;
261
+ apiConfig?: UpdateConnectedAccount["apiConfig"];
262
+ }): Promise<UpdateConnectedAccountResponse> {
263
+ const {
264
+ connectionName,
265
+ identifier,
266
+ authorizationDetails,
267
+ organizationId,
268
+ userId,
269
+ connectedAccountId,
270
+ apiConfig,
271
+ } = params;
272
+
273
+ const connectedAccount = new UpdateConnectedAccount({
274
+ ...(authorizationDetails && { authorizationDetails }),
275
+ ...(apiConfig != null && { apiConfig }),
276
+ });
277
+
278
+ return this.connectedAccounts.updateConnectedAccount({
279
+ connector: connectionName,
280
+ identifier,
281
+ connectedAccount,
282
+ organizationId,
283
+ userId,
284
+ connectedAccountId,
285
+ });
286
+ }
287
+
288
+ /**
289
+ * Make a proxied REST API call on behalf of a connected account.
290
+ */
291
+ async request(params: {
292
+ connectionName: string;
293
+ identifier: string;
294
+ path: string;
295
+ method?: string;
296
+ queryParams?: Record<string, unknown>;
297
+ body?: unknown;
298
+ formData?: Record<string, unknown>;
299
+ headers?: Record<string, string>;
300
+ timeoutMs?: number;
301
+ }): Promise<AxiosResponse<any>> {
302
+ const {
303
+ connectionName,
304
+ identifier,
305
+ path,
306
+ method = "GET",
307
+ queryParams,
308
+ body,
309
+ formData,
310
+ headers,
311
+ timeoutMs,
312
+ } = params;
313
+
314
+ if (!connectionName?.trim()) {
315
+ throw new Error("connectionName is required");
316
+ }
317
+ if (!identifier?.trim()) {
318
+ throw new Error("identifier is required");
319
+ }
320
+ if (!path?.trim()) {
321
+ throw new Error("path is required");
322
+ }
323
+
324
+ const url = `${this.coreClient.envUrl.replace(/\/$/, "")}/proxy${path}`;
325
+ const timeout = timeoutMs ?? 30_000;
326
+
327
+ const proxyHeaders: Record<string, string> = {
328
+ connection_name: connectionName,
329
+ Connection_name: connectionName,
330
+ identifier,
331
+ ...(headers ?? {}),
332
+ };
333
+
334
+
335
+
336
+ return this.coreClient.connectExec(
337
+ (config) => this.coreClient.axios.request(config),
338
+ {
339
+ url,
340
+ method: method.toUpperCase(),
341
+ params: queryParams,
342
+ data: body ?? formData,
343
+ headers: proxyHeaders,
344
+ timeout,
345
+ }
346
+ );
347
+ }
348
+ }
349
+
package/src/core.ts CHANGED
@@ -23,7 +23,7 @@ export default class CoreClient {
23
23
  public keys: JWK[] = [];
24
24
  public accessToken: string | null = null;
25
25
  public axios: Axios;
26
- public sdkVersion = `Scalekit-Node/2.2.0-beta.2`;
26
+ public sdkVersion = `Scalekit-Node/2.2.0-beta.3`;
27
27
  public apiVersion = "20260310";
28
28
  public userAgent = `${this.sdkVersion} Node/${process.version} (${
29
29
  process.platform
package/src/scalekit.ts CHANGED
@@ -17,6 +17,7 @@ import SessionClient from './session';
17
17
  import RoleClient from './role';
18
18
  import PermissionClient from './permission';
19
19
  import WebAuthnClient from './webauthn';
20
+ import ActionsClient from './actions';
20
21
  import { IdpInitiatedLoginClaims, IdTokenClaim, User } from './types/auth';
21
22
  import { AuthenticationOptions, AuthenticationResponse, AuthorizationUrlOptions, GrantType, LogoutUrlOptions, RefreshTokenResponse ,TokenValidationOptions } from './types/scalekit';
22
23
  import { WebhookVerificationError, ScalekitValidateTokenFailureException } from './errors/base-exception';
@@ -64,6 +65,7 @@ export default class ScalekitClient {
64
65
  readonly domain: DomainClient;
65
66
  readonly tools: ToolsClient;
66
67
  readonly connectedAccounts: ConnectedAccountsClient;
68
+ readonly actions: ActionsClient;
67
69
  readonly directory: DirectoryClient;
68
70
  readonly passwordless: PasswordlessClient;
69
71
  readonly user: UserClient;
@@ -97,6 +99,11 @@ export default class ScalekitClient {
97
99
  this.grpcConnect,
98
100
  this.coreClient
99
101
  );
102
+ this.actions = new ActionsClient(
103
+ this.tools,
104
+ this.connectedAccounts,
105
+ this.coreClient
106
+ );
100
107
  this.directory = new DirectoryClient(this.grpcConnect, this.coreClient);
101
108
  this.passwordless = new PasswordlessClient(
102
109
  this.grpcConnect,