@scalekit-sdk/node 2.1.7 → 2.1.8

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 (82) hide show
  1. package/buf.gen.yaml +1 -0
  2. package/lib/auth.d.ts +41 -9
  3. package/lib/auth.js +44 -12
  4. package/lib/auth.js.map +1 -1
  5. package/lib/connection.d.ts +195 -21
  6. package/lib/connection.js +197 -23
  7. package/lib/connection.js.map +1 -1
  8. package/lib/core.d.ts +2 -2
  9. package/lib/core.js +13 -12
  10. package/lib/core.js.map +1 -1
  11. package/lib/directory.d.ts +293 -40
  12. package/lib/directory.js +308 -44
  13. package/lib/directory.js.map +1 -1
  14. package/lib/domain.d.ts +166 -18
  15. package/lib/domain.js +178 -29
  16. package/lib/domain.js.map +1 -1
  17. package/lib/organization.d.ts +404 -44
  18. package/lib/organization.js +419 -54
  19. package/lib/organization.js.map +1 -1
  20. package/lib/permission.d.ts +179 -35
  21. package/lib/permission.js +190 -38
  22. package/lib/permission.js.map +1 -1
  23. package/lib/pkg/grpc/scalekit/v1/auth/auth_connect.d.ts +3 -3
  24. package/lib/pkg/grpc/scalekit/v1/auth/auth_connect.js +2 -2
  25. package/lib/pkg/grpc/scalekit/v1/auth/auth_connect.js.map +1 -1
  26. package/lib/pkg/grpc/scalekit/v1/auth/auth_pb.d.ts +16 -16
  27. package/lib/pkg/grpc/scalekit/v1/auth/auth_pb.js +21 -21
  28. package/lib/pkg/grpc/scalekit/v1/auth/auth_pb.js.map +1 -1
  29. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_connect.d.ts +82 -0
  30. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_connect.js +90 -0
  31. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_connect.js.map +1 -0
  32. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_pb.d.ts +647 -0
  33. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_pb.js +993 -0
  34. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_pb.js.map +1 -0
  35. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.d.ts +142 -0
  36. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.js +165 -1
  37. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.js.map +1 -1
  38. package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.d.ts +1 -10
  39. package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.js +0 -9
  40. package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.js.map +1 -1
  41. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.d.ts +28 -63
  42. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.js +9 -90
  43. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.js.map +1 -1
  44. package/lib/pkg/grpc/scalekit/v1/users/users_pb.d.ts +2 -2
  45. package/lib/pkg/grpc/scalekit/v1/users/users_pb.js +1 -1
  46. package/lib/pkg/grpc/scalekit/v1/users/users_pb.js.map +1 -1
  47. package/lib/role.d.ts +252 -56
  48. package/lib/role.js +262 -62
  49. package/lib/role.js.map +1 -1
  50. package/lib/scalekit.d.ts +323 -54
  51. package/lib/scalekit.js +354 -76
  52. package/lib/scalekit.js.map +1 -1
  53. package/lib/session.d.ts +235 -22
  54. package/lib/session.js +237 -24
  55. package/lib/session.js.map +1 -1
  56. package/lib/user.d.ts +571 -53
  57. package/lib/user.js +598 -89
  58. package/lib/user.js.map +1 -1
  59. package/lib/webauthn.d.ts +33 -0
  60. package/lib/webauthn.js +80 -0
  61. package/lib/webauthn.js.map +1 -0
  62. package/package.json +2 -2
  63. package/src/auth.ts +53 -19
  64. package/src/connection.ts +237 -62
  65. package/src/core.ts +39 -33
  66. package/src/directory.ts +356 -98
  67. package/src/domain.ts +215 -68
  68. package/src/organization.ts +490 -112
  69. package/src/permission.ts +234 -88
  70. package/src/pkg/grpc/scalekit/v1/auth/auth_connect.ts +3 -3
  71. package/src/pkg/grpc/scalekit/v1/auth/auth_pb.ts +24 -24
  72. package/src/pkg/grpc/scalekit/v1/auth/webauthn_connect.ts +89 -0
  73. package/src/pkg/grpc/scalekit/v1/auth/webauthn_pb.ts +1263 -0
  74. package/src/pkg/grpc/scalekit/v1/commons/commons_pb.ts +217 -0
  75. package/src/pkg/grpc/scalekit/v1/connections/connections_connect.ts +1 -10
  76. package/src/pkg/grpc/scalekit/v1/connections/connections_pb.ts +42 -129
  77. package/src/pkg/grpc/scalekit/v1/users/users_pb.ts +3 -3
  78. package/src/role.ts +336 -136
  79. package/src/scalekit.ts +478 -149
  80. package/src/session.ts +266 -63
  81. package/src/user.ts +675 -168
  82. package/src/webauthn.ts +98 -0
package/src/user.ts CHANGED
@@ -1,9 +1,22 @@
1
- import { Empty, PartialMessage } from '@bufbuild/protobuf';
2
- import { PromiseClient } from '@connectrpc/connect';
3
- import GrpcConnect from './connect';
4
- import CoreClient from './core';
5
- import { UserService } from './pkg/grpc/scalekit/v1/users/users_connect';
6
- import {
1
+ /**
2
+ * Client for managing users and their organization memberships.
3
+ *
4
+ * This client provides comprehensive user management capabilities including creating users,
5
+ * managing their memberships across organizations, updating user profiles, and handling
6
+ * invitation emails. Users can belong to multiple organizations with different roles.
7
+ *
8
+ * @example
9
+ * const scalekitClient = new ScalekitClient(envUrl, clientId, clientSecret);
10
+ * const userClient = scalekitClient.user;
11
+ *
12
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | User API Documentation}
13
+ */
14
+ import { Empty, PartialMessage } from "@bufbuild/protobuf";
15
+ import { PromiseClient } from "@connectrpc/connect";
16
+ import GrpcConnect from "./connect";
17
+ import CoreClient from "./core";
18
+ import { UserService } from "./pkg/grpc/scalekit/v1/users/users_connect";
19
+ import {
7
20
  CreateUserAndMembershipRequest,
8
21
  CreateUserAndMembershipResponse,
9
22
  DeleteUserRequest,
@@ -27,9 +40,12 @@ import {
27
40
  CreateMembership,
28
41
  UpdateMembership,
29
42
  ResendInviteRequest,
30
- ResendInviteResponse
31
- } from './pkg/grpc/scalekit/v1/users/users_pb';
32
- import { CreateUserRequest, UpdateUserRequest as UpdateUserRequestType } from './types/user';
43
+ ResendInviteResponse,
44
+ } from "./pkg/grpc/scalekit/v1/users/users_pb";
45
+ import {
46
+ CreateUserRequest,
47
+ UpdateUserRequest as UpdateUserRequestType,
48
+ } from "./types/user";
33
49
 
34
50
  export default class UserClient {
35
51
  private client: PromiseClient<typeof UserService>;
@@ -42,31 +58,87 @@ export default class UserClient {
42
58
  }
43
59
 
44
60
  /**
45
- * Create a new user and add them to an organization
46
- * @param {string} organizationId The organization id
47
- * @param {CreateUserRequest} options The user creation options
48
- * @returns {Promise<CreateUserAndMembershipResponse>} The created user
61
+ * Creates a new user and adds them as a member of an organization in a single operation.
62
+ *
63
+ * This is the primary method for user provisioning. It creates the user account and establishes
64
+ * their membership in the specified organization. Optionally sends an invitation email to the user
65
+ * with instructions to activate their account.
66
+ *
67
+ * @param {string} organizationId - The organization ID to add the user to
68
+ * @param {CreateUserRequest} options - User creation configuration
69
+ * @param {string} options.email - User's email address (required, must be unique)
70
+ * @param {object} [options.userProfile] - Optional user profile information
71
+ * @param {string} [options.userProfile.firstName] - User's first name
72
+ * @param {string} [options.userProfile.lastName] - User's last name
73
+ * @param {Record<string, string>} [options.metadata] - Custom metadata key-value pairs
74
+ * @param {boolean} [options.sendInvitationEmail=true] - Whether to send invitation email to the user
75
+ *
76
+ * @returns {Promise<CreateUserAndMembershipResponse>} Response containing:
77
+ * - user: The created user object with profile and membership details
78
+ *
79
+ * @throws {Error} When organizationId is missing or invalid
80
+ * @throws {Error} When email is missing or already exists
81
+ * @throws {Error} When user creation fails
82
+ *
83
+ * @example
84
+ * // Create user with profile and send invitation
85
+ * const response = await scalekitClient.user.createUserAndMembership(
86
+ * 'org_123456',
87
+ * {
88
+ * email: 'john.doe@company.com',
89
+ * userProfile: {
90
+ * firstName: 'John',
91
+ * lastName: 'Doe'
92
+ * },
93
+ * sendInvitationEmail: true,
94
+ * metadata: {
95
+ * department: 'Engineering',
96
+ * role: 'Developer'
97
+ * }
98
+ * }
99
+ * );
100
+ *
101
+ * console.log('User created:', response.user.id);
102
+ *
103
+ * @example
104
+ * // Create user without sending invitation
105
+ * const response = await scalekitClient.user.createUserAndMembership(
106
+ * 'org_123456',
107
+ * {
108
+ * email: 'jane.smith@company.com',
109
+ * sendInvitationEmail: false
110
+ * }
111
+ * );
112
+ *
113
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | Create User API}
114
+ * @see {@link createMembership} - Add existing user to another organization
115
+ * @see {@link resendInvite} - Resend invitation email to a user
49
116
  */
50
- async createUserAndMembership(organizationId: string, options: CreateUserRequest): Promise<CreateUserAndMembershipResponse> {
117
+ async createUserAndMembership(
118
+ organizationId: string,
119
+ options: CreateUserRequest
120
+ ): Promise<CreateUserAndMembershipResponse> {
51
121
  if (!organizationId) {
52
- throw new Error('organizationId is required');
122
+ throw new Error("organizationId is required");
53
123
  }
54
124
  if (!options.email) {
55
- throw new Error('email is required');
125
+ throw new Error("email is required");
56
126
  }
57
127
 
58
128
  const user = new CreateUser({
59
129
  email: options.email,
60
- userProfile: options.userProfile ? new CreateUserProfile({
61
- firstName: options.userProfile.firstName,
62
- lastName: options.userProfile.lastName
63
- }) : undefined,
64
- metadata: options.metadata
130
+ userProfile: options.userProfile
131
+ ? new CreateUserProfile({
132
+ firstName: options.userProfile.firstName,
133
+ lastName: options.userProfile.lastName,
134
+ })
135
+ : undefined,
136
+ metadata: options.metadata,
65
137
  });
66
138
 
67
139
  const request: PartialMessage<CreateUserAndMembershipRequest> = {
68
140
  organizationId,
69
- user
141
+ user,
70
142
  };
71
143
 
72
144
  if (options.sendInvitationEmail !== undefined) {
@@ -77,242 +149,677 @@ export default class UserClient {
77
149
  this.client.createUserAndMembership,
78
150
  request
79
151
  );
80
-
152
+
81
153
  if (!response.user) {
82
- throw new Error('Failed to create user');
154
+ throw new Error("Failed to create user");
83
155
  }
84
-
156
+
85
157
  return response;
86
158
  }
87
159
 
88
160
  /**
89
- * Get a user by id
90
- * @param {string} userId The user id
91
- * @returns {Promise<GetUserResponse>} The user
161
+ * Retrieves comprehensive details about a specific user including their profile and memberships.
162
+ *
163
+ * Use this method to fetch complete user information including their organization memberships,
164
+ * roles, profile details, and custom metadata. This is useful for displaying user profiles,
165
+ * verifying user access, or checking membership status across organizations.
166
+ *
167
+ * @param {string} userId - The Scalekit-generated user identifier (format: "usr_...")
168
+ *
169
+ * @returns {Promise<GetUserResponse>} Response containing:
170
+ * - user: Complete user object with:
171
+ * - id: Scalekit's unique user identifier
172
+ * - email: User's email address
173
+ * - userProfile: Profile information (firstName, lastName)
174
+ * - memberships: Array of organization memberships with roles
175
+ * - metadata: Custom metadata key-value pairs
176
+ * - createTime: When the user was created
177
+ * - updateTime: When the user was last updated
178
+ *
179
+ * @throws {Error} If the user is not found or access is denied
180
+ *
181
+ * @example
182
+ * // Get user details
183
+ * const response = await scalekitClient.user.getUser('usr_123456');
184
+ * const user = response.user;
185
+ *
186
+ * console.log('User:', user.email);
187
+ * console.log('Name:', user.userProfile?.firstName, user.userProfile?.lastName);
188
+ * console.log('Organizations:', user.memberships?.length);
189
+ *
190
+ * @example
191
+ * // Check user's organization memberships
192
+ * const response = await scalekitClient.user.getUser(userId);
193
+ * const userOrgs = response.user.memberships?.map(m => m.organizationId) || [];
194
+ *
195
+ * if (userOrgs.includes('org_12345')) {
196
+ * console.log('User is a member of this organization');
197
+ * }
198
+ *
199
+ * @example
200
+ * // Display user profile in application
201
+ * app.get('/api/profile', async (req, res) => {
202
+ * const userId = req.user.id;
203
+ *
204
+ * try {
205
+ * const response = await scalekitClient.user.getUser(userId);
206
+ * res.json({
207
+ * email: response.user.email,
208
+ * profile: response.user.userProfile,
209
+ * organizations: response.user.memberships
210
+ * });
211
+ * } catch (error) {
212
+ * res.status(404).json({ error: 'User not found' });
213
+ * }
214
+ * });
215
+ *
216
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | Get User API}
217
+ * @see {@link listUsers} - List all users across the environment
218
+ * @see {@link listOrganizationUsers} - List users in a specific organization
92
219
  */
93
220
  async getUser(userId: string): Promise<GetUserResponse> {
94
- return this.coreClient.connectExec(
95
- this.client.getUser,
96
- {
97
- identities: {
98
- case: 'id',
99
- value: userId
100
- }
101
- }
102
- );
221
+ return this.coreClient.connectExec(this.client.getUser, {
222
+ identities: {
223
+ case: "id",
224
+ value: userId,
225
+ },
226
+ });
103
227
  }
104
228
 
105
229
  /**
106
- * List users with pagination
107
- * @param {object} options The pagination options
108
- * @param {number} options.pageSize The page size
109
- * @param {string} options.pageToken The page token
110
- * @returns {Promise<ListUsersResponse>} The list of users
230
+ * Retrieves a paginated list of all users across your Scalekit environment.
231
+ *
232
+ * This method returns all users in your environment regardless of organization membership.
233
+ * It's useful for administrative oversight, auditing, user management interfaces, and
234
+ * searching across all users. Use pagination to efficiently handle large user bases.
235
+ *
236
+ * @param {object} [options] - Optional pagination parameters
237
+ * @param {number} [options.pageSize] - Number of users to return per page (valid range: 10-100, default: 10)
238
+ * @param {string} [options.pageToken] - Token for retrieving the next page of results.
239
+ * Obtained from the previous response's nextPageToken.
240
+ *
241
+ * @returns {Promise<ListUsersResponse>} Response containing:
242
+ * - users: Array of user objects with profiles and membership details
243
+ * - nextPageToken: Token for fetching the next page (empty if no more pages)
244
+ * - totalSize: Total number of users in the environment
245
+ *
246
+ * @example
247
+ * // List first page of users
248
+ * const response = await scalekitClient.user.listUsers({
249
+ * pageSize: 20
250
+ * });
251
+ *
252
+ * console.log('Users:', response.users.length);
253
+ * console.log('Total users:', response.totalSize);
254
+ *
255
+ * @example
256
+ * // Paginate through all users
257
+ * let pageToken = undefined;
258
+ * let allUsers = [];
259
+ *
260
+ * do {
261
+ * const response = await scalekitClient.user.listUsers({
262
+ * pageSize: 50,
263
+ * pageToken
264
+ * });
265
+ *
266
+ * allUsers.push(...response.users);
267
+ * pageToken = response.nextPageToken;
268
+ * } while (pageToken);
269
+ *
270
+ * console.log('Fetched all users:', allUsers.length);
271
+ *
272
+ * @example
273
+ * // Build user management dashboard
274
+ * app.get('/api/admin/users', async (req, res) => {
275
+ * const { pageSize = 25, pageToken } = req.query;
276
+ *
277
+ * try {
278
+ * const response = await scalekitClient.user.listUsers({
279
+ * pageSize: parseInt(pageSize),
280
+ * pageToken
281
+ * });
282
+ *
283
+ * res.json({
284
+ * users: response.users,
285
+ * nextPageToken: response.nextPageToken,
286
+ * total: response.totalSize
287
+ * });
288
+ * } catch (error) {
289
+ * res.status(500).json({ error: 'Failed to fetch users' });
290
+ * }
291
+ * });
292
+ *
293
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | List Users API}
294
+ * @see {@link listOrganizationUsers} - List users in a specific organization
295
+ * @see {@link getUser} - Get details of a specific user
111
296
  */
112
297
  async listUsers(options?: {
113
- pageSize?: number,
114
- pageToken?: string
298
+ pageSize?: number;
299
+ pageToken?: string;
115
300
  }): Promise<ListUsersResponse> {
116
- return this.coreClient.connectExec(
117
- this.client.listUsers,
118
- {
119
- pageSize: options?.pageSize,
120
- pageToken: options?.pageToken
121
- }
122
- );
301
+ return this.coreClient.connectExec(this.client.listUsers, {
302
+ pageSize: options?.pageSize,
303
+ pageToken: options?.pageToken,
304
+ });
123
305
  }
124
306
 
125
307
  /**
126
- * Update a user
127
- * @param {string} userId The user id
128
- * @param {UpdateUserRequestType} options The update options
129
- * @returns {Promise<UpdateUserResponse>} The updated user
308
+ * Updates a user's profile information and custom metadata.
309
+ *
310
+ * Use this method to modify user profile details such as name or to update custom metadata
311
+ * associated with the user. Note that the user's email address and user ID cannot be changed.
312
+ * Only the fields you specify in the update object will be modified; all other fields remain unchanged.
313
+ *
314
+ * @param {string} userId - The Scalekit user identifier (format: "usr_...")
315
+ * @param {UpdateUserRequestType} options - Object containing fields to update:
316
+ * - userProfile?: Profile information to update
317
+ * - firstName?: User's first name
318
+ * - lastName?: User's last name
319
+ * - metadata?: Custom key-value pairs for storing additional data
320
+ *
321
+ * @returns {Promise<UpdateUserResponse>} Response containing:
322
+ * - user: The updated user object with all current values
323
+ *
324
+ * @throws {Error} If the user is not found or update fails
325
+ *
326
+ * @example
327
+ * // Update user's name
328
+ * const response = await scalekitClient.user.updateUser('usr_123456', {
329
+ * userProfile: {
330
+ * firstName: 'John',
331
+ * lastName: 'Smith'
332
+ * }
333
+ * });
334
+ *
335
+ * console.log('Updated user:', response.user.userProfile);
336
+ *
337
+ * @example
338
+ * // Update user metadata only
339
+ * await scalekitClient.user.updateUser('usr_123456', {
340
+ * metadata: {
341
+ * department: 'Engineering',
342
+ * title: 'Senior Developer',
343
+ * employeeId: 'EMP-12345'
344
+ * }
345
+ * });
346
+ *
347
+ * @example
348
+ * // Update both profile and metadata
349
+ * const response = await scalekitClient.user.updateUser('usr_123456', {
350
+ * userProfile: {
351
+ * firstName: 'Jane',
352
+ * lastName: 'Doe'
353
+ * },
354
+ * metadata: {
355
+ * phoneNumber: '+1-555-0123',
356
+ * timezone: 'America/New_York'
357
+ * }
358
+ * });
359
+ *
360
+ * @example
361
+ * // Update user profile via API endpoint
362
+ * app.patch('/api/users/:userId', async (req, res) => {
363
+ * const { userId } = req.params;
364
+ * const { firstName, lastName, metadata } = req.body;
365
+ *
366
+ * try {
367
+ * const response = await scalekitClient.user.updateUser(userId, {
368
+ * userProfile: { firstName, lastName },
369
+ * metadata
370
+ * });
371
+ * res.json({ user: response.user });
372
+ * } catch (error) {
373
+ * res.status(500).json({ error: 'Failed to update user' });
374
+ * }
375
+ * });
376
+ *
377
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | Update User API}
378
+ * @see {@link getUser} - Retrieve current user details
379
+ * @see {@link createUserAndMembership} - Create a new user
130
380
  */
131
- async updateUser(userId: string, options: UpdateUserRequestType): Promise<UpdateUserResponse> {
381
+ async updateUser(
382
+ userId: string,
383
+ options: UpdateUserRequestType
384
+ ): Promise<UpdateUserResponse> {
132
385
  const updateUser = new UpdateUser({
133
- userProfile: options.userProfile ? {
134
- firstName: options.userProfile.firstName,
135
- lastName: options.userProfile.lastName
136
- } : undefined,
137
- metadata: options.metadata
386
+ userProfile: options.userProfile
387
+ ? {
388
+ firstName: options.userProfile.firstName,
389
+ lastName: options.userProfile.lastName,
390
+ }
391
+ : undefined,
392
+ metadata: options.metadata,
138
393
  });
139
394
 
140
- return this.coreClient.connectExec(
141
- this.client.updateUser,
142
- {
143
- identities: {
144
- case: 'id',
145
- value: userId
146
- },
147
- user: updateUser
148
- }
149
- );
395
+ return this.coreClient.connectExec(this.client.updateUser, {
396
+ identities: {
397
+ case: "id",
398
+ value: userId,
399
+ },
400
+ user: updateUser,
401
+ });
150
402
  }
151
403
 
152
404
  /**
153
- * Delete a user
154
- * @param {string} userId The user id
155
- * @returns {Promise<Empty>} Empty response
405
+ * Permanently deletes a user from your Scalekit environment.
406
+ *
407
+ * This operation removes the user's profile, all organization memberships, and related data
408
+ * across all organizations. This action is irreversible and cannot be undone. Use with extreme
409
+ * caution, especially in production environments. Consider deactivating users or removing specific
410
+ * memberships instead of full deletion for compliance and audit purposes.
411
+ *
412
+ * @param {string} userId - The Scalekit user identifier to delete (format: "usr_...")
413
+ *
414
+ * @returns {Promise<Empty>} Empty response on successful deletion
415
+ *
416
+ * @throws {Error} If the user is not found or deletion fails
417
+ *
418
+ * @example
419
+ * // Delete a user
420
+ * await scalekitClient.user.deleteUser('usr_123456');
421
+ * console.log('User deleted successfully');
422
+ *
423
+ * @example
424
+ * // Delete user with confirmation flow
425
+ * const confirmDelete = await askUserConfirmation(
426
+ * 'Are you sure you want to permanently delete this user? This action cannot be undone.'
427
+ * );
428
+ *
429
+ * if (confirmDelete) {
430
+ * try {
431
+ * await scalekitClient.user.deleteUser(userId);
432
+ * console.log('User permanently deleted');
433
+ * } catch (error) {
434
+ * console.error('Failed to delete user:', error);
435
+ * }
436
+ * }
437
+ *
438
+ *
439
+ *
440
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | Delete User API}
441
+ * @see {@link deleteMembership} - Remove user from a specific organization only
442
+ * @see {@link getUser} - Check if user exists before deletion
156
443
  */
157
444
  async deleteUser(userId: string): Promise<Empty> {
158
- return this.coreClient.connectExec(
159
- this.client.deleteUser,
160
- {
161
- identities: {
162
- case: 'id',
163
- value: userId
164
- }
165
- }
166
- );
445
+ return this.coreClient.connectExec(this.client.deleteUser, {
446
+ identities: {
447
+ case: "id",
448
+ value: userId,
449
+ },
450
+ });
167
451
  }
168
452
 
169
453
  /**
170
- * Create a membership for a user in an organization
171
- * @param {string} organizationId The organization id
172
- * @param {string} userId The user id
173
- * @param {object} options The membership options
174
- * @param {string[]} options.roles The roles to assign
175
- * @param {Record<string, string>} options.metadata Optional metadata
176
- * @param {boolean} options.sendInvitationEmail Whether to send invitation email
177
- * @returns {Promise<CreateMembershipResponse>} The response with updated user
454
+ * Adds an existing user as a member of a new organization with specified roles.
455
+ *
456
+ * Use this method to grant organization access to users who already have accounts in your
457
+ * Scalekit environment. This is useful for adding users to additional organizations, managing
458
+ * multi-tenant access, or onboarding existing users to new teams. Optionally sends an invitation
459
+ * email to notify the user of their new organization access.
460
+ *
461
+ * @param {string} organizationId - The organization ID to add the user to (format: "org_...")
462
+ * @param {string} userId - The user ID to add as a member (format: "usr_...")
463
+ * @param {object} [options={}] - Optional membership configuration
464
+ * @param {string[]} [options.roles] - Array of role names to assign to the user
465
+ * (e.g., ['admin', 'editor', 'viewer'])
466
+ * @param {Record<string, string>} [options.metadata] - Custom metadata key-value pairs
467
+ * for this specific membership
468
+ * @param {boolean} [options.sendInvitationEmail=true] - Whether to send invitation email
469
+ * notifying the user of new access
470
+ *
471
+ * @returns {Promise<CreateMembershipResponse>} Response containing:
472
+ * - user: The updated user object including the new membership details
473
+ *
474
+ * @throws {Error} When the user or organization is not found
475
+ * @throws {Error} When the user is already a member of the organization
476
+ *
477
+ * @example
478
+ * // Add user to organization with admin role
479
+ * const response = await scalekitClient.user.createMembership(
480
+ * 'org_123456',
481
+ * 'usr_789012',
482
+ * {
483
+ * roles: ['admin'],
484
+ * sendInvitationEmail: true
485
+ * }
486
+ * );
487
+ *
488
+ * console.log('Membership created:', response.user.memberships);
489
+ *
490
+ * @example
491
+ * // Add user with multiple roles and metadata
492
+ * await scalekitClient.user.createMembership(
493
+ * 'org_123456',
494
+ * 'usr_789012',
495
+ * {
496
+ * roles: ['member', 'billing_admin'],
497
+ * metadata: {
498
+ * department: 'Finance',
499
+ * accessLevel: 'full'
500
+ * },
501
+ * sendInvitationEmail: true
502
+ * }
503
+ * );
504
+ *
505
+ * @example
506
+ * // Add user to organization without sending email
507
+ * await scalekitClient.user.createMembership(
508
+ * 'org_123456',
509
+ * 'usr_789012',
510
+ * { sendInvitationEmail: false }
511
+ * );
512
+
513
+ *
514
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | Create Membership API}
515
+ * @see {@link createUserAndMembership} - Create new user with initial membership
516
+ * @see {@link updateMembership} - Modify existing membership roles
517
+ * @see {@link deleteMembership} - Remove user from organization
178
518
  */
179
519
  async createMembership(
180
520
  organizationId: string,
181
521
  userId: string,
182
522
  options: {
183
- roles?: string[],
184
- metadata?: Record<string, string>,
185
- sendInvitationEmail?: boolean
523
+ roles?: string[];
524
+ metadata?: Record<string, string>;
525
+ sendInvitationEmail?: boolean;
186
526
  } = {}
187
527
  ): Promise<CreateMembershipResponse> {
188
528
  const membership = new CreateMembership({
189
- roles: options.roles?.map(role => ({ name: role })) || [],
190
- metadata: options.metadata || {}
529
+ roles: options.roles?.map((role) => ({ name: role })) || [],
530
+ metadata: options.metadata || {},
191
531
  });
192
532
 
193
533
  const request: PartialMessage<CreateMembershipRequest> = {
194
534
  organizationId,
195
535
  identities: {
196
- case: 'id',
197
- value: userId
536
+ case: "id",
537
+ value: userId,
198
538
  },
199
- membership
539
+ membership,
200
540
  };
201
541
 
202
542
  if (options.sendInvitationEmail !== undefined) {
203
543
  request.sendInvitationEmail = options.sendInvitationEmail;
204
544
  }
205
545
 
206
- return this.coreClient.connectExec(
207
- this.client.createMembership,
208
- request
209
- );
546
+ return this.coreClient.connectExec(this.client.createMembership, request);
210
547
  }
211
548
 
212
549
  /**
213
- * Delete a user's membership from an organization
214
- * @param {string} organizationId The organization id
215
- * @param {string} userId The user id
216
- * @returns {Promise<Empty>} Empty response
550
+ * Removes a user's membership from a specific organization.
551
+ *
552
+ * This operation revokes the user's access to the specified organization while keeping their
553
+ * user account intact. The user remains in the system and can still access other organizations
554
+ * they're a member of. This is the recommended approach when you want to remove access to a
555
+ * specific organization without deleting the entire user account. This action is irreversible.
556
+ *
557
+ * @param {string} organizationId - The organization ID to remove the user from (format: "org_...")
558
+ * @param {string} userId - The user ID to remove (format: "usr_...")
559
+ *
560
+ * @returns {Promise<Empty>} Empty response on successful removal
561
+ *
562
+ * @throws {Error} If the user or organization is not found
563
+ * @throws {Error} If the membership doesn't exist
564
+ *
565
+ * @example
566
+ * // Remove user from organization
567
+ * await scalekitClient.user.deleteMembership('org_123456', 'usr_789012');
568
+ * console.log('User removed from organization');
569
+ *
570
+ * @example
571
+ * // Remove user with confirmation
572
+ * const confirmRemoval = await askUserConfirmation(
573
+ * 'Remove this user from the organization?'
574
+ * );
575
+ *
576
+ * if (confirmRemoval) {
577
+ * try {
578
+ * await scalekitClient.user.deleteMembership(organizationId, userId);
579
+ * console.log('User access revoked');
580
+ * } catch (error) {
581
+ * console.error('Failed to remove user:', error);
582
+ * }
583
+ * }
584
+ *
585
+ *
586
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | Delete Membership API}
587
+ * @see {@link deleteUser} - Permanently delete user from all organizations
588
+ * @see {@link createMembership} - Add user to an organization
589
+ * @see {@link updateMembership} - Modify user's roles in organization
217
590
  */
218
591
  async deleteMembership(
219
592
  organizationId: string,
220
593
  userId: string
221
594
  ): Promise<Empty> {
222
- return this.coreClient.connectExec(
223
- this.client.deleteMembership,
224
- {
225
- organizationId,
226
- identities: {
227
- case: 'id',
228
- value: userId
229
- }
230
- }
231
- );
595
+ return this.coreClient.connectExec(this.client.deleteMembership, {
596
+ organizationId,
597
+ identities: {
598
+ case: "id",
599
+ value: userId,
600
+ },
601
+ });
232
602
  }
233
603
 
234
604
  /**
235
- * Update a user's membership in an organization
236
- * @param {string} organizationId The organization id
237
- * @param {string} userId The user id
238
- * @param {object} options The update options
239
- * @param {string[]} options.roles The roles to assign
240
- * @param {Record<string, string>} options.metadata Optional metadata
241
- * @returns {Promise<UpdateMembershipResponse>} The response with updated user
605
+ * Updates a user's roles and metadata within a specific organization.
606
+ *
607
+ * Use this method to modify a user's permissions by changing their assigned roles or to
608
+ * update membership-specific metadata. This allows you to adjust user access levels,
609
+ * promote/demote users, or track organization-specific information without affecting
610
+ * the user's memberships in other organizations.
611
+ *
612
+ * @param {string} organizationId - The organization ID where the membership exists (format: "org_...")
613
+ * @param {string} userId - The user ID whose membership to update (format: "usr_...")
614
+ * @param {object} [options={}] - Fields to update
615
+ * @param {string[]} [options.roles] - Array of role names to assign (replaces existing roles)
616
+ * (e.g., ['admin'], ['member', 'billing'])
617
+ * @param {Record<string, string>} [options.metadata] - Custom metadata key-value pairs
618
+ * specific to this membership
619
+ *
620
+ * @returns {Promise<UpdateMembershipResponse>} Response containing:
621
+ * - user: The updated user object with modified membership details
622
+ *
623
+ * @throws {Error} If the user, organization, or membership is not found
624
+ *
625
+ * @example
626
+ * // Promote user to admin
627
+ * const response = await scalekitClient.user.updateMembership(
628
+ * 'org_123456',
629
+ * 'usr_789012',
630
+ * { roles: ['admin'] }
631
+ * );
632
+ *
633
+ * console.log('User promoted:', response.user.memberships);
634
+ *
635
+ * @example
636
+ * // Assign multiple roles
637
+ * await scalekitClient.user.updateMembership(
638
+ * 'org_123456',
639
+ * 'usr_789012',
640
+ * { roles: ['member', 'billing_admin', 'support'] }
641
+ * );
642
+ *
643
+ * @example
644
+ * // Update membership metadata
645
+ * await scalekitClient.user.updateMembership(
646
+ * 'org_123456',
647
+ * 'usr_789012',
648
+ * {
649
+ * metadata: {
650
+ * department: 'Engineering',
651
+ * team: 'Backend',
652
+ * startDate: '2025-01-01'
653
+ * }
654
+ * }
655
+ * );
656
+ *
657
+ * @example
658
+ * // Update both roles and metadata
659
+ * await scalekitClient.user.updateMembership(
660
+ * 'org_123456',
661
+ * 'usr_789012',
662
+ * {
663
+ * roles: ['team_lead', 'developer'],
664
+ * metadata: {
665
+ * level: 'senior',
666
+ * permissions: 'full'
667
+ * }
668
+ * }
669
+ * );
670
+ *
671
+ *
672
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | Update Membership API}
673
+ * @see {@link createMembership} - Add user to organization
674
+ * @see {@link deleteMembership} - Remove user from organization
675
+ * @see {@link getUser} - View current user roles and memberships
242
676
  */
243
677
  async updateMembership(
244
678
  organizationId: string,
245
679
  userId: string,
246
680
  options: {
247
- roles?: string[],
248
- metadata?: Record<string, string>
681
+ roles?: string[];
682
+ metadata?: Record<string, string>;
249
683
  } = {}
250
684
  ): Promise<UpdateMembershipResponse> {
251
685
  const membership = new UpdateMembership({
252
- roles: options.roles?.map(role => ({ name: role })) || [],
253
- metadata: options.metadata || {}
686
+ roles: options.roles?.map((role) => ({ name: role })) || [],
687
+ metadata: options.metadata || {},
254
688
  });
255
689
 
256
- return this.coreClient.connectExec(
257
- this.client.updateMembership,
258
- {
259
- organizationId,
260
- identities: {
261
- case: 'id',
262
- value: userId
263
- },
264
- membership
265
- }
266
- );
690
+ return this.coreClient.connectExec(this.client.updateMembership, {
691
+ organizationId,
692
+ identities: {
693
+ case: "id",
694
+ value: userId,
695
+ },
696
+ membership,
697
+ });
267
698
  }
268
699
 
269
700
  /**
270
- * List users in an organization with pagination
271
- * @param {string} organizationId The organization id
272
- * @param {object} options The pagination options
273
- * @param {number} options.pageSize The page size
274
- * @param {string} options.pageToken The page token
275
- * @returns {Promise<ListOrganizationUsersResponse>} The list of users in the organization
701
+ * Retrieves a paginated list of all users who are members of a specific organization.
702
+ *
703
+ * This method returns all users with access to the specified organization, including their
704
+ * roles, membership details, and profiles. This is useful for displaying team member lists,
705
+ * managing organization access, or building user management interfaces. Use pagination to
706
+ * efficiently handle organizations with large member counts.
707
+ *
708
+ * @param {string} organizationId - The organization ID to list users from (format: "org_...")
709
+ * @param {object} [options] - Optional pagination parameters
710
+ * @param {number} [options.pageSize] - Number of users to return per page (valid range: 1-100)
711
+ * @param {string} [options.pageToken] - Token for retrieving the next page of results.
712
+ * Obtained from the previous response's nextPageToken.
713
+ *
714
+ * @returns {Promise<ListOrganizationUsersResponse>} Response containing:
715
+ * - users: Array of user objects with profiles, roles, and membership details
716
+ * - nextPageToken: Token for fetching the next page (empty if no more pages)
717
+ * - totalSize: Total number of users in the organization
718
+ *
719
+ * @throws {Error} If the organization is not found
720
+ *
721
+ * @example
722
+ * // List first page of organization users
723
+ * const response = await scalekitClient.user.listOrganizationUsers('org_123456', {
724
+ * pageSize: 25
725
+ * });
726
+ *
727
+ * console.log('Organization users:', response.users.length);
728
+ * console.log('Total members:', response.totalSize);
729
+ *
730
+ * @example
731
+ * // Paginate through all organization members
732
+ * let pageToken = undefined;
733
+ * let allMembers = [];
734
+ *
735
+ * do {
736
+ * const response = await scalekitClient.user.listOrganizationUsers(
737
+ * 'org_123456',
738
+ * { pageSize: 50, pageToken }
739
+ * );
740
+ *
741
+ * allMembers.push(...response.users);
742
+ * pageToken = response.nextPageToken;
743
+ * } while (pageToken);
744
+ *
745
+ * console.log('All organization members:', allMembers.length);
746
+ *
747
+ *
748
+ * console.log('Organization admins:', admins.length);
749
+ *
750
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | List Organization Users API}
751
+ * @see {@link listUsers} - List all users across the environment
752
+ * @see {@link getUser} - Get details of a specific user
753
+ * @see {@link createMembership} - Add user to organization
276
754
  */
277
755
  async listOrganizationUsers(
278
756
  organizationId: string,
279
757
  options?: {
280
- pageSize?: number,
281
- pageToken?: string
758
+ pageSize?: number;
759
+ pageToken?: string;
282
760
  }
283
761
  ): Promise<ListOrganizationUsersResponse> {
284
- return this.coreClient.connectExec(
285
- this.client.listOrganizationUsers,
286
- {
287
- organizationId,
288
- pageSize: options?.pageSize,
289
- pageToken: options?.pageToken
290
- }
291
- );
762
+ return this.coreClient.connectExec(this.client.listOrganizationUsers, {
763
+ organizationId,
764
+ pageSize: options?.pageSize,
765
+ pageToken: options?.pageToken,
766
+ });
292
767
  }
293
768
 
294
769
  /**
295
- * Resend an invitation to a user
296
- * @param {string} organizationId The organization id
297
- * @param {string} userId The user id
298
- * @returns {Promise<ResendInviteResponse>} The response with the invite
770
+ * Resends an invitation email to a user for a specific organization.
771
+ *
772
+ * Use this method when a user hasn't received or has lost their invitation email. If the
773
+ * original invitation is still valid, a reminder email will be sent. If the invitation has
774
+ * expired, a new invitation with a secure magic link will be created and sent. This is useful
775
+ * for helping users who need to complete their account setup or activate their organization access.
776
+ *
777
+ * @param {string} organizationId - The organization ID for which to resend the invite (format: "org_...")
778
+ * @param {string} userId - The user ID who should receive the invite (format: "usr_...")
779
+ *
780
+ * @returns {Promise<ResendInviteResponse>} Response containing:
781
+ * - invite: The invitation details including status and expiration
782
+ *
783
+ * @throws {Error} When organizationId is missing or invalid
784
+ * @throws {Error} When userId is missing or invalid
785
+ * @throws {Error} When the user or organization is not found
786
+ * @throws {Error} When the membership doesn't exist
787
+ *
788
+ * @example
789
+ * // Resend invitation to a user
790
+ * const response = await scalekitClient.user.resendInvite('org_123456', 'usr_789012');
791
+ * console.log('Invitation resent:', response.invite);
792
+ *
793
+ * @example
794
+ * // Resend invitation with error handling
795
+ * try {
796
+ * await scalekitClient.user.resendInvite(organizationId, userId);
797
+ * console.log('Invitation email sent successfully');
798
+ * } catch (error) {
799
+ * console.error('Failed to resend invitation:', error);
800
+ * }
801
+ *
802
+ * @see {@link https://docs.scalekit.com/apis/#tag/users | Resend Invite API}
803
+ * @see {@link createUserAndMembership} - Create user with initial invitation
804
+ * @see {@link createMembership} - Add user to organization with invitation option
805
+ * @see {@link getUser} - Check user's invitation status
299
806
  */
300
- async resendInvite(organizationId: string, userId: string): Promise<ResendInviteResponse> {
807
+ async resendInvite(
808
+ organizationId: string,
809
+ userId: string
810
+ ): Promise<ResendInviteResponse> {
301
811
  if (!organizationId) {
302
- throw new Error('organizationId is required');
812
+ throw new Error("organizationId is required");
303
813
  }
304
814
  if (!userId) {
305
- throw new Error('userId is required');
815
+ throw new Error("userId is required");
306
816
  }
307
817
 
308
818
  const request = new ResendInviteRequest({
309
819
  organizationId,
310
- id: userId
820
+ id: userId,
311
821
  });
312
822
 
313
- return this.coreClient.connectExec(
314
- this.client.resendInvite,
315
- request
316
- );
823
+ return this.coreClient.connectExec(this.client.resendInvite, request);
317
824
  }
318
- }
825
+ }