@hyperdrive.bot/cli 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +1598 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +3 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +5 -0
  6. package/dist/commands/account/add.d.ts +16 -0
  7. package/dist/commands/account/add.js +185 -0
  8. package/dist/commands/account/list.d.ts +6 -0
  9. package/dist/commands/account/list.js +37 -0
  10. package/dist/commands/account/remove.d.ts +11 -0
  11. package/dist/commands/account/remove.js +57 -0
  12. package/dist/commands/auth/login.d.ts +16 -0
  13. package/dist/commands/auth/login.js +178 -0
  14. package/dist/commands/auth/logout.d.ts +6 -0
  15. package/dist/commands/auth/logout.js +39 -0
  16. package/dist/commands/auth/refresh.d.ts +6 -0
  17. package/dist/commands/auth/refresh.js +66 -0
  18. package/dist/commands/auth/status.d.ts +6 -0
  19. package/dist/commands/auth/status.js +63 -0
  20. package/dist/commands/ci/account/create.d.ts +16 -0
  21. package/dist/commands/ci/account/create.js +158 -0
  22. package/dist/commands/ci/account/delete.d.ts +14 -0
  23. package/dist/commands/ci/account/delete.js +88 -0
  24. package/dist/commands/ci/account/list.d.ts +10 -0
  25. package/dist/commands/ci/account/list.js +65 -0
  26. package/dist/commands/config/get.d.ts +9 -0
  27. package/dist/commands/config/get.js +37 -0
  28. package/dist/commands/config/set.d.ts +10 -0
  29. package/dist/commands/config/set.js +48 -0
  30. package/dist/commands/config/show.d.ts +6 -0
  31. package/dist/commands/config/show.js +10 -0
  32. package/dist/commands/deployment/create.d.ts +30 -0
  33. package/dist/commands/deployment/create.js +188 -0
  34. package/dist/commands/deployment/get.d.ts +13 -0
  35. package/dist/commands/deployment/get.js +101 -0
  36. package/dist/commands/deployment/launch.d.ts +15 -0
  37. package/dist/commands/deployment/launch.js +105 -0
  38. package/dist/commands/deployment/list.d.ts +11 -0
  39. package/dist/commands/deployment/list.js +91 -0
  40. package/dist/commands/domain/current.d.ts +6 -0
  41. package/dist/commands/domain/current.js +18 -0
  42. package/dist/commands/domain/list.d.ts +6 -0
  43. package/dist/commands/domain/list.js +42 -0
  44. package/dist/commands/domain/switch.d.ts +9 -0
  45. package/dist/commands/domain/switch.js +40 -0
  46. package/dist/commands/example.d.ts +13 -0
  47. package/dist/commands/example.js +24 -0
  48. package/dist/commands/git/connect.d.ts +10 -0
  49. package/dist/commands/git/connect.js +56 -0
  50. package/dist/commands/git/disconnect.d.ts +11 -0
  51. package/dist/commands/git/disconnect.js +93 -0
  52. package/dist/commands/git/list.d.ts +10 -0
  53. package/dist/commands/git/list.js +53 -0
  54. package/dist/commands/git/sync.d.ts +18 -0
  55. package/dist/commands/git/sync.js +235 -0
  56. package/dist/commands/init.d.ts +188 -0
  57. package/dist/commands/init.js +817 -0
  58. package/dist/commands/jira/connect.d.ts +9 -0
  59. package/dist/commands/jira/connect.js +141 -0
  60. package/dist/commands/jira/status.d.ts +9 -0
  61. package/dist/commands/jira/status.js +118 -0
  62. package/dist/commands/module/analyze.d.ts +29 -0
  63. package/dist/commands/module/analyze.js +201 -0
  64. package/dist/commands/module/create.d.ts +42 -0
  65. package/dist/commands/module/create.js +498 -0
  66. package/dist/commands/module/destroy.d.ts +11 -0
  67. package/dist/commands/module/destroy.js +77 -0
  68. package/dist/commands/module/get.d.ts +10 -0
  69. package/dist/commands/module/get.js +43 -0
  70. package/dist/commands/module/link.d.ts +15 -0
  71. package/dist/commands/module/link.js +175 -0
  72. package/dist/commands/module/list.d.ts +9 -0
  73. package/dist/commands/module/list.js +51 -0
  74. package/dist/commands/module/reanalyze.d.ts +30 -0
  75. package/dist/commands/module/reanalyze.js +206 -0
  76. package/dist/commands/module/update.d.ts +27 -0
  77. package/dist/commands/module/update.js +102 -0
  78. package/dist/commands/parameter/add.d.ts +15 -0
  79. package/dist/commands/parameter/add.js +99 -0
  80. package/dist/commands/parameter/backfill.d.ts +12 -0
  81. package/dist/commands/parameter/backfill.js +113 -0
  82. package/dist/commands/parameter/clear.d.ts +14 -0
  83. package/dist/commands/parameter/clear.js +95 -0
  84. package/dist/commands/parameter/list.d.ts +14 -0
  85. package/dist/commands/parameter/list.js +92 -0
  86. package/dist/commands/parameter/pull.d.ts +14 -0
  87. package/dist/commands/parameter/pull.js +124 -0
  88. package/dist/commands/parameter/remove.d.ts +15 -0
  89. package/dist/commands/parameter/remove.js +90 -0
  90. package/dist/commands/parameter/sync.d.ts +14 -0
  91. package/dist/commands/parameter/sync.js +153 -0
  92. package/dist/commands/parameter/update.d.ts +15 -0
  93. package/dist/commands/parameter/update.js +100 -0
  94. package/dist/commands/stage/create.d.ts +28 -0
  95. package/dist/commands/stage/create.js +312 -0
  96. package/dist/commands/stage/list.d.ts +9 -0
  97. package/dist/commands/stage/list.js +63 -0
  98. package/dist/commands/test-api.d.ts +9 -0
  99. package/dist/commands/test-api.js +40 -0
  100. package/dist/index.d.ts +1 -0
  101. package/dist/index.js +1 -0
  102. package/dist/services/auth-service.d.ts +84 -0
  103. package/dist/services/auth-service.js +240 -0
  104. package/dist/services/git.d.ts +46 -0
  105. package/dist/services/git.js +409 -0
  106. package/dist/services/hyperdrive-sigv4.d.ts +449 -0
  107. package/dist/services/hyperdrive-sigv4.js +375 -0
  108. package/dist/services/hyperdrive.d.ts +87 -0
  109. package/dist/services/hyperdrive.js +108 -0
  110. package/dist/services/log-tailer.d.ts +95 -0
  111. package/dist/services/log-tailer.js +242 -0
  112. package/dist/services/tenant-service.d.ts +106 -0
  113. package/dist/services/tenant-service.js +332 -0
  114. package/dist/utils/account-flow.d.ts +74 -0
  115. package/dist/utils/account-flow.js +228 -0
  116. package/dist/utils/auth-flow.d.ts +146 -0
  117. package/dist/utils/auth-flow.js +477 -0
  118. package/dist/utils/git-flow.d.ts +72 -0
  119. package/dist/utils/git-flow.js +232 -0
  120. package/dist/utils/jira-flow.d.ts +71 -0
  121. package/dist/utils/jira-flow.js +120 -0
  122. package/dist/utils/summary-display.d.ts +59 -0
  123. package/dist/utils/summary-display.js +140 -0
  124. package/dist/utils/validation.d.ts +15 -0
  125. package/dist/utils/validation.js +32 -0
  126. package/oclif.manifest.json +2819 -0
  127. package/package.json +112 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Options for executing the AWS account add flow
3
+ */
4
+ export interface AccountAddOptions {
5
+ skipAliasPrompt?: boolean;
6
+ tenantDomain: string;
7
+ }
8
+ /**
9
+ * Result of the account add flow
10
+ */
11
+ export interface AccountResult {
12
+ accountAlias?: string;
13
+ accountId?: string;
14
+ error?: string;
15
+ quickCreateUrl?: string;
16
+ roleVerified?: boolean;
17
+ success: boolean;
18
+ }
19
+ /**
20
+ * AWS Account add request data
21
+ */
22
+ export interface AccountAddData {
23
+ accountId: string;
24
+ defaultRegion: string;
25
+ name?: string;
26
+ roleArn?: string;
27
+ }
28
+ /**
29
+ * Validate AWS Account ID format
30
+ */
31
+ export declare function validateAccountId(input: string): boolean | string;
32
+ /**
33
+ * Prompt user for AWS account details
34
+ */
35
+ export declare function promptAccountDetails(existingData?: Partial<AccountAddData>): Promise<AccountAddData>;
36
+ /**
37
+ * Register an AWS account with the API (no user prompts)
38
+ *
39
+ * This function is separated from user input collection to allow
40
+ * proper spinner timing and better separation of concerns.
41
+ *
42
+ * @param accountData - Account details to register
43
+ * @returns AccountResult indicating success or failure
44
+ */
45
+ export declare function registerAccount(accountData: AccountAddData): Promise<AccountResult>;
46
+ /**
47
+ * Execute the AWS account add flow
48
+ *
49
+ * This function handles:
50
+ * 1. Prompting for account details (ID, name, region)
51
+ * 2. Making API call to register the account
52
+ * 3. Returning result with quickCreateUrl if role needs to be created
53
+ *
54
+ * @param options - Configuration options for the account add flow
55
+ * @returns AccountResult indicating success or failure
56
+ */
57
+ export declare function executeAccountAdd(options: AccountAddOptions): Promise<AccountResult>;
58
+ /**
59
+ * Open CloudFormation URL in browser for role creation
60
+ *
61
+ * Validates URL is an AWS domain before opening to prevent opening malicious URLs
62
+ */
63
+ export declare function openCloudFormationUrl(quickCreateUrl: string): Promise<void>;
64
+ /**
65
+ * Prompt user to open CloudFormation URL
66
+ */
67
+ export declare function promptOpenCloudFormation(quickCreateUrl: string): Promise<boolean>;
68
+ /**
69
+ * Wait for role verification with polling
70
+ */
71
+ export declare function waitForRoleVerification(accountId: string, onProgress?: (message: string) => void): Promise<{
72
+ message?: string;
73
+ verified: boolean;
74
+ }>;
@@ -0,0 +1,228 @@
1
+ import inquirer from 'inquirer';
2
+ import open from 'open';
3
+ import { HyperdriveSigV4Service } from '../services/hyperdrive-sigv4.js';
4
+ /**
5
+ * Comprehensive list of AWS regions
6
+ * Updated to include all major commercial regions as of 2025
7
+ */
8
+ const AWS_REGIONS = [
9
+ // US Regions
10
+ 'us-east-1', // N. Virginia
11
+ 'us-east-2', // Ohio
12
+ 'us-west-1', // N. California
13
+ 'us-west-2', // Oregon
14
+ // South America
15
+ 'sa-east-1', // São Paulo
16
+ // Europe
17
+ 'eu-west-1', // Ireland
18
+ 'eu-west-2', // London
19
+ 'eu-west-3', // Paris
20
+ 'eu-central-1', // Frankfurt
21
+ 'eu-central-2', // Zurich
22
+ 'eu-north-1', // Stockholm
23
+ 'eu-south-1', // Milan
24
+ 'eu-south-2', // Spain
25
+ // Asia Pacific
26
+ 'ap-northeast-1', // Tokyo
27
+ 'ap-northeast-2', // Seoul
28
+ 'ap-northeast-3', // Osaka
29
+ 'ap-southeast-1', // Singapore
30
+ 'ap-southeast-2', // Sydney
31
+ 'ap-southeast-3', // Jakarta
32
+ 'ap-southeast-4', // Melbourne
33
+ 'ap-south-1', // Mumbai
34
+ 'ap-south-2', // Hyderabad
35
+ 'ap-east-1', // Hong Kong
36
+ // Middle East
37
+ 'me-south-1', // Bahrain
38
+ 'me-central-1', // UAE
39
+ // Africa
40
+ 'af-south-1', // Cape Town
41
+ // Canada
42
+ 'ca-central-1', // Canada (Central)
43
+ 'ca-west-1', // Canada West (Calgary)
44
+ ];
45
+ /**
46
+ * Validate AWS Account ID format
47
+ */
48
+ export function validateAccountId(input) {
49
+ if (!/^\d{12}$/.test(input)) {
50
+ return 'AWS Account ID must be exactly 12 digits';
51
+ }
52
+ return true;
53
+ }
54
+ /**
55
+ * Prompt user for AWS account details
56
+ */
57
+ export async function promptAccountDetails(existingData) {
58
+ // Prompts array - using any[] due to complex inquirer types, but validated by inquirer.prompt()
59
+ const prompts = [];
60
+ if (!existingData?.accountId) {
61
+ prompts.push({
62
+ message: 'Enter the AWS Account ID (12 digits):',
63
+ name: 'accountId',
64
+ type: 'input',
65
+ validate: validateAccountId,
66
+ });
67
+ }
68
+ if (!existingData?.name) {
69
+ prompts.push({
70
+ default: 'Production',
71
+ message: 'Enter a friendly name for this account (optional):',
72
+ name: 'name',
73
+ type: 'input',
74
+ });
75
+ }
76
+ if (!existingData?.defaultRegion) {
77
+ prompts.push({
78
+ choices: AWS_REGIONS,
79
+ default: 'us-east-1',
80
+ message: 'Select the default AWS region:',
81
+ name: 'defaultRegion',
82
+ type: 'list',
83
+ });
84
+ }
85
+ if (prompts.length === 0) {
86
+ return existingData;
87
+ }
88
+ const responses = await inquirer.prompt(prompts);
89
+ return { ...existingData, ...responses };
90
+ }
91
+ /**
92
+ * Register an AWS account with the API (no user prompts)
93
+ *
94
+ * This function is separated from user input collection to allow
95
+ * proper spinner timing and better separation of concerns.
96
+ *
97
+ * @param accountData - Account details to register
98
+ * @returns AccountResult indicating success or failure
99
+ */
100
+ export async function registerAccount(accountData) {
101
+ try {
102
+ // Initialize API service
103
+ const service = new HyperdriveSigV4Service();
104
+ // Make API call to add account
105
+ const result = await service.accountAdd({
106
+ accountId: accountData.accountId,
107
+ defaultRegion: accountData.defaultRegion,
108
+ name: accountData.name,
109
+ roleArn: accountData.roleArn,
110
+ });
111
+ return {
112
+ accountAlias: result.name,
113
+ accountId: result.accountId,
114
+ quickCreateUrl: result.quickCreateUrl,
115
+ roleVerified: result.roleVerified,
116
+ success: true,
117
+ };
118
+ }
119
+ catch (error) {
120
+ const errorMessage = error instanceof Error ? error.message : String(error);
121
+ return {
122
+ error: errorMessage,
123
+ success: false,
124
+ };
125
+ }
126
+ }
127
+ /**
128
+ * Execute the AWS account add flow
129
+ *
130
+ * This function handles:
131
+ * 1. Prompting for account details (ID, name, region)
132
+ * 2. Making API call to register the account
133
+ * 3. Returning result with quickCreateUrl if role needs to be created
134
+ *
135
+ * @param options - Configuration options for the account add flow
136
+ * @returns AccountResult indicating success or failure
137
+ */
138
+ export async function executeAccountAdd(options) {
139
+ try {
140
+ // Step 1: Prompt for account details (no spinner - user needs to see prompts)
141
+ const accountData = await promptAccountDetails();
142
+ // Step 2: Register account with API (caller should wrap this with spinner)
143
+ return await registerAccount(accountData);
144
+ }
145
+ catch (error) {
146
+ const errorMessage = error instanceof Error ? error.message : String(error);
147
+ return {
148
+ error: errorMessage,
149
+ success: false,
150
+ };
151
+ }
152
+ }
153
+ /**
154
+ * Open CloudFormation URL in browser for role creation
155
+ *
156
+ * Validates URL is an AWS domain before opening to prevent opening malicious URLs
157
+ */
158
+ export async function openCloudFormationUrl(quickCreateUrl) {
159
+ try {
160
+ // Validate URL is from AWS before opening
161
+ const url = new URL(quickCreateUrl);
162
+ const validDomains = ['console.aws.amazon.com', 'us-east-1.console.aws.amazon.com'];
163
+ const isAwsDomain = validDomains.some(domain => url.hostname === domain || url.hostname.endsWith('.console.aws.amazon.com'));
164
+ if (!isAwsDomain) {
165
+ throw new Error(`Invalid CloudFormation URL: ${quickCreateUrl}. Expected AWS console domain.`);
166
+ }
167
+ await open(quickCreateUrl);
168
+ }
169
+ catch (error) {
170
+ if (error instanceof Error) {
171
+ throw new Error(`Failed to open browser: ${error.message}`);
172
+ }
173
+ throw new Error('Failed to open browser for CloudFormation stack creation');
174
+ }
175
+ }
176
+ /**
177
+ * Prompt user to open CloudFormation URL
178
+ */
179
+ export async function promptOpenCloudFormation(quickCreateUrl) {
180
+ const { openBrowser } = await inquirer.prompt([{
181
+ default: true,
182
+ message: 'Open CloudFormation in browser to create the cross-account role?',
183
+ name: 'openBrowser',
184
+ type: 'confirm',
185
+ }]);
186
+ return openBrowser;
187
+ }
188
+ const VERIFY_POLL_INTERVAL = 5000; // 5 seconds
189
+ const VERIFY_TIMEOUT = 300000; // 5 minutes
190
+ /**
191
+ * Wait for role verification with polling
192
+ */
193
+ export async function waitForRoleVerification(accountId, onProgress) {
194
+ const service = new HyperdriveSigV4Service();
195
+ const startTime = Date.now();
196
+ let attemptCount = 0;
197
+ while (Date.now() - startTime < VERIFY_TIMEOUT) {
198
+ attemptCount++;
199
+ const elapsed = Math.floor((Date.now() - startTime) / 1000);
200
+ try {
201
+ if (onProgress) {
202
+ onProgress(`Verifying role... (attempt ${attemptCount}, ${elapsed}s elapsed)`);
203
+ }
204
+ const result = await service.accountVerify({ accountId });
205
+ if (result.verified) {
206
+ return { message: 'Cross-account role verified successfully', verified: true };
207
+ }
208
+ // Role exists but not verified yet
209
+ if (onProgress) {
210
+ onProgress(`Role not ready yet: ${result.message || 'waiting...'} (attempt ${attemptCount}, ${elapsed}s)`);
211
+ }
212
+ }
213
+ catch (error) {
214
+ // API error - role not ready yet, continue polling
215
+ const errorMessage = error instanceof Error ? error.message : 'unknown error';
216
+ if (onProgress) {
217
+ onProgress(`Checking role... ${errorMessage} (attempt ${attemptCount}, ${elapsed}s)`);
218
+ }
219
+ }
220
+ // Wait before next poll
221
+ await new Promise(resolve => setTimeout(resolve, VERIFY_POLL_INTERVAL));
222
+ }
223
+ // Timeout reached
224
+ return {
225
+ message: `Verification timed out after ${VERIFY_TIMEOUT / 1000} seconds`,
226
+ verified: false,
227
+ };
228
+ }
@@ -0,0 +1,146 @@
1
+ import { TenantConfig } from '../services/tenant-service.js';
2
+ /**
3
+ * Options for executing the OAuth PKCE authentication flow
4
+ */
5
+ export interface AuthFlowOptions {
6
+ callbackPort?: number;
7
+ logger?: (message: string) => void;
8
+ tenantDomain: string;
9
+ timeout?: number;
10
+ }
11
+ /**
12
+ * Result of the authentication flow
13
+ */
14
+ export interface AuthResult {
15
+ error?: string;
16
+ skipped?: boolean;
17
+ success: boolean;
18
+ }
19
+ /**
20
+ * Cognito tokens received from OAuth token exchange
21
+ */
22
+ export interface CognitoTokens {
23
+ access_token: string;
24
+ expires_in: number;
25
+ id_token: string;
26
+ refresh_token: string;
27
+ token_type: string;
28
+ }
29
+ /**
30
+ * AWS credentials obtained from Cognito Identity Pool
31
+ */
32
+ export interface AWSCredentials {
33
+ accessKeyId: string;
34
+ expiration: Date;
35
+ secretAccessKey: string;
36
+ sessionToken: string;
37
+ }
38
+ /**
39
+ * Cognito configuration for storing with credentials
40
+ */
41
+ export interface CognitoConfig {
42
+ clientId: string;
43
+ domain: string;
44
+ identityPoolId: string;
45
+ userPoolId: string;
46
+ }
47
+ /**
48
+ * Complete stored credentials including tokens and AWS credentials
49
+ */
50
+ export interface StoredCredentials extends CognitoTokens {
51
+ apiUrl: string;
52
+ awsCredentials: AWSCredentials;
53
+ cognitoConfig: CognitoConfig;
54
+ obtainedAt: string;
55
+ region: string;
56
+ tenantDomain: string;
57
+ tenantId: string;
58
+ }
59
+ /**
60
+ * Generate PKCE code verifier (random base64url string)
61
+ */
62
+ export declare function generateCodeVerifier(): string;
63
+ /**
64
+ * Generate PKCE code challenge (SHA256 hash of verifier)
65
+ */
66
+ export declare function generateCodeChallenge(verifier: string): string;
67
+ /**
68
+ * Build Cognito authorization URL with PKCE parameters
69
+ */
70
+ export declare function buildAuthUrl(tenantConfig: TenantConfig, codeChallenge: string, port: number): string;
71
+ /**
72
+ * Start local HTTP server to receive OAuth callback
73
+ * Returns a promise that resolves with the authorization code
74
+ */
75
+ export declare function startCallbackServer(port: number, timeout: number): Promise<string>;
76
+ /**
77
+ * Exchange authorization code for Cognito tokens
78
+ */
79
+ export declare function exchangeCodeForTokens(tenantConfig: TenantConfig, code: string, codeVerifier: string, port: number): Promise<CognitoTokens>;
80
+ /**
81
+ * Get AWS credentials from Cognito Identity Pool
82
+ */
83
+ export declare function getAWSCredentials(tenantConfig: TenantConfig, idToken: string): Promise<AWSCredentials>;
84
+ /**
85
+ * Save credentials to domain-specific path (always required)
86
+ */
87
+ export declare function saveCredentials(credentials: StoredCredentials, domain: string): void;
88
+ /**
89
+ * Get the path to the credentials file for a domain
90
+ */
91
+ export declare function getCredentialsPath(domain: string): string;
92
+ /**
93
+ * Execute the complete OAuth PKCE authentication flow
94
+ *
95
+ * This function orchestrates the entire authentication flow:
96
+ * 1. Bootstrap tenant to get Cognito config
97
+ * 2. Generate PKCE codes
98
+ * 3. Start callback server
99
+ * 4. Open browser for authentication
100
+ * 5. Wait for callback with timeout
101
+ * 6. Exchange code for tokens
102
+ * 7. Get AWS credentials from Identity Pool
103
+ * 8. Save credentials to file
104
+ *
105
+ * @param options - Configuration options for the auth flow
106
+ * @returns AuthResult indicating success or failure
107
+ */
108
+ export declare function executeAuthFlow(options: AuthFlowOptions): Promise<AuthResult>;
109
+ /**
110
+ * Options for CI authentication flow
111
+ */
112
+ export interface CIAuthOptions {
113
+ logger?: (message: string) => void;
114
+ password: string;
115
+ tenantDomain: string;
116
+ username: string;
117
+ }
118
+ /**
119
+ * Execute CI authentication flow using USER_PASSWORD_AUTH
120
+ *
121
+ * This is for non-interactive CI/CD environments where browser-based
122
+ * OAuth is not possible. Uses Cognito's USER_PASSWORD_AUTH flow.
123
+ *
124
+ * @param options - CI authentication options
125
+ * @returns AuthResult indicating success or failure
126
+ */
127
+ export declare function executeCIAuthFlow(options: CIAuthOptions): Promise<AuthResult>;
128
+ /**
129
+ * Check if running in a CI environment
130
+ */
131
+ export declare function isCI(): boolean;
132
+ /**
133
+ * Decode a CI token into username and password
134
+ * Token format: hd_sk_{base64url(username:password)}
135
+ */
136
+ export declare function decodeToken(token: string): {
137
+ password: string;
138
+ username: string;
139
+ } | null;
140
+ /**
141
+ * Get CI credentials from HD_TOKEN environment variable
142
+ */
143
+ export declare function getCICredentials(): {
144
+ password: string;
145
+ username: string;
146
+ } | null;