@tamyla/clodo-framework 3.1.9 → 3.1.11

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 (75) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/bin/clodo-service-old.js +2 -2
  3. package/dist/bin/commands/create.js +1 -1
  4. package/dist/bin/commands/diagnose.js +1 -1
  5. package/dist/bin/commands/update.js +1 -1
  6. package/dist/bin/commands/validate.js +1 -1
  7. package/dist/bin/database/enterprise-db-manager.js +4 -4
  8. package/dist/bin/deployment/enterprise-deploy.js +3 -3
  9. package/dist/bin/deployment/master-deploy.js +3 -3
  10. package/dist/bin/deployment/modular-enterprise-deploy.js +3 -3
  11. package/dist/bin/deployment/modules/DeploymentOrchestrator.js +1 -1
  12. package/dist/bin/deployment/modules/EnvironmentManager.js +2 -2
  13. package/dist/bin/portfolio/portfolio-manager.js +3 -3
  14. package/dist/bin/security/security-cli.js +1 -1
  15. package/dist/bin/service-management/create-service.js +1 -1
  16. package/dist/bin/service-management/init-service.js +1 -1
  17. package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
  18. package/dist/bin/shared/config/index.js +1 -1
  19. package/dist/bin/shared/deployment/index.js +2 -2
  20. package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
  21. package/package.json +1 -6
  22. package/bin/README.md +0 -71
  23. package/bin/clodo-service.js +0 -72
  24. package/bin/database/README.md +0 -33
  25. package/bin/database/deployment-db-manager.js +0 -527
  26. package/bin/database/enterprise-db-manager.js +0 -738
  27. package/bin/database/wrangler-d1-manager.js +0 -775
  28. package/bin/security/security-cli.js +0 -117
  29. package/bin/service-management/README.md +0 -74
  30. package/bin/service-management/create-service.js +0 -129
  31. package/bin/service-management/init-service.js +0 -103
  32. package/bin/service-management/init-service.js.backup +0 -889
  33. package/bin/shared/cloudflare/domain-discovery.js +0 -637
  34. package/bin/shared/cloudflare/domain-manager.js +0 -952
  35. package/bin/shared/cloudflare/index.js +0 -8
  36. package/bin/shared/cloudflare/ops.js +0 -401
  37. package/bin/shared/config/ConfigurationManager.js +0 -539
  38. package/bin/shared/config/cache.js +0 -1230
  39. package/bin/shared/config/command-config-manager.js +0 -184
  40. package/bin/shared/config/index.js +0 -21
  41. package/bin/shared/config/manager.js +0 -315
  42. package/bin/shared/database/connection-manager.js +0 -374
  43. package/bin/shared/database/index.js +0 -7
  44. package/bin/shared/database/orchestrator.js +0 -727
  45. package/bin/shared/deployment/auditor.js +0 -970
  46. package/bin/shared/deployment/index.js +0 -10
  47. package/bin/shared/deployment/rollback-manager.js +0 -570
  48. package/bin/shared/deployment/validator.js +0 -779
  49. package/bin/shared/index.js +0 -32
  50. package/bin/shared/logging/Logger.js +0 -214
  51. package/bin/shared/monitoring/health-checker.js +0 -484
  52. package/bin/shared/monitoring/index.js +0 -8
  53. package/bin/shared/monitoring/memory-manager.js +0 -387
  54. package/bin/shared/monitoring/production-monitor.js +0 -403
  55. package/bin/shared/production-tester/api-tester.js +0 -82
  56. package/bin/shared/production-tester/auth-tester.js +0 -132
  57. package/bin/shared/production-tester/core.js +0 -197
  58. package/bin/shared/production-tester/database-tester.js +0 -109
  59. package/bin/shared/production-tester/index.js +0 -77
  60. package/bin/shared/production-tester/load-tester.js +0 -131
  61. package/bin/shared/production-tester/performance-tester.js +0 -103
  62. package/bin/shared/security/api-token-manager.js +0 -312
  63. package/bin/shared/security/index.js +0 -8
  64. package/bin/shared/security/secret-generator.js +0 -942
  65. package/bin/shared/security/secure-token-manager.js +0 -398
  66. package/bin/shared/utils/ErrorHandler.js +0 -675
  67. package/bin/shared/utils/error-recovery.js +0 -245
  68. package/bin/shared/utils/file-manager.js +0 -162
  69. package/bin/shared/utils/formatters.js +0 -247
  70. package/bin/shared/utils/graceful-shutdown-manager.js +0 -390
  71. package/bin/shared/utils/index.js +0 -19
  72. package/bin/shared/utils/interactive-prompts.js +0 -146
  73. package/bin/shared/utils/interactive-utils.js +0 -530
  74. package/bin/shared/utils/rate-limiter.js +0 -246
  75. package/bin/shared/validation/ValidationRegistry.js +0 -143
@@ -1,8 +0,0 @@
1
- /**
2
- * Cloudflare Integration Module
3
- * Exports all Cloudflare-related utilities and managers
4
- */
5
-
6
- export { CloudflareDomainManager } from './domain-manager.js';
7
- export { DomainDiscovery } from './domain-discovery.js';
8
- export { CloudflareOps } from './ops.js';
@@ -1,401 +0,0 @@
1
- /**
2
- * Cloudflare Operations Module
3
- * Standardized Cloudflare Workers and D1 operations
4
- *
5
- * Consolidates cloudflare operations across 14+ scripts
6
- */
7
-
8
- import { exec } from 'child_process';
9
- import { promisify } from 'util';
10
- import { executeWithRateLimit } from '../utils/rate-limiter.js';
11
- import { ErrorRecoveryManager } from '../utils/index.js';
12
- import { SecureTokenManager } from '../security/secure-token-manager.js';
13
- import { ProductionMonitor } from '../monitoring/production-monitor.js';
14
- import { DatabaseConnectionManager } from '../database/connection-manager.js';
15
- import { startMemoryMonitoring } from '../monitoring/memory-manager.js';
16
- import { initializeGracefulShutdown } from '../utils/graceful-shutdown-manager.js';
17
-
18
- const execAsync = promisify(exec);
19
-
20
- // Error recovery for critical operations
21
- const errorRecovery = new ErrorRecoveryManager({
22
- maxRetries: 2,
23
- retryDelay: 2000,
24
- circuitBreakerThreshold: 3,
25
- gracefulDegradation: true
26
- });
27
-
28
- // Secure token management
29
- const tokenManager = new SecureTokenManager();
30
-
31
- // Production monitoring
32
- const monitor = new ProductionMonitor({
33
- logLevel: 'info',
34
- enableMetrics: true,
35
- enableAlerts: true
36
- });
37
-
38
- // Database connection management
39
- const dbManager = new DatabaseConnectionManager({
40
- maxRetries: 2,
41
- retryDelay: 1000,
42
- connectionTimeout: 30000,
43
- queryTimeout: 60000,
44
- enableConnectionPooling: true,
45
- maxPoolSize: 5
46
- });
47
-
48
- // Memory management
49
- const memoryManager = startMemoryMonitoring({
50
- gcInterval: 300000, // 5 minutes
51
- memoryThreshold: 0.8,
52
- cleanupInterval: 60000, // 1 minute
53
- leakDetection: true
54
- });
55
-
56
- // Graceful shutdown handling (lazy initialization to avoid sync issues)
57
- let shutdownManager = null;
58
-
59
- /**
60
- * Initialize graceful shutdown manager
61
- * Call this AFTER interactive input collection to avoid log interruption
62
- * @param {boolean} silent - Suppress registration message
63
- * @returns {Promise<GracefulShutdownManager>} Initialized shutdown manager
64
- */
65
- export async function initializeShutdownManager(silent = false) {
66
- if (!shutdownManager) {
67
- shutdownManager = await initializeGracefulShutdown({
68
- dbManager,
69
- monitor,
70
- tokenManager,
71
- memoryManager
72
- }, {
73
- shutdownTimeout: 30000,
74
- forceShutdownTimeout: 5000
75
- });
76
-
77
- // Register with optional silent mode
78
- if (shutdownManager.register) {
79
- shutdownManager.register(silent);
80
- }
81
- }
82
- return shutdownManager;
83
- }
84
-
85
- // Initialize monitoring
86
- let monitoringInitialized = false;
87
- async function ensureMonitoringInitialized() {
88
- if (!monitoringInitialized) {
89
- await monitor.startMonitoring();
90
- monitoringInitialized = true;
91
- }
92
- }
93
-
94
- // Initialize secure token manager
95
- let tokenManagerInitialized = false;
96
- async function ensureTokenManagerInitialized() {
97
- if (!tokenManagerInitialized) {
98
- await tokenManager.initialize();
99
- tokenManagerInitialized = true;
100
- }
101
- }
102
-
103
- export async function checkAuth() {
104
- try {
105
- await ensureTokenManagerInitialized();
106
- // Try to get a valid token for Cloudflare API
107
- const tokens = tokenManager.listTokens('cloudflare');
108
- if (tokens.length === 0) {
109
- return false;
110
- }
111
-
112
- // Check if we have a non-expired token
113
- const validToken = tokens.find(token => new Date() < token.expires);
114
- return !!validToken;
115
- } catch (error) {
116
- return false;
117
- }
118
- }
119
-
120
- export async function authenticate() {
121
- try {
122
- // Use wrangler auth login for initial authentication
123
- await execAsync('npx wrangler auth login', { stdio: 'inherit' });
124
-
125
- // After successful login, we could extract and store the token securely
126
- // For now, rely on wrangler's built-in token management
127
- console.log('Authentication successful. Use storeCloudflareToken() to store API tokens securely.');
128
- } catch (error) {
129
- throw new Error(`Authentication failed: ${error.message}`);
130
- }
131
- }
132
-
133
- export async function storeCloudflareToken(token, metadata = {}) {
134
- await ensureTokenManagerInitialized();
135
- const fingerprint = await tokenManager.storeToken('cloudflare', token, {
136
- permissions: ['api_access', 'deployment'],
137
- environment: metadata.environment || 'production',
138
- ...metadata
139
- });
140
- console.log(`Cloudflare API token stored securely with fingerprint: ${fingerprint}`);
141
- return fingerprint;
142
- }
143
-
144
- export async function getCloudflareToken(requiredPermissions = ['api_access']) {
145
- await ensureTokenManagerInitialized();
146
- const tokens = tokenManager.listTokens('cloudflare');
147
-
148
- // Find a valid token with required permissions
149
- for (const tokenInfo of tokens) {
150
- if (new Date() < tokenInfo.expires && tokenManager.validatePermissions(tokenInfo.permissions, requiredPermissions)) {
151
- return await tokenManager.retrieveToken('cloudflare', tokenInfo.fingerprint, requiredPermissions);
152
- }
153
- }
154
-
155
- throw new Error('No valid Cloudflare API token found with required permissions');
156
- }
157
-
158
- export async function listWorkers() {
159
- try {
160
- const { stdout: list } = await executeWithRateLimit('npx wrangler list', 'workers');
161
- return list;
162
- } catch (error) {
163
- throw new Error(`Failed to list workers: ${error.message}`);
164
- }
165
- }
166
-
167
- export async function workerExists(workerName) {
168
- try {
169
- const list = await listWorkers();
170
- return list.includes(workerName);
171
- } catch (error) {
172
- return false; // Assume doesn't exist if can't check
173
- }
174
- }
175
-
176
- export async function deployWorker(env = 'production') {
177
- const startTime = Date.now();
178
-
179
- try {
180
- await ensureMonitoringInitialized();
181
-
182
- const result = await errorRecovery.executeWithRecovery(async () => {
183
- await executeWithRateLimit(`npm run deploy:${env}`, 'workers');
184
- return true;
185
- }, { operationId: `deployWorker_${env}` });
186
-
187
- const duration = Date.now() - startTime;
188
- monitor.recordRequest(true, duration, { operation: 'deployWorker', env });
189
- await monitor.log('info', 'Worker deployment successful', { env, duration });
190
-
191
- return result;
192
- } catch (error) {
193
- const duration = Date.now() - startTime;
194
- monitor.recordRequest(false, duration, { operation: 'deployWorker', env, error: error.message });
195
- await monitor.log('error', 'Worker deployment failed', { env, duration, error: error.message });
196
-
197
- throw new Error(`Worker deployment failed after retries: ${error.message}`);
198
- }
199
- }
200
-
201
- export async function deploySecret(key, value, env = 'production') {
202
- const command = process.platform === 'win32'
203
- ? `powershell -Command "Write-Output '${value}' | npx wrangler secret put ${key} --env ${env}"`
204
- : `echo "${value}" | npx wrangler secret put ${key} --env ${env}`;
205
-
206
- try {
207
- await executeWithRateLimit(command, 'workers', 3); // Lower retries for secrets
208
- } catch (error) {
209
- throw new Error(`Secret deployment failed: ${error.message}`);
210
- }
211
- }
212
-
213
- export async function deleteSecret(key, env = 'production') {
214
- try {
215
- await executeWithRateLimit(`npx wrangler secret delete ${key} --env ${env}`, 'workers');
216
- } catch (error) {
217
- throw new Error(`Secret deletion failed: ${error.message}`);
218
- }
219
- }
220
-
221
- export async function listSecrets(env = 'production') {
222
- try {
223
- const { stdout: list } = await executeWithRateLimit(`npx wrangler secret list --env ${env}`, 'workers');
224
- return list;
225
- } catch (error) {
226
- throw new Error(`Failed to list secrets: ${error.message}`);
227
- }
228
- }
229
-
230
- export async function listDatabases(options = {}) {
231
- const { apiToken, accountId } = options;
232
-
233
- // Use API-based operation if credentials provided
234
- if (apiToken && accountId) {
235
- const { CloudflareAPI } = await import('../../../dist/utils/cloudflare/api.js');
236
- const cf = new CloudflareAPI(apiToken);
237
- return await cf.listD1Databases(accountId);
238
- }
239
-
240
- // Fallback to CLI-based operation
241
- try {
242
- const { stdout: list } = await executeWithRateLimit('npx wrangler d1 list', 'd1');
243
- return list;
244
- } catch (error) {
245
- throw new Error(`Failed to list databases: ${error.message}`);
246
- }
247
- }
248
-
249
- export async function databaseExists(databaseName, options = {}) {
250
- const { apiToken, accountId } = options;
251
-
252
- // Use API-based operation if credentials provided
253
- if (apiToken && accountId) {
254
- const { CloudflareAPI } = await import('../../../dist/utils/cloudflare/api.js');
255
- const cf = new CloudflareAPI(apiToken);
256
- return await cf.d1DatabaseExists(accountId, databaseName);
257
- }
258
-
259
- // Fallback to CLI-based operation
260
- try {
261
- const list = await listDatabases();
262
- return list.includes(databaseName);
263
- } catch (error) {
264
- return false; // Assume doesn't exist if can't check
265
- }
266
- }
267
-
268
- export async function createDatabase(name, options = {}) {
269
- const { apiToken, accountId } = options;
270
-
271
- // Use API-based operation if credentials provided
272
- if (apiToken && accountId) {
273
- const { CloudflareAPI } = await import('../../../dist/utils/cloudflare/api.js');
274
- const cf = new CloudflareAPI(apiToken);
275
- const result = await cf.createD1Database(accountId, name);
276
- return result.uuid; // Return UUID to match CLI behavior
277
- }
278
-
279
- // Fallback to CLI-based operation
280
- try {
281
- const { stdout: output } = await executeWithRateLimit(`npx wrangler d1 create ${name}`, 'd1');
282
- const idMatch = output.match(/database_id = "([^"]+)"/);
283
- if (!idMatch) {
284
- throw new Error('Could not extract database ID from creation output');
285
- }
286
- return idMatch[1];
287
- } catch (error) {
288
- throw new Error(`Database creation failed: ${error.message}`);
289
- }
290
- }
291
-
292
- export async function deleteDatabase(name) {
293
- try {
294
- await executeWithRateLimit(`npx wrangler d1 delete ${name} --skip-confirmation`, 'd1');
295
- } catch (error) {
296
- throw new Error(`Database deletion failed: ${error.message}`);
297
- }
298
- }
299
-
300
- export async function runMigrations(databaseName, env = 'production') {
301
- const startTime = Date.now();
302
-
303
- try {
304
- await ensureMonitoringInitialized();
305
-
306
- const result = await errorRecovery.executeWithRecovery(async () => {
307
- await executeWithRateLimit(`npx wrangler d1 migrations apply ${databaseName} --env ${env} --remote`, 'd1');
308
- return true;
309
- }, { operationId: `runMigrations_${databaseName}_${env}` });
310
-
311
- const duration = Date.now() - startTime;
312
- monitor.recordRequest(true, duration, { operation: 'runMigrations', databaseName, env });
313
- await monitor.log('info', 'Database migrations completed', { databaseName, env, duration });
314
-
315
- return result;
316
- } catch (error) {
317
- const duration = Date.now() - startTime;
318
- monitor.recordRequest(false, duration, { operation: 'runMigrations', databaseName, env, error: error.message });
319
- await monitor.log('warn', 'Database migrations had warnings', { databaseName, env, duration, error: error.message });
320
-
321
- return false; // Warnings are often OK
322
- }
323
- }
324
-
325
- export async function executeSql(databaseName, sql, env = 'production') {
326
- const startTime = Date.now();
327
-
328
- try {
329
- await ensureMonitoringInitialized();
330
-
331
- const result = await dbManager.executeQuery(databaseName, sql, { env });
332
-
333
- const duration = Date.now() - startTime;
334
- monitor.recordRequest(true, duration, { operation: 'executeSql', databaseName, env });
335
- await monitor.log('info', 'Database query executed successfully', {
336
- databaseName,
337
- env,
338
- duration,
339
- resultLength: result.result ? result.result.length : 0
340
- });
341
-
342
- return result.result;
343
- } catch (error) {
344
- const duration = Date.now() - startTime;
345
- monitor.recordRequest(false, duration, { operation: 'executeSql', databaseName, env, error: error.message });
346
- await monitor.log('error', 'Database query failed', { databaseName, env, duration, error: error.message });
347
-
348
- throw new Error(`SQL execution failed after retries: ${error.message}`);
349
- }
350
- }
351
-
352
- // Get database ID from list output
353
- export async function getDatabaseId(databaseName, options = {}) {
354
- const { apiToken, accountId } = options;
355
-
356
- // Use API-based operation if credentials provided
357
- if (apiToken && accountId) {
358
- const { CloudflareAPI } = await import('../../../dist/utils/cloudflare/api.js');
359
- const cf = new CloudflareAPI(apiToken);
360
- const db = await cf.getD1Database(accountId, databaseName);
361
- return db?.uuid || null;
362
- }
363
-
364
- // Fallback to CLI-based operation
365
- try {
366
- const list = await listDatabases();
367
- const lines = list.split('\n');
368
- for (const line of lines) {
369
- if (line.includes(databaseName)) {
370
- const match = line.match(/([a-f0-9-]{36})/);
371
- if (match) {
372
- return match[1];
373
- }
374
- }
375
- }
376
- return null;
377
- } catch (error) {
378
- return null;
379
- }
380
- }
381
-
382
- // Validate prerequisites
383
- export async function validatePrerequisites() {
384
- const checks = [
385
- { name: 'Node.js', command: 'node --version' },
386
- { name: 'NPM', command: 'npm --version' },
387
- { name: 'Wrangler', command: 'npx wrangler --version' }
388
- ];
389
-
390
- const results = [];
391
- for (const check of checks) {
392
- try {
393
- const { stdout: version } = await execAsync(check.command, { encoding: 'utf8' });
394
- results.push({ name: check.name, status: 'ok', version: version.trim() });
395
- } catch (error) {
396
- results.push({ name: check.name, status: 'failed', error: error.message });
397
- }
398
- }
399
-
400
- return results;
401
- }