@hyperdrive.bot/cli 1.0.6 → 1.0.7
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 +169 -63
- package/dist/commands/account/add.d.ts +6 -6
- 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/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/jira/connect.d.ts +1 -1
- 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/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 +37 -24
- package/dist/services/hyperdrive-sigv4.js +62 -193
- package/dist/services/tenant-service.d.ts +6 -0
- package/dist/services/tenant-service.js +13 -0
- package/dist/utils/auth-flow.d.ts +1 -0
- package/dist/utils/auth-flow.js +2 -0
- package/dist/utils/table.d.ts +17 -0
- package/dist/utils/table.js +41 -0
- package/oclif.manifest.json +309 -81
- package/package.json +55 -15
|
@@ -1,3 +1,10 @@
|
|
|
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, type OutdatedRoleErrorResponse } from '@hyperdrive.bot/cli-auth';
|
|
1
8
|
import { LoggingConfig } from './log-tailer.js';
|
|
2
9
|
interface DeploymentCheckResponse {
|
|
3
10
|
commit?: string;
|
|
@@ -131,16 +138,9 @@ interface GitAuthInitiateResponse {
|
|
|
131
138
|
}
|
|
132
139
|
/**
|
|
133
140
|
* Hyperdrive API Service with AWS SigV4 authentication
|
|
134
|
-
*
|
|
135
|
-
* This service signs all API requests using AWS Signature Version 4,
|
|
136
|
-
* which allows both CLI and web frontend to use the same endpoints
|
|
137
|
-
* with unified AWS IAM authentication via Cognito.
|
|
138
141
|
*/
|
|
139
|
-
export declare class HyperdriveSigV4Service {
|
|
140
|
-
private
|
|
141
|
-
private authService;
|
|
142
|
-
private region;
|
|
143
|
-
private tenantDomain;
|
|
142
|
+
export declare class HyperdriveSigV4Service extends SigV4ApiClient {
|
|
143
|
+
private readonly userGroupsApiUrl?;
|
|
144
144
|
constructor(domain?: string);
|
|
145
145
|
accountAdd(params: {
|
|
146
146
|
accountId: string;
|
|
@@ -268,9 +268,6 @@ export declare class HyperdriveSigV4Service {
|
|
|
268
268
|
};
|
|
269
269
|
success: boolean;
|
|
270
270
|
}>;
|
|
271
|
-
/**
|
|
272
|
-
* Test API connection
|
|
273
|
-
*/
|
|
274
271
|
makeTestRequest(): Promise<Record<string, unknown>>;
|
|
275
272
|
moduleAnalyze(slug: string): Promise<{
|
|
276
273
|
jobId: string;
|
|
@@ -433,17 +430,33 @@ export declare class HyperdriveSigV4Service {
|
|
|
433
430
|
name: string;
|
|
434
431
|
}): Promise<StageResponse>;
|
|
435
432
|
stageList(): Promise<StageResponse[]>;
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
433
|
+
stageAccessGet(stageName: string): Promise<{
|
|
434
|
+
access: Array<{
|
|
435
|
+
role: string;
|
|
436
|
+
targetId: string;
|
|
437
|
+
targetType: 'user' | 'group';
|
|
438
|
+
}>;
|
|
439
|
+
stageId: string;
|
|
440
|
+
stageName: string;
|
|
441
|
+
}>;
|
|
442
|
+
stageAccessGrant(stageName: string, access: Array<{
|
|
443
|
+
role: 'viewer' | 'deployer' | 'manager';
|
|
444
|
+
targetId: string;
|
|
445
|
+
targetType: 'user' | 'group';
|
|
446
|
+
}>): Promise<{
|
|
447
|
+
added: number;
|
|
448
|
+
message: string;
|
|
449
|
+
}>;
|
|
450
|
+
stageAccessRevoke(stageName: string, targetType: 'user' | 'group', targetId: string): Promise<{
|
|
451
|
+
message: string;
|
|
452
|
+
}>;
|
|
453
|
+
groupList(): Promise<Array<{
|
|
454
|
+
groupId: string;
|
|
455
|
+
name: string;
|
|
456
|
+
description?: string;
|
|
457
|
+
memberCount: number;
|
|
458
|
+
isSystemGroup: boolean;
|
|
459
|
+
}>>;
|
|
460
|
+
protected handleOutdatedRole(errorData: OutdatedRoleErrorResponse): Promise<void>;
|
|
448
461
|
}
|
|
449
462
|
export {};
|
|
@@ -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,15 @@ export class HyperdriveSigV4Service {
|
|
|
119
101
|
});
|
|
120
102
|
return this.makeSignedRequest('GET', `/git/repos?${queryParams}`);
|
|
121
103
|
}
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// Jira Integration Methods
|
|
106
|
+
// ============================================================================
|
|
122
107
|
async jiraPreRegister(params) {
|
|
123
108
|
return this.makeSignedRequest('POST', '/hyperdrive/jira/pre-register', params);
|
|
124
109
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// Module Methods
|
|
112
|
+
// ============================================================================
|
|
128
113
|
async makeTestRequest() {
|
|
129
114
|
return this.makeSignedRequest('GET', '/');
|
|
130
115
|
}
|
|
@@ -145,16 +130,12 @@ export class HyperdriveSigV4Service {
|
|
|
145
130
|
return await this.makeSignedRequest('GET', `/modules/${slug}/dockerfile`);
|
|
146
131
|
}
|
|
147
132
|
catch (error) {
|
|
148
|
-
// Return null if 404 (not found)
|
|
149
133
|
if (error?.response?.status === 404) {
|
|
150
134
|
return null;
|
|
151
135
|
}
|
|
152
136
|
throw error;
|
|
153
137
|
}
|
|
154
138
|
}
|
|
155
|
-
// ============================================================================
|
|
156
|
-
// AWS Account Methods
|
|
157
|
-
// ============================================================================
|
|
158
139
|
async moduleLink(params) {
|
|
159
140
|
return this.makeSignedRequest('POST', '/modules/link', params);
|
|
160
141
|
}
|
|
@@ -168,12 +149,12 @@ export class HyperdriveSigV4Service {
|
|
|
168
149
|
const { slug, ...updateData } = params;
|
|
169
150
|
return this.makeSignedRequest('PUT', `/modules/${slug}`, updateData);
|
|
170
151
|
}
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// Parameter Methods
|
|
154
|
+
// ============================================================================
|
|
171
155
|
async parameterAdd(params) {
|
|
172
156
|
return this.makeSignedRequest('POST', '/parameters', params);
|
|
173
157
|
}
|
|
174
|
-
// ============================================================================
|
|
175
|
-
// Git Integration Methods
|
|
176
|
-
// ============================================================================
|
|
177
158
|
async parameterBackfill(params) {
|
|
178
159
|
return this.makeSignedRequest('POST', '/parameters/backfill', params);
|
|
179
160
|
}
|
|
@@ -189,15 +170,9 @@ export class HyperdriveSigV4Service {
|
|
|
189
170
|
async parameterSync(params) {
|
|
190
171
|
return this.makeSignedRequest('POST', '/parameters/sync', params);
|
|
191
172
|
}
|
|
192
|
-
// ============================================================================
|
|
193
|
-
// Jira Integration Methods
|
|
194
|
-
// ============================================================================
|
|
195
173
|
async parameterSyncStatus(params) {
|
|
196
174
|
return this.makeSignedRequest('GET', `/parameters/sync/${params.taskId}`);
|
|
197
175
|
}
|
|
198
|
-
// ============================================================================
|
|
199
|
-
// CI Account Methods
|
|
200
|
-
// ============================================================================
|
|
201
176
|
async parameterUpdate(params) {
|
|
202
177
|
return this.makeSignedRequest('PUT', `/parameters/${params.key}`, {
|
|
203
178
|
accountId: params.accountId,
|
|
@@ -207,59 +182,39 @@ export class HyperdriveSigV4Service {
|
|
|
207
182
|
stage: params.stage
|
|
208
183
|
});
|
|
209
184
|
}
|
|
185
|
+
// ============================================================================
|
|
186
|
+
// Stage Methods
|
|
187
|
+
// ============================================================================
|
|
210
188
|
async stageCreate(params) {
|
|
211
189
|
return this.makeSignedRequest('POST', '/stages', params);
|
|
212
190
|
}
|
|
213
191
|
async stageGet(params) {
|
|
214
192
|
return this.makeSignedRequest('GET', `/stages/${params.name}`);
|
|
215
193
|
}
|
|
216
|
-
// ============================================================================
|
|
217
|
-
// Dockerfile Discovery Methods
|
|
218
|
-
// ============================================================================
|
|
219
194
|
async stageList() {
|
|
220
195
|
return this.makeSignedRequest('GET', '/stages');
|
|
221
196
|
}
|
|
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;
|
|
197
|
+
// ============================================================================
|
|
198
|
+
// Stage Access Methods
|
|
199
|
+
// ============================================================================
|
|
200
|
+
async stageAccessGet(stageName) {
|
|
201
|
+
return this.makeSignedRequest('GET', `/stages/${stageName}/access`);
|
|
245
202
|
}
|
|
246
|
-
async
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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;
|
|
203
|
+
async stageAccessGrant(stageName, access) {
|
|
204
|
+
return this.makeSignedRequest('PUT', `/stages/${stageName}/access`, { access });
|
|
205
|
+
}
|
|
206
|
+
async stageAccessRevoke(stageName, targetType, targetId) {
|
|
207
|
+
return this.makeSignedRequest('DELETE', `/stages/${stageName}/access/${targetType}/${targetId}`);
|
|
260
208
|
}
|
|
261
209
|
// ============================================================================
|
|
262
|
-
//
|
|
210
|
+
// User Groups Methods
|
|
211
|
+
// ============================================================================
|
|
212
|
+
async groupList() {
|
|
213
|
+
const response = await this.makeSignedRequest('GET', '/groups', undefined, this.userGroupsApiUrl);
|
|
214
|
+
return Array.isArray(response) ? response : [];
|
|
215
|
+
}
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// Override error handling for hyperdrive-specific behavior
|
|
263
218
|
// ============================================================================
|
|
264
219
|
async handleOutdatedRole(errorData) {
|
|
265
220
|
const { data } = errorData;
|
|
@@ -284,92 +239,6 @@ export class HyperdriveSigV4Service {
|
|
|
284
239
|
console.error('\nUpdate URL (copy and paste):');
|
|
285
240
|
console.error(` ${data.quickCreateUrl}\n`);
|
|
286
241
|
}
|
|
287
|
-
// Exit gracefully - user needs to update their role first
|
|
288
242
|
process.exit(1);
|
|
289
243
|
}
|
|
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
244
|
}
|
|
@@ -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
|
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
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface ColumnConfig<T> {
|
|
2
|
+
header: string;
|
|
3
|
+
minWidth?: number;
|
|
4
|
+
get?: (row: T) => string;
|
|
5
|
+
}
|
|
6
|
+
type TableColumns<T> = Record<string, ColumnConfig<T>>;
|
|
7
|
+
/**
|
|
8
|
+
* Print data in a table format using cli-table3
|
|
9
|
+
* Replacement for oclif's deprecated ux.table
|
|
10
|
+
*/
|
|
11
|
+
export declare function printTable<T extends Record<string, unknown>>(data: T[], columns: TableColumns<T>, logger: (msg: string) => void): void;
|
|
12
|
+
/**
|
|
13
|
+
* Print a styled header
|
|
14
|
+
* Replacement for oclif's deprecated ux.styledHeader
|
|
15
|
+
*/
|
|
16
|
+
export declare function printHeader(text: string, logger: (msg: string) => void): void;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import Table from 'cli-table3';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
/**
|
|
4
|
+
* Print data in a table format using cli-table3
|
|
5
|
+
* Replacement for oclif's deprecated ux.table
|
|
6
|
+
*/
|
|
7
|
+
export function printTable(data, columns, logger) {
|
|
8
|
+
const columnKeys = Object.keys(columns);
|
|
9
|
+
const headers = columnKeys.map(key => chalk.bold(columns[key].header));
|
|
10
|
+
const colWidths = columnKeys.map(key => columns[key].minWidth ?? null);
|
|
11
|
+
const hasColWidths = colWidths.some(w => w !== null);
|
|
12
|
+
const tableOptions = {
|
|
13
|
+
head: headers,
|
|
14
|
+
style: { head: [], border: [] },
|
|
15
|
+
};
|
|
16
|
+
if (hasColWidths) {
|
|
17
|
+
tableOptions.colWidths = colWidths;
|
|
18
|
+
}
|
|
19
|
+
const table = new Table(tableOptions);
|
|
20
|
+
for (const row of data) {
|
|
21
|
+
const rowData = columnKeys.map(key => {
|
|
22
|
+
const col = columns[key];
|
|
23
|
+
if (col.get) {
|
|
24
|
+
return col.get(row);
|
|
25
|
+
}
|
|
26
|
+
const value = row[key];
|
|
27
|
+
return value !== undefined && value !== null ? String(value) : '';
|
|
28
|
+
});
|
|
29
|
+
table.push(rowData);
|
|
30
|
+
}
|
|
31
|
+
logger(table.toString());
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Print a styled header
|
|
35
|
+
* Replacement for oclif's deprecated ux.styledHeader
|
|
36
|
+
*/
|
|
37
|
+
export function printHeader(text, logger) {
|
|
38
|
+
logger('');
|
|
39
|
+
logger(chalk.bold(text));
|
|
40
|
+
logger(chalk.gray('─'.repeat(Math.min(text.length + 10, 60))));
|
|
41
|
+
}
|