@scalekit-sdk/node 2.1.2 → 2.1.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.
Files changed (44) hide show
  1. package/README.md +47 -11
  2. package/buf.gen.yaml +1 -0
  3. package/lib/core.js +1 -1
  4. package/lib/permission.d.ts +68 -0
  5. package/lib/permission.js +131 -0
  6. package/lib/permission.js.map +1 -0
  7. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.d.ts +2 -2
  8. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.js +1 -1
  9. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.js.map +1 -1
  10. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.d.ts +16 -0
  11. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.js +4 -0
  12. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.js.map +1 -1
  13. package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.d.ts +0 -8
  14. package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.js +0 -6
  15. package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.js.map +1 -1
  16. package/lib/pkg/grpc/scalekit/v1/roles/roles_connect.d.ts +250 -0
  17. package/lib/pkg/grpc/scalekit/v1/roles/roles_connect.js +258 -0
  18. package/lib/pkg/grpc/scalekit/v1/roles/roles_connect.js.map +1 -0
  19. package/lib/pkg/grpc/scalekit/v1/roles/roles_pb.d.ts +1157 -0
  20. package/lib/pkg/grpc/scalekit/v1/roles/roles_pb.js +1799 -0
  21. package/lib/pkg/grpc/scalekit/v1/roles/roles_pb.js.map +1 -0
  22. package/lib/pkg/grpc/scalekit/v1/users/users_pb.d.ts +2 -2
  23. package/lib/pkg/grpc/scalekit/v1/users/users_pb.js +1 -1
  24. package/lib/pkg/grpc/scalekit/v1/users/users_pb.js.map +1 -1
  25. package/lib/role.d.ts +104 -0
  26. package/lib/role.js +205 -0
  27. package/lib/role.js.map +1 -0
  28. package/lib/scalekit.d.ts +4 -0
  29. package/lib/scalekit.js +4 -0
  30. package/lib/scalekit.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/core.ts +1 -1
  33. package/src/permission.ts +164 -0
  34. package/src/pkg/grpc/scalekit/v1/commons/commons_pb.ts +3 -3
  35. package/src/pkg/grpc/scalekit/v1/connections/connections_pb.ts +24 -0
  36. package/src/pkg/grpc/scalekit/v1/domains/domains_pb.ts +0 -12
  37. package/src/pkg/grpc/scalekit/v1/roles/roles_connect.ts +257 -0
  38. package/src/pkg/grpc/scalekit/v1/roles/roles_pb.ts +2357 -0
  39. package/src/pkg/grpc/scalekit/v1/users/users_pb.ts +3 -3
  40. package/src/role.ts +261 -0
  41. package/src/scalekit.ts +12 -0
  42. package/tests/permission.test.ts +399 -0
  43. package/tests/role.test.ts +323 -0
  44. package/tests/utils/test-data.ts +168 -1
@@ -0,0 +1,323 @@
1
+ import ScalekitClient from '../src/scalekit';
2
+ import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
3
+ import { TestDataGenerator, TestOrganizationManager, TestRoleManager } from './utils/test-data';
4
+
5
+ describe('Roles', () => {
6
+ let client: ScalekitClient;
7
+ let testOrg: string;
8
+ let testRoleName: string | null = null;
9
+ let testOrgRoleName: string | null = null;
10
+
11
+ beforeEach(async () => {
12
+ // Use global client
13
+ client = global.client;
14
+
15
+ // Create test organization for each test
16
+ testOrg = await TestOrganizationManager.createTestOrganization(client);
17
+ });
18
+
19
+ afterEach(async () => {
20
+ // Clean up test resources
21
+ if (testRoleName) {
22
+ await TestRoleManager.cleanupTestRole(client, testRoleName);
23
+ testRoleName = null;
24
+ }
25
+
26
+ if (testOrgRoleName) {
27
+ await TestRoleManager.cleanupTestOrganizationRole(client, testOrg, testOrgRoleName);
28
+ testOrgRoleName = null;
29
+ }
30
+
31
+ // Clean up test organization
32
+ await TestOrganizationManager.cleanupTestOrganization(client, testOrg);
33
+ });
34
+
35
+ describe('RoleClient', () => {
36
+ it('should have role client available', () => {
37
+ expect(client.role).toBeDefined();
38
+ expect(typeof client.role.createRole).toBe('function');
39
+ expect(typeof client.role.getRole).toBe('function');
40
+ expect(typeof client.role.listRoles).toBe('function');
41
+ expect(typeof client.role.updateRole).toBe('function');
42
+ expect(typeof client.role.deleteRole).toBe('function');
43
+ expect(typeof client.role.getRoleUsersCount).toBe('function');
44
+ });
45
+
46
+ it('should have organization role methods available', () => {
47
+ expect(typeof client.role.createOrganizationRole).toBe('function');
48
+ expect(typeof client.role.getOrganizationRole).toBe('function');
49
+ expect(typeof client.role.listOrganizationRoles).toBe('function');
50
+ expect(typeof client.role.updateOrganizationRole).toBe('function');
51
+ expect(typeof client.role.deleteOrganizationRole).toBe('function');
52
+ expect(typeof client.role.getOrganizationRoleUsersCount).toBe('function');
53
+ expect(typeof client.role.updateDefaultOrganizationRoles).toBe('function');
54
+ expect(typeof client.role.deleteOrganizationRoleBase).toBe('function');
55
+ });
56
+ });
57
+
58
+ describe('Role API Integration Tests', () => {
59
+ describe('createRole', () => {
60
+ it('should create a new role', async () => {
61
+ const roleData = TestDataGenerator.generateRoleData();
62
+
63
+ const response = await client.role.createRole(roleData);
64
+
65
+ expect(response).toBeDefined();
66
+ expect(response.role).toBeDefined();
67
+ expect(response.role?.name).toBe(roleData.name);
68
+ expect(response.role?.displayName).toBe(roleData.displayName);
69
+ expect(response.role?.description).toBe(roleData.description);
70
+
71
+ testRoleName = response.role?.name || null;
72
+ });
73
+
74
+ it('should throw error when role name is missing', async () => {
75
+ const roleData = TestDataGenerator.generateRoleData({ name: '' });
76
+
77
+ await expect(
78
+ client.role.createRole(roleData)
79
+ ).rejects.toThrow();
80
+ });
81
+ });
82
+
83
+ describe('listRoles', () => {
84
+ it('should list all roles', async () => {
85
+ const response = await client.role.listRoles();
86
+
87
+ expect(response).toBeDefined();
88
+ expect(response.roles).toBeDefined();
89
+ expect(Array.isArray(response.roles)).toBe(true);
90
+ });
91
+ });
92
+
93
+ describe('getRole', () => {
94
+ it('should get role by name', async () => {
95
+ // Create a test role first
96
+ const roleData = TestDataGenerator.generateRoleData();
97
+ const createResponse = await client.role.createRole(roleData);
98
+ testRoleName = createResponse.role?.name || null;
99
+
100
+ const response = await client.role.getRole(testRoleName!);
101
+
102
+ expect(response).toBeDefined();
103
+ expect(response.role).toBeDefined();
104
+ expect(response.role?.name).toBe(testRoleName);
105
+ expect(response.role?.displayName).toBe(roleData.displayName);
106
+ expect(response.role?.description).toBe(roleData.description);
107
+ });
108
+
109
+ it('should throw error when role does not exist', async () => {
110
+ await expect(
111
+ client.role.getRole('non-existent-role')
112
+ ).rejects.toThrow();
113
+ });
114
+ });
115
+
116
+ describe('updateRole', () => {
117
+ it('should update an existing role', async () => {
118
+ // Create a test role first
119
+ const roleData = TestDataGenerator.generateRoleData();
120
+ const createResponse = await client.role.createRole(roleData);
121
+ testRoleName = createResponse.role?.name || null;
122
+
123
+ const updateData = TestDataGenerator.generateRoleUpdateData();
124
+ const response = await client.role.updateRole(testRoleName!, updateData);
125
+
126
+ expect(response).toBeDefined();
127
+ expect(response.role).toBeDefined();
128
+ expect(response.role?.name).toBe(testRoleName);
129
+ expect(response.role?.displayName).toBe(updateData.displayName);
130
+ expect(response.role?.description).toBe(updateData.description);
131
+ });
132
+
133
+ it('should throw error when updating non-existent role', async () => {
134
+ const updateData = TestDataGenerator.generateRoleUpdateData();
135
+
136
+ await expect(
137
+ client.role.updateRole('non-existent-role', updateData)
138
+ ).rejects.toThrow();
139
+ });
140
+ });
141
+
142
+ describe('deleteRole', () => {
143
+ it('should delete an existing role', async () => {
144
+ // Create a test role first
145
+ const roleData = TestDataGenerator.generateRoleData();
146
+ const createResponse = await client.role.createRole(roleData);
147
+ const roleName = createResponse.role?.name || null;
148
+
149
+ const response = await client.role.deleteRole(roleName!);
150
+
151
+ expect(response).toBeDefined();
152
+
153
+ // Verify role is deleted
154
+ await expect(
155
+ client.role.getRole(roleName!)
156
+ ).rejects.toThrow();
157
+ });
158
+ });
159
+
160
+ describe('getRoleUsersCount', () => {
161
+ it('should get user count for a role', async () => {
162
+ // Create a test role first
163
+ const roleData = TestDataGenerator.generateRoleData();
164
+ const createResponse = await client.role.createRole(roleData);
165
+ testRoleName = createResponse.role?.name || null;
166
+
167
+ const response = await client.role.getRoleUsersCount(testRoleName!);
168
+
169
+ expect(response).toBeDefined();
170
+ expect(Number(response.count)).toBeGreaterThanOrEqual(0);
171
+ });
172
+ });
173
+ });
174
+
175
+ describe('Organization Role API Integration Tests', () => {
176
+ describe('createOrganizationRole', () => {
177
+ it('should create a new organization role', async () => {
178
+ const roleData = TestDataGenerator.generateOrganizationRoleData();
179
+
180
+ const response = await client.role.createOrganizationRole(testOrg, roleData);
181
+
182
+ expect(response).toBeDefined();
183
+ expect(response.role).toBeDefined();
184
+ expect(response.role?.name).toBe(roleData.name);
185
+ expect(response.role?.displayName).toBe(roleData.displayName);
186
+ expect(response.role?.description).toBe(roleData.description);
187
+ expect(response.role?.isOrgRole).toBe(true);
188
+
189
+ testOrgRoleName = response.role?.name || null;
190
+ });
191
+
192
+ it('should throw error when organizationId is missing', async () => {
193
+ const roleData = TestDataGenerator.generateOrganizationRoleData();
194
+
195
+ await expect(
196
+ client.role.createOrganizationRole('', roleData)
197
+ ).rejects.toThrow();
198
+ });
199
+ });
200
+
201
+ describe('listOrganizationRoles', () => {
202
+ it('should list all organization roles', async () => {
203
+ // Create a test organization role first
204
+ const roleData = TestDataGenerator.generateOrganizationRoleData();
205
+ const createResponse = await client.role.createOrganizationRole(testOrg, roleData);
206
+ testOrgRoleName = createResponse.role?.name || null;
207
+
208
+ const response = await client.role.listOrganizationRoles(testOrg);
209
+
210
+ expect(response).toBeDefined();
211
+ expect(response.roles).toBeDefined();
212
+ expect(Array.isArray(response.roles)).toBe(true);
213
+ expect(response.roles.length).toBeGreaterThan(0);
214
+
215
+ // Verify our test role is in the list
216
+ const testRole = response.roles.find(role => role.name === testOrgRoleName);
217
+ expect(testRole).toBeDefined();
218
+ expect(testRole?.isOrgRole).toBe(true);
219
+ });
220
+ });
221
+
222
+ describe('getOrganizationRole', () => {
223
+ it('should get organization role by name', async () => {
224
+ // Create a test organization role first
225
+ const roleData = TestDataGenerator.generateOrganizationRoleData();
226
+ const createResponse = await client.role.createOrganizationRole(testOrg, roleData);
227
+ testOrgRoleName = createResponse.role?.name || null;
228
+
229
+ const response = await client.role.getOrganizationRole(testOrg, testOrgRoleName!);
230
+
231
+ expect(response).toBeDefined();
232
+ expect(response.role).toBeDefined();
233
+ expect(response.role?.name).toBe(testOrgRoleName);
234
+ expect(response.role?.displayName).toBe(roleData.displayName);
235
+ expect(response.role?.isOrgRole).toBe(true);
236
+ });
237
+ });
238
+
239
+ describe('updateOrganizationRole', () => {
240
+ it('should update an existing organization role', async () => {
241
+ // Create a test organization role first
242
+ const roleData = TestDataGenerator.generateOrganizationRoleData();
243
+ const createResponse = await client.role.createOrganizationRole(testOrg, roleData);
244
+ testOrgRoleName = createResponse.role?.name || null;
245
+
246
+ const updateData = TestDataGenerator.generateRoleUpdateData();
247
+ const response = await client.role.updateOrganizationRole(testOrg, testOrgRoleName!, updateData);
248
+
249
+ expect(response).toBeDefined();
250
+ expect(response.role).toBeDefined();
251
+ expect(response.role?.name).toBe(testOrgRoleName);
252
+ expect(response.role?.displayName).toBe(updateData.displayName);
253
+ expect(response.role?.description).toBe(updateData.description);
254
+ expect(response.role?.isOrgRole).toBe(true);
255
+ });
256
+ });
257
+
258
+ describe('deleteOrganizationRole', () => {
259
+ it('should delete an existing organization role', async () => {
260
+ // Create a test organization role first
261
+ const roleData = TestDataGenerator.generateOrganizationRoleData();
262
+ const createResponse = await client.role.createOrganizationRole(testOrg, roleData);
263
+ const roleName = createResponse.role?.name || null;
264
+
265
+ const response = await client.role.deleteOrganizationRole(testOrg, roleName!);
266
+
267
+ expect(response).toBeDefined();
268
+
269
+ // Verify role is deleted
270
+ await expect(
271
+ client.role.getOrganizationRole(testOrg, roleName!)
272
+ ).rejects.toThrow();
273
+ });
274
+ });
275
+
276
+ describe('getOrganizationRoleUsersCount', () => {
277
+ it('should get user count for an organization role', async () => {
278
+ // Create a test organization role first
279
+ const roleData = TestDataGenerator.generateOrganizationRoleData();
280
+ const createResponse = await client.role.createOrganizationRole(testOrg, roleData);
281
+ testOrgRoleName = createResponse.role?.name || null;
282
+
283
+ const response = await client.role.getOrganizationRoleUsersCount(testOrg, testOrgRoleName!);
284
+
285
+ expect(response).toBeDefined();
286
+ expect(Number(response.count)).toBeGreaterThanOrEqual(0);
287
+ });
288
+ });
289
+
290
+ describe('updateDefaultOrganizationRoles', () => {
291
+ it('should update default organization roles', async () => {
292
+ // Create a test organization role first
293
+ const roleData = TestDataGenerator.generateOrganizationRoleData();
294
+ const createResponse = await client.role.createOrganizationRole(testOrg, roleData);
295
+ testOrgRoleName = createResponse.role?.name || null;
296
+
297
+ const response = await client.role.updateDefaultOrganizationRoles(testOrg, testOrgRoleName!);
298
+
299
+ expect(response).toBeDefined();
300
+ expect(response.defaultMember).toBeDefined();
301
+ expect(response.defaultMember?.name).toBe(testOrgRoleName);
302
+ });
303
+ });
304
+
305
+ describe('deleteOrganizationRoleBase', () => {
306
+ it('should delete organization role base relationship', async () => {
307
+ // Create base org role
308
+ const baseRoleData = TestDataGenerator.generateOrganizationRoleData();
309
+ const baseResp = await client.role.createOrganizationRole(testOrg, baseRoleData);
310
+ const baseRoleName = baseResp.role?.name!;
311
+
312
+ // Create extended org role which extends base
313
+ const extendedRoleData = TestDataGenerator.generateOrganizationRoleData({ extends: baseRoleName });
314
+ const extResp = await client.role.createOrganizationRole(testOrg, extendedRoleData);
315
+ testOrgRoleName = extResp.role?.name || null;
316
+
317
+ const response = await client.role.deleteOrganizationRoleBase(testOrg, testOrgRoleName!);
318
+
319
+ expect(response).toBeDefined();
320
+ });
321
+ });
322
+ });
323
+ });
@@ -1,6 +1,8 @@
1
1
  import { CreateUserRequest, UpdateUserRequest } from '../../src/types/user';
2
2
  import { TemplateType } from '../../src/pkg/grpc/scalekit/v1/auth/passwordless_pb';
3
3
  import { DomainType } from '../../src/pkg/grpc/scalekit/v1/domains/domains_pb';
4
+ import { CreateRole, UpdateRole, CreateOrganizationRole } from '../../src/pkg/grpc/scalekit/v1/roles/roles_pb';
5
+ import { CreatePermission } from '../../src/pkg/grpc/scalekit/v1/roles/roles_pb';
4
6
 
5
7
  /**
6
8
  * Test data generation utilities to reduce redundancy across test files
@@ -11,7 +13,10 @@ export class TestDataGenerator {
11
13
  * Generate a unique timestamp-based identifier
12
14
  */
13
15
  static generateUniqueId(): string {
14
- return Date.now().toString();
16
+ // Alphanumeric only (no hyphens), to satisfy backend regex constraints
17
+ const ts = Date.now().toString(36);
18
+ const rnd = Math.random().toString(36).substr(2, 9);
19
+ return `${ts}${rnd}`;
15
20
  }
16
21
 
17
22
  /**
@@ -188,6 +193,62 @@ export class TestDataGenerator {
188
193
  const uniqueId = this.generateUniqueId();
189
194
  return `${prefix}-${uniqueId}.com`;
190
195
  }
196
+
197
+ /**
198
+ * Generate test role data
199
+ */
200
+ static generateRoleData(overrides: Partial<CreateRole> = {}): CreateRole {
201
+ const uniqueId = this.generateUniqueId();
202
+
203
+ return new CreateRole({
204
+ name: `test_role_${uniqueId}`,
205
+ displayName: `Test Role ${uniqueId}`,
206
+ description: `Test role description ${uniqueId}`,
207
+ permissions: [], // Initialize empty permissions array
208
+ ...overrides
209
+ });
210
+ }
211
+
212
+ /**
213
+ * Generate test role update data
214
+ */
215
+ static generateRoleUpdateData(overrides: Partial<UpdateRole> = {}): UpdateRole {
216
+ const uniqueId = this.generateUniqueId();
217
+
218
+ return new UpdateRole({
219
+ displayName: `Updated Role ${uniqueId}`,
220
+ description: `Updated role description ${uniqueId}`,
221
+ ...overrides
222
+ });
223
+ }
224
+
225
+ /**
226
+ * Generate test organization role data
227
+ */
228
+ static generateOrganizationRoleData(overrides: Partial<CreateOrganizationRole> = {}): CreateOrganizationRole {
229
+ const uniqueId = this.generateUniqueId();
230
+
231
+ return new CreateOrganizationRole({
232
+ name: `test_org_role_${uniqueId}`,
233
+ displayName: `Test Organization Role ${uniqueId}`,
234
+ description: `Test organization role description ${uniqueId}`,
235
+ permissions: [], // Initialize empty permissions array
236
+ ...overrides
237
+ });
238
+ }
239
+
240
+ /**
241
+ * Generate test permission data
242
+ */
243
+ static generatePermissionData(overrides: Partial<CreatePermission> = {}): CreatePermission {
244
+ const uniqueId = this.generateUniqueId();
245
+
246
+ return new CreatePermission({
247
+ name: `test_permission_${uniqueId}`,
248
+ description: `Test permission description ${uniqueId}`,
249
+ ...overrides
250
+ });
251
+ }
191
252
  }
192
253
 
193
254
  /**
@@ -311,4 +372,110 @@ export class TestDomainManager {
311
372
  }
312
373
  }
313
374
  }
375
+ }
376
+
377
+ /**
378
+ * Test role management utilities
379
+ */
380
+ export class TestRoleManager {
381
+ /**
382
+ * Create a test role and return role data
383
+ */
384
+ static async createTestRole(client: any, overrides: Partial<CreateRole> = {}) {
385
+ const roleData = TestDataGenerator.generateRoleData(overrides);
386
+ const response = await client.role.createRole(roleData);
387
+ const createdRoleName = response.role?.name;
388
+
389
+ if (!createdRoleName) {
390
+ throw new Error('Failed to create test role');
391
+ }
392
+
393
+ return {
394
+ roleName: createdRoleName,
395
+ roleData,
396
+ response
397
+ };
398
+ }
399
+
400
+ /**
401
+ * Clean up a test role
402
+ */
403
+ static async cleanupTestRole(client: any, roleName: string): Promise<void> {
404
+ if (roleName) {
405
+ try {
406
+ await client.role.deleteRole(roleName);
407
+ } catch (error) {
408
+ // Role may already be deleted
409
+ }
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Create a test organization role and return role data
415
+ */
416
+ static async createTestOrganizationRole(client: any, testOrg: string, overrides: Partial<CreateOrganizationRole> = {}) {
417
+ const roleData = TestDataGenerator.generateOrganizationRoleData(overrides);
418
+ const response = await client.role.createOrganizationRole(testOrg, roleData);
419
+ const createdRoleName = response.role?.name;
420
+
421
+ if (!createdRoleName) {
422
+ throw new Error('Failed to create test organization role');
423
+ }
424
+
425
+ return {
426
+ roleName: createdRoleName,
427
+ roleData,
428
+ response
429
+ };
430
+ }
431
+
432
+ /**
433
+ * Clean up a test organization role
434
+ */
435
+ static async cleanupTestOrganizationRole(client: any, testOrg: string, roleName: string): Promise<void> {
436
+ if (roleName) {
437
+ try {
438
+ await client.role.deleteOrganizationRole(testOrg, roleName);
439
+ } catch (error) {
440
+ // Role may already be deleted
441
+ }
442
+ }
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Test permission management utilities
448
+ */
449
+ export class TestPermissionManager {
450
+ /**
451
+ * Create a test permission and return permission data
452
+ */
453
+ static async createTestPermission(client: any, overrides: Partial<CreatePermission> = {}) {
454
+ const permissionData = TestDataGenerator.generatePermissionData(overrides);
455
+ const response = await client.permission.createPermission(permissionData);
456
+ const createdPermissionName = response.permission?.name;
457
+
458
+ if (!createdPermissionName) {
459
+ throw new Error('Failed to create test permission');
460
+ }
461
+
462
+ return {
463
+ permissionName: createdPermissionName,
464
+ permissionData,
465
+ response
466
+ };
467
+ }
468
+
469
+ /**
470
+ * Clean up a test permission
471
+ */
472
+ static async cleanupTestPermission(client: any, permissionName: string): Promise<void> {
473
+ if (permissionName) {
474
+ try {
475
+ await client.permission.deletePermission(permissionName);
476
+ } catch (error) {
477
+ // Permission may already be deleted
478
+ }
479
+ }
480
+ }
314
481
  }