@sembix/cli 1.5.1 → 1.6.1

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 (38) hide show
  1. package/COMMANDS.md +92 -1
  2. package/README.md +55 -0
  3. package/config.example.yaml +16 -0
  4. package/dist/commands/customer-portal.d.ts +3 -0
  5. package/dist/commands/customer-portal.d.ts.map +1 -0
  6. package/dist/commands/customer-portal.js +146 -0
  7. package/dist/commands/customer-portal.js.map +1 -0
  8. package/dist/commands/update.d.ts.map +1 -1
  9. package/dist/commands/update.js +80 -6
  10. package/dist/commands/update.js.map +1 -1
  11. package/dist/config-schema.d.ts +13 -0
  12. package/dist/config-schema.d.ts.map +1 -1
  13. package/dist/config-schema.js +17 -0
  14. package/dist/config-schema.js.map +1 -1
  15. package/dist/index.js +34 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/prompts/customer-portal-step.d.ts +7 -0
  18. package/dist/prompts/customer-portal-step.d.ts.map +1 -0
  19. package/dist/prompts/customer-portal-step.js +154 -0
  20. package/dist/prompts/customer-portal-step.js.map +1 -0
  21. package/dist/prompts/customer-portal.d.ts +4 -0
  22. package/dist/prompts/customer-portal.d.ts.map +1 -0
  23. package/dist/prompts/customer-portal.js +210 -0
  24. package/dist/prompts/customer-portal.js.map +1 -0
  25. package/dist/sembix-cli-1.6.1.tgz +0 -0
  26. package/dist/types.d.ts +30 -0
  27. package/dist/types.d.ts.map +1 -1
  28. package/dist/types.js +8 -0
  29. package/dist/types.js.map +1 -1
  30. package/dist/utils/config-loader.d.ts.map +1 -1
  31. package/dist/utils/config-loader.js +66 -0
  32. package/dist/utils/config-loader.js.map +1 -1
  33. package/dist/utils/studio-api.d.ts +2 -1
  34. package/dist/utils/studio-api.d.ts.map +1 -1
  35. package/dist/utils/studio-api.js +5 -36
  36. package/dist/utils/studio-api.js.map +1 -1
  37. package/package.json +12 -11
  38. package/dist/sembix-cli-1.5.1.tgz +0 -0
package/COMMANDS.md CHANGED
@@ -9,7 +9,7 @@ sembix <product> <action> [options] [arguments]
9
9
  ```
10
10
 
11
11
  - **product**: The Sembix product (e.g., `studio`)
12
- - **action**: What you want to do (e.g., `create`, `list`, `add-hub`)
12
+ - **action**: What you want to do (e.g., `create`, `list`, `add-hub`, `add-customer-portal`)
13
13
  - **options**: Flags like `--token` or `--repo`
14
14
  - **arguments**: Required or optional values (e.g., environment name)
15
15
 
@@ -1018,6 +1018,97 @@ $ sembix studio add-hub prod --repo acme-corp/deployments
1018
1018
 
1019
1019
  ---
1020
1020
 
1021
+ ### `sembix studio add-customer-portal [name]`
1022
+
1023
+ Add Customer Portal configuration to an existing environment.
1024
+
1025
+ **Usage:**
1026
+
1027
+ ```bash
1028
+ # Interactive mode
1029
+ sembix studio add-customer-portal
1030
+
1031
+ # With environment name
1032
+ sembix studio add-customer-portal acme-production
1033
+
1034
+ # With environment name and repository
1035
+ sembix studio add-customer-portal acme-production --repo acme-corp/sembix-deployment
1036
+
1037
+ # With CLI flags
1038
+ sembix studio add-customer-portal acme-production --repo acme-corp/sembix-deployment \
1039
+ --customer-portal-cloudfront-domain portal.example.com \
1040
+ --customer-portal-cloudfront-cert-arn arn:aws:acm:us-east-1:123456789012:certificate/abc123 \
1041
+ --customer-portal-hosted-zone-id Z1234567890ABC \
1042
+ --customer-portal-data-bucket-name my-portal-data-bucket
1043
+ ```
1044
+
1045
+ **Options:**
1046
+
1047
+ - `[name]` - Optional environment name (will prompt if not provided)
1048
+ - `-r, --repo <repo>` - Target repository in `owner/repo` format
1049
+ - `-t, --token <token>` - GitHub personal access token (overrides `.env`)
1050
+ - `-c, --config <path>` - YAML configuration file with customer portal settings
1051
+ - `--customer-portal-cloudfront-domain <domain>` - CloudFront domain for Customer Portal
1052
+ - `--customer-portal-cloudfront-cert-arn <arn>` - ACM certificate ARN (must be in us-east-1)
1053
+ - `--customer-portal-hosted-zone-id <id>` - Route53 hosted zone ID
1054
+ - `--customer-portal-data-bucket-name <name>` - S3 bucket name for portal data
1055
+ - `--customer-portal-cognito-password-min-length <length>` - Password minimum length (8-128)
1056
+ - `--customer-portal-log-level <level>` - Log level (debug, info, warn, error)
1057
+
1058
+ **When to use:**
1059
+
1060
+ After you've created a Studio environment and want to enable the Customer Portal for your users.
1061
+
1062
+ **What it does:**
1063
+
1064
+ 1. Selects repository and environment (or uses provided values)
1065
+ 2. Prompts for required Customer Portal configuration:
1066
+ - CloudFront domain name
1067
+ - ACM certificate ARN (must be in us-east-1 region)
1068
+ - Route53 hosted zone ID
1069
+ - S3 bucket name for customer portal data
1070
+ 3. Optionally prompts for:
1071
+ - Cognito password minimum length (8-128, default: 8)
1072
+ - Log level (debug, info, warn, error, default: info)
1073
+ 4. Adds environment secrets and variables for Customer Portal deployment
1074
+
1075
+ **Output:**
1076
+
1077
+ - Confirmation that Customer Portal configuration was added
1078
+ - Link to GitHub Actions to deploy Customer Portal
1079
+
1080
+ **Examples:**
1081
+
1082
+ ```bash
1083
+ # Interactive - provide all values through prompts
1084
+ $ sembix studio add-customer-portal
1085
+ ━━━ Repository & Environment Selection ━━━
1086
+ ? Select deployment repository: acme-corp/sembix-deployment
1087
+ ? Select environment to update: acme-production
1088
+ ━━━ Customer Portal Configuration ━━━
1089
+ ? CloudFront domain: portal.acme.com
1090
+ ? ACM certificate ARN: arn:aws:acm:us-east-1:...
1091
+ ...
1092
+
1093
+ # Quick - provide environment name and repo
1094
+ $ sembix studio add-customer-portal acme-production --repo acme-corp/deployments
1095
+ ✓ Using repository: acme-corp/deployments
1096
+ ✓ Using environment: acme-production
1097
+ ━━━ Customer Portal Configuration ━━━
1098
+ ? CloudFront domain: ...
1099
+
1100
+ # Fully automated - use CLI flags
1101
+ $ sembix studio add-customer-portal prod --repo acme-corp/deployments \
1102
+ --customer-portal-cloudfront-domain portal.acme.com \
1103
+ --customer-portal-cloudfront-cert-arn arn:aws:acm:us-east-1:123456789012:certificate/abc \
1104
+ --customer-portal-hosted-zone-id Z1234567890ABC \
1105
+ --customer-portal-data-bucket-name acme-portal-data \
1106
+ --customer-portal-cognito-password-min-length 12 \
1107
+ --customer-portal-log-level info
1108
+ ```
1109
+
1110
+ ---
1111
+
1021
1112
  ### `sembix studio list [repository]`
1022
1113
 
1023
1114
  List all Studio environments in a repository, or list all your repositories.
package/README.md CHANGED
@@ -15,6 +15,7 @@ A unified CLI for managing Sembix Studio with two main capabilities:
15
15
  - [studio create](#sembix-studio-create-name)
16
16
  - [studio update](#sembix-studio-update-name)
17
17
  - [studio add-hub](#sembix-studio-add-hub-name)
18
+ - [studio add-customer-portal](#sembix-studio-add-customer-portal-name)
18
19
  - [studio list](#sembix-studio-list-repository)
19
20
  - [Configuration](#configuration)
20
21
  - [Common Workflows](#common-workflows)
@@ -141,6 +142,7 @@ sembix studio create production --repo owner/repo --skip-hub
141
142
  - Features: `--deploy-studio-memory`, `--deploy-studio-notifications`, `--enable-bff-waf`
142
143
  - Frontend: `--github-app-client-id`, `--jira-client-id`
143
144
  - Hub: `--hub-engine-execution-role`, `--hub-consumer-role`, `--hub-admin-role`
145
+ - Customer Portal: `--customer-portal-cloudfront-domain`, `--customer-portal-cert-arn`, `--customer-portal-data-bucket-name`
144
146
 
145
147
  [See all 50+ options](#complete-studio-options)
146
148
 
@@ -173,6 +175,35 @@ Interactive prompts for Hub role ARNs (or use flags):
173
175
  - `--hub-admin-role <arn>` - Hub Admin Role ARN
174
176
  - `--hub-appconfig-role <arn>` - Hub AppConfig Role ARN (optional)
175
177
 
178
+ ### `sembix studio add-customer-portal [name]`
179
+
180
+ Add Customer Portal configuration to an existing environment.
181
+
182
+ ```bash
183
+ # Interactive mode
184
+ sembix studio add-customer-portal production --repo owner/repo
185
+
186
+ # With YAML config
187
+ sembix studio add-customer-portal production --repo owner/repo --config config.yaml
188
+
189
+ # With CLI flags
190
+ sembix studio add-customer-portal production --repo owner/repo \
191
+ --customer-portal-cloudfront-domain portal.example.com \
192
+ --customer-portal-cloudfront-cert-arn arn:aws:acm:us-east-1:123456789012:certificate/abc123 \
193
+ --customer-portal-hosted-zone-id Z1234567890ABC \
194
+ --customer-portal-data-bucket-name my-portal-data-bucket
195
+ ```
196
+
197
+ **Required Options:**
198
+ - `--customer-portal-cloudfront-domain <domain>` - CloudFront custom domain for the portal
199
+ - `--customer-portal-cloudfront-cert-arn <arn>` - ACM certificate ARN (must be in us-east-1)
200
+ - `--customer-portal-hosted-zone-id <id>` - Route53 hosted zone ID
201
+ - `--customer-portal-data-bucket-name <name>` - S3 bucket name for portal data
202
+
203
+ **Optional Options:**
204
+ - `--customer-portal-cognito-password-min-length <length>` - Minimum password length (8-128, default: 8)
205
+ - `--customer-portal-log-level <level>` - Log level: debug, info, warn, error (default: info)
206
+
176
207
  ### `sembix studio list [repository]`
177
208
 
178
209
  List GitHub Actions environments.
@@ -272,6 +303,22 @@ sembix studio create prod --repo owner/repo --config prod.yaml
272
303
  sembix studio create staging --repo owner/repo --config staging.yaml
273
304
  ```
274
305
 
306
+ **Add Customer Portal to existing environment:**
307
+ ```bash
308
+ # Interactive mode (easiest)
309
+ sembix studio add-customer-portal production --repo owner/repo
310
+
311
+ # With config file
312
+ sembix studio add-customer-portal production --repo owner/repo --config prod.yaml
313
+
314
+ # With CLI flags
315
+ sembix studio add-customer-portal production --repo owner/repo \
316
+ --customer-portal-cloudfront-domain portal.mycompany.com \
317
+ --customer-portal-cloudfront-cert-arn arn:aws:acm:us-east-1:123456789012:certificate/abc123 \
318
+ --customer-portal-hosted-zone-id Z1234567890ABC \
319
+ --customer-portal-data-bucket-name mycompany-portal-data
320
+ ```
321
+
275
322
  ---
276
323
 
277
324
  # Part 2: Environment Interaction
@@ -926,6 +973,14 @@ All options for `sembix studio create` and `sembix studio update`:
926
973
  - `--hub-appconfig-env-id <id>` - Hub AppConfig Environment ID
927
974
  - `--hub-appconfig-profile-id <id>` - Hub AppConfig Profile ID
928
975
 
976
+ **Customer Portal:**
977
+ - `--customer-portal-cloudfront-domain <domain>` - CloudFront domain for Customer Portal
978
+ - `--customer-portal-cloudfront-cert-arn <arn>` - ACM certificate ARN (must be in us-east-1)
979
+ - `--customer-portal-hosted-zone-id <id>` - Route53 hosted zone ID
980
+ - `--customer-portal-data-bucket-name <name>` - S3 bucket name for portal data
981
+ - `--customer-portal-cognito-password-min-length <length>` - Password minimum length (8-128)
982
+ - `--customer-portal-log-level <level>` - Log level (debug, info, warn, error)
983
+
929
984
  ---
930
985
 
931
986
  # License
@@ -119,3 +119,19 @@ frontend:
119
119
  # appId: app-12345
120
120
  # envId: env-67890
121
121
  # profileId: profile-abcde
122
+
123
+ # ============================================================
124
+ # CUSTOMER PORTAL CONFIGURATION (OPTIONAL - Standalone command)
125
+ # ============================================================
126
+ # Use: sembix studio add-customer-portal [environment]
127
+ #
128
+ # customerPortal:
129
+ # # Required fields
130
+ # cloudfrontDomain: portal.acme.com
131
+ # cloudfrontCertArn: arn:aws:acm:us-east-1:123456789012:certificate/xyz789
132
+ # hostedZoneId: Z9876543210ZYX
133
+ # dataBucketName: acme-customer-portal-data
134
+ #
135
+ # # Optional fields (can be omitted)
136
+ # cognitoPasswordMinLength: 12 # Integer 8-128 (default: 8)
137
+ # logLevel: info # One of: debug, info, warn, error (default: info)
@@ -0,0 +1,3 @@
1
+ import type { CommandOptions } from '../types.js';
2
+ export declare function addCustomerPortal(githubToken?: string, environmentName?: string, options?: CommandOptions): Promise<void>;
3
+ //# sourceMappingURL=customer-portal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer-portal.d.ts","sourceRoot":"","sources":["../../src/commands/customer-portal.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAwB,cAAc,EAAE,MAAM,aAAa,CAAC;AAGxE,wBAAsB,iBAAiB,CACrC,WAAW,CAAC,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAkEf"}
@@ -0,0 +1,146 @@
1
+ import { confirm } from '@inquirer/prompts';
2
+ import chalk from 'chalk';
3
+ import { GitHubClient } from '../utils/github.js';
4
+ import { promptCustomerPortal } from '../prompts/customer-portal.js';
5
+ import * as ui from '../utils/ui.js';
6
+ import { loadConfigFile, mergeConfig, getConfigFilePath } from '../utils/config-loader.js';
7
+ export async function addCustomerPortal(githubToken, environmentName, options = {}) {
8
+ try {
9
+ ui.banner();
10
+ console.log(chalk.white(' Add Customer Portal configuration to an environment'));
11
+ console.log();
12
+ const githubClient = new GitHubClient(githubToken);
13
+ // Load config file if provided
14
+ const configFilePath = getConfigFilePath(options);
15
+ let configFile;
16
+ if (configFilePath) {
17
+ const configResult = await loadConfigFile(configFilePath);
18
+ configFile = configResult?.data;
19
+ }
20
+ // Merge config file with CLI flags
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ const mergedConfig = mergeConfig(configFile, options);
23
+ // Extract customer portal config from merged config
24
+ const customerPortalFromConfig = mergedConfig.customerPortal;
25
+ // Create cliFlags object with customer portal fields for promptIfMissing helpers
26
+ const cliFlags = {
27
+ ...options,
28
+ customerPortalCloudfrontDomain: customerPortalFromConfig?.cloudfrontDomain,
29
+ customerPortalCloudfrontCertArn: customerPortalFromConfig?.cloudfrontCertArn,
30
+ customerPortalHostedZoneId: customerPortalFromConfig?.hostedZoneId,
31
+ customerPortalDataBucketName: customerPortalFromConfig?.dataBucketName,
32
+ customerPortalCognitoPasswordMinLength: customerPortalFromConfig?.cognitoPasswordMinLength,
33
+ customerPortalLogLevel: customerPortalFromConfig?.logLevel,
34
+ };
35
+ // Collect configuration through interactive prompts (passing merged config for promptIfMissing)
36
+ const config = await promptCustomerPortal(githubClient, environmentName, options.repo, cliFlags);
37
+ // Confirm before proceeding
38
+ ui.section('Configuration Summary');
39
+ displayConfigurationSummary(config);
40
+ const proceed = await confirm({
41
+ message: 'Update environment with Customer Portal configuration?',
42
+ default: true,
43
+ });
44
+ if (!proceed) {
45
+ ui.warning('Customer Portal configuration cancelled.');
46
+ return;
47
+ }
48
+ // Execute customer portal configuration
49
+ await executeCustomerPortalConfiguration(githubClient, config);
50
+ // Display success message
51
+ displaySuccessMessage(config);
52
+ }
53
+ catch (error) {
54
+ const message = error instanceof Error ? error.message : 'Unknown error';
55
+ ui.error(`Customer Portal configuration failed: ${message}`);
56
+ process.exit(1);
57
+ }
58
+ }
59
+ async function executeCustomerPortalConfiguration(githubClient, config) {
60
+ const { owner, repo } = config.repository;
61
+ // Validate environment exists
62
+ const spinner = ui.spinner('Validating environment...');
63
+ try {
64
+ const exists = await githubClient.environmentExists(owner, repo, config.environmentName);
65
+ if (!exists) {
66
+ spinner.fail(`Environment '${config.environmentName}' does not exist`);
67
+ throw new Error(`Environment '${config.environmentName}' not found in ${owner}/${repo}`);
68
+ }
69
+ spinner.succeed(`Environment '${config.environmentName}' validated`);
70
+ }
71
+ catch (error) {
72
+ const message = error instanceof Error ? error.message : 'Unknown error';
73
+ spinner.fail(`Validation failed: ${message}`);
74
+ throw error;
75
+ }
76
+ // Add Customer Portal secrets (required fields)
77
+ const secretsSpinner = ui.spinner('Adding Customer Portal secrets...');
78
+ try {
79
+ await githubClient.createEnvironmentSecrets(owner, repo, config.environmentName, {
80
+ CUSTOMER_PORTAL_CLOUDFRONT_DOMAIN: config.cloudfrontDomain,
81
+ CUSTOMER_PORTAL_CF_ARN: config.cloudfrontCertArn,
82
+ CUSTOMER_PORTAL_HOSTED_ZONE_ID: config.hostedZoneId,
83
+ CUSTOMER_PORTAL_DATA_BUCKET_NAME: config.dataBucketName,
84
+ });
85
+ secretsSpinner.succeed('Customer Portal secrets added');
86
+ }
87
+ catch (error) {
88
+ const message = error instanceof Error ? error.message : 'Unknown error';
89
+ secretsSpinner.fail(`Failed to add Customer Portal secrets: ${message}`);
90
+ throw error;
91
+ }
92
+ // Add Customer Portal variables (optional fields)
93
+ if (config.cognitoPasswordMinLength !== undefined || config.logLevel !== undefined) {
94
+ const varsSpinner = ui.spinner('Adding Customer Portal variables...');
95
+ try {
96
+ const variables = {};
97
+ if (config.cognitoPasswordMinLength !== undefined) {
98
+ variables.CUSTOMER_PORTAL_COGNITO_PASSWORD_MIN_LENGTH = config.cognitoPasswordMinLength.toString();
99
+ }
100
+ if (config.logLevel !== undefined) {
101
+ variables.CUSTOMER_PORTAL_LOG_LEVEL = config.logLevel;
102
+ }
103
+ await githubClient.createOrUpdateEnvironmentVariables(owner, repo, config.environmentName, variables);
104
+ varsSpinner.succeed('Customer Portal variables added');
105
+ }
106
+ catch (error) {
107
+ const message = error instanceof Error ? error.message : 'Unknown error';
108
+ varsSpinner.fail(`Failed to add Customer Portal variables: ${message}`);
109
+ throw error;
110
+ }
111
+ }
112
+ }
113
+ function displayConfigurationSummary(config) {
114
+ const data = {
115
+ 'Repository': `${config.repository.owner}/${config.repository.repo}`,
116
+ 'Environment': config.environmentName,
117
+ 'CloudFront Domain': config.cloudfrontDomain,
118
+ 'CloudFront Certificate': config.cloudfrontCertArn,
119
+ 'Route53 Zone ID': config.hostedZoneId,
120
+ 'Data Bucket': config.dataBucketName,
121
+ };
122
+ if (config.cognitoPasswordMinLength !== undefined) {
123
+ data['Password Min Length'] = config.cognitoPasswordMinLength.toString();
124
+ }
125
+ if (config.logLevel !== undefined) {
126
+ data['Log Level'] = config.logLevel;
127
+ }
128
+ ui.table(data);
129
+ }
130
+ function displaySuccessMessage(config) {
131
+ const { owner, repo } = config.repository;
132
+ console.log();
133
+ ui.success('Customer Portal configuration updated successfully!');
134
+ console.log();
135
+ ui.section('Next Steps');
136
+ console.log(ui.highlight('Deploy Customer Portal'));
137
+ console.log();
138
+ console.log(` 1. Go to GitHub Actions: ${ui.link(`https://github.com/${owner}/${repo}/actions`)}`);
139
+ console.log(` 2. Select the Customer Portal deployment workflow`);
140
+ console.log(` 3. Choose environment: ${ui.code(config.environmentName)}`);
141
+ console.log(` 4. Run the workflow to deploy Customer Portal`);
142
+ console.log();
143
+ console.log(` ${ui.dim('Your environment now has Customer Portal configured!')}`);
144
+ console.log();
145
+ }
146
+ //# sourceMappingURL=customer-portal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer-portal.js","sourceRoot":"","sources":["../../src/commands/customer-portal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE3F,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAoB,EACpB,eAAwB,EACxB,UAA0B,EAAE;IAE5B,IAAI,CAAC;QACH,EAAE,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC,CAAC;QAClF,OAAO,CAAC,GAAG,EAAE,CAAC;QAEd,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC;QAEnD,+BAA+B;QAC/B,MAAM,cAAc,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,UAAU,CAAC;QACf,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,cAAc,CAAC,CAAC;YAC1D,UAAU,GAAG,YAAY,EAAE,IAAI,CAAC;QAClC,CAAC;QAED,mCAAmC;QACnC,8DAA8D;QAC9D,MAAM,YAAY,GAAG,WAAW,CAAC,UAAU,EAAE,OAAO,CAAQ,CAAC;QAE7D,oDAAoD;QACpD,MAAM,wBAAwB,GAAG,YAAY,CAAC,cAAc,CAAC;QAE7D,iFAAiF;QACjF,MAAM,QAAQ,GAAmB;YAC/B,GAAG,OAAO;YACV,8BAA8B,EAAE,wBAAwB,EAAE,gBAAgB;YAC1E,+BAA+B,EAAE,wBAAwB,EAAE,iBAAiB;YAC5E,0BAA0B,EAAE,wBAAwB,EAAE,YAAY;YAClE,4BAA4B,EAAE,wBAAwB,EAAE,cAAc;YACtE,sCAAsC,EAAE,wBAAwB,EAAE,wBAAwB;YAC1F,sBAAsB,EAAE,wBAAwB,EAAE,QAAQ;SAC3D,CAAC;QAEF,gGAAgG;QAChG,MAAM,MAAM,GAAG,MAAM,oBAAoB,CACvC,YAAY,EACZ,eAAe,EACf,OAAO,CAAC,IAAI,EACZ,QAAQ,CACT,CAAC;QAEF,4BAA4B;QAC5B,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QACpC,2BAA2B,CAAC,MAAM,CAAC,CAAC;QAEpC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC;YAC5B,OAAO,EAAE,wDAAwD;YACjE,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,wCAAwC;QACxC,MAAM,kCAAkC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAE/D,0BAA0B;QAC1B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,EAAE,CAAC,KAAK,CAAC,yCAAyC,OAAO,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kCAAkC,CAC/C,YAA0B,EAC1B,MAA4B;IAE5B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;IAE1C,8BAA8B;IAC9B,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;QACzF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,eAAe,kBAAkB,CAAC,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,gBAAgB,MAAM,CAAC,eAAe,kBAAkB,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,CAAC,OAAO,CAAC,gBAAgB,MAAM,CAAC,eAAe,aAAa,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,OAAO,CAAC,IAAI,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAC;QAC9C,MAAM,KAAK,CAAC;IACd,CAAC;IAED,gDAAgD;IAChD,MAAM,cAAc,GAAG,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,MAAM,YAAY,CAAC,wBAAwB,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,eAAe,EAAE;YAC/E,iCAAiC,EAAE,MAAM,CAAC,gBAAgB;YAC1D,sBAAsB,EAAE,MAAM,CAAC,iBAAiB;YAChD,8BAA8B,EAAE,MAAM,CAAC,YAAY;YACnD,gCAAgC,EAAE,MAAM,CAAC,cAAc;SACxD,CAAC,CAAC;QACH,cAAc,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,cAAc,CAAC,IAAI,CAAC,0CAA0C,OAAO,EAAE,CAAC,CAAC;QACzE,MAAM,KAAK,CAAC;IACd,CAAC;IAED,kDAAkD;IAClD,IAAI,MAAM,CAAC,wBAAwB,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnF,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC;QACtE,IAAI,CAAC;YACH,MAAM,SAAS,GAA2B,EAAE,CAAC;YAE7C,IAAI,MAAM,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;gBAClD,SAAS,CAAC,2CAA2C,GAAG,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,CAAC;YACrG,CAAC;YACD,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAClC,SAAS,CAAC,yBAAyB,GAAG,MAAM,CAAC,QAAQ,CAAC;YACxD,CAAC;YAED,MAAM,YAAY,CAAC,kCAAkC,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;YACtG,WAAW,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACzE,WAAW,CAAC,IAAI,CAAC,4CAA4C,OAAO,EAAE,CAAC,CAAC;YACxE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,2BAA2B,CAAC,MAA4B;IAC/D,MAAM,IAAI,GAA2B;QACnC,YAAY,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE;QACpE,aAAa,EAAE,MAAM,CAAC,eAAe;QACrC,mBAAmB,EAAE,MAAM,CAAC,gBAAgB;QAC5C,wBAAwB,EAAE,MAAM,CAAC,iBAAiB;QAClD,iBAAiB,EAAE,MAAM,CAAC,YAAY;QACtC,aAAa,EAAE,MAAM,CAAC,cAAc;KACrC,CAAC;IAEF,IAAI,MAAM,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;QAClD,IAAI,CAAC,qBAAqB,CAAC,GAAG,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,CAAC;IAC3E,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,IAAI,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC;AAED,SAAS,qBAAqB,CAAC,MAA4B;IACzD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;IAE1C,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,EAAE,CAAC,OAAO,CAAC,qDAAqD,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAEzB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,CAAC,IAAI,CAAC,sBAAsB,KAAK,IAAI,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACpG,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,sDAAsD,CAAC,EAAE,CAAC,CAAC;IACnF,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA0B,cAAc,EAAgB,MAAM,aAAa,CAAC;AAIxF,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAyIf"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA0B,cAAc,EAAoC,MAAM,aAAa,CAAC;AAI5G,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA4If"}
@@ -3,6 +3,7 @@ import chalk from 'chalk';
3
3
  import { GitHubClient } from '../utils/github.js';
4
4
  import { promptEnvironmentSetup } from '../prompts/environment-setup.js';
5
5
  import { promptHubIntegrationStep } from '../prompts/hub-integration-step.js';
6
+ import { promptCustomerPortalStep } from '../prompts/customer-portal-step.js';
6
7
  import * as ui from '../utils/ui.js';
7
8
  import { loadConfigFile, displayConfigErrors, mergeConfig, getConfigFilePath } from '../utils/config-loader.js';
8
9
  export async function updateEnvironment(githubToken, environmentName, options = {}) {
@@ -90,9 +91,11 @@ export async function updateEnvironment(githubToken, environmentName, options =
90
91
  );
91
92
  // Hub Integration
92
93
  const hubConfig = await promptHubIntegrationStep(options.skipHub);
94
+ // Customer Portal Integration
95
+ const customerPortalConfig = await promptCustomerPortalStep(options.skipCustomerPortal);
93
96
  // Confirm before proceeding
94
97
  ui.section('Configuration Summary');
95
- displayConfigurationSummary(config, hubConfig);
98
+ displayConfigurationSummary(config, hubConfig, customerPortalConfig);
96
99
  const proceed = await confirm({
97
100
  message: 'Update environment with this configuration?',
98
101
  default: true,
@@ -102,7 +105,7 @@ export async function updateEnvironment(githubToken, environmentName, options =
102
105
  return;
103
106
  }
104
107
  // Execute full update
105
- await executeFullEnvironmentUpdate(githubClient, config, hubConfig);
108
+ await executeFullEnvironmentUpdate(githubClient, config, hubConfig, customerPortalConfig);
106
109
  console.log();
107
110
  ui.success('Environment updated successfully!');
108
111
  console.log();
@@ -139,6 +142,15 @@ async function executeEnvironmentUpdate(githubClient, owner, repo, environmentNa
139
142
  variables.VITE_GITHUB_APP_NAME = config.frontend.githubAppName;
140
143
  if (config.frontend?.jiraClientId)
141
144
  variables.VITE_JIRA_CLIENT_ID = config.frontend.jiraClientId;
145
+ // Customer Portal optional variables
146
+ if (config.customerPortal) {
147
+ if (config.customerPortal.cognitoPasswordMinLength !== undefined) {
148
+ variables.CUSTOMER_PORTAL_COGNITO_PASSWORD_MIN_LENGTH = config.customerPortal.cognitoPasswordMinLength.toString();
149
+ }
150
+ if (config.customerPortal.logLevel !== undefined) {
151
+ variables.CUSTOMER_PORTAL_LOG_LEVEL = config.customerPortal.logLevel;
152
+ }
153
+ }
142
154
  if (Object.keys(variables).length > 0) {
143
155
  const spinner = ui.spinner('Updating environment variables...');
144
156
  try {
@@ -272,6 +284,21 @@ async function executeEnvironmentUpdate(githubClient, owner, repo, environmentNa
272
284
  }
273
285
  }
274
286
  }
287
+ // Customer Portal
288
+ if (config.customerPortal) {
289
+ if (config.customerPortal.cloudfrontDomain) {
290
+ secrets.CUSTOMER_PORTAL_CLOUDFRONT_DOMAIN = config.customerPortal.cloudfrontDomain;
291
+ }
292
+ if (config.customerPortal.cloudfrontCertArn) {
293
+ secrets.CUSTOMER_PORTAL_CF_ARN = config.customerPortal.cloudfrontCertArn;
294
+ }
295
+ if (config.customerPortal.hostedZoneId) {
296
+ secrets.CUSTOMER_PORTAL_HOSTED_ZONE_ID = config.customerPortal.hostedZoneId;
297
+ }
298
+ if (config.customerPortal.dataBucketName) {
299
+ secrets.CUSTOMER_PORTAL_DATA_BUCKET_NAME = config.customerPortal.dataBucketName;
300
+ }
301
+ }
275
302
  if (Object.keys(secrets).length > 0) {
276
303
  const spinner = ui.spinner('Updating environment secrets...');
277
304
  try {
@@ -290,14 +317,14 @@ async function executeEnvironmentUpdate(githubClient, owner, repo, environmentNa
290
317
  /**
291
318
  * Execute full environment update (same as create, but for existing environment)
292
319
  */
293
- async function executeFullEnvironmentUpdate(githubClient, config, hubConfig) {
320
+ async function executeFullEnvironmentUpdate(githubClient, config, hubConfig, customerPortalConfig) {
294
321
  // This is essentially the same as executeEnvironmentSetup from setup.ts, but without creating the environment
295
322
  // We reuse the same logic to update all fields
296
323
  const { owner, repo } = config.repository;
297
324
  // Update environment variables
298
325
  let spinner = ui.spinner('Updating environment variables...');
299
326
  try {
300
- await githubClient.createOrUpdateEnvironmentVariables(owner, repo, config.environmentName, {
327
+ const variables = {
301
328
  TF_BUCKET_NAME: config.terraformStateBucket,
302
329
  CLOUDFRONT_DOMAIN: config.tls.cloudfrontDomain,
303
330
  DEPLOY_SEMBIX_STUDIO_MEMORY: config.features.deploySembixStudioMemory ? 'true' : 'false',
@@ -306,7 +333,17 @@ async function executeFullEnvironmentUpdate(githubClient, config, hubConfig) {
306
333
  VITE_GITHUB_APP_CLIENT_ID: config.frontend.githubAppClientId,
307
334
  VITE_GITHUB_APP_NAME: config.frontend.githubAppName,
308
335
  VITE_JIRA_CLIENT_ID: config.frontend.jiraClientId,
309
- });
336
+ };
337
+ // Add customer portal optional variables if provided
338
+ if (customerPortalConfig) {
339
+ if (customerPortalConfig.cognitoPasswordMinLength !== undefined) {
340
+ variables.CUSTOMER_PORTAL_COGNITO_PASSWORD_MIN_LENGTH = customerPortalConfig.cognitoPasswordMinLength.toString();
341
+ }
342
+ if (customerPortalConfig.logLevel !== undefined) {
343
+ variables.CUSTOMER_PORTAL_LOG_LEVEL = customerPortalConfig.logLevel;
344
+ }
345
+ }
346
+ await githubClient.createOrUpdateEnvironmentVariables(owner, repo, config.environmentName, variables);
310
347
  spinner.succeed('Environment variables updated');
311
348
  }
312
349
  catch (error) {
@@ -424,6 +461,23 @@ async function executeFullEnvironmentUpdate(githubClient, config, hubConfig) {
424
461
  throw error;
425
462
  }
426
463
  }
464
+ // Add Customer Portal secrets (if provided)
465
+ if (customerPortalConfig) {
466
+ spinner = ui.spinner('Updating Customer Portal secrets...');
467
+ try {
468
+ await githubClient.createEnvironmentSecrets(owner, repo, config.environmentName, {
469
+ CUSTOMER_PORTAL_CLOUDFRONT_DOMAIN: customerPortalConfig.cloudfrontDomain,
470
+ CUSTOMER_PORTAL_CF_ARN: customerPortalConfig.cloudfrontCertArn,
471
+ CUSTOMER_PORTAL_HOSTED_ZONE_ID: customerPortalConfig.hostedZoneId,
472
+ CUSTOMER_PORTAL_DATA_BUCKET_NAME: customerPortalConfig.dataBucketName,
473
+ });
474
+ spinner.succeed('Customer Portal secrets updated');
475
+ }
476
+ catch (error) {
477
+ spinner.fail(`Failed to update Customer Portal secrets: ${error.message}`);
478
+ throw error;
479
+ }
480
+ }
427
481
  }
428
482
  function displayUpdateSummary(config) {
429
483
  console.log(ui.dim('The following configuration will be updated:'));
@@ -460,6 +514,15 @@ function displayUpdateSummary(config) {
460
514
  summary.push(`• Hub Integration: Configured`);
461
515
  }
462
516
  }
517
+ if (config.customerPortal) {
518
+ const hasRequiredFields = config.customerPortal.cloudfrontDomain ||
519
+ config.customerPortal.cloudfrontCertArn ||
520
+ config.customerPortal.hostedZoneId ||
521
+ config.customerPortal.dataBucketName;
522
+ if (hasRequiredFields) {
523
+ summary.push(`• Customer Portal: Configured`);
524
+ }
525
+ }
463
526
  if (summary.length === 0) {
464
527
  console.log(ui.dim(' No specific fields to update'));
465
528
  }
@@ -468,7 +531,7 @@ function displayUpdateSummary(config) {
468
531
  }
469
532
  console.log();
470
533
  }
471
- function displayConfigurationSummary(config, hubConfig) {
534
+ function displayConfigurationSummary(config, hubConfig, customerPortalConfig) {
472
535
  const summary = {
473
536
  'Repository': `${config.repository.owner}/${config.repository.repo}`,
474
537
  'Environment': config.environmentName,
@@ -493,6 +556,17 @@ function displayConfigurationSummary(config, hubConfig) {
493
556
  summary['Hub Integration'] = 'Configured';
494
557
  }
495
558
  }
559
+ // Add Customer Portal summary if provided
560
+ if (customerPortalConfig) {
561
+ summary['Customer Portal Domain'] = customerPortalConfig.cloudfrontDomain;
562
+ summary['Customer Portal Bucket'] = customerPortalConfig.dataBucketName;
563
+ if (customerPortalConfig.cognitoPasswordMinLength) {
564
+ summary['Portal Password Min Length'] = customerPortalConfig.cognitoPasswordMinLength.toString();
565
+ }
566
+ if (customerPortalConfig.logLevel) {
567
+ summary['Portal Log Level'] = customerPortalConfig.logLevel;
568
+ }
569
+ }
496
570
  ui.table(summary);
497
571
  }
498
572
  //# sourceMappingURL=update.js.map