@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,233 +0,0 @@
1
- /**
2
- * BaseGenerator - Abstract base class for all file generators
3
- *
4
- * Provides common functionality for loading templates, rendering content,
5
- * and writing files. All concrete generators should extend this class.
6
- *
7
- * NOTE: This class uses Node.js filesystem APIs and is designed for
8
- * build-time usage during service generation, not runtime in Cloudflare Workers.
9
- *
10
- * @abstract
11
- */
12
- import { promises as fs } from 'fs';
13
- import * as path from 'path';
14
- export class BaseGenerator {
15
- /**
16
- * Create a new generator instance
17
- * @param {Object} options - Generator configuration options
18
- * @param {string} options.name - Generator name (for logging/debugging)
19
- * @param {string} options.templatesPath - Path to templates directory
20
- * @param {string} options.servicePath - Path to service being generated
21
- */
22
- constructor(options = {}) {
23
- if (new.target === BaseGenerator) {
24
- throw new Error('BaseGenerator is abstract and cannot be instantiated directly');
25
- }
26
- this.name = options.name || this.constructor.name;
27
- this.templatesPath = options.templatesPath || options.templatesDir || null;
28
- this.servicePath = options.servicePath || null;
29
-
30
- // Warn if running in Cloudflare Workers environment
31
- if (typeof globalThis !== 'undefined' && globalThis.caches) {
32
- console.warn(`⚠️ ${this.name}: Generators are designed for build-time usage, not runtime in Cloudflare Workers`);
33
- }
34
- this.context = {};
35
- this.logger = options.logger || console;
36
- }
37
-
38
- /**
39
- * Main generation method - must be implemented by concrete generators
40
- * @abstract
41
- * @param {Object} context - Generation context with service configuration
42
- * @returns {Promise<void>}
43
- */
44
- async generate(context) {
45
- throw new Error(`generate() must be implemented by ${this.constructor.name}`);
46
- }
47
-
48
- /**
49
- * Determine if this generator should run for the given context
50
- * Override this to conditionally skip generation
51
- * @param {Object} context - Generation context
52
- * @returns {boolean} - True if generator should run
53
- */
54
- shouldGenerate(context) {
55
- return true;
56
- }
57
-
58
- /**
59
- * Set the generation context
60
- * @param {Object} context - Generation context with service configuration
61
- */
62
- setContext(context) {
63
- this.context = {
64
- ...context
65
- };
66
-
67
- // Update paths if provided in context
68
- if (context.servicePath) {
69
- this.servicePath = context.servicePath;
70
- }
71
- if (context.templatesPath) {
72
- this.templatesPath = context.templatesPath;
73
- }
74
- }
75
-
76
- /**
77
- * Extract and normalize context into consistent format
78
- * @param {Object} context - Generation context
79
- * @returns {Object} - Normalized context with coreInputs, confirmedValues, servicePath
80
- */
81
- extractContext(context) {
82
- return {
83
- coreInputs: context.coreInputs || {},
84
- confirmedValues: context.confirmedValues || {},
85
- servicePath: context.servicePath || this.servicePath || this.outputDir
86
- };
87
- }
88
-
89
- /**
90
- * Get a value from the context
91
- * @param {string} key - Context key (supports dot notation: 'config.name')
92
- * @param {*} defaultValue - Default value if key not found
93
- * @returns {*} - Context value or default
94
- */
95
- getContext(key, defaultValue = undefined) {
96
- if (!key) return this.context;
97
- const keys = key.split('.');
98
- let value = this.context;
99
- for (const k of keys) {
100
- if (value && typeof value === 'object' && k in value) {
101
- value = value[k];
102
- } else {
103
- return defaultValue;
104
- }
105
- }
106
- return value;
107
- }
108
-
109
- /**
110
- * Load a template file from the templates directory
111
- * Subclasses can override this to implement custom template loading
112
- * @param {string} templateName - Template filename or path relative to templatesPath
113
- * @returns {Promise<string>} - Template content
114
- */
115
- async loadTemplate(templateName) {
116
- if (!this.templatesPath) {
117
- throw new Error(`templatesPath not set for ${this.name}`);
118
- }
119
- const templatePath = path.join(this.templatesPath, templateName);
120
- try {
121
- const content = await fs.readFile(templatePath, 'utf8');
122
- return content;
123
- } catch (error) {
124
- const errorMessage = error instanceof Error ? error.message : String(error);
125
- throw new Error(`Failed to load template '${templateName}' from '${templatePath}': ${errorMessage}`);
126
- }
127
- }
128
-
129
- /**
130
- * Render a template with variables
131
- * Replaces {{variable}} placeholders with values from the variables object
132
- * @param {string} template - Template string with {{placeholders}}
133
- * @param {Object} variables - Variable values to replace
134
- * @returns {string} - Rendered template
135
- */
136
- renderTemplate(template, variables = {}) {
137
- if (typeof template !== 'string') {
138
- throw new Error('Template must be a string');
139
- }
140
-
141
- // Merge context with provided variables (variables take precedence)
142
- const mergedVars = {
143
- ...this.context,
144
- ...variables
145
- };
146
-
147
- // Replace {{variable}} placeholders
148
- return template.replace(/\{\{([^}]+)\}\}/g, (match, key) => {
149
- const trimmedKey = key.trim();
150
-
151
- // Check provided variables first (priority), then context
152
- let value;
153
- if (trimmedKey in variables) {
154
- value = variables[trimmedKey];
155
- } else {
156
- // Support dot notation for context: {{config.name}}
157
- value = this.getContext(trimmedKey);
158
- }
159
- if (value === undefined || value === null) {
160
- this.logger.warn(`Template variable '${trimmedKey}' is undefined in ${this.name}`);
161
- return match; // Keep placeholder if variable not found
162
- }
163
- return String(value);
164
- });
165
- }
166
-
167
- /**
168
- * Write content to a file within the service directory
169
- * Creates parent directories if they don't exist
170
- * @param {string} relativePath - Path relative to servicePath
171
- * @param {string} content - File content to write
172
- * @param {Object} options - Write options
173
- * @param {boolean} options.overwrite - Whether to overwrite existing files (default: true)
174
- * @returns {Promise<void>}
175
- */
176
- async writeFile(relativePath, content, options = {}) {
177
- if (!this.servicePath) {
178
- throw new Error(`servicePath not set for ${this.name}`);
179
- }
180
- const fullPath = path.join(this.servicePath, relativePath);
181
- const overwrite = options.overwrite !== false; // Default to true
182
-
183
- // Check if file exists and overwrite is disabled
184
- try {
185
- await fs.access(fullPath);
186
- if (!overwrite) {
187
- this.logger.info(`Skipping existing file: ${relativePath}`);
188
- return;
189
- }
190
- } catch {
191
- // File doesn't exist, continue
192
- }
193
-
194
- // Ensure parent directory exists
195
- const dir = path.dirname(fullPath);
196
- await fs.mkdir(dir, {
197
- recursive: true
198
- });
199
-
200
- // Write file
201
- try {
202
- await fs.writeFile(fullPath, content, 'utf8');
203
- this.logger.info(`Generated: ${relativePath}`);
204
- } catch (error) {
205
- throw new Error(`Failed to write file '${relativePath}': ${error.message}`);
206
- }
207
- }
208
-
209
- /**
210
- * Log a message at info level
211
- * @param {string} message - Message to log
212
- */
213
- log(message) {
214
- this.logger.info(`[${this.name}] ${message}`);
215
- }
216
-
217
- /**
218
- * Log a warning message
219
- * @param {string} message - Warning message
220
- */
221
- warn(message) {
222
- this.logger.warn(`[${this.name}] ${message}`);
223
- }
224
-
225
- /**
226
- * Log an error message
227
- * @param {string} message - Error message
228
- */
229
- error(message) {
230
- this.logger.error(`[${this.name}] ${message}`);
231
- }
232
- }
233
- export default BaseGenerator;
@@ -1,254 +0,0 @@
1
- /**
2
- * GeneratorRegistry - Registry for managing and executing generators
3
- *
4
- * Provides a centralized registry for all generators, organized by category.
5
- * Controls execution order and manages generator lifecycle.
6
- */
7
- export class GeneratorRegistry {
8
- /**
9
- * Create a new generator registry
10
- */
11
- constructor() {
12
- this.categories = new Map();
13
- this.executionOrder = ['core',
14
- // Core configuration files (package.json, wrangler.toml, etc.)
15
- 'config',
16
- // Environment and config files
17
- 'code',
18
- // Source code (schemas, handlers, middleware, utils)
19
- 'scripts',
20
- // Utility scripts (deploy, setup, health-check)
21
- 'tests',
22
- // Test files and test configuration
23
- 'docs',
24
- // Documentation files
25
- 'ci',
26
- // CI/CD workflows
27
- 'service-types' // Service-type specific generation
28
- ];
29
- }
30
-
31
- /**
32
- * Register one or more generators in a category
33
- * @param {string} category - Category name (e.g., 'core', 'config', 'code')
34
- * @param {BaseGenerator|BaseGenerator[]} generators - Generator instance(s) to register
35
- * @throws {Error} If category or generators are invalid
36
- */
37
- register(category, generators) {
38
- if (!category || typeof category !== 'string') {
39
- throw new Error('Category must be a non-empty string');
40
- }
41
- if (!generators) {
42
- throw new Error('Generators must be provided');
43
- }
44
-
45
- // Ensure generators is an array
46
- const generatorArray = Array.isArray(generators) ? generators : [generators];
47
- if (generatorArray.length === 0) {
48
- throw new Error('At least one generator must be provided');
49
- }
50
-
51
- // Validate all generators have a generate() method
52
- for (const generator of generatorArray) {
53
- if (!generator || typeof generator.generate !== 'function') {
54
- throw new Error(`Invalid generator: must have a generate() method. Got: ${generator?.constructor?.name || typeof generator}`);
55
- }
56
- }
57
-
58
- // Get existing generators for this category or create new array
59
- const existing = this.categories.get(category) || [];
60
-
61
- // Add new generators
62
- this.categories.set(category, [...existing, ...generatorArray]);
63
- }
64
-
65
- /**
66
- * Unregister a specific generator from a category
67
- * @param {string} category - Category name
68
- * @param {string} generatorName - Name of the generator to remove
69
- * @returns {boolean} - True if generator was found and removed
70
- */
71
- unregister(category, generatorName) {
72
- if (!this.categories.has(category)) {
73
- return false;
74
- }
75
- const generators = this.categories.get(category);
76
- const initialLength = generators.length;
77
- const filtered = generators.filter(gen => gen.name !== generatorName);
78
- if (filtered.length === 0) {
79
- this.categories.delete(category);
80
- } else {
81
- this.categories.set(category, filtered);
82
- }
83
- return filtered.length < initialLength;
84
- }
85
-
86
- /**
87
- * Get all generators for a specific category
88
- * @param {string} category - Category name
89
- * @returns {BaseGenerator[]} - Array of generators (empty if category not found)
90
- */
91
- getGenerators(category) {
92
- return this.categories.get(category) || [];
93
- }
94
-
95
- /**
96
- * Get all registered categories in execution order
97
- * @returns {string[]} - Array of category names
98
- */
99
- getCategories() {
100
- const registeredCategories = Array.from(this.categories.keys());
101
-
102
- // Return categories in execution order, followed by any unordered categories
103
- const ordered = this.executionOrder.filter(cat => registeredCategories.includes(cat));
104
- const unordered = registeredCategories.filter(cat => !this.executionOrder.includes(cat));
105
- return [...ordered, ...unordered];
106
- }
107
-
108
- /**
109
- * Get total count of registered generators across all categories
110
- * @returns {number} - Total generator count
111
- */
112
- getCount() {
113
- let count = 0;
114
- for (const generators of this.categories.values()) {
115
- count += generators.length;
116
- }
117
- return count;
118
- }
119
-
120
- /**
121
- * Get count of generators in a specific category
122
- * @param {string} category - Category name
123
- * @returns {number} - Generator count for category
124
- */
125
- getCategoryCount(category) {
126
- return this.getGenerators(category).length;
127
- }
128
-
129
- /**
130
- * Check if a category has any generators
131
- * @param {string} category - Category name
132
- * @returns {boolean} - True if category has generators
133
- */
134
- hasCategory(category) {
135
- return this.categories.has(category) && this.categories.get(category).length > 0;
136
- }
137
-
138
- /**
139
- * Clear all generators from a category
140
- * @param {string} category - Category name
141
- * @returns {boolean} - True if category existed and was cleared
142
- */
143
- clearCategory(category) {
144
- return this.categories.delete(category);
145
- }
146
-
147
- /**
148
- * Clear all generators from all categories
149
- */
150
- clearAll() {
151
- this.categories.clear();
152
- }
153
-
154
- /**
155
- * Execute all generators in order
156
- * @param {Object} context - Generation context to pass to all generators
157
- * @param {Object} options - Execution options
158
- * @param {Function} options.logger - Logger for progress tracking
159
- * @param {boolean} options.stopOnError - Whether to stop execution on first error (default: false)
160
- * @returns {Promise<Object>} - Execution results { success, failed, skipped }
161
- */
162
- async execute(context, options = {}) {
163
- const logger = options.logger || console;
164
- const stopOnError = options.stopOnError !== false; // Default to true for safety
165
-
166
- const results = {
167
- success: [],
168
- failed: [],
169
- skipped: []
170
- };
171
- const categories = this.getCategories();
172
- logger.info(`Starting generator execution: ${this.getCount()} generators in ${categories.length} categories`);
173
- for (const category of categories) {
174
- const generators = this.getGenerators(category);
175
- logger.info(`Executing category: ${category} (${generators.length} generators)`);
176
- for (const generator of generators) {
177
- const name = generator.name || generator.constructor.name;
178
- try {
179
- // Check if generator should run
180
- if (generator.shouldGenerate && !generator.shouldGenerate(context)) {
181
- logger.info(`Skipping ${name}: shouldGenerate() returned false`);
182
- results.skipped.push({
183
- name,
184
- category,
185
- reason: 'shouldGenerate() returned false'
186
- });
187
- continue;
188
- }
189
-
190
- // Execute generator
191
- logger.info(`Running ${name}...`);
192
- await generator.generate(context);
193
- results.success.push({
194
- name,
195
- category
196
- });
197
- logger.info(`✓ ${name} completed successfully`);
198
- } catch (error) {
199
- const errorInfo = {
200
- name,
201
- category,
202
- error: error.message,
203
- stack: error.stack
204
- };
205
- results.failed.push(errorInfo);
206
- logger.error(`✗ ${name} failed: ${error.message}`);
207
- if (stopOnError) {
208
- logger.error('Stopping execution due to error (stopOnError=true)');
209
- throw new Error(`Generator execution stopped: ${name} failed - ${error.message}`);
210
- }
211
- }
212
- }
213
- }
214
-
215
- // Log summary
216
- logger.info('\n=== Generator Execution Summary ===');
217
- logger.info(`Total: ${this.getCount()} generators`);
218
- logger.info(`✓ Success: ${results.success.length}`);
219
- logger.info(`✗ Failed: ${results.failed.length}`);
220
- logger.info(`⊘ Skipped: ${results.skipped.length}`);
221
- if (results.failed.length > 0) {
222
- logger.error('\nFailed generators:');
223
- results.failed.forEach(({
224
- name,
225
- error
226
- }) => {
227
- logger.error(` - ${name}: ${error}`);
228
- });
229
- }
230
- return results;
231
- }
232
-
233
- /**
234
- * Get a summary of all registered generators
235
- * @returns {Object} - Summary with categories and generator counts
236
- */
237
- getSummary() {
238
- const categories = this.getCategories();
239
- const summary = {
240
- totalCategories: categories.length,
241
- totalGenerators: this.getCount(),
242
- categories: {}
243
- };
244
- for (const category of categories) {
245
- const generators = this.getGenerators(category);
246
- summary.categories[category] = {
247
- count: generators.length,
248
- generators: generators.map(g => g.name || g.constructor.name)
249
- };
250
- }
251
- return summary;
252
- }
253
- }
254
- export default GeneratorRegistry;
@@ -1,87 +0,0 @@
1
- import { BaseGenerator } from '../BaseGenerator.js';
2
- import { join } from 'path';
3
- import { writeFileSync, mkdirSync } from 'fs';
4
-
5
- /**
6
- * CI Workflow Generator
7
- * Generates GitHub Actions CI workflow for automated testing
8
- */
9
- export class CiWorkflowGenerator extends BaseGenerator {
10
- /**
11
- * Generate CI workflow
12
- * @param {Object} context - Generation context
13
- * @returns {Promise<string>} Path to generated CI workflow file
14
- */
15
- async generate(context) {
16
- const {
17
- coreInputs,
18
- confirmedValues,
19
- servicePath
20
- } = this.extractContext(context);
21
- if (!this.shouldGenerate(context)) {
22
- return null;
23
- }
24
-
25
- // Ensure .github/workflows directory exists
26
- const workflowsDir = join(servicePath, '.github', 'workflows');
27
- mkdirSync(workflowsDir, {
28
- recursive: true
29
- });
30
- const ciWorkflow = this._generateCiWorkflow(coreInputs, confirmedValues);
31
- const filePath = join(workflowsDir, 'ci.yml');
32
- writeFileSync(filePath, ciWorkflow, 'utf8');
33
- return filePath;
34
- }
35
-
36
- /**
37
- * Generate CI workflow content
38
- * @private
39
- */
40
- _generateCiWorkflow(coreInputs, confirmedValues) {
41
- return `name: CI
42
-
43
- on:
44
- push:
45
- branches: [ main, master ]
46
- pull_request:
47
- branches: [ main, master ]
48
-
49
- jobs:
50
- test:
51
- runs-on: ubuntu-latest
52
-
53
- steps:
54
- - uses: actions/checkout@v4
55
-
56
- - name: Setup Node.js
57
- uses: actions/setup-node@v4
58
- with:
59
- node-version: '18'
60
- cache: 'npm'
61
-
62
- - name: Install dependencies
63
- run: npm ci
64
-
65
- - name: Lint code
66
- run: npm run lint
67
-
68
- - name: Run tests
69
- run: npm test
70
-
71
- - name: Build
72
- run: npm run build
73
-
74
- - name: Upload coverage reports
75
- uses: codecov/codecov-action@v3
76
- with:
77
- file: ./coverage/lcov.info
78
- `;
79
- }
80
-
81
- /**
82
- * Determine if generator should run
83
- */
84
- shouldGenerate(context) {
85
- return true; // Always generate CI workflow
86
- }
87
- }
@@ -1,106 +0,0 @@
1
- import { BaseGenerator } from '../BaseGenerator.js';
2
- import { join } from 'path';
3
- import { writeFileSync, mkdirSync } from 'fs';
4
-
5
- /**
6
- * Deploy Workflow Generator
7
- * Generates GitHub Actions deployment workflow for staging and production
8
- */
9
- export class DeployWorkflowGenerator extends BaseGenerator {
10
- /**
11
- * Generate deployment workflow
12
- * @param {Object} context - Generation context
13
- * @returns {Promise<string>} Path to generated deploy workflow file
14
- */
15
- async generate(context) {
16
- const {
17
- coreInputs,
18
- confirmedValues,
19
- servicePath
20
- } = this.extractContext(context);
21
- if (!this.shouldGenerate(context)) {
22
- return null;
23
- }
24
-
25
- // Ensure .github/workflows directory exists
26
- const workflowsDir = join(servicePath, '.github', 'workflows');
27
- mkdirSync(workflowsDir, {
28
- recursive: true
29
- });
30
- const deployWorkflow = this._generateDeployWorkflow(coreInputs, confirmedValues);
31
- const filePath = join(workflowsDir, 'deploy.yml');
32
- writeFileSync(filePath, deployWorkflow, 'utf8');
33
- return filePath;
34
- }
35
-
36
- /**
37
- * Generate deployment workflow content
38
- * @private
39
- */
40
- _generateDeployWorkflow(coreInputs, confirmedValues) {
41
- return `name: Deploy
42
-
43
- on:
44
- push:
45
- branches: [ main, master ]
46
- workflow_run:
47
- workflows: ["CI"]
48
- types:
49
- - completed
50
-
51
- jobs:
52
- deploy-staging:
53
- if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
54
- runs-on: ubuntu-latest
55
- environment: staging
56
-
57
- steps:
58
- - uses: actions/checkout@v4
59
-
60
- - name: Setup Node.js
61
- uses: actions/setup-node@v4
62
- with:
63
- node-version: '18'
64
- cache: 'npm'
65
-
66
- - name: Install dependencies
67
- run: npm ci
68
-
69
- - name: Deploy to staging
70
- run: npx wrangler deploy --env staging
71
- env:
72
- CLOUDFLARE_API_TOKEN: \${{ secrets.CLOUDFLARE_API_TOKEN }}
73
- CLOUDFLARE_ACCOUNT_ID: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
74
-
75
- deploy-production:
76
- if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
77
- runs-on: ubuntu-latest
78
- environment: production
79
-
80
- steps:
81
- - uses: actions/checkout@v4
82
-
83
- - name: Setup Node.js
84
- uses: actions/setup-node@v4
85
- with:
86
- node-version: '18'
87
- cache: 'npm'
88
-
89
- - name: Install dependencies
90
- run: npm ci
91
-
92
- - name: Deploy to production
93
- run: npx wrangler deploy --env production
94
- env:
95
- CLOUDFLARE_API_TOKEN: \${{ secrets.CLOUDFLARE_API_TOKEN }}
96
- CLOUDFLARE_ACCOUNT_ID: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
97
- `;
98
- }
99
-
100
- /**
101
- * Determine if generator should run
102
- */
103
- shouldGenerate(context) {
104
- return true; // Always generate deployment workflow
105
- }
106
- }