@tamyla/clodo-framework 1.0.0
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 +564 -0
- package/LICENSE +21 -0
- package/README.md +1393 -0
- package/bin/README.md +71 -0
- package/bin/clodo-service.js +416 -0
- package/bin/security/security-cli.js +96 -0
- package/bin/service-management/README.md +74 -0
- package/bin/service-management/create-service.js +129 -0
- package/bin/service-management/init-service.js +102 -0
- package/bin/service-management/init-service.js.backup +889 -0
- package/bin/shared/config/customer-cli.js +293 -0
- package/dist/config/ConfigurationManager.js +159 -0
- package/dist/config/CustomerConfigCLI.js +220 -0
- package/dist/config/FeatureManager.js +426 -0
- package/dist/config/customers.js +441 -0
- package/dist/config/domains.js +180 -0
- package/dist/config/features.js +225 -0
- package/dist/config/index.js +6 -0
- package/dist/database/database-orchestrator.js +730 -0
- package/dist/database/index.js +4 -0
- package/dist/deployment/auditor.js +971 -0
- package/dist/deployment/index.js +10 -0
- package/dist/deployment/rollback-manager.js +523 -0
- package/dist/deployment/testers/api-tester.js +80 -0
- package/dist/deployment/testers/auth-tester.js +129 -0
- package/dist/deployment/testers/core.js +217 -0
- package/dist/deployment/testers/database-tester.js +105 -0
- package/dist/deployment/testers/index.js +74 -0
- package/dist/deployment/testers/load-tester.js +120 -0
- package/dist/deployment/testers/performance-tester.js +105 -0
- package/dist/deployment/validator.js +558 -0
- package/dist/deployment/wrangler-deployer.js +574 -0
- package/dist/handlers/GenericRouteHandler.js +532 -0
- package/dist/index.js +39 -0
- package/dist/migration/MigrationAdapters.js +562 -0
- package/dist/modules/ModuleManager.js +668 -0
- package/dist/modules/security.js +98 -0
- package/dist/orchestration/cross-domain-coordinator.js +1083 -0
- package/dist/orchestration/index.js +5 -0
- package/dist/orchestration/modules/DeploymentCoordinator.js +258 -0
- package/dist/orchestration/modules/DomainResolver.js +196 -0
- package/dist/orchestration/modules/StateManager.js +332 -0
- package/dist/orchestration/multi-domain-orchestrator.js +255 -0
- package/dist/routing/EnhancedRouter.js +158 -0
- package/dist/schema/SchemaManager.js +778 -0
- package/dist/security/ConfigurationValidator.js +490 -0
- package/dist/security/DeploymentManager.js +208 -0
- package/dist/security/SecretGenerator.js +142 -0
- package/dist/security/SecurityCLI.js +228 -0
- package/dist/security/index.js +51 -0
- package/dist/security/patterns/environment-rules.js +66 -0
- package/dist/security/patterns/insecure-patterns.js +21 -0
- package/dist/service-management/ConfirmationEngine.js +411 -0
- package/dist/service-management/ErrorTracker.js +294 -0
- package/dist/service-management/GenerationEngine.js +3109 -0
- package/dist/service-management/InputCollector.js +237 -0
- package/dist/service-management/ServiceCreator.js +229 -0
- package/dist/service-management/ServiceInitializer.js +448 -0
- package/dist/service-management/ServiceOrchestrator.js +638 -0
- package/dist/service-management/handlers/ConfigMutator.js +130 -0
- package/dist/service-management/handlers/ConfirmationHandler.js +71 -0
- package/dist/service-management/handlers/GenerationHandler.js +80 -0
- package/dist/service-management/handlers/InputHandler.js +59 -0
- package/dist/service-management/handlers/ValidationHandler.js +203 -0
- package/dist/service-management/index.js +7 -0
- package/dist/services/GenericDataService.js +488 -0
- package/dist/shared/cloudflare/domain-discovery.js +562 -0
- package/dist/shared/cloudflare/domain-manager.js +912 -0
- package/dist/shared/cloudflare/index.js +8 -0
- package/dist/shared/cloudflare/ops.js +387 -0
- package/dist/shared/config/cache.js +1167 -0
- package/dist/shared/config/command-config-manager.js +174 -0
- package/dist/shared/config/customer-cli.js +258 -0
- package/dist/shared/config/index.js +9 -0
- package/dist/shared/config/manager.js +289 -0
- package/dist/shared/database/connection-manager.js +338 -0
- package/dist/shared/database/index.js +7 -0
- package/dist/shared/database/orchestrator.js +632 -0
- package/dist/shared/deployment/auditor.js +971 -0
- package/dist/shared/deployment/index.js +10 -0
- package/dist/shared/deployment/rollback-manager.js +523 -0
- package/dist/shared/deployment/validator.js +558 -0
- package/dist/shared/index.js +32 -0
- package/dist/shared/monitoring/health-checker.js +250 -0
- package/dist/shared/monitoring/index.js +8 -0
- package/dist/shared/monitoring/memory-manager.js +382 -0
- package/dist/shared/monitoring/production-monitor.js +390 -0
- package/dist/shared/production-tester/api-tester.js +80 -0
- package/dist/shared/production-tester/auth-tester.js +129 -0
- package/dist/shared/production-tester/core.js +217 -0
- package/dist/shared/production-tester/database-tester.js +105 -0
- package/dist/shared/production-tester/index.js +74 -0
- package/dist/shared/production-tester/load-tester.js +120 -0
- package/dist/shared/production-tester/performance-tester.js +105 -0
- package/dist/shared/security/api-token-manager.js +296 -0
- package/dist/shared/security/index.js +8 -0
- package/dist/shared/security/secret-generator.js +918 -0
- package/dist/shared/security/secure-token-manager.js +379 -0
- package/dist/shared/utils/error-recovery.js +240 -0
- package/dist/shared/utils/graceful-shutdown-manager.js +380 -0
- package/dist/shared/utils/index.js +9 -0
- package/dist/shared/utils/interactive-prompts.js +134 -0
- package/dist/shared/utils/rate-limiter.js +249 -0
- package/dist/utils/ErrorHandler.js +173 -0
- package/dist/utils/deployment/config-cache.js +1160 -0
- package/dist/utils/deployment/index.js +6 -0
- package/dist/utils/deployment/interactive-prompts.js +97 -0
- package/dist/utils/deployment/secret-generator.js +896 -0
- package/dist/utils/dirname-helper.js +35 -0
- package/dist/utils/domain-config.js +159 -0
- package/dist/utils/error-recovery.js +240 -0
- package/dist/utils/esm-helper.js +52 -0
- package/dist/utils/framework-config.js +481 -0
- package/dist/utils/graceful-shutdown-manager.js +379 -0
- package/dist/utils/health-checker.js +114 -0
- package/dist/utils/index.js +36 -0
- package/dist/utils/prompt-handler.js +98 -0
- package/dist/utils/usage-tracker.js +252 -0
- package/dist/utils/validation.js +112 -0
- package/dist/version/VersionDetector.js +723 -0
- package/dist/worker/index.js +4 -0
- package/dist/worker/integration.js +332 -0
- package/docs/FRAMEWORK-ARCHITECTURE-OVERVIEW.md +206 -0
- package/docs/INTEGRATION_GUIDE.md +2045 -0
- package/docs/README.md +82 -0
- package/docs/SECURITY.md +242 -0
- package/docs/deployment/deployment-guide.md +540 -0
- package/docs/overview.md +280 -0
- package/package.json +176 -0
- package/types/index.d.ts +575 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Customer Configuration Management CLI
|
|
5
|
+
* Manages multi-environment, multi-customer configuration structure
|
|
6
|
+
* Integrates with Clodo Framework domain and feature flag systems
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { CustomerConfigCLI } from '../../../src/config/CustomerConfigCLI.js';
|
|
10
|
+
|
|
11
|
+
const command = process.argv[2];
|
|
12
|
+
const args = process.argv.slice(3);
|
|
13
|
+
|
|
14
|
+
async function main() {
|
|
15
|
+
const cli = new CustomerConfigCLI();
|
|
16
|
+
await cli.initialize();
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
switch (command) {
|
|
20
|
+
case 'create-customer':
|
|
21
|
+
const [customerName, domain] = args;
|
|
22
|
+
const result = await cli.createCustomer(customerName, domain);
|
|
23
|
+
if (result.success) {
|
|
24
|
+
console.log(`\n🎉 Customer ${customerName} configuration created successfully!`);
|
|
25
|
+
console.log(`\n📋 Customer Details:`);
|
|
26
|
+
console.log(` Name: ${result.customer.name}`);
|
|
27
|
+
console.log(` Domain: ${result.customer.domain || 'Not specified'}`);
|
|
28
|
+
console.log(` Config Path: ${result.customer.configPath}`);
|
|
29
|
+
console.log(` Environments: ${result.customer.environments.join(', ')}`);
|
|
30
|
+
console.log(`\n📋 Next steps:`);
|
|
31
|
+
console.log(`1. Review generated configs in: config/customers/${customerName}/`);
|
|
32
|
+
console.log(`2. Update domain-specific URLs if needed`);
|
|
33
|
+
console.log(`3. Generate production secrets: npm run security:generate-key ${customerName}`);
|
|
34
|
+
console.log(`4. Set production secrets: wrangler secret put KEY_NAME --env production`);
|
|
35
|
+
} else {
|
|
36
|
+
console.error(`❌ Failed to create customer: ${result.error}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
case 'validate':
|
|
42
|
+
const validateResult = await cli.validateConfigurations();
|
|
43
|
+
if (validateResult.valid) {
|
|
44
|
+
console.log('✅ All customer configurations are valid');
|
|
45
|
+
} else {
|
|
46
|
+
console.log('❌ Configuration validation failed');
|
|
47
|
+
validateResult.errors.forEach(error => console.log(` - ${error}`));
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
case 'show':
|
|
53
|
+
const [customerNameShow, environment] = args;
|
|
54
|
+
const showResult = cli.showConfiguration(customerNameShow, environment);
|
|
55
|
+
if (showResult.success) {
|
|
56
|
+
console.log(`🔍 Effective configuration: ${customerNameShow}/${environment}\n`);
|
|
57
|
+
if (showResult.config.variables?.base) {
|
|
58
|
+
console.log('📋 Base variables:');
|
|
59
|
+
Object.entries(showResult.config.variables.base).slice(0, 10).forEach(([key, value]) => {
|
|
60
|
+
console.log(` ${key}=${value}`);
|
|
61
|
+
});
|
|
62
|
+
if (Object.keys(showResult.config.variables.base).length > 10) {
|
|
63
|
+
console.log(' ...');
|
|
64
|
+
}
|
|
65
|
+
console.log('');
|
|
66
|
+
}
|
|
67
|
+
if (showResult.config.variables?.customer) {
|
|
68
|
+
console.log(`📋 Customer ${environment} variables:`);
|
|
69
|
+
Object.entries(showResult.config.variables.customer).slice(0, 15).forEach(([key, value]) => {
|
|
70
|
+
console.log(` ${key}=${value}`);
|
|
71
|
+
});
|
|
72
|
+
if (Object.keys(showResult.config.variables.customer).length > 15) {
|
|
73
|
+
console.log(' ...');
|
|
74
|
+
}
|
|
75
|
+
console.log('');
|
|
76
|
+
}
|
|
77
|
+
if (showResult.config.features && Object.keys(showResult.config.features).length > 0) {
|
|
78
|
+
console.log('🚩 Customer features:');
|
|
79
|
+
Object.entries(showResult.config.features).forEach(([feature, enabled]) => {
|
|
80
|
+
console.log(` ${feature}: ${enabled ? '✅' : '❌'}`);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
console.error(`❌ Failed to show configuration: ${showResult.error}`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
case 'deploy-command':
|
|
90
|
+
const [customerNameDeploy, environmentDeploy] = args;
|
|
91
|
+
const deployResult = cli.getDeployCommand(customerNameDeploy, environmentDeploy);
|
|
92
|
+
if (deployResult.success) {
|
|
93
|
+
console.log(`📋 Deploy command for ${customerNameDeploy}/${environmentDeploy}:`);
|
|
94
|
+
console.log(` ${deployResult.command}`);
|
|
95
|
+
console.log(`\n💡 Ensure customer config is loaded: ${deployResult.configPath}`);
|
|
96
|
+
} else {
|
|
97
|
+
console.error(`❌ Failed to get deploy command: ${deployResult.error}`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
|
|
102
|
+
case 'list':
|
|
103
|
+
const listResult = cli.listCustomers();
|
|
104
|
+
if (listResult.success && listResult.customers.length > 0) {
|
|
105
|
+
console.log('📋 Configured customers:\n');
|
|
106
|
+
listResult.customers.forEach(customer => {
|
|
107
|
+
console.log(`🏢 ${customer.name}`);
|
|
108
|
+
console.log(` Domain: ${customer.domain || 'Not specified'}`);
|
|
109
|
+
console.log(` Environments: ${customer.environments.join(', ')}`);
|
|
110
|
+
console.log(` Created: ${customer.createdAt}`);
|
|
111
|
+
console.log(` Config: config/customers/${customer.name}/`);
|
|
112
|
+
console.log('');
|
|
113
|
+
});
|
|
114
|
+
} else if (listResult.success) {
|
|
115
|
+
console.log('📋 No customers configured');
|
|
116
|
+
} else {
|
|
117
|
+
console.error(`❌ Failed to list customers: ${listResult.error}`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
|
|
122
|
+
default:
|
|
123
|
+
console.log('Customer Configuration Management Tool\n');
|
|
124
|
+
console.log('Available commands:');
|
|
125
|
+
console.log(' create-customer <name> [domain] - Create new customer config from template');
|
|
126
|
+
console.log(' validate - Validate configuration structure');
|
|
127
|
+
console.log(' show <customer> <environment> - Show effective configuration');
|
|
128
|
+
console.log(' deploy-command <customer> <env> - Get deployment command');
|
|
129
|
+
console.log(' list - List all configured customers');
|
|
130
|
+
console.log('\nExamples:');
|
|
131
|
+
console.log(' clodo-customer-config create-customer acmecorp acmecorp.com');
|
|
132
|
+
console.log(' clodo-customer-config validate');
|
|
133
|
+
console.log(' clodo-customer-config show acmecorp production');
|
|
134
|
+
console.log(' clodo-customer-config list');
|
|
135
|
+
console.log('\nIntegration:');
|
|
136
|
+
console.log(' This tool integrates with Clodo Framework domain and feature flag systems.');
|
|
137
|
+
console.log(' Customer configurations are automatically registered as domains.');
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error(`❌ Error: ${error.message}`);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
main().catch(error => {
|
|
147
|
+
console.error(`❌ Unexpected error: ${error.message}`);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
async function handleCreateCustomer(args) {
|
|
152
|
+
const [customerName, domain] = args;
|
|
153
|
+
|
|
154
|
+
if (!customerName) {
|
|
155
|
+
console.error('Usage: customer-config create-customer <customer-name> [domain]');
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.log(`🏗️ Creating customer configuration: ${customerName}`);
|
|
160
|
+
|
|
161
|
+
// Pass framework mode flag to skip strict validation
|
|
162
|
+
const customerInfo = await customerManager.createCustomer(customerName, domain, {
|
|
163
|
+
skipValidation: true,
|
|
164
|
+
isFrameworkMode: true
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
console.log(`\n🎉 Customer ${customerName} configuration created successfully!`);
|
|
168
|
+
console.log(`\n📋 Customer Details:`);
|
|
169
|
+
console.log(` Name: ${customerInfo.name}`);
|
|
170
|
+
console.log(` Domain: ${customerInfo.domain || 'Not specified'}`);
|
|
171
|
+
console.log(` Config Path: ${customerInfo.configPath}`);
|
|
172
|
+
console.log(` Environments: ${customerInfo.environments.join(', ')}`);
|
|
173
|
+
|
|
174
|
+
console.log(`\n📋 Next steps:`);
|
|
175
|
+
console.log(`1. Review generated configs in: config/customers/${customerName}/`);
|
|
176
|
+
console.log(`2. Update domain-specific URLs if needed`);
|
|
177
|
+
console.log(`3. Generate production secrets: npm run security:generate-key ${customerName}`);
|
|
178
|
+
console.log(`4. Set production secrets: wrangler secret put KEY_NAME --env production`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function handleValidate() {
|
|
182
|
+
console.log('🔍 Validating customer configuration structure...\n');
|
|
183
|
+
|
|
184
|
+
const result = await customerManager.validateConfigs();
|
|
185
|
+
|
|
186
|
+
if (result.valid) {
|
|
187
|
+
console.log('✅ All customer configurations are valid');
|
|
188
|
+
} else {
|
|
189
|
+
console.log('❌ Configuration validation failed');
|
|
190
|
+
result.errors.forEach(error => console.log(` - ${error}`));
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function handleShow(args) {
|
|
196
|
+
const [customerName, environment] = args;
|
|
197
|
+
|
|
198
|
+
if (!customerName || !environment) {
|
|
199
|
+
console.error('Usage: customer-config show <customer> <environment>');
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const config = customerManager.showConfig(customerName, environment);
|
|
204
|
+
|
|
205
|
+
console.log(`🔍 Effective configuration: ${customerName}/${environment}\n`);
|
|
206
|
+
|
|
207
|
+
if (config.variables.base) {
|
|
208
|
+
console.log('📋 Base variables:');
|
|
209
|
+
Object.entries(config.variables.base).slice(0, 10).forEach(([key, value]) => {
|
|
210
|
+
console.log(` ${key}=${value}`);
|
|
211
|
+
});
|
|
212
|
+
if (Object.keys(config.variables.base).length > 10) {
|
|
213
|
+
console.log(' ...');
|
|
214
|
+
}
|
|
215
|
+
console.log('');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (config.variables.customer) {
|
|
219
|
+
console.log(`📋 Customer ${environment} variables:`);
|
|
220
|
+
Object.entries(config.variables.customer).slice(0, 15).forEach(([key, value]) => {
|
|
221
|
+
console.log(` ${key}=${value}`);
|
|
222
|
+
});
|
|
223
|
+
if (Object.keys(config.variables.customer).length > 15) {
|
|
224
|
+
console.log(' ...');
|
|
225
|
+
}
|
|
226
|
+
console.log('');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (config.features && Object.keys(config.features).length > 0) {
|
|
230
|
+
console.log('🚩 Customer features:');
|
|
231
|
+
Object.entries(config.features).forEach(([feature, enabled]) => {
|
|
232
|
+
console.log(` ${feature}: ${enabled ? '✅' : '❌'}`);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async function handleDeployCommand(args) {
|
|
238
|
+
const [customerName, environment] = args;
|
|
239
|
+
|
|
240
|
+
if (!customerName || !environment) {
|
|
241
|
+
console.error('Usage: customer-config deploy-command <customer> <environment>');
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const deployInfo = customerManager.getDeployCommand(customerName, environment);
|
|
246
|
+
|
|
247
|
+
console.log(`📋 Deploy command for ${customerName}/${environment}:`);
|
|
248
|
+
console.log(` ${deployInfo.command}`);
|
|
249
|
+
console.log(`\n💡 Ensure customer config is loaded: ${deployInfo.configPath}`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async function handleList() {
|
|
253
|
+
const customers = customerManager.listCustomers();
|
|
254
|
+
|
|
255
|
+
if (customers.length === 0) {
|
|
256
|
+
console.log('📋 No customers configured');
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log('📋 Configured customers:\n');
|
|
261
|
+
|
|
262
|
+
customers.forEach(customer => {
|
|
263
|
+
console.log(`🏢 ${customer.name}`);
|
|
264
|
+
console.log(` Domain: ${customer.domain || 'Not specified'}`);
|
|
265
|
+
console.log(` Environments: ${customer.environments.join(', ')}`);
|
|
266
|
+
console.log(` Created: ${customer.createdAt}`);
|
|
267
|
+
console.log(` Config: config/customers/${customer.name}/`);
|
|
268
|
+
console.log('');
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function showHelp() {
|
|
273
|
+
console.log('Customer Configuration Management Tool\n');
|
|
274
|
+
console.log('Available commands:');
|
|
275
|
+
console.log(' create-customer <name> [domain] - Create new customer config from template');
|
|
276
|
+
console.log(' validate - Validate configuration structure');
|
|
277
|
+
console.log(' show <customer> <environment> - Show effective configuration');
|
|
278
|
+
console.log(' deploy-command <customer> <env> - Get deployment command');
|
|
279
|
+
console.log(' list - List all configured customers');
|
|
280
|
+
console.log('\nExamples:');
|
|
281
|
+
console.log(' customer-config create-customer acmecorp acmecorp.com');
|
|
282
|
+
console.log(' customer-config validate');
|
|
283
|
+
console.log(' customer-config show acmecorp production');
|
|
284
|
+
console.log(' customer-config list');
|
|
285
|
+
console.log('\nIntegration:');
|
|
286
|
+
console.log(' This tool integrates with Clodo Framework domain and feature flag systems.');
|
|
287
|
+
console.log(' Customer configurations are automatically registered as domains.');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
main().catch(error => {
|
|
291
|
+
console.error(`❌ Unexpected error: ${error.message}`);
|
|
292
|
+
process.exit(1);
|
|
293
|
+
});
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Deployment Configuration Manager
|
|
3
|
+
* User input-driven configuration setup for deployment workflows
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { askChoice, askUser } from '../utils/deployment/interactive-prompts.js';
|
|
7
|
+
export class InteractiveDeploymentConfigurator {
|
|
8
|
+
/**
|
|
9
|
+
* Generate configuration from user input
|
|
10
|
+
* @param {Object} defaults - Default values
|
|
11
|
+
* @returns {Promise<Object>} User-configured settings
|
|
12
|
+
*/
|
|
13
|
+
static async generateFromUserInput(defaults = {}) {
|
|
14
|
+
console.log('🔧 Configuration Setup');
|
|
15
|
+
console.log('======================');
|
|
16
|
+
const config = {
|
|
17
|
+
...defaults
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Environment selection
|
|
21
|
+
config.environment = await askChoice('Select deployment environment:', ['development', 'staging', 'production'], 2 // Default to production
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Customer/domain input
|
|
25
|
+
config.customer = await askUser('Enter customer name:', defaults.customer || '');
|
|
26
|
+
config.domain = await askUser('Enter domain:', defaults.domain || '');
|
|
27
|
+
|
|
28
|
+
// Security settings
|
|
29
|
+
config.enableSecurityValidation = (await askChoice('Enable security validation?', ['yes', 'no'], 0)) === 'yes';
|
|
30
|
+
|
|
31
|
+
// Deployment options
|
|
32
|
+
config.runTests = (await askChoice('Run post-deployment tests?', ['yes', 'no'], 0)) === 'yes';
|
|
33
|
+
|
|
34
|
+
// Additional deployment settings
|
|
35
|
+
config.dryRun = (await askChoice('Perform dry run first?', ['yes', 'no'], 1 // Default to no
|
|
36
|
+
)) === 'yes';
|
|
37
|
+
config.allowInsecure = (await askChoice('Allow insecure deployment (not recommended)?', ['yes', 'no'], 1 // Default to no
|
|
38
|
+
)) === 'yes';
|
|
39
|
+
return config;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Validate user-provided configuration
|
|
44
|
+
* @param {Object} config - Configuration to validate
|
|
45
|
+
* @returns {Object} Validation result
|
|
46
|
+
*/
|
|
47
|
+
static validateConfiguration(config) {
|
|
48
|
+
const errors = [];
|
|
49
|
+
const warnings = [];
|
|
50
|
+
if (!config.customer) {
|
|
51
|
+
errors.push('Customer name is required');
|
|
52
|
+
} else if (config.customer.length < 2) {
|
|
53
|
+
errors.push('Customer name must be at least 2 characters');
|
|
54
|
+
}
|
|
55
|
+
if (!config.domain) {
|
|
56
|
+
errors.push('Domain is required');
|
|
57
|
+
} else if (!this.isValidDomain(config.domain)) {
|
|
58
|
+
errors.push('Domain format is invalid');
|
|
59
|
+
}
|
|
60
|
+
if (!['development', 'staging', 'production'].includes(config.environment)) {
|
|
61
|
+
errors.push('Invalid environment selection');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Warnings for potentially risky settings
|
|
65
|
+
if (config.allowInsecure) {
|
|
66
|
+
warnings.push('Insecure deployment allowed - security validations will be bypassed');
|
|
67
|
+
}
|
|
68
|
+
if (!config.enableSecurityValidation) {
|
|
69
|
+
warnings.push('Security validation disabled - deployment may be vulnerable');
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
valid: errors.length === 0,
|
|
73
|
+
errors,
|
|
74
|
+
warnings,
|
|
75
|
+
hasWarnings: warnings.length > 0
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validate domain format
|
|
81
|
+
* @param {string} domain - Domain to validate
|
|
82
|
+
* @returns {boolean} True if valid domain format
|
|
83
|
+
*/
|
|
84
|
+
static isValidDomain(domain) {
|
|
85
|
+
// Basic domain validation regex
|
|
86
|
+
const domainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
87
|
+
return domainRegex.test(domain);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Generate deployment URL from configuration
|
|
92
|
+
* @param {Object} config - Configuration object
|
|
93
|
+
* @returns {string} Generated deployment URL
|
|
94
|
+
*/
|
|
95
|
+
static generateDeploymentUrl(config) {
|
|
96
|
+
const {
|
|
97
|
+
customer,
|
|
98
|
+
environment,
|
|
99
|
+
domain
|
|
100
|
+
} = config;
|
|
101
|
+
if (domain) {
|
|
102
|
+
return `https://${customer}.${domain}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Fallback to Cloudflare Workers pattern
|
|
106
|
+
return `https://${customer}-${environment}.workers.dev`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Create deployment configuration summary
|
|
111
|
+
* @param {Object} config - Configuration object
|
|
112
|
+
* @returns {string} Formatted configuration summary
|
|
113
|
+
*/
|
|
114
|
+
static createConfigurationSummary(config) {
|
|
115
|
+
const lines = ['📋 Deployment Configuration Summary', '====================================', '', `👤 Customer: ${config.customer}`, `🌍 Environment: ${config.environment}`, `🔗 Domain: ${config.domain || 'Auto-generated'}`, `🔒 Security Validation: ${config.enableSecurityValidation ? 'Enabled' : 'Disabled'}`, `🧪 Post-deployment Tests: ${config.runTests ? 'Enabled' : 'Disabled'}`, `🧪 Dry Run: ${config.dryRun ? 'Yes' : 'No'}`, `⚠️ Allow Insecure: ${config.allowInsecure ? 'Yes' : 'No'}`, '', `🚀 Deployment URL: ${this.generateDeploymentUrl(config)}`];
|
|
116
|
+
return lines.join('\n');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Interactive configuration wizard
|
|
121
|
+
* @param {Object} defaults - Default configuration values
|
|
122
|
+
* @returns {Promise<Object>} Complete configuration object
|
|
123
|
+
*/
|
|
124
|
+
static async runConfigurationWizard(defaults = {}) {
|
|
125
|
+
console.log('\n🚀 CLODO Framework Deployment Configuration Wizard');
|
|
126
|
+
console.log('================================================\n');
|
|
127
|
+
let config;
|
|
128
|
+
let isValid = false;
|
|
129
|
+
do {
|
|
130
|
+
config = await this.generateFromUserInput(defaults);
|
|
131
|
+
const validation = this.validateConfiguration(config);
|
|
132
|
+
if (!validation.valid) {
|
|
133
|
+
console.log('\n❌ Configuration Validation Failed:');
|
|
134
|
+
validation.errors.forEach(error => console.log(` - ${error}`));
|
|
135
|
+
console.log('\nPlease correct the errors and try again.\n');
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (validation.hasWarnings) {
|
|
139
|
+
console.log('\n⚠️ Configuration Warnings:');
|
|
140
|
+
validation.warnings.forEach(warning => console.log(` - ${warning}`));
|
|
141
|
+
const proceed = await askChoice('\nProceed with deployment despite warnings?', ['yes', 'no'], 1 // Default to no
|
|
142
|
+
);
|
|
143
|
+
if (proceed === 'no') {
|
|
144
|
+
console.log('Configuration cancelled. Please adjust settings.\n');
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
isValid = true;
|
|
149
|
+
} while (!isValid);
|
|
150
|
+
console.log('\n✅ Configuration Complete!');
|
|
151
|
+
console.log(this.createConfigurationSummary(config));
|
|
152
|
+
const confirm = await askChoice('\nDeploy with this configuration?', ['yes', 'no'], 0 // Default to yes
|
|
153
|
+
);
|
|
154
|
+
if (confirm === 'no') {
|
|
155
|
+
throw new Error('Deployment cancelled by user');
|
|
156
|
+
}
|
|
157
|
+
return config;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clodo Framework - Customer Configuration CLI
|
|
3
|
+
* Programmatic API for customer configuration management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { CustomerConfigurationManager } from '../config/customers.js';
|
|
7
|
+
export class CustomerConfigCLI {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.customerManager = new CustomerConfigurationManager();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Initialize the customer manager by loading existing customers
|
|
14
|
+
* @returns {Promise<Object>} Initialization result
|
|
15
|
+
*/
|
|
16
|
+
async initialize() {
|
|
17
|
+
try {
|
|
18
|
+
await this.customerManager.loadExistingCustomers();
|
|
19
|
+
return {
|
|
20
|
+
success: true,
|
|
21
|
+
message: 'Customer manager initialized successfully'
|
|
22
|
+
};
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
error: error.message
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create a new customer configuration
|
|
33
|
+
* @param {string} customerName - Customer name
|
|
34
|
+
* @param {string} domain - Customer domain (optional)
|
|
35
|
+
* @param {Object} options - Creation options
|
|
36
|
+
* @returns {Promise<Object>} Creation result
|
|
37
|
+
*/
|
|
38
|
+
async createCustomer(customerName, domain, options = {}) {
|
|
39
|
+
try {
|
|
40
|
+
if (!customerName) {
|
|
41
|
+
throw new Error('Customer name is required');
|
|
42
|
+
}
|
|
43
|
+
const customerInfo = await this.customerManager.createCustomer(customerName, domain, {
|
|
44
|
+
skipValidation: true,
|
|
45
|
+
isFrameworkMode: true,
|
|
46
|
+
...options
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
success: true,
|
|
50
|
+
customer: customerInfo
|
|
51
|
+
};
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
customerName,
|
|
56
|
+
error: error.message
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Validate customer configuration structure
|
|
63
|
+
* @returns {Promise<Object>} Validation result
|
|
64
|
+
*/
|
|
65
|
+
async validateConfigurations() {
|
|
66
|
+
try {
|
|
67
|
+
const result = await this.customerManager.validateConfigs();
|
|
68
|
+
return {
|
|
69
|
+
success: result.valid,
|
|
70
|
+
valid: result.valid,
|
|
71
|
+
errors: result.errors || []
|
|
72
|
+
};
|
|
73
|
+
} catch (error) {
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
error: error.message
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Show effective configuration for a customer and environment
|
|
83
|
+
* @param {string} customerName - Customer name
|
|
84
|
+
* @param {string} environment - Environment name
|
|
85
|
+
* @returns {Object} Configuration display result
|
|
86
|
+
*/
|
|
87
|
+
showConfiguration(customerName, environment) {
|
|
88
|
+
try {
|
|
89
|
+
if (!customerName || !environment) {
|
|
90
|
+
throw new Error('Customer name and environment are required');
|
|
91
|
+
}
|
|
92
|
+
const config = this.customerManager.showConfig(customerName, environment);
|
|
93
|
+
return {
|
|
94
|
+
success: true,
|
|
95
|
+
customer: customerName,
|
|
96
|
+
environment,
|
|
97
|
+
config
|
|
98
|
+
};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
customer: customerName,
|
|
103
|
+
environment,
|
|
104
|
+
error: error.message
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get deployment command for a customer and environment
|
|
111
|
+
* @param {string} customerName - Customer name
|
|
112
|
+
* @param {string} environment - Environment name
|
|
113
|
+
* @returns {Object} Deployment command result
|
|
114
|
+
*/
|
|
115
|
+
getDeployCommand(customerName, environment) {
|
|
116
|
+
try {
|
|
117
|
+
if (!customerName || !environment) {
|
|
118
|
+
throw new Error('Customer name and environment are required');
|
|
119
|
+
}
|
|
120
|
+
const deployInfo = this.customerManager.getDeployCommand(customerName, environment);
|
|
121
|
+
return {
|
|
122
|
+
success: true,
|
|
123
|
+
customer: customerName,
|
|
124
|
+
environment,
|
|
125
|
+
command: deployInfo.command,
|
|
126
|
+
configPath: deployInfo.configPath
|
|
127
|
+
};
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return {
|
|
130
|
+
success: false,
|
|
131
|
+
customer: customerName,
|
|
132
|
+
environment,
|
|
133
|
+
error: error.message
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* List all configured customers
|
|
140
|
+
* @returns {Object} Customer list result
|
|
141
|
+
*/
|
|
142
|
+
listCustomers() {
|
|
143
|
+
try {
|
|
144
|
+
const customers = this.customerManager.listCustomers();
|
|
145
|
+
return {
|
|
146
|
+
success: true,
|
|
147
|
+
customers
|
|
148
|
+
};
|
|
149
|
+
} catch (error) {
|
|
150
|
+
return {
|
|
151
|
+
success: false,
|
|
152
|
+
error: error.message
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get available commands
|
|
159
|
+
* @returns {string[]} Array of available commands
|
|
160
|
+
*/
|
|
161
|
+
getAvailableCommands() {
|
|
162
|
+
return ['create-customer', 'validate', 'show', 'deploy-command', 'list'];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get command help
|
|
167
|
+
* @param {string} command - Command name (optional)
|
|
168
|
+
* @returns {string} Help text
|
|
169
|
+
*/
|
|
170
|
+
getHelp(command) {
|
|
171
|
+
const help = {
|
|
172
|
+
'create-customer': 'create-customer <name> [domain] - Create new customer config from template',
|
|
173
|
+
'validate': 'validate - Validate configuration structure',
|
|
174
|
+
'show': 'show <customer> <environment> - Show effective configuration',
|
|
175
|
+
'deploy-command': 'deploy-command <customer> <environment> - Get deployment command',
|
|
176
|
+
'list': 'list - List all configured customers'
|
|
177
|
+
};
|
|
178
|
+
if (command && help[command]) {
|
|
179
|
+
return help[command];
|
|
180
|
+
}
|
|
181
|
+
return `Customer Configuration Management Tool
|
|
182
|
+
|
|
183
|
+
Available commands:
|
|
184
|
+
${Object.values(help).map(cmd => ` ${cmd}`).join('\n')}
|
|
185
|
+
|
|
186
|
+
Examples:
|
|
187
|
+
create-customer acmecorp acmecorp.com
|
|
188
|
+
validate
|
|
189
|
+
show acmecorp production
|
|
190
|
+
list
|
|
191
|
+
|
|
192
|
+
Integration:
|
|
193
|
+
This tool integrates with Clodo Framework domain and feature flag systems.
|
|
194
|
+
Customer configurations are automatically registered as domains.`;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Convenience functions for direct use
|
|
199
|
+
export async function createCustomer(customerName, domain, options = {}) {
|
|
200
|
+
const cli = new CustomerConfigCLI();
|
|
201
|
+
await cli.initialize();
|
|
202
|
+
return await cli.createCustomer(customerName, domain, options);
|
|
203
|
+
}
|
|
204
|
+
export async function validateCustomerConfigs() {
|
|
205
|
+
const cli = new CustomerConfigCLI();
|
|
206
|
+
await cli.initialize();
|
|
207
|
+
return await cli.validateConfigurations();
|
|
208
|
+
}
|
|
209
|
+
export function showCustomerConfig(customerName, environment) {
|
|
210
|
+
const cli = new CustomerConfigCLI();
|
|
211
|
+
return cli.showConfiguration(customerName, environment);
|
|
212
|
+
}
|
|
213
|
+
export function getCustomerDeployCommand(customerName, environment) {
|
|
214
|
+
const cli = new CustomerConfigCLI();
|
|
215
|
+
return cli.getDeployCommand(customerName, environment);
|
|
216
|
+
}
|
|
217
|
+
export function listConfiguredCustomers() {
|
|
218
|
+
const cli = new CustomerConfigCLI();
|
|
219
|
+
return cli.listCustomers();
|
|
220
|
+
}
|