@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.
- package/README.md +415 -67
- package/dist/commands/account/add.d.ts +6 -6
- package/dist/commands/account/list.d.ts +3 -0
- package/dist/commands/account/list.js +9 -2
- package/dist/commands/account/remove.d.ts +3 -3
- package/dist/commands/auth/login.d.ts +4 -4
- package/dist/commands/auth/login.js +1 -0
- package/dist/commands/ci/account/create.d.ts +7 -6
- package/dist/commands/ci/account/create.js +49 -3
- package/dist/commands/ci/account/delete.d.ts +3 -3
- package/dist/commands/ci/account/list.d.ts +2 -2
- package/dist/commands/config/get.d.ts +1 -1
- package/dist/commands/config/set.d.ts +2 -2
- package/dist/commands/deployment/create.d.ts +10 -10
- package/dist/commands/deployment/get.d.ts +4 -4
- package/dist/commands/deployment/launch.d.ts +6 -6
- package/dist/commands/deployment/list.d.ts +3 -3
- package/dist/commands/deployment/list.js +17 -17
- package/dist/commands/domain/switch.d.ts +1 -1
- package/dist/commands/example.d.ts +3 -3
- package/dist/commands/git/connect.d.ts +2 -2
- package/dist/commands/git/connect.js +1 -0
- package/dist/commands/git/disconnect.d.ts +3 -3
- package/dist/commands/git/list.d.ts +2 -2
- package/dist/commands/git/sync.d.ts +7 -7
- package/dist/commands/git/sync.js +24 -23
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +20 -19
- package/dist/commands/jira/connect.d.ts +2 -1
- package/dist/commands/jira/connect.js +17 -6
- package/dist/commands/jira/hook/add.d.ts +17 -0
- package/dist/commands/jira/hook/add.js +147 -0
- package/dist/commands/jira/hook/list.d.ts +14 -0
- package/dist/commands/jira/hook/list.js +105 -0
- package/dist/commands/jira/hook/remove.d.ts +15 -0
- package/dist/commands/jira/hook/remove.js +119 -0
- package/dist/commands/jira/hook/toggle.d.ts +15 -0
- package/dist/commands/jira/hook/toggle.js +136 -0
- package/dist/commands/jira/status.d.ts +1 -1
- package/dist/commands/module/analyze.d.ts +5 -5
- package/dist/commands/module/create.d.ts +17 -17
- package/dist/commands/module/create.js +9 -1
- package/dist/commands/module/destroy.d.ts +3 -3
- package/dist/commands/module/get.d.ts +2 -2
- package/dist/commands/module/link.d.ts +4 -4
- package/dist/commands/module/list.d.ts +1 -1
- package/dist/commands/module/list.js +12 -11
- package/dist/commands/module/reanalyze.d.ts +6 -6
- package/dist/commands/module/update.d.ts +19 -19
- package/dist/commands/parameter/add.d.ts +7 -7
- package/dist/commands/parameter/backfill.d.ts +4 -4
- package/dist/commands/parameter/backfill.js +4 -3
- package/dist/commands/parameter/clear.d.ts +6 -6
- package/dist/commands/parameter/list.d.ts +6 -6
- package/dist/commands/parameter/list.js +4 -3
- package/dist/commands/parameter/pull.d.ts +6 -6
- package/dist/commands/parameter/remove.d.ts +7 -7
- package/dist/commands/parameter/sync.d.ts +6 -6
- package/dist/commands/parameter/update.d.ts +7 -7
- package/dist/commands/project/init.d.ts +21 -0
- package/dist/commands/project/init.js +576 -0
- package/dist/commands/project/list.d.ts +10 -0
- package/dist/commands/project/list.js +119 -0
- package/dist/commands/project/status.d.ts +13 -0
- package/dist/commands/project/status.js +163 -0
- package/dist/commands/project/sync.d.ts +26 -0
- package/dist/commands/project/sync.js +388 -0
- package/dist/commands/stage/access.d.ts +15 -0
- package/dist/commands/stage/access.js +130 -0
- package/dist/commands/stage/create.d.ts +11 -11
- package/dist/commands/stage/list.d.ts +1 -1
- package/dist/commands/stage/list.js +21 -20
- package/dist/commands/stage/revoke.d.ts +18 -0
- package/dist/commands/stage/revoke.js +171 -0
- package/dist/commands/stage/share.d.ts +23 -0
- package/dist/commands/stage/share.js +292 -0
- package/dist/commands/test-api.d.ts +1 -1
- package/dist/services/auth-service.d.ts +15 -82
- package/dist/services/auth-service.js +24 -237
- package/dist/services/hyperdrive-sigv4.d.ts +162 -24
- package/dist/services/hyperdrive-sigv4.js +107 -193
- package/dist/services/tenant-service.d.ts +6 -0
- package/dist/services/tenant-service.js +13 -0
- package/dist/utils/account-flow.d.ts +2 -2
- package/dist/utils/account-flow.js +4 -4
- package/dist/utils/auth-flow.d.ts +1 -0
- package/dist/utils/auth-flow.js +2 -0
- package/dist/utils/git-flow.d.ts +1 -0
- package/dist/utils/git-flow.js +2 -2
- package/dist/utils/hook-flow.d.ts +21 -0
- package/dist/utils/hook-flow.js +154 -0
- package/dist/utils/jira-flow.d.ts +2 -2
- package/dist/utils/jira-flow.js +4 -4
- package/dist/utils/table.d.ts +17 -0
- package/dist/utils/table.js +41 -0
- package/oclif.manifest.json +844 -154
- package/package.json +59 -15
|
@@ -1,72 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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 {
|
|
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
|
-
|
|
41
|
-
authService;
|
|
42
|
-
region;
|
|
43
|
-
tenantDomain;
|
|
20
|
+
export class HyperdriveSigV4Service extends SigV4ApiClient {
|
|
21
|
+
userGroupsApiUrl;
|
|
44
22
|
constructor(domain) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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
|
|
247
|
-
|
|
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
|
-
|
|
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) {
|
package/dist/utils/auth-flow.js
CHANGED
|
@@ -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
|
}
|
package/dist/utils/git-flow.d.ts
CHANGED
package/dist/utils/git-flow.js
CHANGED
|
@@ -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>;
|