@hyperdrive.bot/cli 1.0.6 → 1.0.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 (97) hide show
  1. package/README.md +415 -67
  2. package/dist/commands/account/add.d.ts +6 -6
  3. package/dist/commands/account/list.d.ts +3 -0
  4. package/dist/commands/account/list.js +9 -2
  5. package/dist/commands/account/remove.d.ts +3 -3
  6. package/dist/commands/auth/login.d.ts +4 -4
  7. package/dist/commands/auth/login.js +1 -0
  8. package/dist/commands/ci/account/create.d.ts +7 -6
  9. package/dist/commands/ci/account/create.js +49 -3
  10. package/dist/commands/ci/account/delete.d.ts +3 -3
  11. package/dist/commands/ci/account/list.d.ts +2 -2
  12. package/dist/commands/config/get.d.ts +1 -1
  13. package/dist/commands/config/set.d.ts +2 -2
  14. package/dist/commands/deployment/create.d.ts +10 -10
  15. package/dist/commands/deployment/get.d.ts +4 -4
  16. package/dist/commands/deployment/launch.d.ts +6 -6
  17. package/dist/commands/deployment/list.d.ts +3 -3
  18. package/dist/commands/deployment/list.js +17 -17
  19. package/dist/commands/domain/switch.d.ts +1 -1
  20. package/dist/commands/example.d.ts +3 -3
  21. package/dist/commands/git/connect.d.ts +2 -2
  22. package/dist/commands/git/connect.js +1 -0
  23. package/dist/commands/git/disconnect.d.ts +3 -3
  24. package/dist/commands/git/list.d.ts +2 -2
  25. package/dist/commands/git/sync.d.ts +7 -7
  26. package/dist/commands/git/sync.js +24 -23
  27. package/dist/commands/init.d.ts +1 -0
  28. package/dist/commands/init.js +20 -19
  29. package/dist/commands/jira/connect.d.ts +2 -1
  30. package/dist/commands/jira/connect.js +17 -6
  31. package/dist/commands/jira/hook/add.d.ts +17 -0
  32. package/dist/commands/jira/hook/add.js +147 -0
  33. package/dist/commands/jira/hook/list.d.ts +14 -0
  34. package/dist/commands/jira/hook/list.js +105 -0
  35. package/dist/commands/jira/hook/remove.d.ts +15 -0
  36. package/dist/commands/jira/hook/remove.js +119 -0
  37. package/dist/commands/jira/hook/toggle.d.ts +15 -0
  38. package/dist/commands/jira/hook/toggle.js +136 -0
  39. package/dist/commands/jira/status.d.ts +1 -1
  40. package/dist/commands/module/analyze.d.ts +5 -5
  41. package/dist/commands/module/create.d.ts +17 -17
  42. package/dist/commands/module/create.js +9 -1
  43. package/dist/commands/module/destroy.d.ts +3 -3
  44. package/dist/commands/module/get.d.ts +2 -2
  45. package/dist/commands/module/link.d.ts +4 -4
  46. package/dist/commands/module/list.d.ts +1 -1
  47. package/dist/commands/module/list.js +12 -11
  48. package/dist/commands/module/reanalyze.d.ts +6 -6
  49. package/dist/commands/module/update.d.ts +19 -19
  50. package/dist/commands/parameter/add.d.ts +7 -7
  51. package/dist/commands/parameter/backfill.d.ts +4 -4
  52. package/dist/commands/parameter/backfill.js +4 -3
  53. package/dist/commands/parameter/clear.d.ts +6 -6
  54. package/dist/commands/parameter/list.d.ts +6 -6
  55. package/dist/commands/parameter/list.js +4 -3
  56. package/dist/commands/parameter/pull.d.ts +6 -6
  57. package/dist/commands/parameter/remove.d.ts +7 -7
  58. package/dist/commands/parameter/sync.d.ts +6 -6
  59. package/dist/commands/parameter/update.d.ts +7 -7
  60. package/dist/commands/project/init.d.ts +21 -0
  61. package/dist/commands/project/init.js +576 -0
  62. package/dist/commands/project/list.d.ts +10 -0
  63. package/dist/commands/project/list.js +119 -0
  64. package/dist/commands/project/status.d.ts +13 -0
  65. package/dist/commands/project/status.js +163 -0
  66. package/dist/commands/project/sync.d.ts +26 -0
  67. package/dist/commands/project/sync.js +388 -0
  68. package/dist/commands/stage/access.d.ts +15 -0
  69. package/dist/commands/stage/access.js +130 -0
  70. package/dist/commands/stage/create.d.ts +11 -11
  71. package/dist/commands/stage/list.d.ts +1 -1
  72. package/dist/commands/stage/list.js +21 -20
  73. package/dist/commands/stage/revoke.d.ts +18 -0
  74. package/dist/commands/stage/revoke.js +171 -0
  75. package/dist/commands/stage/share.d.ts +23 -0
  76. package/dist/commands/stage/share.js +292 -0
  77. package/dist/commands/test-api.d.ts +1 -1
  78. package/dist/services/auth-service.d.ts +15 -82
  79. package/dist/services/auth-service.js +24 -237
  80. package/dist/services/hyperdrive-sigv4.d.ts +162 -24
  81. package/dist/services/hyperdrive-sigv4.js +107 -193
  82. package/dist/services/tenant-service.d.ts +6 -0
  83. package/dist/services/tenant-service.js +13 -0
  84. package/dist/utils/account-flow.d.ts +2 -2
  85. package/dist/utils/account-flow.js +4 -4
  86. package/dist/utils/auth-flow.d.ts +1 -0
  87. package/dist/utils/auth-flow.js +2 -0
  88. package/dist/utils/git-flow.d.ts +1 -0
  89. package/dist/utils/git-flow.js +2 -2
  90. package/dist/utils/hook-flow.d.ts +21 -0
  91. package/dist/utils/hook-flow.js +154 -0
  92. package/dist/utils/jira-flow.d.ts +2 -2
  93. package/dist/utils/jira-flow.js +4 -4
  94. package/dist/utils/table.d.ts +17 -0
  95. package/dist/utils/table.js +41 -0
  96. package/oclif.manifest.json +844 -154
  97. package/package.json +59 -15
@@ -1,72 +1,45 @@
1
- import { Sha256 } from '@aws-crypto/sha256-js';
2
- import { HttpRequest } from '@smithy/protocol-http';
3
- import { SignatureV4 } from '@smithy/signature-v4';
4
- import axios from 'axios';
1
+ /**
2
+ * Hyperdrive API Service with AWS SigV4 authentication
3
+ *
4
+ * This service extends @devsquad/cli-auth SigV4ApiClient to provide
5
+ * hyperdrive-specific API methods with AWS Signature V4 signing.
6
+ */
7
+ import { SigV4ApiClient, } from '@hyperdrive.bot/cli-auth';
5
8
  import { readFileSync } from 'fs';
6
9
  import { dirname, join } from 'path';
7
10
  import { fileURLToPath } from 'url';
8
- import { AuthService } from './auth-service.js';
11
+ import { HYPERDRIVE_AUTH_CONFIG } from './auth-service.js';
9
12
  // Get CLI version from package.json
10
13
  const __filename = fileURLToPath(import.meta.url);
11
14
  const __dirname = dirname(__filename);
12
15
  const packageJson = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
13
16
  const CLI_VERSION = packageJson.version;
14
- // Type guards
15
- function isOutdatedCLIError(data) {
16
- return (data &&
17
- data.code === 'OUTDATED_CLI_VERSION' &&
18
- data.data &&
19
- typeof data.data.currentVersion === 'string' &&
20
- typeof data.data.requiredVersion === 'string' &&
21
- typeof data.data.updateCommand === 'string');
22
- }
23
- function isOutdatedRoleError(data) {
24
- return (data &&
25
- data.code === 'OUTDATED_ROLE_VERSION' &&
26
- data.data &&
27
- typeof data.data.accountId === 'string' &&
28
- typeof data.data.currentVersion === 'string' &&
29
- typeof data.data.requiredVersion === 'string' &&
30
- typeof data.data.quickCreateUrl === 'string');
31
- }
32
17
  /**
33
18
  * Hyperdrive API Service with AWS SigV4 authentication
34
- *
35
- * This service signs all API requests using AWS Signature Version 4,
36
- * which allows both CLI and web frontend to use the same endpoints
37
- * with unified AWS IAM authentication via Cognito.
38
19
  */
39
- export class HyperdriveSigV4Service {
40
- apiUrl;
41
- authService;
42
- region;
43
- tenantDomain;
20
+ export class HyperdriveSigV4Service extends SigV4ApiClient {
21
+ userGroupsApiUrl;
44
22
  constructor(domain) {
45
- this.authService = new AuthService(domain);
46
- // Load credentials to get API URL and region
47
- const credentials = this.authService.loadCredentials();
48
- if (!credentials) {
49
- const domainMsg = domain ? ` for domain "${domain}"` : '';
50
- throw new Error(`Not authenticated${domainMsg}. Please run "hd auth login${domain ? ' --domain ' + domain : ''}" first.`);
51
- }
52
- // Use environment variable override if set, otherwise use from credentials
53
- this.apiUrl = process.env.HYPERDRIVE_API_URL || credentials.apiUrl;
54
- this.region = process.env.HYPERDRIVE_AWS_REGION || credentials.region;
55
- this.tenantDomain = credentials.tenantDomain;
56
- if (!this.apiUrl) {
57
- throw new Error('Hyperdrive API URL not configured.\n' +
58
- 'Please re-authenticate with "hd auth login".');
59
- }
23
+ super({
24
+ authConfig: HYPERDRIVE_AUTH_CONFIG,
25
+ domain,
26
+ cliName: 'hyperdrive-cli',
27
+ cliVersion: CLI_VERSION,
28
+ apiUrlOverride: process.env.HYPERDRIVE_API_URL,
29
+ regionOverride: process.env.HYPERDRIVE_AWS_REGION,
30
+ });
31
+ // Get user groups API URL from credentials
32
+ this.userGroupsApiUrl = this.getAdditionalApiUrl('userGroupsApiUrl');
60
33
  }
34
+ // ============================================================================
35
+ // AWS Account Methods
36
+ // ============================================================================
61
37
  async accountAdd(params) {
62
38
  return this.makeSignedRequest('POST', '/cloud-account/aws/account', params);
63
39
  }
64
40
  async accountGet(params) {
65
41
  return this.makeSignedRequest('GET', `/cloud-account/aws/account/${params.accountId}`);
66
42
  }
67
- // ============================================================================
68
- // Public API Methods
69
- // ============================================================================
70
43
  async accountList() {
71
44
  return this.makeSignedRequest('GET', '/cloud-account/aws/accounts');
72
45
  }
@@ -76,6 +49,9 @@ export class HyperdriveSigV4Service {
76
49
  async accountVerify(params) {
77
50
  return this.makeSignedRequest('POST', `/cloud-account/aws/account/${params.accountId}/verify`);
78
51
  }
52
+ // ============================================================================
53
+ // CI Account Methods
54
+ // ============================================================================
79
55
  async ciAccountCreate(params) {
80
56
  return this.makeSignedRequest('POST', '/ci/accounts', params);
81
57
  }
@@ -85,6 +61,9 @@ export class HyperdriveSigV4Service {
85
61
  async ciAccountList() {
86
62
  return this.makeSignedRequest('GET', '/ci/accounts');
87
63
  }
64
+ // ============================================================================
65
+ // Deployment Methods
66
+ // ============================================================================
88
67
  async deploymentCheck(params) {
89
68
  return this.makeSignedRequest('POST', '/deployments/check', params);
90
69
  }
@@ -97,6 +76,9 @@ export class HyperdriveSigV4Service {
97
76
  async deploymentList(params) {
98
77
  return this.makeSignedRequest('GET', `/deployments?projectSlug=${params.projectSlug}&stage=${params.stage}`);
99
78
  }
79
+ // ============================================================================
80
+ // Git Integration Methods
81
+ // ============================================================================
100
82
  async gitAuthInitiate(provider) {
101
83
  return this.makeSignedRequest('POST', `/git/${provider}/auth/initiate`);
102
84
  }
@@ -119,12 +101,60 @@ export class HyperdriveSigV4Service {
119
101
  });
120
102
  return this.makeSignedRequest('GET', `/git/repos?${queryParams}`);
121
103
  }
104
+ // ============================================================================
105
+ // Hook Methods
106
+ // ============================================================================
107
+ async hookCreate(projectId, body) {
108
+ return this.makeSignedRequest('POST', `/hyperdrive/projects/${encodeURIComponent(projectId)}/hooks`, body);
109
+ }
110
+ async hookDelete(projectId, hookId) {
111
+ return this.makeSignedRequest('DELETE', `/hyperdrive/projects/${encodeURIComponent(projectId)}/hooks/${encodeURIComponent(hookId)}`);
112
+ }
113
+ async hookList(projectId) {
114
+ return this.makeSignedRequest('GET', `/hyperdrive/projects/${encodeURIComponent(projectId)}/hooks`);
115
+ }
116
+ async hookUpdate(projectId, hookId, body) {
117
+ return this.makeSignedRequest('PATCH', `/hyperdrive/projects/${encodeURIComponent(projectId)}/hooks/${encodeURIComponent(hookId)}`, body);
118
+ }
119
+ async projectGetJiraStatuses(projectId) {
120
+ return this.makeSignedRequest('GET', `/hyperdrive/projects/${encodeURIComponent(projectId)}/jira/statuses`);
121
+ }
122
+ // ============================================================================
123
+ // Jira Integration Methods
124
+ // ============================================================================
125
+ async jiraGetProjectStatuses(jiraProjectKey) {
126
+ return this.makeSignedRequest('GET', `/hyperdrive/jira/projects/${encodeURIComponent(jiraProjectKey)}/statuses`);
127
+ }
122
128
  async jiraPreRegister(params) {
123
129
  return this.makeSignedRequest('POST', '/hyperdrive/jira/pre-register', params);
124
130
  }
125
- /**
126
- * Test API connection
127
- */
131
+ // ============================================================================
132
+ // Hyperdrive Project Methods
133
+ // ============================================================================
134
+ async projectAddRepo(projectId, repo) {
135
+ return this.makeSignedRequest('POST', `/hyperdrive/projects/${encodeURIComponent(projectId)}/repos`, repo);
136
+ }
137
+ async projectFindByJiraKey(jiraProjectKey) {
138
+ return this.makeSignedRequest('GET', `/hyperdrive/projects/by-jira-key/${encodeURIComponent(jiraProjectKey)}`);
139
+ }
140
+ async projectGetJiraConfig(projectId) {
141
+ return this.makeSignedRequest('GET', `/hyperdrive/projects/${encodeURIComponent(projectId)}/jira-config`);
142
+ }
143
+ async projectListRepos(projectId) {
144
+ return this.makeSignedRequest('GET', `/hyperdrive/projects/${encodeURIComponent(projectId)}/repos`);
145
+ }
146
+ async projectSetJiraConfig(projectId, config) {
147
+ return this.makeSignedRequest('PUT', `/hyperdrive/projects/${encodeURIComponent(projectId)}/jira-config`, config);
148
+ }
149
+ async projectUpdateRepo(projectId, repoId, updateData) {
150
+ return this.makeSignedRequest('PATCH', `/hyperdrive/projects/${encodeURIComponent(projectId)}/repos/${encodeURIComponent(repoId)}`, updateData);
151
+ }
152
+ async projectUpdateEntities(projectId, repoId, entities) {
153
+ return this.makeSignedRequest('PUT', `/hyperdrive/projects/${encodeURIComponent(projectId)}/repos/${encodeURIComponent(repoId)}/entities`, entities);
154
+ }
155
+ // ============================================================================
156
+ // Module Methods
157
+ // ============================================================================
128
158
  async makeTestRequest() {
129
159
  return this.makeSignedRequest('GET', '/');
130
160
  }
@@ -145,16 +175,12 @@ export class HyperdriveSigV4Service {
145
175
  return await this.makeSignedRequest('GET', `/modules/${slug}/dockerfile`);
146
176
  }
147
177
  catch (error) {
148
- // Return null if 404 (not found)
149
178
  if (error?.response?.status === 404) {
150
179
  return null;
151
180
  }
152
181
  throw error;
153
182
  }
154
183
  }
155
- // ============================================================================
156
- // AWS Account Methods
157
- // ============================================================================
158
184
  async moduleLink(params) {
159
185
  return this.makeSignedRequest('POST', '/modules/link', params);
160
186
  }
@@ -168,12 +194,12 @@ export class HyperdriveSigV4Service {
168
194
  const { slug, ...updateData } = params;
169
195
  return this.makeSignedRequest('PUT', `/modules/${slug}`, updateData);
170
196
  }
197
+ // ============================================================================
198
+ // Parameter Methods
199
+ // ============================================================================
171
200
  async parameterAdd(params) {
172
201
  return this.makeSignedRequest('POST', '/parameters', params);
173
202
  }
174
- // ============================================================================
175
- // Git Integration Methods
176
- // ============================================================================
177
203
  async parameterBackfill(params) {
178
204
  return this.makeSignedRequest('POST', '/parameters/backfill', params);
179
205
  }
@@ -189,15 +215,9 @@ export class HyperdriveSigV4Service {
189
215
  async parameterSync(params) {
190
216
  return this.makeSignedRequest('POST', '/parameters/sync', params);
191
217
  }
192
- // ============================================================================
193
- // Jira Integration Methods
194
- // ============================================================================
195
218
  async parameterSyncStatus(params) {
196
219
  return this.makeSignedRequest('GET', `/parameters/sync/${params.taskId}`);
197
220
  }
198
- // ============================================================================
199
- // CI Account Methods
200
- // ============================================================================
201
221
  async parameterUpdate(params) {
202
222
  return this.makeSignedRequest('PUT', `/parameters/${params.key}`, {
203
223
  accountId: params.accountId,
@@ -207,59 +227,39 @@ export class HyperdriveSigV4Service {
207
227
  stage: params.stage
208
228
  });
209
229
  }
230
+ // ============================================================================
231
+ // Stage Methods
232
+ // ============================================================================
210
233
  async stageCreate(params) {
211
234
  return this.makeSignedRequest('POST', '/stages', params);
212
235
  }
213
236
  async stageGet(params) {
214
237
  return this.makeSignedRequest('GET', `/stages/${params.name}`);
215
238
  }
216
- // ============================================================================
217
- // Dockerfile Discovery Methods
218
- // ============================================================================
219
239
  async stageList() {
220
240
  return this.makeSignedRequest('GET', '/stages');
221
241
  }
222
- async handleError(error) {
223
- const axiosError = error;
224
- if (axiosError.response) {
225
- const data = axiosError.response.data;
226
- // Handle outdated CLI version error with type safety
227
- if (axiosError.response.status === 426 && isOutdatedCLIError(data)) {
228
- await this.handleOutdatedCLI(data);
229
- }
230
- // Handle outdated role version error with type safety
231
- if (axiosError.response.status === 426 && isOutdatedRoleError(data)) {
232
- await this.handleOutdatedRole(data);
233
- }
234
- console.error('Error response:', axiosError.response.data);
235
- console.error('Error status:', axiosError.response.status);
236
- console.error('Error headers:', axiosError.response.headers);
237
- }
238
- else if (axiosError.request) {
239
- console.error('Error request:', axiosError.request);
240
- }
241
- else {
242
- console.error('Error message:', axiosError.message);
243
- }
244
- throw axiosError;
242
+ // ============================================================================
243
+ // Stage Access Methods
244
+ // ============================================================================
245
+ async stageAccessGet(stageName) {
246
+ return this.makeSignedRequest('GET', `/stages/${stageName}/access`);
245
247
  }
246
- async handleOutdatedCLI(errorData) {
247
- const { data } = errorData;
248
- console.error('\n❌ Your Hyperdrive CLI is outdated\n');
249
- console.error(`Current version: ${data.currentVersion}`);
250
- console.error(`Required version: ${data.requiredVersion}\n`);
251
- console.error('To update:');
252
- console.error(' npm install -g hyperdrive.bot@latest');
253
- console.error(' # or');
254
- console.error(' hd update\n');
255
- // Throw error to be caught by top-level handler
256
- const error = new Error('CLI_OUTDATED');
257
- error.code = 'OUTDATED_CLI_VERSION';
258
- error.data = data;
259
- throw error;
248
+ async stageAccessGrant(stageName, access) {
249
+ return this.makeSignedRequest('PUT', `/stages/${stageName}/access`, { access });
260
250
  }
251
+ async stageAccessRevoke(stageName, targetType, targetId) {
252
+ return this.makeSignedRequest('DELETE', `/stages/${stageName}/access/${targetType}/${targetId}`);
253
+ }
254
+ // ============================================================================
255
+ // User Groups Methods
261
256
  // ============================================================================
262
- // Helper Methods
257
+ async groupList() {
258
+ const response = await this.makeSignedRequest('GET', '/groups', undefined, this.userGroupsApiUrl);
259
+ return Array.isArray(response) ? response : [];
260
+ }
261
+ // ============================================================================
262
+ // Override error handling for hyperdrive-specific behavior
263
263
  // ============================================================================
264
264
  async handleOutdatedRole(errorData) {
265
265
  const { data } = errorData;
@@ -284,92 +284,6 @@ export class HyperdriveSigV4Service {
284
284
  console.error('\nUpdate URL (copy and paste):');
285
285
  console.error(` ${data.quickCreateUrl}\n`);
286
286
  }
287
- // Exit gracefully - user needs to update their role first
288
287
  process.exit(1);
289
288
  }
290
- handleResponse(response) {
291
- return response.data;
292
- }
293
- /**
294
- * Make a signed API request
295
- */
296
- async makeSignedRequest(method, path, data) {
297
- try {
298
- // Ensure we have valid credentials (auto-refreshes if needed)
299
- const credentials = await this.authService.ensureValidCredentials();
300
- // Sign the request
301
- const signedRequest = await this.signRequest(method, path, credentials.awsCredentials, data);
302
- // Convert signed request to axios config
303
- // Build URL with query string if present
304
- let url = `${signedRequest.protocol}//${signedRequest.hostname}${signedRequest.path}`;
305
- if (signedRequest.query && Object.keys(signedRequest.query).length > 0) {
306
- const queryString = new URLSearchParams(signedRequest.query).toString();
307
- url += `?${queryString}`;
308
- }
309
- const response = await axios({
310
- data: signedRequest.body,
311
- headers: signedRequest.headers,
312
- method: signedRequest.method,
313
- url,
314
- });
315
- return this.handleResponse(response);
316
- }
317
- catch (error) {
318
- return this.handleError(error);
319
- }
320
- }
321
- /**
322
- * Sign an HTTP request using AWS Signature V4
323
- */
324
- async signRequest(method, path, credentials, body) {
325
- // Parse API URL
326
- const url = new URL(this.apiUrl);
327
- const hostname = url.hostname;
328
- const protocol = url.protocol.replace(':', '');
329
- const basePath = url.pathname.replace(/\/$/, ''); // Remove trailing slash
330
- // Parse query string from path if present
331
- let pathWithoutQuery = path;
332
- let query;
333
- const queryIndex = path.indexOf('?');
334
- if (queryIndex !== -1) {
335
- pathWithoutQuery = path.substring(0, queryIndex);
336
- const queryString = path.substring(queryIndex + 1);
337
- query = {};
338
- const params = new URLSearchParams(queryString);
339
- for (const [key, value] of params) {
340
- query[key] = value;
341
- }
342
- }
343
- // Combine base path with request path (without query string)
344
- const fullPath = basePath + pathWithoutQuery;
345
- // Create signer
346
- const signer = new SignatureV4({
347
- credentials: {
348
- accessKeyId: credentials.accessKeyId,
349
- secretAccessKey: credentials.secretAccessKey,
350
- sessionToken: credentials.sessionToken,
351
- },
352
- region: this.region,
353
- service: 'execute-api',
354
- sha256: Sha256,
355
- });
356
- // Prepare request
357
- const request = new HttpRequest({
358
- body: body ? JSON.stringify(body) : undefined,
359
- headers: {
360
- 'Content-Type': 'application/json',
361
- 'User-Agent': `hyperdrive-cli/${CLI_VERSION}`,
362
- 'X-Tenant-Domain': this.tenantDomain,
363
- host: hostname,
364
- },
365
- hostname,
366
- method: method.toUpperCase(),
367
- path: fullPath,
368
- protocol,
369
- query,
370
- });
371
- // Sign the request
372
- const signedRequest = await signer.sign(request);
373
- return signedRequest;
374
- }
375
289
  }
@@ -8,6 +8,7 @@ export interface TenantConfig {
8
8
  region: string;
9
9
  tenantDomain: string;
10
10
  tenantId: string;
11
+ userGroupsApiUrl?: string;
11
12
  }
12
13
  export interface CLIConfig {
13
14
  apiUrl?: string;
@@ -87,6 +88,11 @@ export declare class TenantService {
87
88
  * Get API URL for a region
88
89
  */
89
90
  private getApiUrl;
91
+ /**
92
+ * Get User Groups API URL from bootstrap config
93
+ * Returns undefined if not available (optional module)
94
+ */
95
+ private getUserGroupsApiUrl;
90
96
  /**
91
97
  * Get bootstrap URL with fallback chain:
92
98
  * 1. Environment variable
@@ -85,6 +85,7 @@ export class TenantService {
85
85
  region,
86
86
  tenantDomain: domain,
87
87
  tenantId: bootstrap.tenantId,
88
+ userGroupsApiUrl: this.getUserGroupsApiUrl(bootstrap.amplifyConfig.API),
88
89
  };
89
90
  // Cache the tenant domain for future use
90
91
  this.saveTenantDomainToConfig(domain);
@@ -269,6 +270,18 @@ export class TenantService {
269
270
  chalk.yellow('This tenant does not have access to Hyperdrive.\n') +
270
271
  chalk.gray('Please contact your administrator to enable the Hyperdrive module.'));
271
272
  }
273
+ /**
274
+ * Get User Groups API URL from bootstrap config
275
+ * Returns undefined if not available (optional module)
276
+ */
277
+ getUserGroupsApiUrl(apiConfig) {
278
+ // Check for user-groups endpoint in bootstrap
279
+ if (apiConfig?.REST?.['user-groups']?.endpoint) {
280
+ console.log(chalk.gray(`✓ Using user-groups API endpoint from bootstrap: ${apiConfig.REST['user-groups'].endpoint}`));
281
+ return apiConfig.REST['user-groups'].endpoint;
282
+ }
283
+ return undefined;
284
+ }
272
285
  /**
273
286
  * Get bootstrap URL with fallback chain:
274
287
  * 1. Environment variable
@@ -42,7 +42,7 @@ export declare function promptAccountDetails(existingData?: Partial<AccountAddDa
42
42
  * @param accountData - Account details to register
43
43
  * @returns AccountResult indicating success or failure
44
44
  */
45
- export declare function registerAccount(accountData: AccountAddData): Promise<AccountResult>;
45
+ export declare function registerAccount(accountData: AccountAddData, tenantDomain?: string): Promise<AccountResult>;
46
46
  /**
47
47
  * Execute the AWS account add flow
48
48
  *
@@ -68,7 +68,7 @@ export declare function promptOpenCloudFormation(quickCreateUrl: string): Promis
68
68
  /**
69
69
  * Wait for role verification with polling
70
70
  */
71
- export declare function waitForRoleVerification(accountId: string, onProgress?: (message: string) => void): Promise<{
71
+ export declare function waitForRoleVerification(accountId: string, onProgress?: (message: string) => void, tenantDomain?: string): Promise<{
72
72
  message?: string;
73
73
  verified: boolean;
74
74
  }>;
@@ -97,10 +97,10 @@ export async function promptAccountDetails(existingData) {
97
97
  * @param accountData - Account details to register
98
98
  * @returns AccountResult indicating success or failure
99
99
  */
100
- export async function registerAccount(accountData) {
100
+ export async function registerAccount(accountData, tenantDomain) {
101
101
  try {
102
102
  // Initialize API service
103
- const service = new HyperdriveSigV4Service();
103
+ const service = new HyperdriveSigV4Service(tenantDomain);
104
104
  // Make API call to add account
105
105
  const result = await service.accountAdd({
106
106
  accountId: accountData.accountId,
@@ -190,8 +190,8 @@ const VERIFY_TIMEOUT = 300000; // 5 minutes
190
190
  /**
191
191
  * Wait for role verification with polling
192
192
  */
193
- export async function waitForRoleVerification(accountId, onProgress) {
194
- const service = new HyperdriveSigV4Service();
193
+ export async function waitForRoleVerification(accountId, onProgress, tenantDomain) {
194
+ const service = new HyperdriveSigV4Service(tenantDomain);
195
195
  const startTime = Date.now();
196
196
  let attemptCount = 0;
197
197
  while (Date.now() - startTime < VERIFY_TIMEOUT) {
@@ -55,6 +55,7 @@ export interface StoredCredentials extends CognitoTokens {
55
55
  region: string;
56
56
  tenantDomain: string;
57
57
  tenantId: string;
58
+ userGroupsApiUrl?: string;
58
59
  }
59
60
  /**
60
61
  * Generate PKCE code verifier (random base64url string)
@@ -333,6 +333,7 @@ export async function executeAuthFlow(options) {
333
333
  region: tenantConfig.region,
334
334
  tenantDomain: tenantConfig.tenantDomain,
335
335
  tenantId: tenantConfig.tenantId,
336
+ userGroupsApiUrl: tenantConfig.userGroupsApiUrl,
336
337
  }, tenantConfig.tenantDomain);
337
338
  return { success: true };
338
339
  }
@@ -420,6 +421,7 @@ export async function executeCIAuthFlow(options) {
420
421
  tenantDomain: tenantConfig.tenantDomain,
421
422
  tenantId: tenantConfig.tenantId,
422
423
  token_type: authResult.TokenType || 'Bearer',
424
+ userGroupsApiUrl: tenantConfig.userGroupsApiUrl,
423
425
  }, tenantConfig.tenantDomain);
424
426
  return { success: true };
425
427
  }
@@ -3,6 +3,7 @@
3
3
  */
4
4
  export interface GitConnectOptions {
5
5
  callbackPort?: number;
6
+ domain?: string;
6
7
  logger?: (message: string) => void;
7
8
  provider?: 'github' | 'gitlab';
8
9
  timeout?: number;
@@ -159,7 +159,7 @@ export function waitForCallback(expectedState, port = 8765, timeout = 5 * 60 * 1
159
159
  * @returns GitConnectResult indicating success or failure
160
160
  */
161
161
  export async function executeGitConnect(options = {}) {
162
- const { callbackPort = 8765, logger = () => { }, // No-op by default
162
+ const { callbackPort = 8765, domain, logger = () => { }, // No-op by default
163
163
  provider: initialProvider, timeout = 5 * 60 * 1000, } = options;
164
164
  try {
165
165
  // Step 1: Determine provider (prompt if not specified)
@@ -175,7 +175,7 @@ export async function executeGitConnect(options = {}) {
175
175
  provider = selected;
176
176
  }
177
177
  // Step 2: Initialize API service
178
- const service = new HyperdriveSigV4Service();
178
+ const service = new HyperdriveSigV4Service(domain);
179
179
  // Step 3: Initiate OAuth flow via API
180
180
  const authResponse = await service.gitAuthInitiate(provider);
181
181
  logger(`Opening browser for ${provider === 'github' ? 'GitHub' : 'GitLab'} authorization...`);
@@ -0,0 +1,21 @@
1
+ import type { HookActionType, HookResponse } from '../services/hyperdrive-sigv4.js';
2
+ /**
3
+ * Prompt user to select a trigger status from available Jira statuses
4
+ */
5
+ export declare function promptTriggerStatus(statuses: string[]): Promise<string>;
6
+ /**
7
+ * Prompt user to select an action type
8
+ */
9
+ export declare function promptActionType(): Promise<HookActionType>;
10
+ /**
11
+ * Prompt for action-specific configuration based on action type
12
+ */
13
+ export declare function promptActionConfig(actionType: HookActionType): Promise<Record<string, unknown>>;
14
+ /**
15
+ * Prompt user to select a hook from a list
16
+ */
17
+ export declare function promptSelectHook(hooks: HookResponse[]): Promise<HookResponse>;
18
+ /**
19
+ * Prompt user to confirm hook deletion
20
+ */
21
+ export declare function promptConfirmDelete(hook: HookResponse): Promise<boolean>;