@tamyla/clodo-framework 3.1.21 → 3.1.22

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 (169) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +53 -0
  3. package/dist/bin/clodo-service.js +47 -15
  4. package/dist/bin/commands/deploy.js +115 -83
  5. package/dist/bin/commands/helpers/deployment-ui.js +138 -0
  6. package/dist/bin/commands/helpers/deployment-verification.js +251 -0
  7. package/dist/bin/commands/helpers/error-recovery.js +80 -0
  8. package/dist/bin/commands/helpers/resource-detection.js +113 -0
  9. package/dist/bin/commands/validate.js +1 -1
  10. package/dist/bin/security/security-cli.js +1 -1
  11. package/dist/bin/shared/cache/configuration-cache.js +82 -0
  12. package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
  13. package/dist/bin/shared/cloudflare/index.js +1 -1
  14. package/dist/bin/shared/cloudflare/ops.js +6 -4
  15. package/dist/bin/shared/config/ConfigurationManager.js +23 -1
  16. package/dist/bin/shared/config/command-config-manager.js +19 -3
  17. package/dist/bin/shared/config/index.js +1 -1
  18. package/dist/bin/shared/deployment/credential-collector.js +30 -7
  19. package/dist/bin/shared/deployment/index.js +2 -2
  20. package/dist/bin/shared/deployment/rollback-manager.js +4 -520
  21. package/dist/bin/shared/deployment/utilities/d1-error-recovery.js +177 -0
  22. package/dist/bin/shared/deployment/validator.js +40 -10
  23. package/dist/bin/shared/deployment/workflows/deployment-summary.js +214 -0
  24. package/dist/bin/shared/deployment/workflows/interactive-confirmation.js +188 -0
  25. package/dist/bin/shared/deployment/workflows/interactive-database-workflow.js +234 -0
  26. package/dist/bin/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
  27. package/dist/bin/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
  28. package/dist/bin/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
  29. package/dist/bin/shared/deployment/workflows/interactive-validation.js +218 -0
  30. package/dist/bin/shared/error-handling/error-classifier.js +46 -0
  31. package/dist/bin/shared/monitoring/health-checker.js +129 -1
  32. package/dist/bin/shared/monitoring/memory-manager.js +17 -6
  33. package/dist/bin/shared/routing/domain-router.js +1 -1
  34. package/dist/bin/shared/utils/deployment-validator.js +97 -0
  35. package/dist/bin/shared/utils/formatters.js +10 -0
  36. package/dist/bin/shared/utils/index.js +13 -1
  37. package/dist/bin/shared/utils/interactive-prompts.js +34 -18
  38. package/dist/bin/shared/utils/progress-manager.js +2 -2
  39. package/dist/bin/shared/utils/progress-spinner.js +53 -0
  40. package/dist/bin/shared/utils/sensitive-redactor.js +91 -0
  41. package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
  42. package/dist/security/index.js +1 -1
  43. package/dist/security/patterns/insecure-patterns.js +1 -1
  44. package/dist/utils/constants.js +102 -0
  45. package/dist/utils/deployment/wrangler-config-manager.js +215 -48
  46. package/dist/utils/framework-config.js +2 -2
  47. package/dist/utils/interactive-prompts.js +10 -59
  48. package/package.json +16 -8
  49. package/dist/bin/clodo-service-old.js +0 -868
  50. package/dist/bin/clodo-service-test.js +0 -10
  51. package/dist/bin/commands/assess.js +0 -91
  52. package/dist/bin/commands/create.js +0 -77
  53. package/dist/bin/commands/diagnose.js +0 -83
  54. package/dist/bin/commands/helpers.js +0 -138
  55. package/dist/bin/commands/update.js +0 -75
  56. package/dist/bin/database/deployment-db-manager.js +0 -423
  57. package/dist/bin/database/enterprise-db-manager.js +0 -457
  58. package/dist/bin/database/wrangler-d1-manager.js +0 -685
  59. package/dist/bin/deployment/enterprise-deploy.js +0 -877
  60. package/dist/bin/deployment/master-deploy.js +0 -1376
  61. package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
  62. package/dist/bin/deployment/modules/DeploymentConfiguration.js +0 -395
  63. package/dist/bin/deployment/modules/DeploymentOrchestrator.js +0 -492
  64. package/dist/bin/deployment/modules/EnvironmentManager.js +0 -517
  65. package/dist/bin/deployment/modules/MonitoringIntegration.js +0 -560
  66. package/dist/bin/deployment/modules/ValidationManager.js +0 -342
  67. package/dist/bin/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
  68. package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  69. package/dist/bin/deployment/orchestration/PortfolioOrchestrator.js +0 -273
  70. package/dist/bin/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
  71. package/dist/bin/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
  72. package/dist/bin/deployment/test-interactive-utils.js +0 -66
  73. package/dist/bin/portfolio/portfolio-manager.js +0 -487
  74. package/dist/bin/service-management/create-service.js +0 -122
  75. package/dist/bin/service-management/init-service.js +0 -79
  76. package/dist/config/customers.js +0 -623
  77. package/dist/config/domains.js +0 -186
  78. package/dist/config/index.js +0 -6
  79. package/dist/database/database-orchestrator.js +0 -795
  80. package/dist/database/index.js +0 -4
  81. package/dist/deployment/index.js +0 -11
  82. package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
  83. package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  84. package/dist/deployment/orchestration/PortfolioOrchestrator.js +0 -273
  85. package/dist/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
  86. package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
  87. package/dist/deployment/orchestration/index.js +0 -17
  88. package/dist/deployment/rollback-manager.js +0 -36
  89. package/dist/deployment/wrangler-deployer.js +0 -640
  90. package/dist/handlers/GenericRouteHandler.js +0 -532
  91. package/dist/migration/MigrationAdapters.js +0 -562
  92. package/dist/modules/ModuleManager.js +0 -668
  93. package/dist/modules/security.js +0 -96
  94. package/dist/orchestration/cross-domain-coordinator.js +0 -1083
  95. package/dist/orchestration/index.js +0 -5
  96. package/dist/orchestration/modules/DeploymentCoordinator.js +0 -368
  97. package/dist/orchestration/modules/DomainResolver.js +0 -198
  98. package/dist/orchestration/modules/StateManager.js +0 -332
  99. package/dist/orchestration/multi-domain-orchestrator.js +0 -724
  100. package/dist/routing/EnhancedRouter.js +0 -158
  101. package/dist/schema/SchemaManager.js +0 -778
  102. package/dist/service-management/ConfirmationEngine.js +0 -412
  103. package/dist/service-management/ErrorTracker.js +0 -299
  104. package/dist/service-management/GenerationEngine.js +0 -447
  105. package/dist/service-management/InputCollector.js +0 -619
  106. package/dist/service-management/ServiceCreator.js +0 -265
  107. package/dist/service-management/ServiceInitializer.js +0 -453
  108. package/dist/service-management/ServiceOrchestrator.js +0 -633
  109. package/dist/service-management/generators/BaseGenerator.js +0 -233
  110. package/dist/service-management/generators/GeneratorRegistry.js +0 -254
  111. package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +0 -87
  112. package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +0 -106
  113. package/dist/service-management/generators/code/ServiceHandlersGenerator.js +0 -235
  114. package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +0 -116
  115. package/dist/service-management/generators/code/ServiceUtilsGenerator.js +0 -246
  116. package/dist/service-management/generators/code/WorkerIndexGenerator.js +0 -143
  117. package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +0 -101
  118. package/dist/service-management/generators/config/DomainsConfigGenerator.js +0 -175
  119. package/dist/service-management/generators/config/EnvExampleGenerator.js +0 -178
  120. package/dist/service-management/generators/config/ProductionEnvGenerator.js +0 -97
  121. package/dist/service-management/generators/config/StagingEnvGenerator.js +0 -97
  122. package/dist/service-management/generators/config/WranglerTomlGenerator.js +0 -238
  123. package/dist/service-management/generators/core/PackageJsonGenerator.js +0 -243
  124. package/dist/service-management/generators/core/SiteConfigGenerator.js +0 -115
  125. package/dist/service-management/generators/documentation/ApiDocsGenerator.js +0 -331
  126. package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +0 -294
  127. package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +0 -244
  128. package/dist/service-management/generators/documentation/ReadmeGenerator.js +0 -196
  129. package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +0 -190
  130. package/dist/service-management/generators/scripts/DeployScriptGenerator.js +0 -123
  131. package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +0 -101
  132. package/dist/service-management/generators/scripts/SetupScriptGenerator.js +0 -88
  133. package/dist/service-management/generators/service-types/StaticSiteGenerator.js +0 -342
  134. package/dist/service-management/generators/testing/EslintConfigGenerator.js +0 -85
  135. package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +0 -237
  136. package/dist/service-management/generators/testing/JestConfigGenerator.js +0 -72
  137. package/dist/service-management/generators/testing/UnitTestsGenerator.js +0 -277
  138. package/dist/service-management/generators/tooling/DockerComposeGenerator.js +0 -71
  139. package/dist/service-management/generators/tooling/GitignoreGenerator.js +0 -143
  140. package/dist/service-management/generators/utils/FileWriter.js +0 -179
  141. package/dist/service-management/generators/utils/PathResolver.js +0 -157
  142. package/dist/service-management/generators/utils/ServiceManifestGenerator.js +0 -111
  143. package/dist/service-management/generators/utils/TemplateEngine.js +0 -185
  144. package/dist/service-management/generators/utils/index.js +0 -18
  145. package/dist/service-management/handlers/ConfirmationHandler.js +0 -71
  146. package/dist/service-management/handlers/GenerationHandler.js +0 -80
  147. package/dist/service-management/handlers/InputHandler.js +0 -59
  148. package/dist/service-management/handlers/ValidationHandler.js +0 -203
  149. package/dist/service-management/index.js +0 -14
  150. package/dist/service-management/routing/DomainRouteMapper.js +0 -311
  151. package/dist/service-management/routing/RouteGenerator.js +0 -266
  152. package/dist/service-management/routing/WranglerRoutesBuilder.js +0 -273
  153. package/dist/service-management/routing/index.js +0 -14
  154. package/dist/service-management/services/DirectoryStructureService.js +0 -56
  155. package/dist/service-management/services/GenerationCoordinator.js +0 -208
  156. package/dist/service-management/services/GeneratorRegistry.js +0 -174
  157. package/dist/services/GenericDataService.js +0 -501
  158. package/dist/ui-structures/concepts/second-order-acquisition-strategy.md +0 -286
  159. package/dist/ui-structures/concepts/service-lifecycle-management.md +0 -150
  160. package/dist/ui-structures/concepts/service-manifest-guide.md +0 -309
  161. package/dist/ui-structures/concepts/three-tier-categorization-strategy.md +0 -231
  162. package/dist/ui-structures/creation/automated-generation-ui.json +0 -246
  163. package/dist/ui-structures/creation/core-inputs-ui.json +0 -217
  164. package/dist/ui-structures/creation/smart-confirmable-ui.json +0 -451
  165. package/dist/ui-structures/reference/absolutely-required-inputs.json +0 -315
  166. package/dist/ui-structures/reference/service-manifest-template.json +0 -342
  167. package/dist/version/VersionDetector.js +0 -723
  168. package/dist/worker/index.js +0 -4
  169. package/dist/worker/integration.js +0 -351
@@ -1,412 +0,0 @@
1
- /**
2
- * ConfirmationEngine - Tier 2: Smart Confirmations
3
- *
4
- * Takes the 6 core inputs and generates 15 derived confirmation values
5
- * that users can review and modify before service generation.
6
- *
7
- * Core Inputs (6):
8
- * 1. Service Name
9
- * 2. Service Type
10
- * 3. Domain Name
11
- * 4. Cloudflare Token
12
- * 5. Cloudflare Account ID
13
- * 6. Cloudflare Zone ID
14
- * 7. Environment
15
- *
16
- * Derived Confirmations (15):
17
- * 1. Display Name
18
- * 2. Description
19
- * 3. Version
20
- * 4. Author
21
- * 5. Production URL
22
- * 6. Staging URL
23
- * 7. Development URL
24
- * 8. Features Configuration
25
- * 9. Database Name
26
- * 10. Worker Name
27
- * 11. Package Name
28
- * 12. Git Repository URL
29
- * 13. Documentation URL
30
- * 14. Health Check Path
31
- * 15. API Base Path
32
- */
33
-
34
- import { createInterface } from 'readline';
35
- import chalk from 'chalk';
36
- import { validateServiceName, validateDomainName } from '../utils/validation.js';
37
- import { NameFormatters, UrlFormatters, ResourceFormatters } from "../../dist/bin/shared/utils/Formatters.js";
38
- export class ConfirmationEngine {
39
- constructor(options = {}) {
40
- this.interactive = options.interactive !== false;
41
- this.rl = this.interactive ? createInterface({
42
- input: process.stdin,
43
- output: process.stdout
44
- }) : null;
45
- }
46
-
47
- /**
48
- * Generate and confirm all derived values from core inputs
49
- */
50
- async generateAndConfirm(coreInputs) {
51
- console.log(chalk.cyan('\nšŸ” Tier 2: Smart Confirmations'));
52
- console.log(chalk.white('Reviewing and confirming 15 derived configuration values...\n'));
53
-
54
- // Generate smart defaults
55
- const derivedValues = this.generateSmartDefaults(coreInputs);
56
-
57
- // Interactive confirmation if enabled
58
- if (this.interactive) {
59
- return await this.interactiveConfirmation(derivedValues, coreInputs);
60
- } else {
61
- console.log(chalk.gray('āš ļø Non-interactive mode: Using generated defaults'));
62
- return derivedValues;
63
- }
64
- }
65
-
66
- /**
67
- * Generate smart defaults for all 15 confirmation values
68
- */
69
- generateSmartDefaults(coreInputs) {
70
- const {
71
- serviceName,
72
- serviceType,
73
- domainName,
74
- environment
75
- } = coreInputs;
76
- return {
77
- // 1. Display Name - Convert kebab-case to Title Case
78
- displayName: this.generateDisplayName(serviceName),
79
- // 2. Description - Based on service type
80
- description: this.generateDescription(serviceType),
81
- // 3. Version - Standard semantic versioning
82
- version: '1.0.0',
83
- // 4. Author - Default framework author
84
- author: 'Clodo Framework',
85
- // 5-7. URLs - Derived from domain and service name
86
- productionUrl: UrlFormatters.buildProductionUrl(serviceName, domainName),
87
- stagingUrl: UrlFormatters.buildStagingUrl(serviceName, domainName),
88
- developmentUrl: UrlFormatters.buildDevUrl(serviceName, domainName),
89
- // 8. Features - Based on service type
90
- features: this.generateFeaturesForType(serviceType),
91
- // 9. Database Name - Cloudflare D1 naming
92
- databaseName: ResourceFormatters.databaseName(serviceName),
93
- // 10. Worker Name - Cloudflare Worker naming
94
- workerName: ResourceFormatters.workerName(serviceName),
95
- // 11. Package Name - NPM package naming
96
- packageName: ResourceFormatters.packageName(serviceName),
97
- // 12. Git Repository URL - GitHub naming
98
- gitRepositoryUrl: `https://github.com/tamylaa/${serviceName}`,
99
- // 13. Documentation URL - Based on domain
100
- documentationUrl: `https://docs.${domainName}`,
101
- // 14. Health Check Path - Standard health endpoint
102
- healthCheckPath: '/health',
103
- // 15. API Base Path - Service-specific API path
104
- apiBasePath: `/api/v1/${serviceName.replace('-', '/')}`
105
- };
106
- }
107
-
108
- /**
109
- * Interactive confirmation process
110
- */
111
- async interactiveConfirmation(derivedValues, coreInputs) {
112
- console.log(chalk.cyan('Please review and confirm the following derived values:'));
113
- console.log(chalk.gray('Press Enter to accept default, or type new value to modify.\n'));
114
- const confirmed = {
115
- ...derivedValues
116
- };
117
-
118
- // Group confirmations for better UX
119
- const confirmationGroups = [{
120
- title: 'šŸ“‹ Basic Information',
121
- items: [{
122
- key: 'displayName',
123
- label: 'Display Name',
124
- description: 'Human-readable service name'
125
- }, {
126
- key: 'description',
127
- label: 'Description',
128
- description: 'Service description'
129
- }, {
130
- key: 'version',
131
- label: 'Version',
132
- description: 'Initial version number'
133
- }, {
134
- key: 'author',
135
- label: 'Author',
136
- description: 'Service author/maintainer'
137
- }]
138
- }, {
139
- title: '🌐 URLs & Endpoints',
140
- items: [{
141
- key: 'productionUrl',
142
- label: 'Production URL',
143
- description: 'Live production endpoint'
144
- }, {
145
- key: 'stagingUrl',
146
- label: 'Staging URL',
147
- description: 'Staging environment endpoint'
148
- }, {
149
- key: 'developmentUrl',
150
- label: 'Development URL',
151
- description: 'Development environment endpoint'
152
- }, {
153
- key: 'documentationUrl',
154
- label: 'Documentation URL',
155
- description: 'API documentation location'
156
- }]
157
- }, {
158
- title: 'āš™ļø Service Configuration',
159
- items: [{
160
- key: 'databaseName',
161
- label: 'Database Name',
162
- description: 'Cloudflare D1 database name'
163
- }, {
164
- key: 'workerName',
165
- label: 'Worker Name',
166
- description: 'Cloudflare Worker script name'
167
- }, {
168
- key: 'packageName',
169
- label: 'Package Name',
170
- description: 'NPM package identifier'
171
- }, {
172
- key: 'healthCheckPath',
173
- label: 'Health Check Path',
174
- description: 'Health endpoint path'
175
- }, {
176
- key: 'apiBasePath',
177
- label: 'API Base Path',
178
- description: 'Base path for API endpoints'
179
- }]
180
- }];
181
- for (const group of confirmationGroups) {
182
- console.log(chalk.yellow(`\n${group.title}`));
183
- console.log(chalk.gray('─'.repeat(50)));
184
- for (const item of group.items) {
185
- const currentValue = confirmed[item.key];
186
- const newValue = await this.confirmValue(`${item.label} (${item.description})`, currentValue);
187
- if (newValue !== null && newValue !== currentValue) {
188
- // Validate the new value if it's a URL or name
189
- if (this.validateConfirmationValue(item.key, newValue)) {
190
- confirmed[item.key] = newValue;
191
- console.log(chalk.green(`āœ“ Updated: ${newValue}`));
192
- } else {
193
- console.log(chalk.red(`āœ— Invalid value, keeping: ${currentValue}`));
194
- }
195
- } else {
196
- console.log(chalk.gray(`āœ“ Keeping: ${currentValue}`));
197
- }
198
- }
199
- }
200
-
201
- // Special handling for features
202
- console.log(chalk.yellow('\nšŸ”§ Feature Configuration'));
203
- console.log(chalk.gray('─'.repeat(50)));
204
- console.log(chalk.white('Current features for service type:'), chalk.cyan(coreInputs.serviceType));
205
- this.displayFeatures(confirmed.features);
206
- const modifyFeatures = await this.confirmYesNo('\nWould you like to modify feature flags?', false);
207
- if (modifyFeatures) {
208
- confirmed.features = await this.interactiveFeatureConfiguration(confirmed.features, coreInputs.serviceType);
209
- }
210
- return confirmed;
211
- }
212
-
213
- /**
214
- * Confirm a single value with user
215
- */
216
- async confirmValue(prompt, currentValue) {
217
- return new Promise(resolve => {
218
- const displayValue = typeof currentValue === 'object' ? JSON.stringify(currentValue, null, 2) : String(currentValue);
219
- this.rl.question(`${prompt} [${displayValue}]: `, answer => {
220
- resolve(answer.trim() || null);
221
- });
222
- });
223
- }
224
-
225
- /**
226
- * Confirm yes/no question
227
- */
228
- async confirmYesNo(question, defaultValue = true) {
229
- return new Promise(resolve => {
230
- const defaultText = defaultValue ? '[Y/n]' : '[y/N]';
231
- this.rl.question(`${question} ${defaultText}: `, answer => {
232
- const normalized = answer.toLowerCase().trim();
233
- if (normalized === '') {
234
- resolve(defaultValue);
235
- } else if (normalized === 'y' || normalized === 'yes') {
236
- resolve(true);
237
- } else if (normalized === 'n' || normalized === 'no') {
238
- resolve(false);
239
- } else {
240
- resolve(defaultValue);
241
- }
242
- });
243
- });
244
- }
245
-
246
- /**
247
- * Interactive feature configuration
248
- */
249
- async interactiveFeatureConfiguration(currentFeatures, serviceType) {
250
- console.log(chalk.cyan('\nFeature Configuration:'));
251
- console.log(chalk.white('Type feature name to toggle, or "done" to finish'));
252
- const features = {
253
- ...currentFeatures
254
- };
255
- for (;;) {
256
- console.log(chalk.gray('\nCurrent features:'));
257
- this.displayFeatures(features);
258
- const input = await new Promise(resolve => {
259
- this.rl.question('Feature to toggle (or "done"): ', resolve);
260
- });
261
- const feature = input.trim().toLowerCase();
262
- if (feature === 'done' || feature === '') {
263
- break;
264
- }
265
- if (Object.prototype.hasOwnProperty.call(features, feature)) {
266
- features[feature] = !features[feature];
267
- console.log(chalk.green(`āœ“ ${feature}: ${features[feature] ? 'ENABLED' : 'DISABLED'}`));
268
- } else {
269
- console.log(chalk.red(`āœ— Unknown feature: ${feature}`));
270
- console.log(chalk.gray('Available features:'), Object.keys(features).join(', '));
271
- }
272
- }
273
- return features;
274
- }
275
-
276
- /**
277
- * Display features in a nice format
278
- */
279
- displayFeatures(features) {
280
- const enabled = Object.entries(features).filter(([, enabled]) => enabled).map(([name]) => name);
281
- const disabled = Object.entries(features).filter(([, enabled]) => !enabled).map(([name]) => name);
282
- if (enabled.length > 0) {
283
- console.log(chalk.green(' Enabled:'), enabled.join(', '));
284
- }
285
- if (disabled.length > 0) {
286
- console.log(chalk.gray(' Disabled:'), disabled.join(', '));
287
- }
288
- }
289
-
290
- /**
291
- * Validate confirmation value based on type
292
- */
293
- validateConfirmationValue(key, value) {
294
- switch (key) {
295
- case 'displayName':
296
- return value.length > 0 && value.length <= 100;
297
- case 'description':
298
- return value.length > 0 && value.length <= 500;
299
- case 'version':
300
- return /^\d+\.\d+\.\d+$/.test(value);
301
- case 'productionUrl':
302
- case 'stagingUrl':
303
- case 'developmentUrl':
304
- case 'documentationUrl':
305
- return /^https?:\/\/.+/.test(value);
306
- case 'databaseName':
307
- case 'workerName':
308
- return validateServiceName(value);
309
- case 'packageName':
310
- return /^@?[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]*$/.test(value);
311
- case 'healthCheckPath':
312
- case 'apiBasePath':
313
- return value.startsWith('/');
314
- default:
315
- return true;
316
- }
317
- }
318
-
319
- /**
320
- * Generate display name from service name
321
- */
322
- generateDisplayName(serviceName) {
323
- return NameFormatters.toDisplayName(serviceName);
324
- }
325
-
326
- /**
327
- * Generate description based on service type
328
- */
329
- generateDescription(serviceType) {
330
- const descriptions = {
331
- 'data-service': 'A comprehensive data service providing CRUD operations, search, filtering, and pagination capabilities',
332
- 'auth-service': 'Authentication and authorization service with user management and security features',
333
- 'content-service': 'Content management service with file storage, search, and delivery capabilities',
334
- 'api-gateway': 'API gateway providing routing, rate limiting, authentication, and monitoring',
335
- 'generic': 'A Clodo Framework service providing core functionality and extensibility'
336
- };
337
- return descriptions[serviceType] || descriptions.generic;
338
- }
339
-
340
- /**
341
- * Generate features based on service type
342
- */
343
- generateFeaturesForType(serviceType) {
344
- const baseFeatures = {
345
- logging: true,
346
- monitoring: true,
347
- errorReporting: true,
348
- metrics: true,
349
- healthChecks: true
350
- };
351
- const typeSpecificFeatures = {
352
- 'data-service': {
353
- authentication: true,
354
- authorization: true,
355
- database: true,
356
- search: true,
357
- filtering: true,
358
- pagination: true,
359
- caching: true,
360
- backup: true
361
- },
362
- 'auth-service': {
363
- authentication: true,
364
- authorization: true,
365
- userProfiles: true,
366
- emailNotifications: true,
367
- magicLinkAuth: true,
368
- passwordReset: true,
369
- sessionManagement: true,
370
- rateLimiting: true
371
- },
372
- 'content-service': {
373
- fileStorage: true,
374
- search: true,
375
- filtering: true,
376
- pagination: true,
377
- caching: true,
378
- cdn: true,
379
- imageProcessing: true,
380
- metadata: true
381
- },
382
- 'api-gateway': {
383
- authentication: true,
384
- authorization: true,
385
- rateLimiting: true,
386
- caching: true,
387
- monitoring: true,
388
- loadBalancing: true,
389
- requestRouting: true,
390
- responseTransformation: true
391
- },
392
- 'generic': {
393
- extensibility: true,
394
- configuration: true,
395
- deployment: true
396
- }
397
- };
398
- return {
399
- ...baseFeatures,
400
- ...(typeSpecificFeatures[serviceType] || typeSpecificFeatures.generic)
401
- };
402
- }
403
-
404
- /**
405
- * Close readline interface
406
- */
407
- close() {
408
- if (this.rl) {
409
- this.rl.close();
410
- }
411
- }
412
- }
@@ -1,299 +0,0 @@
1
- /**
2
- * ErrorTracker - Comprehensive Error Handling and Recovery System
3
- *
4
- * Captures failures, tracks input states, and provides recovery mechanisms
5
- * for the Clodo Framework service lifecycle management.
6
- */
7
-
8
- import fs from 'fs/promises';
9
- import path from 'path';
10
- import chalk from 'chalk';
11
- import { logger } from "../../dist/bin/shared/logging/Logger.js";
12
- export class ErrorTracker {
13
- constructor() {
14
- this.errors = [];
15
- this.errorLogPath = './clodo-service-errors.log';
16
- this.maxErrors = 100; // Keep last 100 errors
17
- }
18
-
19
- /**
20
- * Capture an error with context and input state
21
- */
22
- captureError(error, context = {}) {
23
- const errorEntry = {
24
- timestamp: new Date().toISOString(),
25
- error: {
26
- message: error.message,
27
- stack: error.stack,
28
- name: error.name
29
- },
30
- context: {
31
- command: context.command || 'unknown',
32
- servicePath: context.servicePath || process.cwd(),
33
- inputState: context.inputState || {},
34
- userInputs: context.userInputs || {},
35
- action: context.action || 'unknown',
36
- options: context.options || {}
37
- },
38
- recovery: this.generateRecoverySuggestions(error, context),
39
- severity: this.determineSeverity(error, context)
40
- };
41
- this.errors.push(errorEntry);
42
-
43
- // Keep only recent errors
44
- if (this.errors.length > this.maxErrors) {
45
- this.errors = this.errors.slice(-this.maxErrors);
46
- }
47
-
48
- // Log to file asynchronously (don't block)
49
- this.logErrorToFile(errorEntry).catch(err => {
50
- logger.warn('Failed to write error log', {
51
- error: err.message
52
- });
53
- });
54
- return errorEntry;
55
- }
56
-
57
- /**
58
- * Generate recovery suggestions based on error type and context
59
- */
60
- generateRecoverySuggestions(error, context) {
61
- const suggestions = [];
62
-
63
- // Network/API errors
64
- if (error.message.includes('fetch') || error.message.includes('network') || error.message.includes('API')) {
65
- suggestions.push('Check your internet connection');
66
- suggestions.push('Verify Cloudflare API token is valid and has required permissions');
67
- suggestions.push('Confirm Cloudflare account and zone IDs are correct');
68
- }
69
-
70
- // Authentication errors
71
- if (error.message.includes('auth') || error.message.includes('token') || error.message.includes('401') || error.message.includes('403')) {
72
- suggestions.push('Verify Cloudflare API token has not expired');
73
- suggestions.push('Check that the token has permissions for the required operations');
74
- suggestions.push('Regenerate API token if necessary');
75
- }
76
-
77
- // File system errors
78
- if (error.message.includes('ENOENT') || error.message.includes('permission') || error.message.includes('access')) {
79
- suggestions.push('Check file permissions on the service directory');
80
- suggestions.push('Ensure you have write access to the target directory');
81
- suggestions.push('Verify the service path exists and is accessible');
82
- }
83
-
84
- // Validation errors
85
- if (error.message.includes('validation') || error.message.includes('invalid')) {
86
- suggestions.push('Review input values for correctness');
87
- suggestions.push('Use clodo-service validate <path> to check service configuration');
88
- suggestions.push('Run clodo-service diagnose <path> for detailed issue analysis');
89
- }
90
-
91
- // Configuration errors
92
- if (error.message.includes('config') || error.message.includes('configuration')) {
93
- suggestions.push('Run clodo-service update --fix-errors to attempt automatic fixes');
94
- suggestions.push('Check domain configuration in src/config/domains.js');
95
- suggestions.push('Verify package.json has all required fields');
96
- }
97
-
98
- // Template errors
99
- if (error.message.includes('template') || error.message.includes('variable')) {
100
- suggestions.push('Check that all required template variables are provided');
101
- suggestions.push('Verify template files exist and are readable');
102
- suggestions.push('Regenerate service with clodo-service update --regenerate-configs');
103
- }
104
-
105
- // Service creation/update specific
106
- if (context.action === 'create' || context.action === 'update') {
107
- suggestions.push('Try running the command again with --non-interactive flag');
108
- suggestions.push('Use clodo-service diagnose to identify specific issues');
109
- suggestions.push('Check that service name follows naming conventions (lowercase, hyphens only)');
110
- }
111
-
112
- // Cloudflare specific
113
- if (context.action && context.action.includes('cloudflare')) {
114
- suggestions.push('Verify Cloudflare account has D1 database enabled');
115
- suggestions.push('Check zone ID corresponds to the correct domain');
116
- suggestions.push('Ensure API token has D1:Edit permission');
117
- }
118
-
119
- // Add generic suggestions if none specific found
120
- if (suggestions.length === 0) {
121
- suggestions.push('Check the error message for specific details');
122
- suggestions.push('Review the Clodo Framework documentation');
123
- suggestions.push('Try the operation again after reviewing inputs');
124
- suggestions.push('Contact support if the issue persists');
125
- }
126
- return suggestions;
127
- }
128
-
129
- /**
130
- * Determine error severity level
131
- */
132
- determineSeverity(error, context) {
133
- // Critical errors that prevent operation
134
- if (error.message.includes('authentication') || error.message.includes('permission') || error.message.includes('access denied') || error.message.includes('critical')) {
135
- return 'critical';
136
- }
137
-
138
- // High severity - operation fails but may be recoverable
139
- if (error.message.includes('network') || error.message.includes('timeout') || error.message.includes('connection') || error.message.includes('validation')) {
140
- return 'high';
141
- }
142
-
143
- // Medium severity - partial failure or warnings
144
- if (error.message.includes('warning') || error.message.includes('deprecated') || error.message.includes('not found')) {
145
- return 'medium';
146
- }
147
-
148
- // Low severity - minor issues
149
- return 'low';
150
- }
151
-
152
- /**
153
- * Log error to file
154
- */
155
- async logErrorToFile(errorEntry) {
156
- try {
157
- const logEntry = JSON.stringify(errorEntry, null, 2) + '\n---\n';
158
- await fs.appendFile(this.errorLogPath, logEntry);
159
- } catch (error) {
160
- // If we can't write to the log file, at least show a warning
161
- logger.warn('Could not write to error log', {
162
- error: error.message
163
- });
164
- }
165
- }
166
-
167
- /**
168
- * Get recent errors
169
- */
170
- getRecentErrors(limit = 10) {
171
- return this.errors.slice(-limit);
172
- }
173
-
174
- /**
175
- * Get errors by severity
176
- */
177
- getErrorsBySeverity(severity) {
178
- return this.errors.filter(error => error.severity === severity);
179
- }
180
-
181
- /**
182
- * Get errors by command
183
- */
184
- getErrorsByCommand(command) {
185
- return this.errors.filter(error => error.context.command === command);
186
- }
187
-
188
- /**
189
- * Clear error history
190
- */
191
- clearErrors() {
192
- this.errors = [];
193
- }
194
-
195
- /**
196
- * Export error report
197
- */
198
- async exportErrorReport(filePath) {
199
- const report = {
200
- generated: new Date().toISOString(),
201
- totalErrors: this.errors.length,
202
- errorsBySeverity: {
203
- critical: this.getErrorsBySeverity('critical').length,
204
- high: this.getErrorsBySeverity('high').length,
205
- medium: this.getErrorsBySeverity('medium').length,
206
- low: this.getErrorsBySeverity('low').length
207
- },
208
- recentErrors: this.getRecentErrors(20),
209
- summary: this.generateErrorSummary()
210
- };
211
- await fs.writeFile(filePath, JSON.stringify(report, null, 2), 'utf8');
212
- }
213
-
214
- /**
215
- * Generate error summary
216
- */
217
- generateErrorSummary() {
218
- const summary = {
219
- mostCommonErrors: [],
220
- mostProblematicCommands: [],
221
- recentTrends: 'Analysis not implemented yet'
222
- };
223
-
224
- // Count error types
225
- const errorCounts = {};
226
- this.errors.forEach(error => {
227
- const key = error.error.name || 'Unknown';
228
- errorCounts[key] = (errorCounts[key] || 0) + 1;
229
- });
230
- summary.mostCommonErrors = Object.entries(errorCounts).sort(([, a], [, b]) => b - a).slice(0, 5).map(([type, count]) => ({
231
- type,
232
- count
233
- }));
234
-
235
- // Count problematic commands
236
- const commandCounts = {};
237
- this.errors.forEach(error => {
238
- const command = error.context.command || 'unknown';
239
- commandCounts[command] = (commandCounts[command] || 0) + 1;
240
- });
241
- summary.mostProblematicCommands = Object.entries(commandCounts).sort(([, a], [, b]) => b - a).slice(0, 5).map(([command, count]) => ({
242
- command,
243
- count
244
- }));
245
- return summary;
246
- }
247
-
248
- /**
249
- * Display error summary to console
250
- */
251
- displayErrorSummary() {
252
- const summary = this.generateErrorSummary();
253
- console.log(chalk.cyan('\nšŸ“Š Error Summary'));
254
- console.log(chalk.white(`Total Errors: ${this.errors.length}`));
255
- if (summary.mostCommonErrors.length > 0) {
256
- console.log(chalk.cyan('\nMost Common Errors:'));
257
- summary.mostCommonErrors.forEach(({
258
- type,
259
- count
260
- }) => {
261
- console.log(chalk.white(` ${type}: ${count} times`));
262
- });
263
- }
264
- if (summary.mostProblematicCommands.length > 0) {
265
- console.log(chalk.cyan('\nMost Problematic Commands:'));
266
- summary.mostProblematicCommands.forEach(({
267
- command,
268
- count
269
- }) => {
270
- console.log(chalk.white(` ${command}: ${count} errors`));
271
- });
272
- }
273
- }
274
-
275
- /**
276
- * Attempt automatic error recovery
277
- */
278
- async attemptRecovery(errorEntry) {
279
- const recoveries = [];
280
- try {
281
- // Try common recovery actions based on error type
282
- if (errorEntry.error.message.includes('permission') || errorEntry.error.message.includes('access')) {
283
- // Try to fix permissions (limited in what we can do)
284
- recoveries.push('Checked permissions - manual intervention may be required');
285
- }
286
- if (errorEntry.error.message.includes('network') || errorEntry.error.message.includes('timeout')) {
287
- // Wait and retry logic could be implemented here
288
- recoveries.push('Network error detected - consider retrying the operation');
289
- }
290
- if (errorEntry.context.action === 'validate' || errorEntry.context.action === 'create') {
291
- // Try to validate/fix configuration
292
- recoveries.push('Consider running clodo-service update --fix-errors');
293
- }
294
- } catch (recoveryError) {
295
- recoveries.push(`Recovery attempt failed: ${recoveryError.message}`);
296
- }
297
- return recoveries;
298
- }
299
- }