@scalekit-sdk/node 2.1.0 → 2.1.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.
package/src/domain.ts CHANGED
@@ -2,7 +2,8 @@ import { PromiseClient } from '@connectrpc/connect';
2
2
  import GrpcConnect from './connect';
3
3
  import CoreClient from './core';
4
4
  import { DomainService } from './pkg/grpc/scalekit/v1/domains/domains_connect';
5
- import { CreateDomainResponse, GetDomainResponse, ListDomainResponse } from './pkg/grpc/scalekit/v1/domains/domains_pb';
5
+ import { CreateDomainResponse, GetDomainResponse, ListDomainResponse, DomainType } from './pkg/grpc/scalekit/v1/domains/domains_pb';
6
+ import { Empty } from '@bufbuild/protobuf';
6
7
 
7
8
  export default class DomainClient {
8
9
  private client: PromiseClient<typeof DomainService>;
@@ -17,9 +18,23 @@ export default class DomainClient {
17
18
  * Create a domain for an organization with the given name. Optionally, you can provide an external id.
18
19
  * @param {string} organizationId The organization id
19
20
  * @param {string} name The domain name
21
+ * @param {object} options The options to create a domain
22
+ * @param {DomainType | string} options.domainType The type of domain (ALLOWED_EMAIL_DOMAIN or ORGANIZATION_DOMAIN)
20
23
  * @returns {Promise<CreateDomainResponse>} The created domain
21
24
  */
22
- async createDomain(organizationId: string, name: string): Promise<CreateDomainResponse> {
25
+ async createDomain(organizationId: string, name: string, options?: { domainType?: DomainType | string }): Promise<CreateDomainResponse> {
26
+ let domainTypeValue: DomainType | undefined;
27
+ if (options?.domainType) {
28
+ if (typeof options.domainType === 'string') {
29
+ domainTypeValue = DomainType[options.domainType as keyof typeof DomainType];
30
+ if (domainTypeValue === undefined) {
31
+ throw new Error('Invalid domain type');
32
+ }
33
+ } else {
34
+ domainTypeValue = options.domainType;
35
+ }
36
+ }
37
+
23
38
  return this.coreClient.connectExec(
24
39
  this.client.createDomain,
25
40
  {
@@ -28,12 +43,32 @@ export default class DomainClient {
28
43
  value: organizationId
29
44
  },
30
45
  domain: {
31
- domain: name
46
+ domain: name,
47
+ ...(domainTypeValue && { domainType: domainTypeValue })
32
48
  }
33
49
  }
34
50
  )
35
51
  }
36
52
 
53
+ /**
54
+ * Get a specific domain by ID for an organization
55
+ * @param organizationId The organization id
56
+ * @param domainId The domain id
57
+ * @returns {Promise<GetDomainResponse>} The domain details
58
+ */
59
+ async getDomain(organizationId: string, domainId: string): Promise<GetDomainResponse> {
60
+ return this.coreClient.connectExec(
61
+ this.client.getDomain,
62
+ {
63
+ id: domainId,
64
+ identities: {
65
+ case: 'organizationId',
66
+ value: organizationId
67
+ }
68
+ }
69
+ );
70
+ }
71
+
37
72
  /**
38
73
  * List domains for an organization
39
74
  * @param organizationId The organization id
@@ -50,5 +85,19 @@ export default class DomainClient {
50
85
  },
51
86
  );
52
87
  }
88
+
89
+ async deleteDomain(organizationId: string, domainId: string): Promise<Empty> {
90
+ return this.coreClient.connectExec(
91
+ this.client.deleteDomain,
92
+ {
93
+ id: domainId,
94
+ identities: {
95
+ case: 'organizationId',
96
+ value: organizationId
97
+ }
98
+ }
99
+ );
100
+ }
101
+
53
102
  }
54
103
 
@@ -3314,6 +3314,11 @@ export class ListAppConnectionsRequest extends Message<ListAppConnectionsRequest
3314
3314
  */
3315
3315
  pageToken = "";
3316
3316
 
3317
+ /**
3318
+ * @generated from field: optional string provider = 3;
3319
+ */
3320
+ provider?: string;
3321
+
3317
3322
  constructor(data?: PartialMessage<ListAppConnectionsRequest>) {
3318
3323
  super();
3319
3324
  proto3.util.initPartial(data, this);
@@ -3324,6 +3329,7 @@ export class ListAppConnectionsRequest extends Message<ListAppConnectionsRequest
3324
3329
  static readonly fields: FieldList = proto3.util.newFieldList(() => [
3325
3330
  { no: 1, name: "page_size", kind: "scalar", T: 13 /* ScalarType.UINT32 */ },
3326
3331
  { no: 2, name: "page_token", kind: "scalar", T: 9 /* ScalarType.STRING */ },
3332
+ { no: 3, name: "provider", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
3327
3333
  ]);
3328
3334
 
3329
3335
  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ListAppConnectionsRequest {
@@ -29,6 +29,11 @@ export enum VerificationStatus {
29
29
  * @generated from enum value: FAILED = 3;
30
30
  */
31
31
  FAILED = 3,
32
+
33
+ /**
34
+ * @generated from enum value: AUTO_VERIFIED = 4;
35
+ */
36
+ AUTO_VERIFIED = 4,
32
37
  }
33
38
  // Retrieve enum metadata with: proto3.getEnumType(VerificationStatus)
34
39
  proto3.util.setEnumType(VerificationStatus, "scalekit.v1.domains.VerificationStatus", [
@@ -36,6 +41,7 @@ proto3.util.setEnumType(VerificationStatus, "scalekit.v1.domains.VerificationSta
36
41
  { no: 1, name: "PENDING" },
37
42
  { no: 2, name: "VERIFIED" },
38
43
  { no: 3, name: "FAILED" },
44
+ { no: 4, name: "AUTO_VERIFIED" },
39
45
  ]);
40
46
 
41
47
  /**
@@ -48,20 +54,20 @@ export enum DomainType {
48
54
  DOMAIN_TYPE_UNSPECIFIED = 0,
49
55
 
50
56
  /**
51
- * @generated from enum value: HOME_REALM_DISCOVERY = 1;
57
+ * @generated from enum value: ALLOWED_EMAIL_DOMAIN = 1;
52
58
  */
53
- HOME_REALM_DISCOVERY = 1,
59
+ ALLOWED_EMAIL_DOMAIN = 1,
54
60
 
55
61
  /**
56
- * @generated from enum value: JIT_PROVISIONING_DOMAIN = 2;
62
+ * @generated from enum value: ORGANIZATION_DOMAIN = 2;
57
63
  */
58
- JIT_PROVISIONING_DOMAIN = 2,
64
+ ORGANIZATION_DOMAIN = 2,
59
65
  }
60
66
  // Retrieve enum metadata with: proto3.getEnumType(DomainType)
61
67
  proto3.util.setEnumType(DomainType, "scalekit.v1.domains.DomainType", [
62
68
  { no: 0, name: "DOMAIN_TYPE_UNSPECIFIED" },
63
- { no: 1, name: "HOME_REALM_DISCOVERY" },
64
- { no: 2, name: "JIT_PROVISIONING_DOMAIN" },
69
+ { no: 1, name: "ALLOWED_EMAIL_DOMAIN" },
70
+ { no: 2, name: "ORGANIZATION_DOMAIN" },
65
71
  ]);
66
72
 
67
73
  /**
@@ -475,9 +475,14 @@ export class ToolErrorInfo extends Message<ToolErrorInfo> {
475
475
  executionId = "";
476
476
 
477
477
  /**
478
- * @generated from field: string tool_message = 2;
478
+ * @generated from field: string tool_error_message = 2;
479
479
  */
480
- toolMessage = "";
480
+ toolErrorMessage = "";
481
+
482
+ /**
483
+ * @generated from field: string tool_error_code = 3;
484
+ */
485
+ toolErrorCode = "";
481
486
 
482
487
  constructor(data?: PartialMessage<ToolErrorInfo>) {
483
488
  super();
@@ -488,7 +493,8 @@ export class ToolErrorInfo extends Message<ToolErrorInfo> {
488
493
  static readonly typeName = "scalekit.v1.errdetails.ToolErrorInfo";
489
494
  static readonly fields: FieldList = proto3.util.newFieldList(() => [
490
495
  { no: 1, name: "execution_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
491
- { no: 2, name: "tool_message", kind: "scalar", T: 9 /* ScalarType.STRING */ },
496
+ { no: 2, name: "tool_error_message", kind: "scalar", T: 9 /* ScalarType.STRING */ },
497
+ { no: 3, name: "tool_error_code", kind: "scalar", T: 9 /* ScalarType.STRING */ },
492
498
  ]);
493
499
 
494
500
  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ToolErrorInfo {
@@ -1055,6 +1055,11 @@ export class CreateMembership extends Message<CreateMembership> {
1055
1055
  */
1056
1056
  metadata: { [key: string]: string } = {};
1057
1057
 
1058
+ /**
1059
+ * @generated from field: optional string inviter_email = 8;
1060
+ */
1061
+ inviterEmail?: string;
1062
+
1058
1063
  constructor(data?: PartialMessage<CreateMembership>) {
1059
1064
  super();
1060
1065
  proto3.util.initPartial(data, this);
@@ -1065,6 +1070,7 @@ export class CreateMembership extends Message<CreateMembership> {
1065
1070
  static readonly fields: FieldList = proto3.util.newFieldList(() => [
1066
1071
  { no: 4, name: "roles", kind: "message", T: Role, repeated: true },
1067
1072
  { no: 7, name: "metadata", kind: "map", K: 9 /* ScalarType.STRING */, V: {kind: "scalar", T: 9 /* ScalarType.STRING */} },
1073
+ { no: 8, name: "inviter_email", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
1068
1074
  ]);
1069
1075
 
1070
1076
  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreateMembership {
@@ -1453,9 +1459,9 @@ export class Invite extends Message<Invite> {
1453
1459
  userId = "";
1454
1460
 
1455
1461
  /**
1456
- * @generated from field: string invited_by = 3;
1462
+ * @generated from field: optional string invited_by = 3;
1457
1463
  */
1458
- invitedBy = "";
1464
+ invitedBy?: string;
1459
1465
 
1460
1466
  /**
1461
1467
  * @generated from field: string status = 4;
@@ -1492,7 +1498,7 @@ export class Invite extends Message<Invite> {
1492
1498
  static readonly fields: FieldList = proto3.util.newFieldList(() => [
1493
1499
  { no: 1, name: "organization_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1494
1500
  { no: 2, name: "user_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1495
- { no: 3, name: "invited_by", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1501
+ { no: 3, name: "invited_by", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
1496
1502
  { no: 4, name: "status", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1497
1503
  { no: 5, name: "created_at", kind: "message", T: Timestamp },
1498
1504
  { no: 6, name: "expires_at", kind: "message", T: Timestamp },
@@ -1731,10 +1737,16 @@ export class AssignUserRolesRequest extends Message<AssignUserRolesRequest> {
1731
1737
  */
1732
1738
  export class AssignRoleRequest extends Message<AssignRoleRequest> {
1733
1739
  /**
1734
- * @generated from field: string id = 1;
1740
+ * @generated from field: string id = 1 [deprecated = true];
1741
+ * @deprecated
1735
1742
  */
1736
1743
  id = "";
1737
1744
 
1745
+ /**
1746
+ * @generated from field: string role_name = 2;
1747
+ */
1748
+ roleName = "";
1749
+
1738
1750
  constructor(data?: PartialMessage<AssignRoleRequest>) {
1739
1751
  super();
1740
1752
  proto3.util.initPartial(data, this);
@@ -1744,6 +1756,7 @@ export class AssignRoleRequest extends Message<AssignRoleRequest> {
1744
1756
  static readonly typeName = "scalekit.v1.users.AssignRoleRequest";
1745
1757
  static readonly fields: FieldList = proto3.util.newFieldList(() => [
1746
1758
  { no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1759
+ { no: 2, name: "role_name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1747
1760
  ]);
1748
1761
 
1749
1762
  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): AssignRoleRequest {
@@ -1815,9 +1828,9 @@ export class RemoveUserRoleRequest extends Message<RemoveUserRoleRequest> {
1815
1828
  userId = "";
1816
1829
 
1817
1830
  /**
1818
- * @generated from field: string role_id = 3;
1831
+ * @generated from field: string role_name = 3;
1819
1832
  */
1820
- roleId = "";
1833
+ roleName = "";
1821
1834
 
1822
1835
  constructor(data?: PartialMessage<RemoveUserRoleRequest>) {
1823
1836
  super();
@@ -1829,7 +1842,7 @@ export class RemoveUserRoleRequest extends Message<RemoveUserRoleRequest> {
1829
1842
  static readonly fields: FieldList = proto3.util.newFieldList(() => [
1830
1843
  { no: 1, name: "organization_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1831
1844
  { no: 2, name: "user_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1832
- { no: 3, name: "role_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1845
+ { no: 3, name: "role_name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
1833
1846
  ]);
1834
1847
 
1835
1848
  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): RemoveUserRoleRequest {
@@ -0,0 +1,239 @@
1
+ import ScalekitClient from '../src/scalekit';
2
+ import { DomainType } from '../src/pkg/grpc/scalekit/v1/domains/domains_pb';
3
+ import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
4
+ import { TestDataGenerator, TestOrganizationManager, TestDomainManager } from './utils/test-data';
5
+
6
+ describe('Domains', () => {
7
+ let client: ScalekitClient;
8
+ let testOrg: string;
9
+
10
+ beforeEach(async () => {
11
+ // Use global client
12
+ client = global.client;
13
+
14
+ // Create test organization for each test
15
+ testOrg = await TestOrganizationManager.createTestOrganization(client);
16
+ });
17
+
18
+ afterEach(async () => {
19
+ // Clean up test organization
20
+ await TestOrganizationManager.cleanupTestOrganization(client, testOrg);
21
+ });
22
+
23
+ describe('createDomain', () => {
24
+ it('should create domain without domainType (backward compatibility)', async () => {
25
+ const domainName = TestDataGenerator.generateUniqueDomainName('backward-compat');
26
+
27
+ const response = await client.domain.createDomain(testOrg, domainName);
28
+
29
+ expect(response).toBeDefined();
30
+ expect(response.domain).toBeDefined();
31
+ expect(response.domain?.domain).toBe(domainName);
32
+ expect(response.domain?.id).toBeDefined();
33
+ expect(response.domain?.organizationId).toBe(testOrg);
34
+ });
35
+
36
+ it('should create domain with ALLOWED_EMAIL_DOMAIN type', async () => {
37
+ const domainName = TestDataGenerator.generateUniqueDomainName('allowed-email');
38
+
39
+ const response = await client.domain.createDomain(testOrg, domainName, {
40
+ domainType: DomainType.ALLOWED_EMAIL_DOMAIN
41
+ });
42
+
43
+ expect(response).toBeDefined();
44
+ expect(response.domain).toBeDefined();
45
+ expect(response.domain?.domain).toBe(domainName);
46
+ expect(response.domain?.domainType).toBe(DomainType.ALLOWED_EMAIL_DOMAIN);
47
+ expect(response.domain?.id).toBeDefined();
48
+ expect(response.domain?.organizationId).toBe(testOrg);
49
+ });
50
+
51
+ it('should create domain with ORGANIZATION_DOMAIN type', async () => {
52
+ const domainName = TestDataGenerator.generateUniqueDomainName('org-domain');
53
+
54
+ const response = await client.domain.createDomain(testOrg, domainName, {
55
+ domainType: DomainType.ORGANIZATION_DOMAIN
56
+ });
57
+
58
+ expect(response).toBeDefined();
59
+ expect(response.domain).toBeDefined();
60
+ expect(response.domain?.domain).toBe(domainName);
61
+ expect(response.domain?.domainType).toBe(DomainType.ORGANIZATION_DOMAIN);
62
+ expect(response.domain?.id).toBeDefined();
63
+ expect(response.domain?.organizationId).toBe(testOrg);
64
+ });
65
+
66
+ it('should create multiple domains of different types', async () => {
67
+ const allowedDomainName = TestDataGenerator.generateUniqueDomainName('allowed');
68
+ const orgDomainName = TestDataGenerator.generateUniqueDomainName('org');
69
+
70
+ // Create allowed email domain
71
+ const allowedResponse = await client.domain.createDomain(testOrg, allowedDomainName, {
72
+ domainType: DomainType.ALLOWED_EMAIL_DOMAIN
73
+ });
74
+
75
+ // Create organization domain
76
+ const orgResponse = await client.domain.createDomain(testOrg, orgDomainName, {
77
+ domainType: DomainType.ORGANIZATION_DOMAIN
78
+ });
79
+
80
+ expect(allowedResponse.domain?.domainType).toBe(DomainType.ALLOWED_EMAIL_DOMAIN);
81
+ expect(orgResponse.domain?.domainType).toBe(DomainType.ORGANIZATION_DOMAIN);
82
+ expect(allowedResponse.domain?.domain).toBe(allowedDomainName);
83
+ expect(orgResponse.domain?.domain).toBe(orgDomainName);
84
+ });
85
+
86
+ it('should create domain using TestDomainManager utility', async () => {
87
+ const { domainId, domainName, domainType, response } = await TestDomainManager.createTestDomain(
88
+ client,
89
+ testOrg,
90
+ 'allowed'
91
+ );
92
+
93
+ expect(domainId).toBeDefined();
94
+ expect(domainName).toBeDefined();
95
+ expect(domainType).toBe(DomainType.ALLOWED_EMAIL_DOMAIN);
96
+ expect(response.domain?.domain).toBe(domainName);
97
+ });
98
+ });
99
+
100
+ describe('listDomains', () => {
101
+ it('should list domains for organization', async () => {
102
+ // Create a test domain first
103
+ const { domainName } = await TestDomainManager.createTestDomain(client, testOrg, 'allowed');
104
+
105
+ const response = await client.domain.listDomains(testOrg);
106
+
107
+ expect(response).toBeDefined();
108
+ expect(response.domains).toBeDefined();
109
+ expect(Array.isArray(response.domains)).toBe(true);
110
+ expect(response.domains.length).toBeGreaterThan(0);
111
+
112
+ // Verify basic domain attributes
113
+ const firstDomain = response.domains[0];
114
+ expect(firstDomain.id).toBeDefined();
115
+ expect(firstDomain.domain).toBeDefined();
116
+ expect(firstDomain.organizationId).toBe(testOrg);
117
+ });
118
+
119
+ it('should return empty list when no domains exist', async () => {
120
+ // Use a fresh organization without any domains
121
+ const freshOrg = await TestOrganizationManager.createTestOrganization(client);
122
+
123
+ try {
124
+ const response = await client.domain.listDomains(freshOrg);
125
+
126
+ expect(response).toBeDefined();
127
+ expect(response.domains).toBeDefined();
128
+ expect(Array.isArray(response.domains)).toBe(true);
129
+ expect(response.domains.length).toBe(0);
130
+ } finally {
131
+ await TestOrganizationManager.cleanupTestOrganization(client, freshOrg);
132
+ }
133
+ });
134
+
135
+ it('should list domains with different types', async () => {
136
+ // Create domains of different types
137
+ const { domainName: allowedDomainName } = await TestDomainManager.createTestDomain(client, testOrg, 'allowed');
138
+ const { domainName: orgDomainName } = await TestDomainManager.createTestDomain(client, testOrg, 'organization');
139
+
140
+ const response = await client.domain.listDomains(testOrg);
141
+
142
+ expect(response.domains.length).toBeGreaterThanOrEqual(2);
143
+
144
+ const domainNames = response.domains.map(d => d.domain);
145
+ const domainTypes = response.domains.map(d => d.domainType);
146
+
147
+ expect(domainNames).toContain(allowedDomainName);
148
+ expect(domainNames).toContain(orgDomainName);
149
+ expect(domainTypes).toContain(DomainType.ALLOWED_EMAIL_DOMAIN);
150
+ expect(domainTypes).toContain(DomainType.ORGANIZATION_DOMAIN);
151
+ });
152
+ });
153
+
154
+ describe('getDomain', () => {
155
+ it('should get domain by ID successfully', async () => {
156
+ // Create a test domain first
157
+ const { domainId, domainName } = await TestDomainManager.createTestDomain(client, testOrg, 'allowed');
158
+
159
+ const response = await client.domain.getDomain(testOrg, domainId);
160
+
161
+ expect(response).toBeDefined();
162
+ expect(response.domain).toBeDefined();
163
+ expect(response.domain?.id).toBe(domainId);
164
+ expect(response.domain?.domain).toBe(domainName);
165
+ expect(response.domain?.organizationId).toBe(testOrg);
166
+ });
167
+
168
+ it('should throw error for non-existent domain', async () => {
169
+ const nonExistentDomainId = 'non-existent-domain-id';
170
+
171
+ await expect(
172
+ client.domain.getDomain(testOrg, nonExistentDomainId)
173
+ ).rejects.toThrow();
174
+ });
175
+
176
+ it('should throw error for invalid organization ID', async () => {
177
+ // Create a test domain first
178
+ const { domainId } = await TestDomainManager.createTestDomain(client, testOrg, 'allowed');
179
+ const invalidOrgId = 'invalid-org-id';
180
+
181
+ await expect(
182
+ client.domain.getDomain(invalidOrgId, domainId)
183
+ ).rejects.toThrow();
184
+ });
185
+ });
186
+
187
+ describe('deleteDomain', () => {
188
+ it('should delete domain successfully', async () => {
189
+ // Create a test domain for deletion
190
+ const { domainId, domainName } = await TestDomainManager.createTestDomain(client, testOrg, 'allowed');
191
+
192
+ // Verify domain exists before deletion
193
+ const getResponse = await client.domain.getDomain(testOrg, domainId);
194
+ expect(getResponse.domain?.id).toBe(domainId);
195
+
196
+ // Delete the domain
197
+ const deleteResponse = await client.domain.deleteDomain(testOrg, domainId);
198
+ expect(deleteResponse).toBeDefined();
199
+
200
+ // Verify domain is deleted by trying to get it
201
+ await expect(
202
+ client.domain.getDomain(testOrg, domainId)
203
+ ).rejects.toThrow();
204
+ });
205
+
206
+ it('should throw error when deleting non-existent domain', async () => {
207
+ const nonExistentDomainId = 'non-existent-domain-id';
208
+
209
+ await expect(
210
+ client.domain.deleteDomain(testOrg, nonExistentDomainId)
211
+ ).rejects.toThrow();
212
+ });
213
+
214
+
215
+ });
216
+
217
+ describe('error handling', () => {
218
+ it('should handle invalid organization ID', async () => {
219
+ const invalidOrgId = 'invalid-org-id';
220
+ const domainName = TestDataGenerator.generateUniqueDomainName('error-test');
221
+
222
+ await expect(
223
+ client.domain.createDomain(invalidOrgId, domainName)
224
+ ).rejects.toThrow();
225
+
226
+ await expect(
227
+ client.domain.listDomains(invalidOrgId)
228
+ ).rejects.toThrow();
229
+ });
230
+
231
+ it('should handle invalid domain name format', async () => {
232
+ const invalidDomainName = 'invalid-domain-name';
233
+
234
+ await expect(
235
+ client.domain.createDomain(testOrg, invalidDomainName)
236
+ ).rejects.toThrow();
237
+ });
238
+ });
239
+ });
@@ -1,5 +1,6 @@
1
1
  import { CreateUserRequest, UpdateUserRequest } from '../../src/types/user';
2
2
  import { TemplateType } from '../../src/pkg/grpc/scalekit/v1/auth/passwordless_pb';
3
+ import { DomainType } from '../../src/pkg/grpc/scalekit/v1/domains/domains_pb';
3
4
 
4
5
  /**
5
6
  * Test data generation utilities to reduce redundancy across test files
@@ -165,6 +166,28 @@ export class TestDataGenerator {
165
166
  return { linkToken: 'mock-link-token' };
166
167
  }
167
168
  }
169
+
170
+ /**
171
+ * Generate test domain data
172
+ */
173
+ static generateDomainData(domainType?: 'allowed' | 'organization') {
174
+ const uniqueId = this.generateUniqueId();
175
+ const baseDomain = `test-domain-${uniqueId}.com`;
176
+
177
+ return {
178
+ domain: baseDomain,
179
+ domainType: domainType === 'allowed' ? 'ALLOWED_EMAIL_DOMAIN' :
180
+ domainType === 'organization' ? 'ORGANIZATION_DOMAIN' : undefined
181
+ };
182
+ }
183
+
184
+ /**
185
+ * Generate unique domain name for testing
186
+ */
187
+ static generateUniqueDomainName(prefix: string = 'test'): string {
188
+ const uniqueId = this.generateUniqueId();
189
+ return `${prefix}-${uniqueId}.com`;
190
+ }
168
191
  }
169
192
 
170
193
  /**
@@ -245,4 +268,47 @@ export class TestUserManager {
245
268
  }
246
269
  }
247
270
  }
271
+ }
272
+
273
+ /**
274
+ * Test domain management utilities
275
+ */
276
+ export class TestDomainManager {
277
+ /**
278
+ * Create a test domain and return domain data
279
+ */
280
+ static async createTestDomain(client: any, testOrg: string, domainType?: 'allowed' | 'organization') {
281
+ const domainName = TestDataGenerator.generateUniqueDomainName();
282
+ const options = domainType ? {
283
+ domainType: domainType === 'allowed' ? DomainType.ALLOWED_EMAIL_DOMAIN : DomainType.ORGANIZATION_DOMAIN
284
+ } : undefined;
285
+
286
+ const response = await client.domain.createDomain(testOrg, domainName, options);
287
+ const createdDomainId = response.domain?.id;
288
+
289
+ if (!createdDomainId) {
290
+ throw new Error('Failed to create test domain');
291
+ }
292
+
293
+ return {
294
+ domainId: createdDomainId,
295
+ domainName,
296
+ domainType: response.domain?.domainType,
297
+ response
298
+ };
299
+ }
300
+
301
+ /**
302
+ * Clean up a test domain (if domain deletion is supported)
303
+ */
304
+ static async cleanupTestDomain(client: any, testOrg: string, domainId: string): Promise<void> {
305
+ if (domainId) {
306
+ try {
307
+ // Note: Domain deletion may not be implemented yet
308
+ // await client.domain.deleteDomain(testOrg, domainId);
309
+ } catch (error) {
310
+ // Domain may already be deleted or deletion not supported
311
+ }
312
+ }
313
+ }
248
314
  }