@tamyla/clodo-framework 3.1.27 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/cli/clodo-simple.js +1 -1
- package/dist/cli/commands/assess.js +1 -1
- package/dist/cli/commands/create.js +1 -1
- package/dist/cli/commands/deploy.js +59 -21
- package/dist/cli/commands/diagnose.js +1 -1
- package/dist/cli/commands/update.js +1 -1
- package/dist/cli/commands/validate.js +1 -1
- package/dist/cli/security-cli.js +1 -1
- package/dist/config/.env.staging.example +25 -0
- package/dist/deployment/index.js +2 -2
- package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +1 -1
- package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +2 -4
- package/dist/index.js +11 -12
- package/dist/lib/deployment/orchestration/BaseDeploymentOrchestrator.js +1 -1
- package/dist/lib/shared/cloudflare/ops.js +103 -17
- package/dist/lib/shared/deployment/credential-collector.js +134 -1
- package/dist/lib/shared/deployment/index.js +7 -3
- package/dist/lib/shared/deployment/rollback-manager.js +1 -1
- package/dist/lib/shared/deployment/utilities/d1-error-recovery.js +1 -1
- package/dist/lib/shared/deployment/workflows/index.js +13 -0
- package/dist/lib/shared/deployment/workflows/interactive-confirmation.js +1 -1
- package/dist/lib/shared/deployment/workflows/interactive-deployment-coordinator.js +229 -0
- package/dist/lib/shared/deployment/workflows/interactive-domain-info-gatherer.js +1 -1
- package/dist/lib/shared/deployment/workflows/interactive-secret-workflow.js +3 -3
- package/dist/lib/shared/deployment/workflows/interactive-testing-workflow.js +2 -2
- package/dist/lib/shared/deployment/workflows/interactive-validation.js +2 -2
- package/dist/lib/shared/monitoring/health-checker.js +11 -5
- package/dist/lib/shared/validation/ValidationRegistry.js +1 -1
- package/dist/utils/deployment/index.js +2 -1
- package/dist/utils/health-checker.js +53 -76
- package/dist/utils/index.js +3 -0
- package/package.json +4 -11
- package/templates/generic/src/worker/index.js +1 -1
- package/templates/static-site/src/worker/index.js +1 -1
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export { DeploymentValidator } from './validator.js';
|
|
7
|
-
export { MultiDomainOrchestrator } from '
|
|
8
|
-
export { CrossDomainCoordinator } from '
|
|
7
|
+
export { MultiDomainOrchestrator } from '@tamyla/clodo-framework/orchestration';
|
|
8
|
+
export { CrossDomainCoordinator } from '@tamyla/clodo-framework/orchestration';
|
|
9
9
|
export { DeploymentAuditor } from './auditor.js';
|
|
10
|
-
export { RollbackManager } from './rollback-manager.js';
|
|
10
|
+
export { RollbackManager } from './rollback-manager.js';
|
|
11
|
+
export { DeploymentCredentialCollector } from './credential-collector.js';
|
|
12
|
+
|
|
13
|
+
// Export workflow modules
|
|
14
|
+
export * from './workflows/index.js';
|
|
@@ -42,7 +42,7 @@ export class D1ErrorRecoveryManager {
|
|
|
42
42
|
// Import WranglerDeployer for D1 error handling
|
|
43
43
|
const {
|
|
44
44
|
WranglerDeployer
|
|
45
|
-
} = await import('
|
|
45
|
+
} = await import('@tamyla/clodo-framework/deployment');
|
|
46
46
|
deployer = new WranglerDeployer({
|
|
47
47
|
cwd: config.cwd || process.cwd(),
|
|
48
48
|
environment: config.environment
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment Workflows Module
|
|
3
|
+
* Exports all interactive deployment workflow coordinators and helpers
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { InteractiveDeploymentCoordinator } from './interactive-deployment-coordinator.js';
|
|
7
|
+
export { InteractiveConfirmationWorkflow } from './interactive-confirmation.js';
|
|
8
|
+
export { InteractiveDatabaseWorkflow } from './interactive-database-workflow.js';
|
|
9
|
+
export { InteractiveDomainInfoGatherer } from './interactive-domain-info-gatherer.js';
|
|
10
|
+
export { InteractiveSecretWorkflow } from './interactive-secret-workflow.js';
|
|
11
|
+
export { InteractiveTestingWorkflow } from './interactive-testing-workflow.js';
|
|
12
|
+
export { InteractiveValidationWorkflow } from './interactive-validation.js';
|
|
13
|
+
export { DeploymentSummaryWorkflow } from './deployment-summary.js';
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Deployment Coordinator
|
|
3
|
+
*
|
|
4
|
+
* Restores the interactive deployment functionality that was lost during enterprise code separation.
|
|
5
|
+
* Orchestrates the interactive workflows that were extracted from enterprise-deployment/master-deploy.js.
|
|
6
|
+
*
|
|
7
|
+
* This coordinator brings together:
|
|
8
|
+
* - InteractiveDomainInfoGatherer
|
|
9
|
+
* - InteractiveDatabaseWorkflow
|
|
10
|
+
* - InteractiveSecretWorkflow
|
|
11
|
+
* - InteractiveValidation
|
|
12
|
+
* - InteractiveConfirmation
|
|
13
|
+
* - InteractiveTestingWorkflow
|
|
14
|
+
*
|
|
15
|
+
* @module interactive-deployment-coordinator
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { InteractiveDomainInfoGatherer } from './interactive-domain-info-gatherer.js';
|
|
19
|
+
import { InteractiveDatabaseWorkflow } from './interactive-database-workflow.js';
|
|
20
|
+
import { InteractiveSecretWorkflow } from './interactive-secret-workflow.js';
|
|
21
|
+
import { InteractiveValidation } from './interactive-validation.js';
|
|
22
|
+
import { InteractiveConfirmation } from './interactive-confirmation.js';
|
|
23
|
+
import { InteractiveTestingWorkflow } from './interactive-testing-workflow.js';
|
|
24
|
+
import { Clodo } from '@tamyla/clodo-framework';
|
|
25
|
+
import { OutputFormatter } from '../../utils/output-formatter.js';
|
|
26
|
+
import { DeploymentCredentialCollector } from '../credential-collector.js';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Interactive Deployment Coordinator
|
|
30
|
+
* Orchestrates the complete interactive deployment workflow
|
|
31
|
+
*/
|
|
32
|
+
export class InteractiveDeploymentCoordinator {
|
|
33
|
+
/**
|
|
34
|
+
* @param {Object} options - Coordinator options
|
|
35
|
+
* @param {string} options.servicePath - Path to service directory
|
|
36
|
+
* @param {string} options.environment - Target environment
|
|
37
|
+
* @param {string} options.domain - Specific domain (optional)
|
|
38
|
+
* @param {boolean} options.dryRun - Dry run mode
|
|
39
|
+
* @param {Object} options.credentials - Cloudflare credentials
|
|
40
|
+
* @param {boolean} options.checkPrereqs - Check prerequisites
|
|
41
|
+
* @param {boolean} options.checkAuth - Check authentication
|
|
42
|
+
* @param {boolean} options.checkNetwork - Check network connectivity
|
|
43
|
+
* @param {boolean} options.verbose - Verbose output
|
|
44
|
+
* @param {boolean} options.quiet - Quiet output
|
|
45
|
+
* @param {boolean} options.json - JSON output
|
|
46
|
+
*/
|
|
47
|
+
constructor(options = {}) {
|
|
48
|
+
this.options = options;
|
|
49
|
+
this.output = new OutputFormatter(options);
|
|
50
|
+
this.deploymentState = {
|
|
51
|
+
config: {},
|
|
52
|
+
validation: {},
|
|
53
|
+
resources: {},
|
|
54
|
+
testing: {}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Initialize credential collector
|
|
58
|
+
this.credentialCollector = new DeploymentCredentialCollector({
|
|
59
|
+
quiet: options.quiet,
|
|
60
|
+
servicePath: options.servicePath
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Initialize interactive workflow components
|
|
64
|
+
this.workflows = {
|
|
65
|
+
domainGatherer: new InteractiveDomainInfoGatherer({
|
|
66
|
+
interactive: true,
|
|
67
|
+
configCache: null // TODO: Add config cache if available
|
|
68
|
+
}),
|
|
69
|
+
databaseWorkflow: new InteractiveDatabaseWorkflow({
|
|
70
|
+
interactive: true
|
|
71
|
+
}),
|
|
72
|
+
secretWorkflow: new InteractiveSecretWorkflow({
|
|
73
|
+
interactive: true
|
|
74
|
+
}),
|
|
75
|
+
validation: new InteractiveValidation({
|
|
76
|
+
interactive: true
|
|
77
|
+
}),
|
|
78
|
+
confirmation: InteractiveConfirmation,
|
|
79
|
+
testingWorkflow: new InteractiveTestingWorkflow({
|
|
80
|
+
interactive: true
|
|
81
|
+
})
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Run the complete interactive deployment workflow
|
|
87
|
+
* @returns {Promise<Object>} Deployment result
|
|
88
|
+
*/
|
|
89
|
+
async runInteractiveDeployment() {
|
|
90
|
+
try {
|
|
91
|
+
console.log('\n🔄 Starting Interactive Deployment Workflow...\n');
|
|
92
|
+
|
|
93
|
+
// Phase 1: Gather domain and environment information
|
|
94
|
+
await this.gatherDeploymentInfo();
|
|
95
|
+
|
|
96
|
+
// Phase 2: Configure database resources
|
|
97
|
+
await this.configureDatabase();
|
|
98
|
+
|
|
99
|
+
// Phase 3: Configure secrets and credentials
|
|
100
|
+
await this.configureSecrets();
|
|
101
|
+
|
|
102
|
+
// Phase 4: Validate configuration
|
|
103
|
+
await this.validateConfiguration();
|
|
104
|
+
|
|
105
|
+
// Phase 5: Show final confirmation
|
|
106
|
+
await this.showConfirmation();
|
|
107
|
+
|
|
108
|
+
// Phase 6: Execute deployment
|
|
109
|
+
const result = await this.executeDeployment();
|
|
110
|
+
|
|
111
|
+
// Phase 7: Run post-deployment testing
|
|
112
|
+
await this.runPostDeploymentTests();
|
|
113
|
+
return result;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
this.output.error(`Interactive deployment failed: ${error.message}`);
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Phase 1: Gather domain and environment information
|
|
122
|
+
*/
|
|
123
|
+
async gatherDeploymentInfo() {
|
|
124
|
+
console.log('📋 Phase 1: Gathering Deployment Information');
|
|
125
|
+
console.log('─'.repeat(50));
|
|
126
|
+
|
|
127
|
+
// Start with basic config from options
|
|
128
|
+
this.deploymentState.config = {
|
|
129
|
+
servicePath: this.options.servicePath || '.',
|
|
130
|
+
environment: this.options.environment || 'production',
|
|
131
|
+
domain: this.options.domain,
|
|
132
|
+
dryRun: this.options.dryRun || false
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Collect credentials with prerequisite checking
|
|
136
|
+
const credentialOptions = {
|
|
137
|
+
token: this.options.credentials?.token,
|
|
138
|
+
accountId: this.options.credentials?.accountId,
|
|
139
|
+
zoneId: this.options.credentials?.zoneId,
|
|
140
|
+
checkAuth: this.options.checkAuth,
|
|
141
|
+
checkNetwork: this.options.checkNetwork
|
|
142
|
+
};
|
|
143
|
+
this.deploymentState.config.credentials = await this.credentialCollector.collectCredentials(credentialOptions);
|
|
144
|
+
|
|
145
|
+
// Use interactive domain gatherer for missing information
|
|
146
|
+
if (!this.deploymentState.config.domain) {
|
|
147
|
+
this.deploymentState.config = await this.workflows.domainGatherer.gatherSingleDomainInfo(this.deploymentState.config);
|
|
148
|
+
}
|
|
149
|
+
console.log('✅ Domain information gathered\n');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Phase 2: Configure database resources
|
|
154
|
+
*/
|
|
155
|
+
async configureDatabase() {
|
|
156
|
+
console.log('🗄️ Phase 2: Configuring Database Resources');
|
|
157
|
+
console.log('─'.repeat(50));
|
|
158
|
+
this.deploymentState.resources.database = await this.workflows.databaseWorkflow.handleDatabaseSetup(this.deploymentState.config.domain, this.deploymentState.config.environment, {
|
|
159
|
+
interactive: true
|
|
160
|
+
});
|
|
161
|
+
console.log('✅ Database configuration complete\n');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Phase 3: Configure secrets and credentials
|
|
166
|
+
*/
|
|
167
|
+
async configureSecrets() {
|
|
168
|
+
console.log('🔐 Phase 3: Configuring Secrets & Credentials');
|
|
169
|
+
console.log('─'.repeat(50));
|
|
170
|
+
const workerName = `${this.deploymentState.config.domain}-data-service`;
|
|
171
|
+
this.deploymentState.resources.secrets = await this.workflows.secretWorkflow.handleSecretManagement(this.deploymentState.config.domain, this.deploymentState.config.environment, workerName, {
|
|
172
|
+
interactive: true
|
|
173
|
+
});
|
|
174
|
+
console.log('✅ Secrets configuration complete\n');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Phase 4: Validate configuration
|
|
179
|
+
*/
|
|
180
|
+
async validateConfiguration() {
|
|
181
|
+
console.log('✅ Phase 4: Validating Configuration');
|
|
182
|
+
console.log('─'.repeat(50));
|
|
183
|
+
this.deploymentState.validation = await this.workflows.validation.executePreDeploymentChecks(this.deploymentState.config);
|
|
184
|
+
console.log('✅ Configuration validation complete\n');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Phase 5: Show final confirmation
|
|
189
|
+
*/
|
|
190
|
+
async showConfirmation() {
|
|
191
|
+
console.log('🎯 Phase 5: Final Confirmation');
|
|
192
|
+
console.log('─'.repeat(50));
|
|
193
|
+
await this.workflows.confirmation.showFinalConfirmation(this.deploymentState.config, this.deploymentState, {
|
|
194
|
+
defaultAnswer: 'n'
|
|
195
|
+
});
|
|
196
|
+
console.log('✅ Deployment confirmed\n');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Phase 6: Execute deployment
|
|
201
|
+
*/
|
|
202
|
+
async executeDeployment() {
|
|
203
|
+
console.log('🚀 Phase 6: Executing Deployment');
|
|
204
|
+
console.log('─'.repeat(50));
|
|
205
|
+
const result = await Clodo.deploy({
|
|
206
|
+
servicePath: this.deploymentState.config.servicePath,
|
|
207
|
+
environment: this.deploymentState.config.environment,
|
|
208
|
+
domain: this.deploymentState.config.domain,
|
|
209
|
+
dryRun: this.deploymentState.config.dryRun,
|
|
210
|
+
credentials: this.deploymentState.config.credentials
|
|
211
|
+
});
|
|
212
|
+
if (result.success) {
|
|
213
|
+
console.log('✅ Deployment executed successfully\n');
|
|
214
|
+
} else {
|
|
215
|
+
throw new Error('Deployment execution failed');
|
|
216
|
+
}
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Phase 7: Run post-deployment testing
|
|
222
|
+
*/
|
|
223
|
+
async runPostDeploymentTests() {
|
|
224
|
+
console.log('🧪 Phase 7: Running Post-Deployment Tests');
|
|
225
|
+
console.log('─'.repeat(50));
|
|
226
|
+
this.deploymentState.testing = await this.workflows.testingWorkflow.executePostDeploymentTesting(this.deploymentState.config);
|
|
227
|
+
console.log('✅ Post-deployment testing complete\n');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @module interactive-domain-info-gatherer
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { askUser, askYesNo, askChoice } from '
|
|
10
|
+
import { askUser, askYesNo, askChoice } from '../../utils/interactive-prompts.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Interactive Domain Info Gatherer
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* @module interactive-secret-workflow
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { askYesNo } from '
|
|
11
|
-
import { generateSecrets, saveSecrets, distributeSecrets } from '
|
|
12
|
-
import { deploySecret } from '
|
|
10
|
+
import { askYesNo } from '../../utils/interactive-prompts.js';
|
|
11
|
+
import { generateSecrets, saveSecrets, distributeSecrets } from '../../security/secret-generator.js';
|
|
12
|
+
import { deploySecret } from '../../cloudflare/ops.js';
|
|
13
13
|
import { join } from 'path';
|
|
14
14
|
import { existsSync, readFileSync } from 'fs';
|
|
15
15
|
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* @module interactive-testing-workflow
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { askYesNo } from '
|
|
11
|
-
import { checkHealth } from '
|
|
10
|
+
import { askYesNo } from '../../utils/interactive-prompts.js';
|
|
11
|
+
import { checkHealth } from '../../monitoring/health-checker.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Interactive Testing Workflow
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* @module interactive-validation
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { askYesNo } from '
|
|
11
|
-
import { validatePrerequisites, checkAuth, authenticate, workerExists } from '
|
|
10
|
+
import { askYesNo } from '../../utils/interactive-prompts.js';
|
|
11
|
+
import { validatePrerequisites, checkAuth, authenticate, workerExists } from '../../cloudflare/ops.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Interactive Validation Workflow
|
|
@@ -12,10 +12,16 @@ import http from 'http';
|
|
|
12
12
|
const execAsync = promisify(exec);
|
|
13
13
|
|
|
14
14
|
// Load framework configuration
|
|
15
|
-
const {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
// const { frameworkConfig } = await import('@tamyla/clodo-framework/utils');
|
|
16
|
+
// const timing = frameworkConfig.getTiming();
|
|
17
|
+
|
|
18
|
+
// Use default timing values for now
|
|
19
|
+
const timing = {
|
|
20
|
+
healthCheckTimeout: 10000,
|
|
21
|
+
deploymentTimeout: 300000,
|
|
22
|
+
deploymentInterval: 5000,
|
|
23
|
+
endpointValidationTimeout: 5000
|
|
24
|
+
};
|
|
19
25
|
function makeHttpRequest(url, method = 'GET', timeout = 5000) {
|
|
20
26
|
return new Promise((resolve, reject) => {
|
|
21
27
|
const protocol = url.startsWith('https:') ? https : http;
|
|
@@ -546,7 +552,7 @@ export async function verifyWorkerDeployment(workerName, credentials, options =
|
|
|
546
552
|
}
|
|
547
553
|
const {
|
|
548
554
|
CloudflareAPI
|
|
549
|
-
} = await import('
|
|
555
|
+
} = await import('@tamyla/clodo-framework/utils/cloudflare');
|
|
550
556
|
const cfApi = new CloudflareAPI(credentials.token);
|
|
551
557
|
|
|
552
558
|
// List all workers to find ours
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
/**
|
|
9
9
|
* Import validators from utils (source of truth)
|
|
10
10
|
*/
|
|
11
|
-
import { validateServiceName, validateDomainName, validateCloudflareToken, validateCloudflareId, validateServiceType, validateEnvironment } from '
|
|
11
|
+
import { validateServiceName, validateDomainName, validateCloudflareToken, validateCloudflareId, validateServiceType, validateEnvironment } from '@tamyla/clodo-framework/utils';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Validation Registry - Single source of truth for all validators
|
|
@@ -4,4 +4,5 @@
|
|
|
4
4
|
export { ConfigurationCacheManager } from './config-cache.js';
|
|
5
5
|
export { EnhancedSecretManager } from './secret-generator.js';
|
|
6
6
|
export { UnifiedConfigManager, unifiedConfigManager } from '../config/unified-config-manager.js';
|
|
7
|
-
export { askUser, askYesNo, askChoice, closePrompts } from '../interactive-prompts.js';
|
|
7
|
+
export { askUser, askYesNo, askChoice, closePrompts } from '../interactive-prompts.js';
|
|
8
|
+
export { DeploymentCredentialCollector } from '../../../lib/shared/deployment/credential-collector.js';
|
|
@@ -1,43 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Health Checker Module
|
|
3
3
|
* Endpoint health checking and validation utilities
|
|
4
|
+
* Worker-compatible version using fetch API
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
import https from 'https';
|
|
7
|
-
import http from 'http';
|
|
8
|
-
|
|
9
7
|
/**
|
|
10
|
-
* Make HTTP request with timeout
|
|
8
|
+
* Make HTTP request with timeout using fetch
|
|
11
9
|
* @param {string} url - URL to request
|
|
12
10
|
* @param {string} method - HTTP method
|
|
13
11
|
* @param {number} timeout - Request timeout in ms
|
|
14
12
|
* @returns {Promise<Object>} Response data and status
|
|
15
13
|
*/
|
|
16
|
-
function makeHttpRequest(url, method = 'GET', timeout = 5000) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
async function makeHttpRequest(url, method = 'GET', timeout = 5000) {
|
|
15
|
+
const controller = new AbortController();
|
|
16
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(url, {
|
|
20
19
|
method,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
res.on('end', () => {
|
|
26
|
-
resolve({
|
|
27
|
-
data,
|
|
28
|
-
statusCode: res.statusCode
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
req.on('error', err => {
|
|
33
|
-
reject(err);
|
|
20
|
+
signal: controller.signal,
|
|
21
|
+
headers: {
|
|
22
|
+
'User-Agent': 'Clodo-Framework-Health-Check/1.0'
|
|
23
|
+
}
|
|
34
24
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
25
|
+
clearTimeout(timeoutId);
|
|
26
|
+
const data = await response.text();
|
|
27
|
+
return {
|
|
28
|
+
data,
|
|
29
|
+
statusCode: response.status,
|
|
30
|
+
headers: Object.fromEntries(response.headers.entries())
|
|
31
|
+
};
|
|
32
|
+
} catch (error) {
|
|
33
|
+
clearTimeout(timeoutId);
|
|
34
|
+
if (error.name === 'AbortError') {
|
|
35
|
+
throw new Error('Request timed out');
|
|
36
|
+
}
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
/**
|
|
@@ -47,55 +45,34 @@ function makeHttpRequest(url, method = 'GET', timeout = 5000) {
|
|
|
47
45
|
* @returns {Promise<Object>} Health check result
|
|
48
46
|
*/
|
|
49
47
|
export async function checkHealth(url, timeout = 10000) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
req.startTime = Date.now();
|
|
81
|
-
req.on('error', err => {
|
|
82
|
-
reject({
|
|
83
|
-
url: healthUrl,
|
|
84
|
-
error: err.message,
|
|
85
|
-
healthy: false,
|
|
86
|
-
responseTime: Date.now() - req.startTime
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
req.on('timeout', () => {
|
|
90
|
-
req.destroy();
|
|
91
|
-
reject({
|
|
92
|
-
url: healthUrl,
|
|
93
|
-
error: 'Health check timed out',
|
|
94
|
-
healthy: false,
|
|
95
|
-
responseTime: timeout
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
});
|
|
48
|
+
const startTime = Date.now();
|
|
49
|
+
const healthUrl = `${url.replace(/\/$/, '')}/health`;
|
|
50
|
+
try {
|
|
51
|
+
const result = await makeHttpRequest(healthUrl, 'GET', timeout);
|
|
52
|
+
const responseTime = Date.now() - startTime;
|
|
53
|
+
let data = null;
|
|
54
|
+
let parseError = null;
|
|
55
|
+
try {
|
|
56
|
+
data = result.data ? JSON.parse(result.data) : null;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
parseError = error.message;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
url: healthUrl,
|
|
62
|
+
status: result.statusCode,
|
|
63
|
+
healthy: result.statusCode >= 200 && result.statusCode < 300,
|
|
64
|
+
responseTime,
|
|
65
|
+
data,
|
|
66
|
+
parseError
|
|
67
|
+
};
|
|
68
|
+
} catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
url: healthUrl,
|
|
71
|
+
error: error.message,
|
|
72
|
+
healthy: false,
|
|
73
|
+
responseTime: Date.now() - startTime
|
|
74
|
+
};
|
|
75
|
+
}
|
|
99
76
|
}
|
|
100
77
|
|
|
101
78
|
/**
|
package/dist/utils/index.js
CHANGED
|
@@ -32,5 +32,8 @@ export const createLogger = (prefix = 'ClodoFramework') => {
|
|
|
32
32
|
// Health checking utilities
|
|
33
33
|
export * from './health-checker.js';
|
|
34
34
|
|
|
35
|
+
// Framework configuration
|
|
36
|
+
export * from './framework-config.js';
|
|
37
|
+
|
|
35
38
|
// Deployment utilities
|
|
36
39
|
export * from './deployment/index.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamyla/clodo-framework",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "Reusable framework for Clodo-style software architecture on Cloudflare Workers + D1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -19,26 +19,18 @@
|
|
|
19
19
|
"./routing": "./dist/routing/EnhancedRouter.js",
|
|
20
20
|
"./handlers": "./dist/handlers/GenericRouteHandler.js",
|
|
21
21
|
"./config": "./dist/config/index.js",
|
|
22
|
-
"./config/discovery": "./dist/config/discovery/domain-discovery.js",
|
|
23
22
|
"./config/customers": "./dist/config/customers.js",
|
|
24
23
|
"./utils/config": "./dist/utils/config/unified-config-manager.js",
|
|
25
24
|
"./worker": "./dist/worker/index.js",
|
|
26
|
-
"./utils": "./dist/utils/index.js",
|
|
25
|
+
"./utils/cloudflare": "./dist/utils/cloudflare/index.js",
|
|
27
26
|
"./utils/deployment": "./dist/utils/deployment/index.js",
|
|
28
27
|
"./orchestration": "./dist/orchestration/index.js",
|
|
29
28
|
"./deployment": "./dist/deployment/index.js",
|
|
30
|
-
"./deployment/testers": "./dist/deployment/testers/index.js",
|
|
31
|
-
"./deployment/testers/api": "./dist/deployment/testers/api-tester.js",
|
|
32
|
-
"./deployment/testers/auth": "./dist/deployment/testers/auth-tester.js",
|
|
33
|
-
"./deployment/testers/database": "./dist/deployment/testers/database-tester.js",
|
|
34
|
-
"./deployment/testers/performance": "./dist/deployment/testers/performance-tester.js",
|
|
35
|
-
"./deployment/testers/load": "./dist/deployment/testers/load-tester.js",
|
|
36
29
|
"./database": "./dist/database/index.js",
|
|
37
30
|
"./security": "./dist/security/index.js",
|
|
38
31
|
"./security/cli": "./dist/security/SecurityCLI.js",
|
|
39
32
|
"./service-management": "./dist/service-management/index.js",
|
|
40
33
|
"./service-management/create": "./dist/service-management/ServiceCreator.js",
|
|
41
|
-
"./service-management/init": "./dist/service-management/ServiceInitializer.js",
|
|
42
34
|
"./modules/security": "./dist/modules/security.js"
|
|
43
35
|
},
|
|
44
36
|
"bin": {
|
|
@@ -68,7 +60,7 @@
|
|
|
68
60
|
"build:ci": "npm run prebuild:ci && babel src/ --out-dir dist/ && babel cli/ --out-dir dist/cli/ --ignore 'cli/**/*.test.js' && babel lib/ --out-dir dist/lib/ --ignore 'lib/**/*.test.js' && node -e \"const fs=require('fs'); fs.cpSync('ui-structures', 'dist/ui-structures', {recursive: true}); fs.cpSync('config', 'dist/config', {recursive: true});\" && npm run postbuild",
|
|
69
61
|
"prebuild": "npm run clean && npm run type-check",
|
|
70
62
|
"prebuild:ci": "npm run clean && npm run type-check",
|
|
71
|
-
"postbuild": "npm run check:bundle && npm run check:imports && node scripts/utilities/fix-dist-imports.js",
|
|
63
|
+
"postbuild": "npm run check:bundle && npm run check:imports && node scripts/utilities/fix-dist-imports.js && node scripts/utilities/validate-dist-imports.js",
|
|
72
64
|
"clean": "rimraf dist",
|
|
73
65
|
"clean:generated": "rimraf generated",
|
|
74
66
|
"clean:all": "npm run clean && npm run clean:generated",
|
|
@@ -126,6 +118,7 @@
|
|
|
126
118
|
"test:automated:deployment": "node scripts/automated-testing-suite.js deployment",
|
|
127
119
|
"test:automated:lifecycle": "node scripts/automated-testing-suite.js lifecycle",
|
|
128
120
|
"test:automated:integration": "node scripts/automated-testing-suite.js integration",
|
|
121
|
+
"test:downstream": "node scripts/test-downstream-install.js",
|
|
129
122
|
"test:automated:performance": "node scripts/automated-testing-suite.js performance",
|
|
130
123
|
"test:automated:regression": "node scripts/automated-testing-suite.js regression"
|
|
131
124
|
},
|