@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,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress Spinner Utility
|
|
3
|
+
* Enhanced progress display with spinner animation
|
|
4
|
+
* Extracted from clodo-service-old.js for modular reuse
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Display progress with animated spinner
|
|
11
|
+
* @param {string} message - Progress message to display
|
|
12
|
+
* @param {number} duration - Duration in milliseconds (default: 2000)
|
|
13
|
+
* @returns {Promise} Resolves when progress completes
|
|
14
|
+
*/
|
|
15
|
+
export function showProgressSpinner(message, duration = 2000) {
|
|
16
|
+
return new Promise(resolve => {
|
|
17
|
+
process.stdout.write(chalk.cyan(`⏳ ${message}...`));
|
|
18
|
+
const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
19
|
+
let i = 0;
|
|
20
|
+
const interval = setInterval(() => {
|
|
21
|
+
process.stdout.write(`\r${chalk.cyan(spinner[i])} ${message}...`);
|
|
22
|
+
i = (i + 1) % spinner.length;
|
|
23
|
+
}, 100);
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
clearInterval(interval);
|
|
26
|
+
process.stdout.write(`\r${chalk.green('✅')} ${message}... Done!\n`);
|
|
27
|
+
resolve();
|
|
28
|
+
}, duration);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Display progress with custom spinner characters
|
|
34
|
+
* @param {string} message - Progress message
|
|
35
|
+
* @param {Array<string>} spinnerChars - Custom spinner characters
|
|
36
|
+
* @param {number} duration - Duration in milliseconds
|
|
37
|
+
* @returns {Promise} Resolves when complete
|
|
38
|
+
*/
|
|
39
|
+
export function showProgressWithSpinner(message, spinnerChars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'], duration = 2000) {
|
|
40
|
+
return new Promise(resolve => {
|
|
41
|
+
process.stdout.write(chalk.cyan(`⏳ ${message}...`));
|
|
42
|
+
let i = 0;
|
|
43
|
+
const interval = setInterval(() => {
|
|
44
|
+
process.stdout.write(`\r${chalk.cyan(spinnerChars[i])} ${message}...`);
|
|
45
|
+
i = (i + 1) % spinnerChars.length;
|
|
46
|
+
}, 100);
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
clearInterval(interval);
|
|
49
|
+
process.stdout.write(`\r${chalk.green('✅')} ${message}... Done!\n`);
|
|
50
|
+
resolve();
|
|
51
|
+
}, duration);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sensitive Information Redactor
|
|
3
|
+
* Advanced pattern-based redaction for logs and output
|
|
4
|
+
* Extracted from clodo-service-old.js for modular reuse
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Redact sensitive information from text using pattern matching
|
|
9
|
+
* @param {string} text - Text to redact
|
|
10
|
+
* @returns {string} Redacted text
|
|
11
|
+
*/
|
|
12
|
+
export function redactSensitiveInfo(text) {
|
|
13
|
+
if (typeof text !== 'string') return text;
|
|
14
|
+
|
|
15
|
+
// Patterns to redact
|
|
16
|
+
const patterns = [
|
|
17
|
+
// Cloudflare API tokens
|
|
18
|
+
[/(CLOUDFLARE_API_TOKEN=?)(\w{20,})/gi, '$1[REDACTED]'],
|
|
19
|
+
// Generic API tokens/keys - require minimum length
|
|
20
|
+
[/(token|api[_-]?token|api[_-]?key|auth[_-]?token)["']?[:=]\s*([a-zA-Z0-9_-]{6,})/gi, '$1: [REDACTED]'],
|
|
21
|
+
// Passwords - require minimum length
|
|
22
|
+
[/(password|passwd|pwd)["']?[:=]\s*([^"'\s]{4,})/gi, '$1: [REDACTED]'],
|
|
23
|
+
// Secrets - require minimum length
|
|
24
|
+
[/(secret|key)["']?[:=]\s*([a-zA-Z0-9_-]{6,})/gi, '$1: [REDACTED]'],
|
|
25
|
+
// Account IDs (partial redaction) - match 8+ characters
|
|
26
|
+
[/(account[_-]?id|zone[_-]?id)["']?[:=]\s*["']?([a-zA-Z0-9]{8})([a-zA-Z0-9]*)/gi, '$1: $2[REDACTED]']];
|
|
27
|
+
let redacted = text;
|
|
28
|
+
patterns.forEach(([pattern, replacement]) => {
|
|
29
|
+
redacted = redacted.replace(pattern, replacement);
|
|
30
|
+
});
|
|
31
|
+
return redacted;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Redact sensitive information from an object recursively
|
|
36
|
+
* @param {any} obj - Object to redact
|
|
37
|
+
* @param {Set} visited - Set of visited objects to prevent circular references
|
|
38
|
+
* @returns {any} Redacted object
|
|
39
|
+
*/
|
|
40
|
+
export function redactSensitiveObject(obj, visited = new Set()) {
|
|
41
|
+
// Handle circular references by returning a placeholder
|
|
42
|
+
if (obj && typeof obj === 'object') {
|
|
43
|
+
if (visited.has(obj)) {
|
|
44
|
+
return '[CIRCULAR REFERENCE]';
|
|
45
|
+
}
|
|
46
|
+
visited.add(obj);
|
|
47
|
+
}
|
|
48
|
+
if (typeof obj === 'string') {
|
|
49
|
+
return redactSensitiveInfo(obj);
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(obj)) {
|
|
52
|
+
// Process each array element individually
|
|
53
|
+
return obj.map(item => redactSensitiveObject(item, visited));
|
|
54
|
+
}
|
|
55
|
+
if (obj && typeof obj === 'object') {
|
|
56
|
+
const redacted = {};
|
|
57
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
58
|
+
const lowerKey = key.toLowerCase();
|
|
59
|
+
// Special handling for accountId and zoneId - allow partial redaction via regex
|
|
60
|
+
if (lowerKey.includes('accountid') || lowerKey.includes('zoneid')) {
|
|
61
|
+
if (typeof value === 'string') {
|
|
62
|
+
// Apply partial redaction for account/zone IDs
|
|
63
|
+
redacted[key] = value.replace(/^([a-zA-Z0-9]{8})([a-zA-Z0-9]*)$/, '$1[REDACTED]');
|
|
64
|
+
} else {
|
|
65
|
+
redacted[key] = redactSensitiveObject(value, visited);
|
|
66
|
+
}
|
|
67
|
+
} else if (isSensitiveKey(key)) {
|
|
68
|
+
if (Array.isArray(value)) {
|
|
69
|
+
// Redact each element in sensitive arrays
|
|
70
|
+
redacted[key] = value.map(() => '[REDACTED]');
|
|
71
|
+
} else {
|
|
72
|
+
redacted[key] = '[REDACTED]';
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
redacted[key] = redactSensitiveObject(value, visited);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return redacted;
|
|
79
|
+
}
|
|
80
|
+
return obj;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if a key name indicates sensitive information
|
|
85
|
+
* @param {string} key - Key name to check
|
|
86
|
+
* @returns {boolean} True if key is sensitive
|
|
87
|
+
*/
|
|
88
|
+
function isSensitiveKey(key) {
|
|
89
|
+
const sensitiveKeys = ['password', 'passwd', 'pwd', 'secret', 'key', 'token', 'apikey', 'cloudflaretoken', 'apitoken', 'authkey', 'privatekey'];
|
|
90
|
+
return sensitiveKeys.some(sensitive => key.toLowerCase().includes(sensitive.toLowerCase()));
|
|
91
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
/**
|
|
9
9
|
* Import validators from src/utils (source of truth)
|
|
10
10
|
*/
|
|
11
|
-
import { validateServiceName, validateDomainName, validateCloudflareToken, validateCloudflareId, validateServiceType, validateEnvironment } from
|
|
11
|
+
import { validateServiceName, validateDomainName, validateCloudflareToken, validateCloudflareId, validateServiceType, validateEnvironment } from '../../utils/validation.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Validation Registry - Single source of truth for all validators
|
|
@@ -274,6 +274,26 @@ export class DataServiceAdapter {
|
|
|
274
274
|
});
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Query with optional advanced features
|
|
279
|
+
*/
|
|
280
|
+
async query(sql, params = [], options = {}) {
|
|
281
|
+
return this._withAsyncMigrationLogging('query', async () => {
|
|
282
|
+
return featureManager.withFeature(FEATURES.ENABLE_ADVANCED_QUERIES, async () => {
|
|
283
|
+
return await this.enhanced.query(sql, params, {
|
|
284
|
+
...options,
|
|
285
|
+
usePreparedStatements: true,
|
|
286
|
+
enableQueryAnalysis: true
|
|
287
|
+
});
|
|
288
|
+
}, async () => {
|
|
289
|
+
if (this.legacy && this.legacy.query) {
|
|
290
|
+
return await this.legacy.query(sql, params, options);
|
|
291
|
+
}
|
|
292
|
+
return await this.enhanced.queryDirect(sql, params, options);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
277
297
|
/**
|
|
278
298
|
* List with optional advanced pagination
|
|
279
299
|
*/
|
|
@@ -310,9 +330,17 @@ export class DataServiceAdapter {
|
|
|
310
330
|
* Get migration progress and statistics
|
|
311
331
|
*/
|
|
312
332
|
getMigrationStats() {
|
|
333
|
+
// Get enhanced service stats and merge with adapter stats
|
|
334
|
+
const enhancedStats = this.enhanced.getMigrationStats ? this.enhanced.getMigrationStats() : {};
|
|
313
335
|
return {
|
|
314
|
-
callCounts:
|
|
315
|
-
|
|
336
|
+
callCounts: {
|
|
337
|
+
...enhancedStats.callCounts,
|
|
338
|
+
...Object.fromEntries(this.migrationState.callCounts)
|
|
339
|
+
},
|
|
340
|
+
cacheHitRates: {
|
|
341
|
+
...enhancedStats.cacheHitRates,
|
|
342
|
+
...Object.fromEntries(this.migrationState.cacheHitRates)
|
|
343
|
+
},
|
|
316
344
|
performanceGains: Object.fromEntries(this.migrationState.performanceGains),
|
|
317
345
|
featureUsage: this._getFeatureUsageStats()
|
|
318
346
|
};
|
|
@@ -420,6 +448,16 @@ export class ModuleManagerAdapter {
|
|
|
420
448
|
});
|
|
421
449
|
}
|
|
422
450
|
|
|
451
|
+
/**
|
|
452
|
+
* Execute single hook (convenience method)
|
|
453
|
+
*/
|
|
454
|
+
async executeHook(hookName, context = {}) {
|
|
455
|
+
const results = await this.executeHooks(hookName, context);
|
|
456
|
+
return results && results.length > 0 ? results[0] : {
|
|
457
|
+
success: false
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
423
461
|
/**
|
|
424
462
|
* Get hook metrics if available
|
|
425
463
|
*/
|
|
@@ -433,9 +471,17 @@ export class ModuleManagerAdapter {
|
|
|
433
471
|
* Get migration statistics
|
|
434
472
|
*/
|
|
435
473
|
getMigrationStats() {
|
|
474
|
+
// Get enhanced service stats and merge with adapter stats
|
|
475
|
+
const enhancedStats = this.enhanced.getMigrationStats ? this.enhanced.getMigrationStats() : {};
|
|
436
476
|
return {
|
|
437
|
-
hookExecutions:
|
|
438
|
-
|
|
477
|
+
hookExecutions: {
|
|
478
|
+
...enhancedStats.hookExecutions,
|
|
479
|
+
...Object.fromEntries(this.migrationState.hookExecutions)
|
|
480
|
+
},
|
|
481
|
+
timeoutEvents: {
|
|
482
|
+
...enhancedStats.timeoutEvents,
|
|
483
|
+
...Object.fromEntries(this.migrationState.timeoutEvents)
|
|
484
|
+
},
|
|
439
485
|
performanceMetrics: Object.fromEntries(this.migrationState.performanceMetrics),
|
|
440
486
|
featureUsage: this._getFeatureUsageStats()
|
|
441
487
|
};
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
|
|
20
20
|
import { access } from 'fs/promises';
|
|
21
21
|
import { MultiDomainOrchestrator } from './multi-domain-orchestrator.js';
|
|
22
|
-
import { DeploymentValidator } from
|
|
23
|
-
import { RollbackManager } from
|
|
24
|
-
import { DomainDiscovery } from
|
|
22
|
+
import { DeploymentValidator } from '../lib/shared/deployment/validator.js';
|
|
23
|
+
import { RollbackManager } from '../lib/shared/deployment/rollback-manager.js';
|
|
24
|
+
import { DomainDiscovery } from '../lib/shared/cloudflare/domain-discovery.js';
|
|
25
25
|
import { DatabaseOrchestrator } from '../database/database-orchestrator.js';
|
|
26
26
|
import { EnhancedSecretManager } from '../utils/deployment/secret-generator.js';
|
|
27
|
-
import { ProductionTester } from
|
|
28
|
-
import { DeploymentAuditor } from
|
|
27
|
+
import { ProductionTester } from '../lib/shared/production-tester/index.js';
|
|
28
|
+
import { DeploymentAuditor } from '../lib/shared/deployment/auditor.js';
|
|
29
29
|
import { ConfigurationCacheManager } from '../utils/deployment/config-cache.js';
|
|
30
30
|
export class CrossDomainCoordinator {
|
|
31
31
|
constructor(options = {}) {
|
|
@@ -14,6 +14,7 @@ import { DatabaseOrchestrator } from '../database/database-orchestrator.js';
|
|
|
14
14
|
import { EnhancedSecretManager } from '../utils/deployment/secret-generator.js';
|
|
15
15
|
import { WranglerConfigManager } from '../utils/deployment/wrangler-config-manager.js';
|
|
16
16
|
import { ConfigurationValidator } from '../security/ConfigurationValidator.js';
|
|
17
|
+
import { buildCustomDomain } from '../utils/constants.js';
|
|
17
18
|
import { exec } from 'child_process';
|
|
18
19
|
import { promisify } from 'util';
|
|
19
20
|
import { join } from 'path';
|
|
@@ -34,13 +35,24 @@ export class MultiDomainOrchestrator {
|
|
|
34
35
|
this.skipTests = options.skipTests || false;
|
|
35
36
|
this.parallelDeployments = options.parallelDeployments || 3;
|
|
36
37
|
this.servicePath = options.servicePath || process.cwd();
|
|
38
|
+
this.serviceName = options.serviceName || 'worker'; // Service name for custom domain
|
|
39
|
+
|
|
40
|
+
// Wrangler config path - allows using customer-specific wrangler.toml files
|
|
41
|
+
// If not specified, wrangler uses the default wrangler.toml in servicePath
|
|
42
|
+
this.wranglerConfigPath = options.wranglerConfigPath;
|
|
37
43
|
|
|
38
44
|
// Cloudflare credentials for API-based operations
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
// Support both legacy individual params and new cloudflareSettings object
|
|
46
|
+
const cfSettings = options.cloudflareSettings || {};
|
|
47
|
+
this.cloudflareToken = options.cloudflareToken || cfSettings.token;
|
|
48
|
+
this.cloudflareAccountId = options.cloudflareAccountId || cfSettings.accountId;
|
|
49
|
+
this.cloudflareZoneId = options.cloudflareZoneId || cfSettings.zoneId;
|
|
50
|
+
this.cloudflareZoneName = options.cloudflareZoneName || cfSettings.zoneName;
|
|
41
51
|
|
|
42
52
|
// Configure wrangler to use API token when available
|
|
43
|
-
//
|
|
53
|
+
// Configure wrangler authentication via environment variables
|
|
54
|
+
// Note: account_id comes from wrangler.toml, not env var
|
|
55
|
+
// (env var would be ignored by wrangler when wrangler.toml has account_id)
|
|
44
56
|
if (this.cloudflareToken) {
|
|
45
57
|
process.env.CLOUDFLARE_API_TOKEN = this.cloudflareToken;
|
|
46
58
|
console.log(`🔑 Configured wrangler to use API token authentication`);
|
|
@@ -49,9 +61,12 @@ export class MultiDomainOrchestrator {
|
|
|
49
61
|
process.env.CLOUDFLARE_ACCOUNT_ID = this.cloudflareAccountId;
|
|
50
62
|
console.log(`🔑 Configured wrangler to use account ID: ${this.cloudflareAccountId}`);
|
|
51
63
|
}
|
|
52
|
-
if (this.
|
|
53
|
-
process.env.
|
|
54
|
-
console.log(`🔑 Configured wrangler to use
|
|
64
|
+
if (this.cloudflareZoneId) {
|
|
65
|
+
process.env.CLOUDFLARE_ZONE_ID = this.cloudflareZoneId;
|
|
66
|
+
console.log(`🔑 Configured wrangler to use zone ID: ${this.cloudflareZoneId}`);
|
|
67
|
+
}
|
|
68
|
+
if (this.cloudflareZoneName) {
|
|
69
|
+
console.log(`🌐 Deploying to zone: ${this.cloudflareZoneName}`);
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
// Initialize modular components
|
|
@@ -80,7 +95,8 @@ export class MultiDomainOrchestrator {
|
|
|
80
95
|
projectRoot: this.servicePath,
|
|
81
96
|
dryRun: this.dryRun,
|
|
82
97
|
cloudflareToken: this.cloudflareToken,
|
|
83
|
-
cloudflareAccountId: this.cloudflareAccountId
|
|
98
|
+
cloudflareAccountId: this.cloudflareAccountId,
|
|
99
|
+
cloudflareZoneId: this.cloudflareZoneId
|
|
84
100
|
});
|
|
85
101
|
this.secretManager = new EnhancedSecretManager({
|
|
86
102
|
projectRoot: this.servicePath,
|
|
@@ -509,15 +525,40 @@ export class MultiDomainOrchestrator {
|
|
|
509
525
|
console.log(` 🚀 Deploying worker for ${domain}`);
|
|
510
526
|
if (this.dryRun) {
|
|
511
527
|
console.log(` 🔍 DRY RUN: Would deploy worker for ${domain}`);
|
|
512
|
-
|
|
528
|
+
// Use centralized domain template from validation-config.json
|
|
529
|
+
const customUrl = buildCustomDomain(this.serviceName, domain, this.environment);
|
|
513
530
|
return {
|
|
514
|
-
url:
|
|
531
|
+
url: customUrl,
|
|
515
532
|
deployed: false,
|
|
516
533
|
dryRun: true
|
|
517
534
|
};
|
|
518
535
|
}
|
|
519
536
|
try {
|
|
520
|
-
//
|
|
537
|
+
// Generate/update customer-specific wrangler.toml, then copy to root
|
|
538
|
+
// This implements the architecture where:
|
|
539
|
+
// 1. Customer configs are persistent (deployment history/state)
|
|
540
|
+
// 2. Root wrangler.toml is ephemeral (reflects current active deployment)
|
|
541
|
+
if (this.cloudflareZoneName) {
|
|
542
|
+
console.log(` 🔧 Preparing customer config for zone: ${this.cloudflareZoneName}`);
|
|
543
|
+
|
|
544
|
+
// Generate or update customer config with current deployment parameters
|
|
545
|
+
const customerConfigPath = await this.wranglerConfigManager.generateCustomerConfig(this.cloudflareZoneName, {
|
|
546
|
+
accountId: this.cloudflareAccountId,
|
|
547
|
+
environment: this.environment
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
// Copy customer config to root (ephemeral working copy for this deployment)
|
|
551
|
+
console.log(` 📋 Copying customer config to root wrangler.toml`);
|
|
552
|
+
await this.wranglerConfigManager.copyCustomerConfig(customerConfigPath);
|
|
553
|
+
} else {
|
|
554
|
+
// Fallback: Update root wrangler.toml directly if no zone name available
|
|
555
|
+
console.log(` ⚠️ No zone name available, updating root wrangler.toml directly`);
|
|
556
|
+
if (this.cloudflareAccountId) {
|
|
557
|
+
await this.wranglerConfigManager.setAccountId(this.cloudflareAccountId);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Ensure environment section exists in wrangler.toml
|
|
521
562
|
console.log(` 📝 Verifying wrangler.toml configuration...`);
|
|
522
563
|
try {
|
|
523
564
|
await this.wranglerConfigManager.ensureEnvironment(this.environment);
|
|
@@ -526,18 +567,18 @@ export class MultiDomainOrchestrator {
|
|
|
526
567
|
// Continue anyway - wrangler will provide clearer error if config is wrong
|
|
527
568
|
}
|
|
528
569
|
|
|
529
|
-
//
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
// Build deploy command with environment
|
|
570
|
+
// Build deploy command
|
|
571
|
+
// Note: We already copied customer config to root wrangler.toml above
|
|
572
|
+
// So wrangler will use root wrangler.toml which has the correct account_id
|
|
533
573
|
let deployCommand = `npx wrangler deploy`;
|
|
534
574
|
|
|
535
|
-
//
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
console.log(` � Executing: ${deployCommand}`);
|
|
575
|
+
// ALWAYS add environment flag to use environment-specific config
|
|
576
|
+
// Even for production, we use [env.production] section which has the correct worker name and DB
|
|
577
|
+
deployCommand += ` --env ${this.environment}`;
|
|
578
|
+
console.log(` 🔧 Executing: ${deployCommand}`);
|
|
540
579
|
console.log(` 📁 Working directory: ${this.servicePath}`);
|
|
580
|
+
console.log(` 📄 Using wrangler.toml from service root (already updated with customer config)`);
|
|
581
|
+
console.log(` 🌍 Environment: ${this.environment}`);
|
|
541
582
|
|
|
542
583
|
// Execute deployment with timeout
|
|
543
584
|
const {
|
|
@@ -566,9 +607,9 @@ export class MultiDomainOrchestrator {
|
|
|
566
607
|
const urlMatch = stdout.match(/https:\/\/[^\s]+/);
|
|
567
608
|
const workerUrl = urlMatch ? urlMatch[0] : null;
|
|
568
609
|
|
|
569
|
-
//
|
|
570
|
-
|
|
571
|
-
const customUrl =
|
|
610
|
+
// Construct custom domain URL using centralized template from validation-config.json
|
|
611
|
+
// Handles all environment patterns: production, staging, development
|
|
612
|
+
const customUrl = buildCustomDomain(this.serviceName, domain, this.environment);
|
|
572
613
|
|
|
573
614
|
// Store URLs in domain state
|
|
574
615
|
const domainState = this.portfolioState.domainStates.get(domain);
|
package/dist/security/index.js
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
import { ConfigurationValidator } from './ConfigurationValidator.js';
|
|
7
7
|
// DeploymentManager removed - replaced by MultiDomainOrchestrator + WranglerConfigManager
|
|
8
8
|
import { SecretGenerator } from './SecretGenerator.js';
|
|
9
|
-
import { ErrorHandler } from
|
|
9
|
+
import { ErrorHandler } from '../lib/shared/utils/index.js';
|
|
10
10
|
// InteractiveDeploymentConfigurator removed - replaced by InputCollector
|
|
11
11
|
|
|
12
12
|
export { ConfigurationValidator } from './ConfigurationValidator.js';
|
|
13
13
|
// export { DeploymentManager } - DEPRECATED: Use MultiDomainOrchestrator instead
|
|
14
14
|
export { SecretGenerator } from './SecretGenerator.js';
|
|
15
|
-
export { ErrorHandler } from '
|
|
15
|
+
export { ErrorHandler } from '../lib/shared/utils/index.js';
|
|
16
16
|
// export { InteractiveDeploymentConfigurator } - DEPRECATED: Use InputCollector instead
|
|
17
17
|
|
|
18
18
|
// Re-export patterns and rules for advanced usage
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
export const INSECURE_PATTERNS = {
|
|
7
7
|
// Development/dummy API keys
|
|
8
|
-
DUMMY_API_KEYS: ['content-skimmer-dev-key', 'logger-service-dev-key', 'auth-service-dev-key', 'test-key', 'dev-key', 'dummy-key', 'placeholder-key', 'example-key', 'sample-key', 'demo-key', 'test-api-key-*', 'dummy-*-key', 'dev-*-secret', 'placeholder-*', 'example-*-token', 'fake-*-credential', 'mock-*-password'],
|
|
8
|
+
DUMMY_API_KEYS: ['content-skimmer-dev-key', 'logger-service-dev-key', 'auth-service-dev-key', 'test-key', 'dev-key', 'dummy-key', 'dummy-api-key', 'placeholder-key', 'example-key', 'sample-key', 'demo-key', 'test-api-key-*', 'dummy-*-key', 'dev-*-secret', 'placeholder-*', 'example-*-token', 'fake-*-credential', 'mock-*-password'],
|
|
9
9
|
// Weak secrets (common insecure values)
|
|
10
10
|
WEAK_SECRETS: ['secret', 'password', '123456', 'admin', 'test', 'changeme', 'default', 'password123', 'admin123', 'root', 'guest'],
|
|
11
11
|
// Development URLs that shouldn't be in production
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
import { createInterface } from 'readline';
|
|
35
35
|
import chalk from 'chalk';
|
|
36
36
|
import { validateServiceName, validateDomainName } from '../utils/validation.js';
|
|
37
|
-
import { NameFormatters, UrlFormatters, ResourceFormatters } from
|
|
37
|
+
import { NameFormatters, UrlFormatters, ResourceFormatters } from '../lib/shared/utils/formatters.js';
|
|
38
38
|
export class ConfirmationEngine {
|
|
39
39
|
constructor(options = {}) {
|
|
40
40
|
this.interactive = options.interactive !== false;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import chalk from 'chalk';
|
|
11
|
-
import { logger } from
|
|
11
|
+
import { logger } from '../lib/shared/logging/Logger.js';
|
|
12
12
|
export class ErrorTracker {
|
|
13
13
|
constructor() {
|
|
14
14
|
this.errors = [];
|
|
@@ -15,7 +15,7 @@ import { createInterface } from 'readline';
|
|
|
15
15
|
import chalk from 'chalk';
|
|
16
16
|
import { validateServiceName, validateDomainName } from '../utils/validation.js';
|
|
17
17
|
import { uiStructuresLoader } from '../utils/ui-structures-loader.js';
|
|
18
|
-
import { NameFormatters, UrlFormatters, ResourceFormatters } from
|
|
18
|
+
import { NameFormatters, UrlFormatters, ResourceFormatters } from '../lib/shared/utils/formatters.js';
|
|
19
19
|
|
|
20
20
|
// Assessment capabilities moved to @tamyla/clodo-orchestration (professional edition)
|
|
21
21
|
|