@tamyla/clodo-framework 3.1.21 → 3.1.23
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/CHANGELOG.md +17 -0
- package/README.md +283 -1
- package/dist/{bin → cli}/clodo-service.js +47 -15
- package/dist/cli/commands/assess.js +183 -0
- package/dist/{bin → cli}/commands/create.js +5 -5
- package/dist/{bin → cli}/commands/deploy.js +122 -90
- package/dist/{bin → cli}/commands/diagnose.js +5 -5
- package/dist/cli/commands/helpers/deployment-ui.js +138 -0
- package/dist/cli/commands/helpers/deployment-verification.js +250 -0
- package/dist/cli/commands/helpers/error-recovery.js +80 -0
- package/dist/cli/commands/helpers/resource-detection.js +113 -0
- package/dist/{bin → cli}/commands/helpers.js +0 -28
- package/dist/cli/commands/init-config.js +57 -0
- package/dist/{bin → cli}/commands/update.js +5 -5
- package/dist/{bin → cli}/commands/validate.js +5 -5
- package/dist/cli/security-cli.js +118 -0
- package/dist/config/FeatureManager.js +6 -0
- package/dist/config/clodo-create.example.json +26 -0
- package/dist/config/clodo-deploy.example.json +41 -0
- package/dist/config/clodo-update.example.json +46 -0
- package/dist/config/clodo-validate.example.json +41 -0
- package/dist/config/customers/template/development.env.template +37 -0
- package/dist/config/customers/template/production.env.template +39 -0
- package/dist/config/customers/template/staging.env.template +37 -0
- package/dist/config/customers.js +28 -26
- package/dist/config/domain-examples/README.md +464 -0
- package/dist/config/domain-examples/environment-mapped.json +168 -0
- package/dist/config/domain-examples/multi-domain.json +144 -0
- package/dist/config/domain-examples/single-domain.json +50 -0
- package/dist/config/examples +12 -0
- package/dist/config/features.js +61 -0
- package/dist/config/staging-deployment.json +60 -0
- package/dist/config/validation-config.json +347 -0
- package/dist/deployment/wrangler-deployer.js +1 -1
- package/dist/{bin → lib}/deployment/modules/DeploymentOrchestrator.js +2 -2
- package/dist/{bin → lib}/deployment/modules/EnvironmentManager.js +2 -2
- package/dist/lib/deployment/orchestration/EnterpriseOrchestrator.js +21 -0
- package/dist/lib/shared/cache/configuration-cache.js +82 -0
- package/dist/{bin → lib}/shared/cloudflare/domain-discovery.js +1 -1
- package/dist/{bin → lib}/shared/cloudflare/domain-manager.js +1 -1
- package/dist/{bin → lib}/shared/cloudflare/index.js +1 -1
- package/dist/{bin → lib}/shared/cloudflare/ops.js +10 -8
- package/dist/{bin → lib}/shared/config/ConfigurationManager.js +23 -1
- package/dist/{bin → lib}/shared/config/command-config-manager.js +19 -3
- package/dist/{bin → lib}/shared/config/index.js +1 -1
- package/dist/{bin → lib}/shared/deployment/credential-collector.js +30 -7
- package/dist/lib/shared/deployment/index.js +10 -0
- package/dist/lib/shared/deployment/rollback-manager.js +7 -0
- package/dist/lib/shared/deployment/utilities/d1-error-recovery.js +177 -0
- package/dist/{bin → lib}/shared/deployment/validator.js +40 -10
- package/dist/lib/shared/deployment/workflows/deployment-summary.js +214 -0
- package/dist/lib/shared/deployment/workflows/interactive-confirmation.js +188 -0
- package/dist/lib/shared/deployment/workflows/interactive-database-workflow.js +234 -0
- package/dist/lib/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
- package/dist/lib/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
- package/dist/lib/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
- package/dist/lib/shared/deployment/workflows/interactive-validation.js +218 -0
- package/dist/lib/shared/error-handling/error-classifier.js +46 -0
- package/dist/{bin → lib}/shared/monitoring/health-checker.js +129 -1
- package/dist/{bin → lib}/shared/monitoring/memory-manager.js +17 -6
- package/dist/{bin → lib}/shared/routing/domain-router.js +1 -1
- package/dist/lib/shared/utils/deployment-validator.js +97 -0
- package/dist/{bin → lib}/shared/utils/formatters.js +10 -0
- package/dist/{bin → lib}/shared/utils/index.js +13 -1
- package/dist/{bin → lib}/shared/utils/interactive-prompts.js +34 -18
- package/dist/{bin → lib}/shared/utils/progress-manager.js +2 -2
- package/dist/lib/shared/utils/progress-spinner.js +53 -0
- package/dist/lib/shared/utils/sensitive-redactor.js +91 -0
- package/dist/{bin → lib}/shared/validation/ValidationRegistry.js +1 -1
- package/dist/migration/MigrationAdapters.js +50 -4
- package/dist/orchestration/cross-domain-coordinator.js +5 -5
- package/dist/orchestration/multi-domain-orchestrator.js +63 -22
- package/dist/security/index.js +2 -2
- package/dist/security/patterns/insecure-patterns.js +1 -1
- package/dist/service-management/ConfirmationEngine.js +1 -1
- package/dist/service-management/ErrorTracker.js +1 -1
- package/dist/service-management/InputCollector.js +1 -1
- package/dist/service-management/ServiceCreator.js +11 -255
- package/dist/service-management/ServiceOrchestrator.js +0 -2
- package/dist/service-management/generators/testing/UnitTestsGenerator.js +4 -4
- package/dist/service-management/index.js +1 -1
- package/dist/utils/cloudflare/ops.js +1 -1
- package/dist/utils/constants.js +102 -0
- package/dist/utils/deployment/wrangler-config-manager.js +215 -48
- package/dist/utils/file-manager.js +1 -1
- package/dist/utils/formatters.js +1 -1
- package/dist/utils/framework-config.js +2 -2
- package/dist/utils/interactive-prompts.js +10 -59
- package/dist/utils/logger.js +1 -1
- package/dist/version/VersionDetector.js +99 -9
- package/dist/worker/integration.js +1 -1
- package/package.json +10 -10
- package/dist/bin/clodo-service-old.js +0 -868
- package/dist/bin/clodo-service-test.js +0 -10
- package/dist/bin/commands/assess.js +0 -91
- package/dist/bin/database/enterprise-db-manager.js +0 -457
- package/dist/bin/deployment/enterprise-deploy.js +0 -877
- package/dist/bin/deployment/master-deploy.js +0 -1376
- package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
- package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
- package/dist/bin/deployment/test-interactive-utils.js +0 -66
- package/dist/bin/portfolio/portfolio-manager.js +0 -487
- package/dist/bin/security/security-cli.js +0 -108
- package/dist/bin/service-management/create-service.js +0 -122
- package/dist/bin/service-management/init-service.js +0 -79
- package/dist/bin/shared/deployment/index.js +0 -10
- package/dist/bin/shared/deployment/rollback-manager.js +0 -523
- package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
- package/dist/service-management/ServiceInitializer.js +0 -453
- /package/dist/{bin → lib}/database/deployment-db-manager.js +0 -0
- /package/dist/{bin → lib}/database/wrangler-d1-manager.js +0 -0
- /package/dist/{bin → lib}/deployment/modules/DeploymentConfiguration.js +0 -0
- /package/dist/{bin → lib}/deployment/modules/MonitoringIntegration.js +0 -0
- /package/dist/{bin → lib}/deployment/modules/ValidationManager.js +0 -0
- /package/dist/{bin → lib}/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -0
- /package/dist/{bin → lib}/deployment/orchestration/PortfolioOrchestrator.js +0 -0
- /package/dist/{bin → lib}/deployment/orchestration/SingleServiceOrchestrator.js +0 -0
- /package/dist/{bin → lib}/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -0
- /package/dist/{bin → lib}/shared/config/cache.js +0 -0
- /package/dist/{bin → lib}/shared/config/cloudflare-service-validator.js +0 -0
- /package/dist/{bin → lib}/shared/config/manager.js +0 -0
- /package/dist/{bin → lib}/shared/config/manifest-loader.js +0 -0
- /package/dist/{bin → lib}/shared/database/connection-manager.js +0 -0
- /package/dist/{bin → lib}/shared/database/index.js +0 -0
- /package/dist/{bin → lib}/shared/database/orchestrator.js +0 -0
- /package/dist/{bin → lib}/shared/deployment/auditor.js +0 -0
- /package/dist/{bin → lib}/shared/index.js +0 -0
- /package/dist/{bin → lib}/shared/logging/Logger.js +0 -0
- /package/dist/{bin → lib}/shared/monitoring/index.js +0 -0
- /package/dist/{bin → lib}/shared/monitoring/production-monitor.js +0 -0
- /package/dist/{bin → lib}/shared/production-tester/api-tester.js +0 -0
- /package/dist/{bin → lib}/shared/production-tester/auth-tester.js +0 -0
- /package/dist/{bin → lib}/shared/production-tester/core.js +0 -0
- /package/dist/{bin → lib}/shared/production-tester/database-tester.js +0 -0
- /package/dist/{bin → lib}/shared/production-tester/index.js +0 -0
- /package/dist/{bin → lib}/shared/production-tester/load-tester.js +0 -0
- /package/dist/{bin → lib}/shared/production-tester/performance-tester.js +0 -0
- /package/dist/{bin → lib}/shared/security/api-token-manager.js +0 -0
- /package/dist/{bin → lib}/shared/security/index.js +0 -0
- /package/dist/{bin → lib}/shared/security/secret-generator.js +0 -0
- /package/dist/{bin → lib}/shared/security/secure-token-manager.js +0 -0
- /package/dist/{bin → lib}/shared/utils/ErrorHandler.js +0 -0
- /package/dist/{bin → lib}/shared/utils/cli-options.js +0 -0
- /package/dist/{bin → lib}/shared/utils/config-loader.js +0 -0
- /package/dist/{bin → lib}/shared/utils/error-recovery.js +0 -0
- /package/dist/{bin → lib}/shared/utils/file-manager.js +0 -0
- /package/dist/{bin → lib}/shared/utils/graceful-shutdown-manager.js +0 -0
- /package/dist/{bin → lib}/shared/utils/interactive-utils.js +0 -0
- /package/dist/{bin → lib}/shared/utils/output-formatter.js +0 -0
- /package/dist/{bin → lib}/shared/utils/rate-limiter.js +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment Summary Module
|
|
3
|
+
*
|
|
4
|
+
* Provides reusable deployment success/failure summary reporting.
|
|
5
|
+
* Extracted from enterprise-deployment/master-deploy.js for modularity.
|
|
6
|
+
*
|
|
7
|
+
* @module deployment-summary
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Deployment Summary Manager
|
|
12
|
+
* Handles success summaries, enterprise summaries, and deployment statistics
|
|
13
|
+
*/
|
|
14
|
+
export class DeploymentSummary {
|
|
15
|
+
/**
|
|
16
|
+
* Display standard deployment success summary
|
|
17
|
+
*
|
|
18
|
+
* @param {Object} deploymentState - Deployment state object
|
|
19
|
+
* @param {Object} config - Deployment configuration
|
|
20
|
+
* @param {Object} options - Display options
|
|
21
|
+
* @returns {Promise<void>}
|
|
22
|
+
*/
|
|
23
|
+
static async displaySuccessSummary(deploymentState, config, options = {}) {
|
|
24
|
+
const duration = (Date.now() - deploymentState.startTime.getTime()) / 1000;
|
|
25
|
+
console.log('\n🎉 DEPLOYMENT SUCCESSFUL!');
|
|
26
|
+
console.log('=========================');
|
|
27
|
+
console.log(`\n📊 Summary:`);
|
|
28
|
+
console.log(` 🆔 Deployment ID: ${deploymentState.deploymentId}`);
|
|
29
|
+
console.log(` 🌐 Domain: ${config.domain}`);
|
|
30
|
+
console.log(` ⏱️ Duration: ${duration.toFixed(1)}s`);
|
|
31
|
+
console.log(` 🔑 Secrets: ${Object.keys(config.secrets.keys).length} deployed`);
|
|
32
|
+
this.displayEndpoints(config);
|
|
33
|
+
this.displayDistributionFiles(config);
|
|
34
|
+
this.displayNextSteps(config);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Display enterprise deployment success summary
|
|
39
|
+
*
|
|
40
|
+
* @param {Object} deploymentState - Deployment state object
|
|
41
|
+
* @param {Object} config - Deployment configuration
|
|
42
|
+
* @param {Object} frameworkPaths - Framework paths configuration
|
|
43
|
+
* @param {Object} enterpriseModules - Enterprise modules
|
|
44
|
+
* @returns {Promise<void>}
|
|
45
|
+
*/
|
|
46
|
+
static async displayEnterpriseSuccessSummary(deploymentState, config, frameworkPaths, enterpriseModules) {
|
|
47
|
+
console.log('\n🎉 ENTERPRISE DEPLOYMENT SUCCESSFUL!');
|
|
48
|
+
console.log('====================================');
|
|
49
|
+
const duration = (new Date() - deploymentState.startTime) / 1000;
|
|
50
|
+
this.displayDeploymentStats(deploymentState, config, duration);
|
|
51
|
+
this.displayEnterpriseEndpoints(config);
|
|
52
|
+
this.displayGeneratedFiles(frameworkPaths, config, deploymentState);
|
|
53
|
+
this.displayEnabledFeatures(config);
|
|
54
|
+
|
|
55
|
+
// End audit session successfully
|
|
56
|
+
if (enterpriseModules?.auditor) {
|
|
57
|
+
enterpriseModules.auditor.endDeploymentAudit(deploymentState.deploymentId, 'success', {
|
|
58
|
+
duration,
|
|
59
|
+
endpoints: 4,
|
|
60
|
+
testsRun: config.deployment.runTests,
|
|
61
|
+
enterpriseFeatures: Object.keys(config.enterprise).filter(k => config.enterprise[k]).length
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
this.displayEnterpriseNextSteps();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Display deployment statistics
|
|
69
|
+
*
|
|
70
|
+
* @param {Object} deploymentState - Deployment state
|
|
71
|
+
* @param {Object} config - Configuration
|
|
72
|
+
* @param {number} duration - Deployment duration in seconds
|
|
73
|
+
*/
|
|
74
|
+
static displayDeploymentStats(deploymentState, config, duration) {
|
|
75
|
+
console.log('\n📊 Deployment Statistics:');
|
|
76
|
+
console.log(` ⏱️ Duration: ${duration.toFixed(1)} seconds`);
|
|
77
|
+
console.log(` 🆔 Deployment ID: ${deploymentState.deploymentId}`);
|
|
78
|
+
console.log(` 🌐 Domain: ${config.domain}`);
|
|
79
|
+
console.log(` 🌍 Environment: ${config.environment}`);
|
|
80
|
+
console.log(` 📱 Mode: ${config.deploymentMode}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Display service endpoints
|
|
85
|
+
*
|
|
86
|
+
* @param {Object} config - Configuration
|
|
87
|
+
*/
|
|
88
|
+
static displayEndpoints(config) {
|
|
89
|
+
console.log(`\n🌐 Your service is now live at:`);
|
|
90
|
+
console.log(` ${config.worker.url}/health`);
|
|
91
|
+
console.log(` ${config.worker.url}/auth/magic-link`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Display enterprise endpoints
|
|
96
|
+
*
|
|
97
|
+
* @param {Object} config - Configuration
|
|
98
|
+
*/
|
|
99
|
+
static displayEnterpriseEndpoints(config) {
|
|
100
|
+
console.log('\n🌐 Enterprise Endpoints:');
|
|
101
|
+
console.log(` 🏠 Main: ${config.worker.url}`);
|
|
102
|
+
console.log(` ❤️ Health: ${config.worker.url}/health`);
|
|
103
|
+
console.log(` 🔐 Auth: ${config.worker.url}/auth/magic-link`);
|
|
104
|
+
console.log(` 📊 API: ${config.worker.url}/api`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Display secret distribution files
|
|
109
|
+
*
|
|
110
|
+
* @param {Object} config - Configuration
|
|
111
|
+
*/
|
|
112
|
+
static displayDistributionFiles(config) {
|
|
113
|
+
console.log(`\n📄 Secret distribution files:`);
|
|
114
|
+
console.log(` secrets/distribution/${config.domain}/.env`);
|
|
115
|
+
console.log(` secrets/distribution/${config.domain}/secrets.json`);
|
|
116
|
+
console.log(` secrets/distribution/${config.domain}/deploy-secrets.sh`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Display generated enterprise files
|
|
121
|
+
*
|
|
122
|
+
* @param {Object} frameworkPaths - Framework paths
|
|
123
|
+
* @param {Object} config - Configuration
|
|
124
|
+
* @param {Object} deploymentState - Deployment state
|
|
125
|
+
*/
|
|
126
|
+
static displayGeneratedFiles(frameworkPaths, config, deploymentState) {
|
|
127
|
+
console.log('\n📄 Generated Enterprise Files:');
|
|
128
|
+
console.log(` 📝 Audit Log: ${frameworkPaths.auditLogs}/deployments/session-${deploymentState.deploymentId}.log`);
|
|
129
|
+
console.log(` 📊 Report: ${frameworkPaths.auditReports}/deployment-${deploymentState.deploymentId}.html`);
|
|
130
|
+
console.log(` 🔐 Secrets: ${frameworkPaths.secureTokens}/distribution/${config.domain}/`);
|
|
131
|
+
console.log(` ⚙️ Config: ${frameworkPaths.configCache}/domains/${config.domain}/`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Display enabled enterprise features
|
|
136
|
+
*
|
|
137
|
+
* @param {Object} config - Configuration
|
|
138
|
+
*/
|
|
139
|
+
static displayEnabledFeatures(config) {
|
|
140
|
+
console.log('\n🚀 Enterprise Features Enabled:');
|
|
141
|
+
console.log(` 🔍 Validation: ${config.deployment.validationLevel}`);
|
|
142
|
+
console.log(` 📋 Audit: ${config.deployment.auditLevel}`);
|
|
143
|
+
console.log(` 🧪 Testing: ${config.deployment.runTests ? 'Comprehensive' : 'Disabled'}`);
|
|
144
|
+
console.log(` 🔄 Rollback: ${config.deployment.enableRollback ? 'Available' : 'Disabled'}`);
|
|
145
|
+
console.log(` 💾 Caching: Smart configuration caching enabled`);
|
|
146
|
+
console.log(` 🎯 Orchestration: Enterprise orchestration active`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Display next steps
|
|
151
|
+
*
|
|
152
|
+
* @param {Object} config - Configuration
|
|
153
|
+
*/
|
|
154
|
+
static displayNextSteps(config) {
|
|
155
|
+
console.log('\n🚀 Next steps:');
|
|
156
|
+
console.log(' 1. Test the endpoints above');
|
|
157
|
+
console.log(' 2. Distribute secrets to upstream/downstream applications');
|
|
158
|
+
console.log(' 3. Configure DNS if using custom domain');
|
|
159
|
+
console.log(' 4. Update your applications to use the new service');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Display enterprise next steps
|
|
164
|
+
*/
|
|
165
|
+
static displayEnterpriseNextSteps() {
|
|
166
|
+
console.log('\n✅ Enterprise deployment completed successfully!');
|
|
167
|
+
console.log(' Visit the health endpoint to verify deployment');
|
|
168
|
+
console.log(' Check audit logs for detailed deployment history');
|
|
169
|
+
console.log(' Use enterprise modules for ongoing management');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Display failure summary
|
|
174
|
+
*
|
|
175
|
+
* @param {Error} error - Deployment error
|
|
176
|
+
* @param {Object} deploymentState - Deployment state
|
|
177
|
+
* @param {Object} config - Configuration
|
|
178
|
+
*/
|
|
179
|
+
static displayFailureSummary(error, deploymentState, config) {
|
|
180
|
+
const duration = (Date.now() - deploymentState.startTime.getTime()) / 1000;
|
|
181
|
+
console.log('\n❌ DEPLOYMENT FAILED');
|
|
182
|
+
console.log('===================');
|
|
183
|
+
console.log(`\n📊 Summary:`);
|
|
184
|
+
console.log(` 🆔 Deployment ID: ${deploymentState.deploymentId}`);
|
|
185
|
+
console.log(` 🌐 Domain: ${config.domain}`);
|
|
186
|
+
console.log(` ⏱️ Duration: ${duration.toFixed(1)}s`);
|
|
187
|
+
console.log(` ❌ Error: ${error.message}`);
|
|
188
|
+
if (deploymentState.currentPhase) {
|
|
189
|
+
console.log(` 📍 Failed at: ${deploymentState.currentPhase}`);
|
|
190
|
+
}
|
|
191
|
+
console.log('\n🔄 Rollback options:');
|
|
192
|
+
console.log(` ${deploymentState.rollbackActions.length} rollback actions available`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get deployment summary statistics
|
|
197
|
+
*
|
|
198
|
+
* @param {Object} deploymentState - Deployment state
|
|
199
|
+
* @param {Object} config - Configuration
|
|
200
|
+
* @returns {Object} Summary statistics
|
|
201
|
+
*/
|
|
202
|
+
static getSummaryStats(deploymentState, config) {
|
|
203
|
+
const duration = (Date.now() - deploymentState.startTime.getTime()) / 1000;
|
|
204
|
+
return {
|
|
205
|
+
deploymentId: deploymentState.deploymentId,
|
|
206
|
+
domain: config.domain,
|
|
207
|
+
environment: config.environment,
|
|
208
|
+
duration: duration.toFixed(1),
|
|
209
|
+
secretsDeployed: Object.keys(config.secrets.keys).length,
|
|
210
|
+
currentPhase: deploymentState.currentPhase,
|
|
211
|
+
rollbackActionsAvailable: deploymentState.rollbackActions.length
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Confirmation Module
|
|
3
|
+
*
|
|
4
|
+
* Provides reusable interactive confirmation workflows.
|
|
5
|
+
* Extracted from enterprise-deployment/master-deploy.js for modularity.
|
|
6
|
+
*
|
|
7
|
+
* @module interactive-confirmation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { askYesNo } from '../utils/interactive-prompts.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Interactive Confirmation Manager
|
|
14
|
+
* Handles deployment confirmations and configuration reviews
|
|
15
|
+
*/
|
|
16
|
+
export class InteractiveConfirmation {
|
|
17
|
+
/**
|
|
18
|
+
* Display final deployment confirmation
|
|
19
|
+
*
|
|
20
|
+
* @param {Object} config - Deployment configuration
|
|
21
|
+
* @param {Object} deploymentState - Deployment state
|
|
22
|
+
* @param {Object} options - Confirmation options
|
|
23
|
+
* @returns {Promise<boolean>} True if confirmed, throws if cancelled
|
|
24
|
+
*/
|
|
25
|
+
static async showFinalConfirmation(config, deploymentState, options = {}) {
|
|
26
|
+
console.log('\n🎯 Final Deployment Confirmation');
|
|
27
|
+
console.log('===============================');
|
|
28
|
+
this.displayDeploymentSummary(config, deploymentState);
|
|
29
|
+
this.displayActionsToPerform(config);
|
|
30
|
+
const finalConfirm = await askYesNo('\n🚨 PROCEED WITH DEPLOYMENT? This will make changes to your Cloudflare account.', options.defaultAnswer || 'n');
|
|
31
|
+
if (!finalConfirm) {
|
|
32
|
+
throw new Error('Deployment cancelled by user');
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Display deployment summary
|
|
39
|
+
*
|
|
40
|
+
* @param {Object} config - Configuration
|
|
41
|
+
* @param {Object} deploymentState - Deployment state
|
|
42
|
+
*/
|
|
43
|
+
static displayDeploymentSummary(config, deploymentState) {
|
|
44
|
+
console.log('\n📋 DEPLOYMENT SUMMARY');
|
|
45
|
+
console.log('=====================');
|
|
46
|
+
console.log(`🌐 Domain: ${config.domain}`);
|
|
47
|
+
console.log(`🌍 Environment: ${config.environment}`);
|
|
48
|
+
console.log(`⚡ Worker: ${config.worker.name}`);
|
|
49
|
+
console.log(`🔗 URL: ${config.worker.url}`);
|
|
50
|
+
console.log(`🗄️ Database: ${config.database.name} (${config.database.id})`);
|
|
51
|
+
console.log(`🔑 Secrets: ${Object.keys(config.secrets.keys).length} configured`);
|
|
52
|
+
console.log(`🆔 Deployment ID: ${deploymentState.deploymentId}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Display actions that will be performed
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} config - Configuration
|
|
59
|
+
*/
|
|
60
|
+
static displayActionsToPerform(config) {
|
|
61
|
+
console.log('\n🚀 ACTIONS TO PERFORM:');
|
|
62
|
+
console.log('1. Update wrangler.toml configuration');
|
|
63
|
+
console.log('2. Run database migrations');
|
|
64
|
+
console.log('3. Deploy Cloudflare Worker');
|
|
65
|
+
console.log('4. Verify deployment health');
|
|
66
|
+
if (config.deployment.runTests) {
|
|
67
|
+
console.log('5. Run integration tests');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Display and confirm configuration review
|
|
73
|
+
*
|
|
74
|
+
* @param {Object} config - Configuration to review
|
|
75
|
+
* @param {Object} deploymentState - Deployment state
|
|
76
|
+
* @param {Function} reconfigureCallback - Callback to reconfigure if rejected
|
|
77
|
+
* @returns {Promise<boolean>} True if confirmed
|
|
78
|
+
*/
|
|
79
|
+
static async showConfigurationReview(config, deploymentState, reconfigureCallback) {
|
|
80
|
+
console.log('\n🔍 Configuration Review');
|
|
81
|
+
console.log('======================');
|
|
82
|
+
console.log('\nPlease review your configuration:');
|
|
83
|
+
console.log(` 🌐 Domain: ${config.domain}`);
|
|
84
|
+
console.log(` 🌍 Environment: ${config.environment}`);
|
|
85
|
+
console.log(` ⚡ Worker: ${config.worker.name}`);
|
|
86
|
+
console.log(` 🔗 URL: ${config.worker.url}`);
|
|
87
|
+
console.log(` 🆔 Deployment ID: ${deploymentState.deploymentId}`);
|
|
88
|
+
const confirmed = await askYesNo('\nIs this configuration correct?', 'y');
|
|
89
|
+
if (!confirmed) {
|
|
90
|
+
if (reconfigureCallback && typeof reconfigureCallback === 'function') {
|
|
91
|
+
console.log('\n🔄 Let\'s reconfigure...');
|
|
92
|
+
await reconfigureCallback();
|
|
93
|
+
return this.showConfigurationReview(config, deploymentState, reconfigureCallback);
|
|
94
|
+
} else {
|
|
95
|
+
throw new Error('Configuration rejected by user');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Show enterprise final confirmation with additional details
|
|
103
|
+
*
|
|
104
|
+
* @param {Object} config - Deployment configuration
|
|
105
|
+
* @param {Object} deploymentState - Deployment state
|
|
106
|
+
* @param {Object} enterpriseModules - Enterprise modules
|
|
107
|
+
* @returns {Promise<boolean>} True if confirmed
|
|
108
|
+
*/
|
|
109
|
+
static async showEnterpriseFinalConfirmation(config, deploymentState, enterpriseModules) {
|
|
110
|
+
console.log('\n🎯 Enterprise Final Confirmation');
|
|
111
|
+
console.log('================================');
|
|
112
|
+
this.displayEnterpriseDeploymentSummary(config, deploymentState);
|
|
113
|
+
this.displayEnterpriseActionsToPerform(config, enterpriseModules);
|
|
114
|
+
const finalConfirm = await askYesNo('\n🚨 PROCEED WITH ENTERPRISE DEPLOYMENT?', 'n');
|
|
115
|
+
if (!finalConfirm) {
|
|
116
|
+
throw new Error('Enterprise deployment cancelled by user');
|
|
117
|
+
}
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Display enterprise deployment summary
|
|
123
|
+
*
|
|
124
|
+
* @param {Object} config - Configuration
|
|
125
|
+
* @param {Object} deploymentState - Deployment state
|
|
126
|
+
*/
|
|
127
|
+
static displayEnterpriseDeploymentSummary(config, deploymentState) {
|
|
128
|
+
console.log('\n📋 ENTERPRISE DEPLOYMENT SUMMARY');
|
|
129
|
+
console.log('================================');
|
|
130
|
+
console.log(`🌐 Domain: ${config.domain}`);
|
|
131
|
+
console.log(`🌍 Environment: ${config.environment}`);
|
|
132
|
+
console.log(`📱 Mode: ${config.deploymentMode}`);
|
|
133
|
+
console.log(`⚡ Worker: ${config.worker.name}`);
|
|
134
|
+
console.log(`🔗 URL: ${config.worker.url}`);
|
|
135
|
+
console.log(`🗄️ Database: ${config.database.name} (${config.database.id})`);
|
|
136
|
+
console.log(`🔑 Secrets: ${Object.keys(config.secrets.keys).length} configured`);
|
|
137
|
+
console.log(`🆔 Deployment ID: ${deploymentState.deploymentId}`);
|
|
138
|
+
console.log(`🔍 Validation: ${config.deployment.validationLevel}`);
|
|
139
|
+
console.log(`📋 Audit: ${config.deployment.auditLevel}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Display enterprise actions
|
|
144
|
+
*
|
|
145
|
+
* @param {Object} config - Configuration
|
|
146
|
+
* @param {Object} enterpriseModules - Enterprise modules
|
|
147
|
+
*/
|
|
148
|
+
static displayEnterpriseActionsToPerform(config, enterpriseModules) {
|
|
149
|
+
console.log('\n🚀 ENTERPRISE ACTIONS TO PERFORM:');
|
|
150
|
+
console.log('1. Comprehensive validation');
|
|
151
|
+
console.log('2. Database orchestration');
|
|
152
|
+
console.log('3. Enterprise secret management');
|
|
153
|
+
console.log('4. Configuration management');
|
|
154
|
+
console.log('5. Cloudflare Worker deployment with D1 recovery');
|
|
155
|
+
console.log('6. Deployment verification');
|
|
156
|
+
if (config.deployment.runTests) {
|
|
157
|
+
console.log('7. Comprehensive integration tests');
|
|
158
|
+
}
|
|
159
|
+
console.log(`8. Audit logging and reporting`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Quick yes/no confirmation
|
|
164
|
+
*
|
|
165
|
+
* @param {string} message - Confirmation message
|
|
166
|
+
* @param {string} defaultAnswer - Default answer ('y' or 'n')
|
|
167
|
+
* @returns {Promise<boolean>} Confirmation result
|
|
168
|
+
*/
|
|
169
|
+
static async quickConfirm(message, defaultAnswer = 'y') {
|
|
170
|
+
return await askYesNo(message, defaultAnswer);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Confirm dangerous action with warning
|
|
175
|
+
*
|
|
176
|
+
* @param {string} action - Action description
|
|
177
|
+
* @param {string} warning - Warning message
|
|
178
|
+
* @returns {Promise<boolean>} Confirmation result
|
|
179
|
+
*/
|
|
180
|
+
static async confirmDangerousAction(action, warning) {
|
|
181
|
+
console.log(`\n⚠️ WARNING: ${warning}`);
|
|
182
|
+
const confirm = await askYesNo(`Are you sure you want to ${action}?`, 'n');
|
|
183
|
+
if (!confirm) {
|
|
184
|
+
throw new Error(`Dangerous action cancelled: ${action}`);
|
|
185
|
+
}
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Database Workflow Module
|
|
3
|
+
*
|
|
4
|
+
* Provides reusable interactive database creation and configuration workflows.
|
|
5
|
+
* Extracted from enterprise-deployment/master-deploy.js for modularity.
|
|
6
|
+
*
|
|
7
|
+
* @module interactive-database-workflow
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { askUser, askYesNo, askChoice } from '../utils/interactive-prompts.js';
|
|
11
|
+
import { databaseExists, createDatabase, deleteDatabase } from '../../cloudflare/ops.js';
|
|
12
|
+
import { exec } from 'child_process';
|
|
13
|
+
import { promisify } from 'util';
|
|
14
|
+
const execAsync = promisify(exec);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Interactive Database Workflow
|
|
18
|
+
* Handles database naming, existence checking, and creation with user interaction
|
|
19
|
+
*/
|
|
20
|
+
export class InteractiveDatabaseWorkflow {
|
|
21
|
+
/**
|
|
22
|
+
* @param {Object} options - Configuration options
|
|
23
|
+
* @param {Array} options.rollbackActions - Array to track rollback actions
|
|
24
|
+
*/
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
this.rollbackActions = options.rollbackActions || [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Handle complete database setup workflow
|
|
31
|
+
*
|
|
32
|
+
* @param {string} domain - Domain name for database
|
|
33
|
+
* @param {string} environment - Deployment environment
|
|
34
|
+
* @param {Object} options - Additional options
|
|
35
|
+
* @param {string} [options.suggestedName] - Suggested database name
|
|
36
|
+
* @param {boolean} [options.interactive=true] - Enable interactive prompts
|
|
37
|
+
* @returns {Promise<Object>} Database configuration { name, id, created, reused }
|
|
38
|
+
*/
|
|
39
|
+
async handleDatabaseSetup(domain, environment, options = {}) {
|
|
40
|
+
console.log('\n🗄️ Database Configuration');
|
|
41
|
+
console.log('=========================');
|
|
42
|
+
|
|
43
|
+
// Generate default database name
|
|
44
|
+
const suggestedName = options.suggestedName || `${domain}-auth-db`;
|
|
45
|
+
|
|
46
|
+
// Get final database name
|
|
47
|
+
const databaseName = await this.promptForDatabaseName(suggestedName, options.interactive);
|
|
48
|
+
|
|
49
|
+
// Check if database exists
|
|
50
|
+
const existingInfo = await this.checkExistingDatabase(databaseName);
|
|
51
|
+
if (existingInfo.exists) {
|
|
52
|
+
return await this.handleExistingDatabase(databaseName, existingInfo, options.interactive);
|
|
53
|
+
} else {
|
|
54
|
+
return await this.createNewDatabase(databaseName, options.interactive);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Prompt user for database name
|
|
60
|
+
*
|
|
61
|
+
* @param {string} suggested - Suggested database name
|
|
62
|
+
* @param {boolean} interactive - Enable interactive prompts
|
|
63
|
+
* @returns {Promise<string>} Final database name
|
|
64
|
+
*/
|
|
65
|
+
async promptForDatabaseName(suggested, interactive = true) {
|
|
66
|
+
console.log(`\n📋 Generated database name: ${suggested}`);
|
|
67
|
+
if (!interactive) {
|
|
68
|
+
return suggested;
|
|
69
|
+
}
|
|
70
|
+
const useGeneratedName = await askYesNo('Use this database name?', 'y');
|
|
71
|
+
if (!useGeneratedName) {
|
|
72
|
+
return await askUser('Enter custom database name', suggested);
|
|
73
|
+
}
|
|
74
|
+
return suggested;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check if database exists and get its details
|
|
79
|
+
*
|
|
80
|
+
* @param {string} name - Database name
|
|
81
|
+
* @returns {Promise<Object>} { exists: boolean, id?: string, error?: string }
|
|
82
|
+
*/
|
|
83
|
+
async checkExistingDatabase(name) {
|
|
84
|
+
console.log('\n🔍 Checking for existing database...');
|
|
85
|
+
try {
|
|
86
|
+
const exists = await databaseExists(name);
|
|
87
|
+
if (exists) {
|
|
88
|
+
console.log(` 📋 Database '${name}' already exists`);
|
|
89
|
+
|
|
90
|
+
// Extract database ID from the list command
|
|
91
|
+
try {
|
|
92
|
+
const dbListResult = await execAsync('npx wrangler d1 list');
|
|
93
|
+
const lines = dbListResult.stdout.split('\n');
|
|
94
|
+
for (const line of lines) {
|
|
95
|
+
if (line.includes(name)) {
|
|
96
|
+
const match = line.match(/([a-f0-9-]{36})/);
|
|
97
|
+
if (match) {
|
|
98
|
+
return {
|
|
99
|
+
exists: true,
|
|
100
|
+
id: match[1]
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.log(' ⚠️ Could not extract database ID');
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
exists: true
|
|
110
|
+
};
|
|
111
|
+
} else {
|
|
112
|
+
console.log(` ✅ Database '${name}' does not exist`);
|
|
113
|
+
return {
|
|
114
|
+
exists: false
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.log(' ⚠️ Could not check existing databases');
|
|
119
|
+
return {
|
|
120
|
+
exists: false,
|
|
121
|
+
error: error.message
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Handle workflow for existing database
|
|
128
|
+
*
|
|
129
|
+
* @param {string} name - Database name
|
|
130
|
+
* @param {Object} existingInfo - Information about existing database
|
|
131
|
+
* @param {boolean} interactive - Enable interactive prompts
|
|
132
|
+
* @returns {Promise<Object>} Database configuration
|
|
133
|
+
*/
|
|
134
|
+
async handleExistingDatabase(name, existingInfo, interactive = true) {
|
|
135
|
+
if (!interactive) {
|
|
136
|
+
// Non-interactive mode: reuse existing
|
|
137
|
+
console.log(` ✅ Using existing database: ${name}`);
|
|
138
|
+
return {
|
|
139
|
+
name,
|
|
140
|
+
id: existingInfo.id,
|
|
141
|
+
created: false,
|
|
142
|
+
reused: true
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const databaseChoice = await askChoice('What would you like to do with the existing database?', ['Use the existing database (recommended)', 'Create a new database with different name', 'Delete existing and create new (DANGER: DATA LOSS)'], 0);
|
|
146
|
+
switch (databaseChoice) {
|
|
147
|
+
case 0:
|
|
148
|
+
{
|
|
149
|
+
// Use existing database
|
|
150
|
+
if (existingInfo.id) {
|
|
151
|
+
console.log(` ✅ Using existing database ID: ${existingInfo.id}`);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
name,
|
|
155
|
+
id: existingInfo.id,
|
|
156
|
+
created: false,
|
|
157
|
+
reused: true
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
case 1:
|
|
161
|
+
{
|
|
162
|
+
// Create new database with different name
|
|
163
|
+
const newName = await askUser('Enter new database name');
|
|
164
|
+
return await this.createNewDatabase(newName, interactive);
|
|
165
|
+
}
|
|
166
|
+
case 2:
|
|
167
|
+
{
|
|
168
|
+
// Delete and recreate
|
|
169
|
+
const confirmDelete = await askYesNo('⚠️ ARE YOU SURE? This will DELETE all data in the existing database!', 'n');
|
|
170
|
+
if (!confirmDelete) {
|
|
171
|
+
throw new Error('Database deletion cancelled');
|
|
172
|
+
}
|
|
173
|
+
console.log(`\n🗑️ Deleting existing database...`);
|
|
174
|
+
await deleteDatabase(name);
|
|
175
|
+
return await this.createNewDatabase(name, interactive);
|
|
176
|
+
}
|
|
177
|
+
default:
|
|
178
|
+
throw new Error('Invalid database choice');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Create a new database
|
|
184
|
+
*
|
|
185
|
+
* @param {string} name - Database name
|
|
186
|
+
* @param {boolean} interactive - Enable interactive prompts
|
|
187
|
+
* @returns {Promise<Object>} Database configuration
|
|
188
|
+
*/
|
|
189
|
+
async createNewDatabase(name, interactive = true) {
|
|
190
|
+
console.log(`\n🆕 Creating new database: ${name}`);
|
|
191
|
+
if (interactive) {
|
|
192
|
+
const confirmCreate = await askYesNo('Proceed with database creation?', 'y');
|
|
193
|
+
if (!confirmCreate) {
|
|
194
|
+
throw new Error('Database creation cancelled');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
const databaseId = await createDatabase(name);
|
|
199
|
+
console.log(` ✅ Database created with ID: ${databaseId}`);
|
|
200
|
+
|
|
201
|
+
// Add to rollback actions
|
|
202
|
+
this.rollbackActions.push({
|
|
203
|
+
type: 'delete-database',
|
|
204
|
+
name: name,
|
|
205
|
+
command: `npx wrangler d1 delete ${name} --skip-confirmation`,
|
|
206
|
+
description: `Delete database '${name}' created during deployment`
|
|
207
|
+
});
|
|
208
|
+
return {
|
|
209
|
+
name,
|
|
210
|
+
id: databaseId,
|
|
211
|
+
created: true,
|
|
212
|
+
reused: false
|
|
213
|
+
};
|
|
214
|
+
} catch (error) {
|
|
215
|
+
throw new Error(`Database creation failed: ${error.message}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get database configuration summary
|
|
221
|
+
*
|
|
222
|
+
* @param {Object} dbConfig - Database configuration
|
|
223
|
+
* @returns {string} Summary message
|
|
224
|
+
*/
|
|
225
|
+
getSummary(dbConfig) {
|
|
226
|
+
if (dbConfig.created) {
|
|
227
|
+
return `✅ Database configured: ${dbConfig.name} (${dbConfig.id}) - CREATED`;
|
|
228
|
+
} else if (dbConfig.reused) {
|
|
229
|
+
return `✅ Database configured: ${dbConfig.name} (${dbConfig.id}) - REUSED`;
|
|
230
|
+
} else {
|
|
231
|
+
return `✅ Database configured: ${dbConfig.name} (${dbConfig.id})`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|