@tamyla/clodo-framework 3.1.8 → 3.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/bin/clodo-service-old.js +868 -0
  3. package/dist/bin/clodo-service-test.js +10 -0
  4. package/dist/bin/clodo-service.js +62 -0
  5. package/dist/bin/commands/assess.js +76 -0
  6. package/dist/bin/commands/create.js +56 -0
  7. package/dist/bin/commands/deploy.js +196 -0
  8. package/dist/bin/commands/diagnose.js +70 -0
  9. package/dist/bin/commands/helpers.js +138 -0
  10. package/dist/bin/commands/update.js +55 -0
  11. package/dist/bin/commands/validate.js +26 -0
  12. package/dist/bin/database/deployment-db-manager.js +423 -0
  13. package/dist/bin/database/enterprise-db-manager.js +457 -0
  14. package/dist/bin/database/wrangler-d1-manager.js +685 -0
  15. package/dist/bin/deployment/enterprise-deploy.js +877 -0
  16. package/dist/bin/deployment/master-deploy.js +1376 -0
  17. package/dist/bin/deployment/modular-enterprise-deploy.js +466 -0
  18. package/dist/bin/deployment/modules/DeploymentConfiguration.js +395 -0
  19. package/dist/bin/deployment/modules/DeploymentOrchestrator.js +492 -0
  20. package/dist/bin/deployment/modules/EnvironmentManager.js +517 -0
  21. package/dist/bin/deployment/modules/MonitoringIntegration.js +560 -0
  22. package/dist/bin/deployment/modules/ValidationManager.js +342 -0
  23. package/dist/bin/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  24. package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +401 -0
  25. package/dist/bin/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  26. package/dist/bin/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  27. package/dist/bin/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  28. package/dist/bin/deployment/test-interactive-utils.js +66 -0
  29. package/dist/bin/portfolio/portfolio-manager.js +487 -0
  30. package/dist/bin/security/security-cli.js +108 -0
  31. package/dist/bin/service-management/create-service.js +122 -0
  32. package/dist/bin/service-management/init-service.js +79 -0
  33. package/dist/deployment/index.js +10 -9
  34. package/dist/deployment/rollback-manager.js +21 -508
  35. package/package.json +7 -7
  36. package/dist/shared/deployment/auditor.js +0 -986
  37. package/dist/shared/deployment/validator.js +0 -670
  38. package/dist/shared/production-tester/api-tester.js +0 -80
  39. package/dist/shared/production-tester/auth-tester.js +0 -129
  40. package/dist/shared/production-tester/core.js +0 -217
  41. package/dist/shared/production-tester/database-tester.js +0 -105
  42. package/dist/shared/production-tester/index.js +0 -74
  43. package/dist/shared/production-tester/load-tester.js +0 -120
  44. package/dist/shared/production-tester/performance-tester.js +0 -105
  45. /package/dist/{shared → bin/shared}/cloudflare/domain-discovery.js +0 -0
  46. /package/dist/{shared → bin/shared}/cloudflare/domain-manager.js +0 -0
  47. /package/dist/{shared → bin/shared}/cloudflare/index.js +0 -0
  48. /package/dist/{shared → bin/shared}/cloudflare/ops.js +0 -0
  49. /package/dist/{shared → bin/shared}/config/ConfigurationManager.js +0 -0
  50. /package/dist/{shared → bin/shared}/config/cache.js +0 -0
  51. /package/dist/{shared → bin/shared}/config/command-config-manager.js +0 -0
  52. /package/dist/{shared → bin/shared}/config/index.js +0 -0
  53. /package/dist/{shared → bin/shared}/config/manager.js +0 -0
  54. /package/dist/{shared → bin/shared}/database/connection-manager.js +0 -0
  55. /package/dist/{shared → bin/shared}/database/index.js +0 -0
  56. /package/dist/{shared → bin/shared}/database/orchestrator.js +0 -0
  57. /package/dist/{deployment → bin/shared/deployment}/auditor.js +0 -0
  58. /package/dist/{shared → bin/shared}/deployment/index.js +0 -0
  59. /package/dist/{shared → bin/shared}/deployment/rollback-manager.js +0 -0
  60. /package/dist/{deployment → bin/shared/deployment}/validator.js +0 -0
  61. /package/dist/{shared → bin/shared}/index.js +0 -0
  62. /package/dist/{shared → bin/shared}/logging/Logger.js +0 -0
  63. /package/dist/{shared → bin/shared}/monitoring/health-checker.js +0 -0
  64. /package/dist/{shared → bin/shared}/monitoring/index.js +0 -0
  65. /package/dist/{shared → bin/shared}/monitoring/memory-manager.js +0 -0
  66. /package/dist/{shared → bin/shared}/monitoring/production-monitor.js +0 -0
  67. /package/dist/{deployment/testers → bin/shared/production-tester}/api-tester.js +0 -0
  68. /package/dist/{deployment/testers → bin/shared/production-tester}/auth-tester.js +0 -0
  69. /package/dist/{deployment/testers → bin/shared/production-tester}/core.js +0 -0
  70. /package/dist/{deployment/testers → bin/shared/production-tester}/database-tester.js +0 -0
  71. /package/dist/{deployment/testers → bin/shared/production-tester}/index.js +0 -0
  72. /package/dist/{deployment/testers → bin/shared/production-tester}/load-tester.js +0 -0
  73. /package/dist/{deployment/testers → bin/shared/production-tester}/performance-tester.js +0 -0
  74. /package/dist/{shared → bin/shared}/security/api-token-manager.js +0 -0
  75. /package/dist/{shared → bin/shared}/security/index.js +0 -0
  76. /package/dist/{shared → bin/shared}/security/secret-generator.js +0 -0
  77. /package/dist/{shared → bin/shared}/security/secure-token-manager.js +0 -0
  78. /package/dist/{shared → bin/shared}/utils/ErrorHandler.js +0 -0
  79. /package/dist/{shared → bin/shared}/utils/error-recovery.js +0 -0
  80. /package/dist/{shared → bin/shared}/utils/file-manager.js +0 -0
  81. /package/dist/{shared → bin/shared}/utils/formatters.js +0 -0
  82. /package/dist/{shared → bin/shared}/utils/graceful-shutdown-manager.js +0 -0
  83. /package/dist/{shared → bin/shared}/utils/index.js +0 -0
  84. /package/dist/{shared → bin/shared}/utils/interactive-prompts.js +0 -0
  85. /package/dist/{shared → bin/shared}/utils/interactive-utils.js +0 -0
  86. /package/dist/{shared → bin/shared}/utils/rate-limiter.js +0 -0
  87. /package/dist/{shared → bin/shared}/validation/ValidationRegistry.js +0 -0
@@ -1,670 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Advanced Deployment Validator Module
5
- * Enterprise-grade validation system for comprehensive deployment verification
6
- *
7
- * Extracted from bulletproof-deploy.js and check-endpoint-structure.js with enhancements
8
- */
9
- import { access, readFile } from 'fs/promises';
10
- import { readFileSync } from 'fs';
11
- import { promisify } from 'util';
12
- import { exec } from 'child_process';
13
- import { join } from 'path';
14
- import { getCommandConfig } from '../config/command-config-manager.js';
15
- const execAsync = promisify(exec);
16
-
17
- /**
18
- * Advanced Deployment Validator
19
- * Provides comprehensive validation pipeline for enterprise deployments
20
- */
21
- export class DeploymentValidator {
22
- constructor(options = {}) {
23
- this.options = options; // Store options for later merging
24
- this.environment = options.environment || 'production';
25
- this.strictMode = options.strictMode || false;
26
- this.timeout = options.timeout || 30000;
27
- this.retryAttempts = options.retryAttempts || 3;
28
- this.retryDelay = options.retryDelay || 2000;
29
-
30
- // Initialize command configuration
31
- this.cmdConfig = getCommandConfig();
32
-
33
- // Load validation configuration from file
34
- this.validationConfig = this.loadValidationConfig();
35
-
36
- // Validation results tracking
37
- this.results = {
38
- overall: 'pending',
39
- categories: {
40
- prerequisites: 'pending',
41
- authentication: 'pending',
42
- network: 'pending',
43
- configuration: 'pending',
44
- endpoints: 'pending',
45
- deployment: 'pending'
46
- },
47
- details: [],
48
- warnings: [],
49
- errors: [],
50
- startTime: null,
51
- endTime: null
52
- };
53
- }
54
-
55
- /**
56
- * Load validation configuration from JSON file
57
- */
58
- loadValidationConfig() {
59
- const configPath = join(process.cwd(), 'validation-config.json');
60
- try {
61
- const configData = readFileSync(configPath, 'utf-8');
62
- const userConfig = JSON.parse(configData);
63
-
64
- // Merge with defaults
65
- const defaultConfig = {
66
- requiredCommands: Object.keys(this.cmdConfig?.config?.requiredCommands || {}) || ['npx', 'node', 'npm', 'wrangler'],
67
- requiredFiles: ['package.json', 'wrangler.toml'],
68
- requiredEnvironmentVars: [],
69
- networkEndpoints: ['https://api.cloudflare.com', 'https://registry.npmjs.org'],
70
- expectedEndpoints: this.getExpectedEndpoints()
71
- };
72
-
73
- // Handle new format with command objects
74
- if (userConfig.requiredCommands && typeof userConfig.requiredCommands === 'object' && !Array.isArray(userConfig.requiredCommands)) {
75
- // Convert object format to array for backward compatibility
76
- defaultConfig.requiredCommands = Object.values(userConfig.requiredCommands);
77
- } else if (userConfig.requiredCommands) {
78
- defaultConfig.requiredCommands = userConfig.requiredCommands;
79
- }
80
-
81
- // Override other config values
82
- if (userConfig.requiredFiles) defaultConfig.requiredFiles = userConfig.requiredFiles;
83
- if (userConfig.requiredEnvironmentVars) defaultConfig.requiredEnvironmentVars = userConfig.requiredEnvironmentVars;
84
- if (userConfig.networkEndpoints) defaultConfig.networkEndpoints = userConfig.networkEndpoints;
85
- console.log('📋 Loaded validation config from validation-config.json');
86
- return defaultConfig;
87
- } catch (error) {
88
- // Fall back to defaults if file doesn't exist or is invalid
89
- console.log('📋 Using default validation config (validation-config.json not found or invalid)');
90
- return {
91
- requiredCommands: Object.keys(this.cmdConfig?.config?.requiredCommands || {}) || ['npx', 'node', 'npm', 'wrangler'],
92
- requiredFiles: ['package.json', 'wrangler.toml'],
93
- requiredEnvironmentVars: [],
94
- networkEndpoints: ['https://api.cloudflare.com', 'https://registry.npmjs.org'],
95
- expectedEndpoints: this.getExpectedEndpoints()
96
- };
97
- }
98
- }
99
-
100
- /**
101
- * Get expected endpoints for validation
102
- * @returns {Array<string>} List of expected endpoints
103
- */
104
- getExpectedEndpoints() {
105
- return [
106
- // Authentication
107
- 'POST /register', 'POST /auth/magic-link', 'GET /auth/me', 'POST /auth/verify', 'POST /auth/session',
108
- // User Management
109
- 'GET /users', 'GET /users/profile', 'PATCH /users/profile',
110
- // File Management
111
- 'GET /files', 'POST /files', 'GET /files/stats', 'GET /files/:id', 'PATCH /files/:id', 'DELETE /files/:id',
112
- // Logging
113
- 'POST /logs/store', 'GET /logs', 'GET /logs/analytics',
114
- // Enhanced Framework (Auto-generated CRUD)
115
- 'GET /api/users', 'POST /api/users', 'GET /api/users/:id', 'PATCH /api/users/:id', 'DELETE /api/users/:id', 'GET /api/files', 'POST /api/files', 'GET /api/files/:id', 'PATCH /api/files/:id', 'DELETE /api/files/:id', 'GET /api/products', 'POST /api/products', 'GET /api/products/:id', 'PATCH /api/products/:id', 'DELETE /api/products/:id', 'GET /api/orders', 'POST /api/orders', 'GET /api/orders/:id', 'PATCH /api/orders/:id', 'DELETE /api/orders/:id',
116
- // System
117
- 'GET /health', 'GET /'];
118
- }
119
-
120
- /**
121
- * Run comprehensive validation pipeline
122
- * @param {string|Array<string>} domains - Domain(s) to validate
123
- * @param {Object} options - Validation options
124
- * @returns {Promise<Object>} Validation results
125
- */
126
- async validateDeployment(domains = [], options = {}) {
127
- this.options = {
128
- ...this.options,
129
- ...options
130
- }; // Merge with existing options
131
- this.results.startTime = new Date();
132
- const domainList = Array.isArray(domains) ? domains : [domains];
133
- try {
134
- console.log('🔍 Advanced Deployment Validation');
135
- console.log('=================================');
136
- console.log(`🌍 Environment: ${this.environment}`);
137
- console.log(`📋 Domains: ${domainList.length > 0 ? domainList.join(', ') : 'Pre-deployment only'}`);
138
- console.log(`⚙️ Strict Mode: ${this.strictMode ? 'ON' : 'OFF'}`);
139
- console.log('');
140
-
141
- // Phase 1: Prerequisites Validation
142
- await this.validatePrerequisites();
143
-
144
- // Phase 2: Authentication Validation
145
- await this.validateAuthentication();
146
-
147
- // Phase 3: Network Connectivity
148
- await this.validateNetworkConnectivity();
149
-
150
- // Phase 4: Configuration Validation
151
- await this.validateConfiguration();
152
-
153
- // Phase 5: Endpoint Structure (if domains provided and not a new deployment)
154
- if (domainList.length > 0 && domainList[0] && !this.options.skipEndpointCheck) {
155
- await this.validateEndpointStructure(domainList);
156
- } else if (this.options.skipEndpointCheck) {
157
- console.log('🔗 Phase 5: Endpoint Structure Validation');
158
- console.log(' ⏭️ Skipping endpoint validation for new deployment');
159
- this.results.categories.endpoints = 'skipped';
160
- this.addResult('endpoints', 'Skipped for new deployment', 'info');
161
- } else {
162
- // No domains to validate
163
- console.log('🔗 Phase 5: Endpoint Structure Validation');
164
- console.log(' ⏭️ No domains provided for validation');
165
- this.results.categories.endpoints = 'skipped';
166
- this.addResult('endpoints', 'No domains to validate', 'info');
167
- }
168
-
169
- // Phase 6: Deployment Readiness
170
- await this.validateDeploymentReadiness();
171
- this.results.overall = 'passed';
172
- this.results.endTime = new Date();
173
- console.log('\n✅ VALIDATION COMPLETE');
174
- this.printValidationSummary();
175
- return this.results;
176
- } catch (error) {
177
- this.results.overall = 'failed';
178
- this.results.endTime = new Date();
179
- this.results.errors.push({
180
- phase: 'validation',
181
- message: error.message,
182
- timestamp: new Date()
183
- });
184
- console.error('\n❌ VALIDATION FAILED');
185
- console.error(`Error: ${error.message}`);
186
- this.printValidationSummary();
187
- throw error;
188
- }
189
- }
190
-
191
- /**
192
- * Validate system prerequisites
193
- */
194
- async validatePrerequisites() {
195
- console.log('🔧 Phase 1: Prerequisites Validation');
196
- try {
197
- // Check required commands
198
- for (const cmd of this.validationConfig.requiredCommands) {
199
- await this.validateCommand(cmd);
200
- }
201
-
202
- // Check required files
203
- for (const file of this.validationConfig.requiredFiles) {
204
- await this.validateFile(file);
205
- }
206
-
207
- // Check Node.js version
208
- await this.validateNodeVersion();
209
- this.results.categories.prerequisites = 'passed';
210
- this.addResult('prerequisites', 'All prerequisites validated', 'success');
211
- } catch (error) {
212
- this.results.categories.prerequisites = 'failed';
213
- throw new Error(`Prerequisites validation failed: ${error.message}`);
214
- }
215
- }
216
-
217
- /**
218
- * Validate authentication systems
219
- */
220
- async validateAuthentication() {
221
- console.log('🔐 Phase 2: Authentication Validation');
222
- try {
223
- // Cloudflare authentication (optional for development)
224
- try {
225
- await this.validateCloudflareAuth();
226
- } catch (error) {
227
- console.log(` ⚠️ Cloudflare: ${error.message} (optional for development)`);
228
- this.addResult('cloudflare-auth', 'Cloudflare not authenticated (development mode)', 'warning');
229
- }
230
-
231
- // NPM authentication (if needed)
232
- await this.validateNpmAuth();
233
- this.results.categories.authentication = 'passed';
234
- this.addResult('authentication', 'Authentication validation completed', 'success');
235
- } catch (error) {
236
- this.results.categories.authentication = 'failed';
237
- throw new Error(`Authentication validation failed: ${error.message}`);
238
- }
239
- }
240
-
241
- /**
242
- * Validate network connectivity
243
- */
244
- async validateNetworkConnectivity() {
245
- console.log('🌐 Phase 3: Network Connectivity');
246
- try {
247
- for (const endpoint of this.validationConfig.networkEndpoints) {
248
- await this.validateNetworkEndpoint(endpoint);
249
- }
250
- this.results.categories.network = 'passed';
251
- this.addResult('network', 'Network connectivity verified', 'success');
252
- } catch (error) {
253
- this.results.categories.network = 'failed';
254
- throw new Error(`Network validation failed: ${error.message}`);
255
- }
256
- }
257
-
258
- /**
259
- * Validate configuration files
260
- */
261
- async validateConfiguration() {
262
- console.log('⚙️ Phase 4: Configuration Validation');
263
- try {
264
- // Validate package.json
265
- await this.validatePackageJson();
266
-
267
- // Skip wrangler.toml validation for multi-service framework
268
- // Each service has its own wrangler.toml
269
- console.log(' ⏭️ Skipping wrangler.toml validation (per-service configuration)');
270
-
271
- // Validate environment configuration
272
- await this.validateEnvironmentConfig();
273
-
274
- // Validate D1 database bindings
275
- await this.validateD1Configuration();
276
- this.results.categories.configuration = 'passed';
277
- this.addResult('configuration', 'Configuration files validated', 'success');
278
- } catch (error) {
279
- this.results.categories.configuration = 'failed';
280
- throw new Error(`Configuration validation failed: ${error.message}`);
281
- }
282
- }
283
-
284
- /**
285
- * Validate endpoint structure for deployed domains
286
- * @param {Array<string>} domains - Domains to validate
287
- */
288
- async validateEndpointStructure(domains) {
289
- console.log('🔗 Phase 5: Endpoint Structure Validation');
290
-
291
- // Double-check skip condition
292
- if (this.options?.skipEndpointCheck) {
293
- console.log(' ⏭️ Skipping endpoint validation (skipEndpointCheck=true)');
294
- this.results.categories.endpoints = 'skipped';
295
- this.addResult('endpoints', 'Skipped for new deployment', 'info');
296
- return;
297
- }
298
- try {
299
- for (const domain of domains) {
300
- await this.validateDomainEndpoints(domain);
301
- }
302
- this.results.categories.endpoints = 'passed';
303
- this.addResult('endpoints', 'Endpoint structure validated', 'success');
304
- } catch (error) {
305
- this.results.categories.endpoints = 'failed';
306
- throw new Error(`Endpoint validation failed: ${error.message}`);
307
- }
308
- }
309
-
310
- /**
311
- * Validate deployment readiness
312
- */
313
- async validateDeploymentReadiness() {
314
- console.log('🚀 Phase 6: Deployment Readiness');
315
- try {
316
- // Check disk space
317
- await this.validateDiskSpace();
318
-
319
- // Check memory usage
320
- await this.validateMemoryUsage();
321
-
322
- // Validate build process
323
- await this.validateBuildProcess();
324
- this.results.categories.deployment = 'passed';
325
- this.addResult('deployment', 'Deployment readiness confirmed', 'success');
326
- return {
327
- valid: true
328
- };
329
- } catch (error) {
330
- this.results.categories.deployment = 'failed';
331
- this.addResult('deployment', `Deployment readiness failed: ${error.message}`, 'error');
332
- return {
333
- valid: false,
334
- errors: [error.message]
335
- };
336
- }
337
- }
338
-
339
- // Individual validation methods
340
-
341
- async validateCommand(command) {
342
- console.log(` Checking ${command}...`);
343
- try {
344
- // Get command from configuration if available
345
- let actualCommand = command;
346
- try {
347
- actualCommand = this.cmdConfig.getRequiredCommand(command);
348
- } catch (error) {
349
- // Use original command if not in config
350
- }
351
- const result = await this.executeWithRetry(`${actualCommand} --version`);
352
- const version = result.trim().split('\\n')[0];
353
- console.log(` ✅ ${command}: ${version}`);
354
- this.addResult('command', `${command} available: ${version}`, 'info');
355
- } catch (error) {
356
- throw new Error(`Required command '${command}' not available: ${error.message}`);
357
- }
358
- }
359
- async validateFile(filePath) {
360
- console.log(` Checking ${filePath}...`);
361
- try {
362
- await access(filePath);
363
- console.log(` ✅ ${filePath}: exists`);
364
- this.addResult('file', `${filePath} exists`, 'info');
365
- } catch {
366
- throw new Error(`Required file '${filePath}' not found`);
367
- }
368
- }
369
- async validateNodeVersion() {
370
- console.log(' Checking Node.js version...');
371
- try {
372
- const version = process.version;
373
- const majorVersion = parseInt(version.slice(1).split('.')[0]);
374
- if (majorVersion < 16) {
375
- throw new Error(`Node.js version ${version} is too old. Minimum required: v16.0.0`);
376
- }
377
- console.log(` ✅ Node.js: ${version}`);
378
- this.addResult('node', `Node.js version: ${version}`, 'info');
379
- } catch (error) {
380
- throw new Error(`Node.js validation failed: ${error.message}`);
381
- }
382
- }
383
- async validateCloudflareAuth() {
384
- console.log(' Checking Cloudflare authentication...');
385
- try {
386
- const whoamiCmd = this.cmdConfig.getCloudflareCommand('whoami');
387
- const result = await this.executeWithRetry(whoamiCmd);
388
- if (result.includes('You are not authenticated') || result.includes('not logged in')) {
389
- const authCmd = this.cmdConfig.getCloudflareCommand('auth_login');
390
- throw new Error(`Cloudflare authentication required. Run: ${authCmd}`);
391
- }
392
- console.log(` ✅ Cloudflare: authenticated`);
393
- this.addResult('cloudflare-auth', 'Cloudflare authenticated', 'success');
394
- } catch (error) {
395
- throw new Error(`Cloudflare authentication failed: ${error.message}`);
396
- }
397
- }
398
- async validateNpmAuth() {
399
- console.log(' Checking NPM authentication...');
400
- try {
401
- // NPM auth is optional for most deployments
402
- const npmCmd = this.cmdConfig.getRequiredCommand('npm');
403
- const result = await this.executeWithRetry(`${npmCmd} whoami`);
404
- console.log(` ✅ NPM: authenticated as ${result.trim()}`);
405
- this.addResult('npm-auth', `NPM authenticated: ${result.trim()}`, 'info');
406
- } catch (error) {
407
- // NPM auth failure is usually not critical
408
- console.log(` ⚠️ NPM: not authenticated (optional)`);
409
- this.addResult('npm-auth', 'NPM not authenticated (optional)', 'warning');
410
- }
411
- }
412
- async validateNetworkEndpoint(endpoint) {
413
- console.log(` Testing connectivity to ${endpoint}...`);
414
- try {
415
- // Use configurable network test command
416
- const command = this.cmdConfig.getNetworkTestCommand(endpoint);
417
- await this.executeWithRetry(command, 15000);
418
- console.log(` ✅ ${endpoint}: reachable`);
419
- this.addResult('network', `${endpoint} reachable`, 'info');
420
- } catch (error) {
421
- throw new Error(`Cannot reach ${endpoint}: ${error.message}`);
422
- }
423
- }
424
- async validatePackageJson() {
425
- console.log(' Validating package.json...');
426
- try {
427
- const packageContent = await readFile('package.json', 'utf8');
428
- const packageJson = JSON.parse(packageContent);
429
-
430
- // Check required fields
431
- const requiredFields = ['name', 'version', 'scripts'];
432
- const missingFields = requiredFields.filter(field => !packageJson[field]);
433
- if (missingFields.length > 0) {
434
- throw new Error(`Missing required fields in package.json: ${missingFields.join(', ')}`);
435
- }
436
- console.log(` ✅ package.json: valid`);
437
- this.addResult('package-json', 'package.json validation passed', 'info');
438
- } catch (error) {
439
- throw new Error(`package.json validation failed: ${error.message}`);
440
- }
441
- }
442
- async validateWranglerConfig() {
443
- console.log(' Validating wrangler.toml...');
444
- try {
445
- const wranglerContent = await readFile('wrangler.toml', 'utf8');
446
-
447
- // Basic validation - check for required sections
448
- if (!wranglerContent.includes('name') || !wranglerContent.includes('compatibility_date')) {
449
- throw new Error('wrangler.toml missing required configuration');
450
- }
451
- console.log(` ✅ wrangler.toml: valid`);
452
- this.addResult('wrangler-config', 'wrangler.toml validation passed', 'info');
453
- } catch (error) {
454
- throw new Error(`wrangler.toml validation failed: ${error.message}`);
455
- }
456
- }
457
- async validateEnvironmentConfig() {
458
- console.log(' Validating environment configuration...');
459
- // Environment validation logic here
460
- console.log(` ✅ Environment: ${this.environment} configuration valid`);
461
- this.addResult('environment', `${this.environment} environment validated`, 'info');
462
- }
463
-
464
- /**
465
- * Validate D1 database configuration across all services
466
- */
467
- async validateD1Configuration() {
468
- console.log(' 🗄️ Validating D1 database configuration...');
469
- try {
470
- // Import WranglerDeployer for D1 validation capabilities
471
- const {
472
- WranglerDeployer
473
- } = await import('../../../dist/deployment/wrangler-deployer.js');
474
-
475
- // Check if this is a framework-level validation (no specific service)
476
- if (!this.options?.servicePath) {
477
- console.log(' ⏭️ Skipping D1 validation (framework-level validation)');
478
- this.addResult('d1-config', 'D1 validation skipped for framework-level validation', 'info');
479
- return;
480
- }
481
-
482
- // Create deployer instance for the specific service
483
- const deployer = new WranglerDeployer({
484
- cwd: this.options.servicePath,
485
- environment: this.environment
486
- });
487
-
488
- // Discover deployment configuration
489
- const deployConfig = await deployer.discoverDeploymentConfig(this.environment);
490
- if (!deployConfig.configPath) {
491
- console.log(' ⏭️ No wrangler.toml found, skipping D1 validation');
492
- this.addResult('d1-config', 'No wrangler.toml found', 'info');
493
- return;
494
- }
495
-
496
- // Validate D1 bindings
497
- const d1Validation = await deployer.validateD1Bindings(deployConfig);
498
- if (d1Validation.valid) {
499
- if (d1Validation.bindings.length === 0) {
500
- console.log(' ✅ No D1 databases configured');
501
- this.addResult('d1-config', 'No D1 databases configured', 'info');
502
- } else {
503
- console.log(` ✅ All ${d1Validation.summary.total} D1 database bindings valid`);
504
- this.addResult('d1-config', `${d1Validation.summary.total} D1 bindings validated`, 'success');
505
-
506
- // Log details about each binding
507
- d1Validation.bindings.forEach(binding => {
508
- if (binding.valid) {
509
- console.log(` ✅ ${binding.binding}: ${binding.database_name}`);
510
- }
511
- });
512
- }
513
- } else {
514
- console.log(` ❌ D1 validation failed: ${d1Validation.summary.invalid} invalid bindings`);
515
-
516
- // Log details about invalid bindings
517
- d1Validation.invalidBindings.forEach(binding => {
518
- console.log(` ❌ ${binding.binding || 'unnamed'}: ${binding.issues.join(', ')}`);
519
- });
520
-
521
- // Add warning with suggestions
522
- const suggestions = this.generateD1Suggestions(d1Validation);
523
- this.addWarning('d1-config', `D1 configuration issues found. ${suggestions}`);
524
-
525
- // Don't fail validation entirely for D1 issues if not in strict mode
526
- if (!this.strictMode) {
527
- console.log(' ⚠️ Continuing with warnings (non-strict mode)');
528
- this.addResult('d1-config', 'D1 issues found but continuing', 'warning');
529
- } else {
530
- throw new Error(`D1 validation failed: ${d1Validation.summary.invalid} invalid bindings`);
531
- }
532
- }
533
- } catch (error) {
534
- if (error.message.includes('D1 validation failed')) {
535
- throw error; // Re-throw D1 validation errors
536
- }
537
-
538
- // Handle other errors (import errors, etc.)
539
- console.log(` ⚠️ D1 validation error: ${error.message}`);
540
- this.addWarning('d1-config', `D1 validation error: ${error.message}`);
541
- if (this.strictMode) {
542
- throw new Error(`D1 validation failed: ${error.message}`);
543
- }
544
- }
545
- }
546
-
547
- /**
548
- * Generate helpful suggestions for D1 configuration issues
549
- * @param {Object} d1Validation - D1 validation results
550
- * @returns {string} Suggestions text
551
- */
552
- generateD1Suggestions(d1Validation) {
553
- const suggestions = [];
554
- d1Validation.invalidBindings.forEach(binding => {
555
- binding.issues.forEach(issue => {
556
- if (issue.includes('not found')) {
557
- suggestions.push('Run "wrangler d1 list" to see available databases');
558
- suggestions.push('Create missing database with "wrangler d1 create <name>"');
559
- } else if (issue.includes('Missing')) {
560
- suggestions.push('Check wrangler.toml [[d1_databases]] section completeness');
561
- }
562
- });
563
- });
564
-
565
- // Remove duplicates
566
- const uniqueSuggestions = [...new Set(suggestions)];
567
- return uniqueSuggestions.length > 0 ? `Suggestions: ${uniqueSuggestions.slice(0, 2).join('; ')}` : 'Check D1 database configuration in wrangler.toml';
568
- }
569
- async validateDomainEndpoints(domain) {
570
- console.log(` Validating endpoints for ${domain}...`);
571
- console.log(` 🔧 DEBUG: skipEndpointCheck = ${this.options?.skipEndpointCheck}`);
572
- console.log(` 🔧 DEBUG: deploymentType = ${this.options?.deploymentType}`);
573
- console.log(` 🔧 DEBUG: options = ${JSON.stringify(this.options)}`);
574
-
575
- // Skip endpoint validation for new deployments
576
- if (this.options?.skipEndpointCheck) {
577
- console.log(` ⏭️ Skipping endpoint validation for new deployment`);
578
- this.addResult('endpoints', 'Skipped for new deployment', 'info');
579
- return;
580
- }
581
- try {
582
- // Test health endpoint first
583
- const healthUrl = `https://${domain}/health`;
584
- const command = this.cmdConfig.getNetworkTestCommand(healthUrl);
585
- await this.executeWithRetry(command, 15000);
586
- console.log(` ✅ ${domain}: health endpoint responding`);
587
- this.addResult('endpoints', `${domain} endpoints accessible`, 'success');
588
- } catch (error) {
589
- throw new Error(`Domain ${domain} endpoints validation failed: ${error.message}`);
590
- }
591
- }
592
- async validateDiskSpace() {
593
- console.log(' Checking disk space...');
594
- // Disk space validation logic
595
- console.log(` ✅ Disk space: sufficient`);
596
- this.addResult('disk-space', 'Sufficient disk space available', 'info');
597
- }
598
- async validateMemoryUsage() {
599
- console.log(' Checking memory usage...');
600
- // Memory usage validation logic
601
- console.log(` ✅ Memory: sufficient`);
602
- this.addResult('memory', 'Sufficient memory available', 'info');
603
- }
604
- async validateBuildProcess() {
605
- console.log(' Validating build process...');
606
- try {
607
- // Test build without deploying
608
- await this.executeWithRetry('npm run build', 60000);
609
- console.log(` ✅ Build: successful`);
610
- this.addResult('build', 'Build process validated', 'success');
611
- } catch (error) {
612
- throw new Error(`Build validation failed: ${error.message}`);
613
- }
614
- }
615
-
616
- // Utility methods
617
-
618
- async executeWithRetry(command, timeout = this.timeout) {
619
- for (let attempt = 1; attempt <= this.retryAttempts; attempt++) {
620
- try {
621
- const {
622
- stdout
623
- } = await execAsync(command, {
624
- encoding: 'utf8',
625
- stdio: 'pipe',
626
- timeout
627
- });
628
- return stdout;
629
- } catch (error) {
630
- if (attempt === this.retryAttempts) {
631
- throw error;
632
- }
633
- await new Promise(resolve => setTimeout(resolve, this.retryDelay));
634
- }
635
- }
636
- }
637
- addResult(category, message, level) {
638
- this.results.details.push({
639
- category,
640
- message,
641
- level,
642
- timestamp: new Date()
643
- });
644
- if (level === 'warning') {
645
- this.results.warnings.push(message);
646
- } else if (level === 'error') {
647
- this.results.errors.push(message);
648
- }
649
- }
650
- addWarning(category, message) {
651
- this.addResult(category, message, 'warning');
652
- }
653
- printValidationSummary() {
654
- console.log('\n📊 VALIDATION SUMMARY');
655
- console.log('====================');
656
- Object.entries(this.results.categories).forEach(([category, status]) => {
657
- const icon = status === 'passed' ? '✅' : status === 'failed' ? '❌' : '⏳';
658
- console.log(`${icon} ${category}: ${status}`);
659
- });
660
- if (this.results.warnings.length > 0) {
661
- console.log(`\n⚠️ Warnings: ${this.results.warnings.length}`);
662
- }
663
- if (this.results.errors.length > 0) {
664
- console.log(`\n❌ Errors: ${this.results.errors.length}`);
665
- }
666
- const duration = this.results.endTime ? ((this.results.endTime - this.results.startTime) / 1000).toFixed(1) : 'N/A';
667
- console.log(`\n⏱️ Duration: ${duration}s`);
668
- }
669
- }
670
- export default DeploymentValidator;