@tamyla/clodo-framework 3.0.15 → 3.1.0

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 (70) hide show
  1. package/CHANGELOG.md +215 -163
  2. package/README.md +133 -1
  3. package/bin/clodo-service.js +0 -0
  4. package/bin/security/security-cli.js +0 -0
  5. package/bin/service-management/create-service.js +0 -0
  6. package/bin/service-management/init-service.js +2 -1
  7. package/dist/service-management/GenerationEngine.js +298 -3025
  8. package/dist/service-management/ServiceCreator.js +19 -3
  9. package/dist/service-management/generators/BaseGenerator.js +233 -0
  10. package/dist/service-management/generators/GeneratorRegistry.js +254 -0
  11. package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +87 -0
  12. package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +106 -0
  13. package/dist/service-management/generators/code/ServiceHandlersGenerator.js +235 -0
  14. package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +116 -0
  15. package/dist/service-management/generators/code/ServiceUtilsGenerator.js +246 -0
  16. package/dist/service-management/generators/code/WorkerIndexGenerator.js +143 -0
  17. package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +101 -0
  18. package/dist/service-management/generators/config/DomainsConfigGenerator.js +175 -0
  19. package/dist/service-management/generators/config/EnvExampleGenerator.js +178 -0
  20. package/dist/service-management/generators/config/ProductionEnvGenerator.js +97 -0
  21. package/dist/service-management/generators/config/StagingEnvGenerator.js +97 -0
  22. package/dist/service-management/generators/config/WranglerTomlGenerator.js +238 -0
  23. package/dist/service-management/generators/core/PackageJsonGenerator.js +243 -0
  24. package/dist/service-management/generators/core/SiteConfigGenerator.js +115 -0
  25. package/dist/service-management/generators/documentation/ApiDocsGenerator.js +331 -0
  26. package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +294 -0
  27. package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +244 -0
  28. package/dist/service-management/generators/documentation/ReadmeGenerator.js +196 -0
  29. package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +190 -0
  30. package/dist/service-management/generators/scripts/DeployScriptGenerator.js +123 -0
  31. package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +101 -0
  32. package/dist/service-management/generators/scripts/SetupScriptGenerator.js +88 -0
  33. package/dist/service-management/generators/service-types/StaticSiteGenerator.js +342 -0
  34. package/dist/service-management/generators/testing/EslintConfigGenerator.js +85 -0
  35. package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +237 -0
  36. package/dist/service-management/generators/testing/JestConfigGenerator.js +72 -0
  37. package/dist/service-management/generators/testing/UnitTestsGenerator.js +277 -0
  38. package/dist/service-management/generators/tooling/DockerComposeGenerator.js +71 -0
  39. package/dist/service-management/generators/tooling/GitignoreGenerator.js +143 -0
  40. package/dist/service-management/generators/utils/FileWriter.js +179 -0
  41. package/dist/service-management/generators/utils/PathResolver.js +157 -0
  42. package/dist/service-management/generators/utils/ServiceManifestGenerator.js +111 -0
  43. package/dist/service-management/generators/utils/TemplateEngine.js +185 -0
  44. package/dist/service-management/generators/utils/index.js +18 -0
  45. package/dist/service-management/routing/DomainRouteMapper.js +311 -0
  46. package/dist/service-management/routing/RouteGenerator.js +266 -0
  47. package/dist/service-management/routing/WranglerRoutesBuilder.js +273 -0
  48. package/dist/service-management/routing/index.js +14 -0
  49. package/dist/service-management/services/DirectoryStructureService.js +56 -0
  50. package/dist/service-management/services/GenerationCoordinator.js +208 -0
  51. package/dist/service-management/services/GeneratorRegistry.js +174 -0
  52. package/dist/services/GenericDataService.js +14 -1
  53. package/dist/utils/config/unified-config-manager.js +128 -12
  54. package/dist/utils/framework-config.js +74 -2
  55. package/dist/worker/integration.js +4 -1
  56. package/package.json +6 -1
  57. package/templates/generic/clodo-service-manifest.json +25 -0
  58. package/templates/static-site/.env.example +61 -0
  59. package/templates/static-site/README.md +176 -0
  60. package/templates/static-site/clodo-service-manifest.json +66 -0
  61. package/templates/static-site/package.json +28 -0
  62. package/templates/static-site/public/404.html +87 -0
  63. package/templates/static-site/public/app.js +100 -0
  64. package/templates/static-site/public/index.html +48 -0
  65. package/templates/static-site/public/styles.css +123 -0
  66. package/templates/static-site/scripts/deploy.ps1 +121 -0
  67. package/templates/static-site/scripts/setup.ps1 +179 -0
  68. package/templates/static-site/src/config/domains.js +35 -0
  69. package/templates/static-site/src/worker/index.js +153 -0
  70. package/templates/static-site/wrangler.toml +43 -0
@@ -31,7 +31,10 @@
31
31
  * 15. API Base Path
32
32
  */
33
33
 
34
- import { ServiceInitializer } from './ServiceInitializer.js';
34
+ import { ServiceManifestGenerator } from './generators/utils/ServiceManifestGenerator.js';
35
+ import { DirectoryStructureService } from './services/DirectoryStructureService.js';
36
+ import { GenerationCoordinator } from './services/GenerationCoordinator.js';
37
+ import { GeneratorRegistry } from './services/GeneratorRegistry.js';
35
38
  import { fileURLToPath } from 'url';
36
39
  import { dirname, join, relative } from 'path';
37
40
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
@@ -49,8 +52,280 @@ export class GenerationEngine {
49
52
  this.templatesDir = options.templatesDir || join(__dirname, '..', '..', 'templates');
50
53
  this.outputDir = options.outputDir || process.cwd();
51
54
  this.force = options.force || false;
55
+
56
+ // Initialize generator registry for centralized management
57
+ this.generatorRegistry = new GeneratorRegistry({
58
+ templatesDir: this.templatesDir,
59
+ outputDir: this.outputDir
60
+ });
61
+
62
+ // Utility services
63
+ this.serviceManifestGenerator = new ServiceManifestGenerator();
64
+ this.directoryStructureService = new DirectoryStructureService();
65
+ this.generationCoordinator = new GenerationCoordinator(this);
66
+
67
+ // Initialize dynamic proxy methods
68
+ this.initializeProxyMethods();
69
+ }
70
+
71
+ // Generator getters (lazy instantiation via registry)
72
+ get routeGenerator() {
73
+ return this.generatorRegistry.get('routeGenerator');
74
+ }
75
+ get packageJsonGenerator() {
76
+ return this.generatorRegistry.get('packageJsonGenerator');
77
+ }
78
+ get siteConfigGenerator() {
79
+ return this.generatorRegistry.get('siteConfigGenerator');
80
+ }
81
+ get staticSiteGenerator() {
82
+ return this.generatorRegistry.get('staticSiteGenerator');
83
+ }
84
+ get wranglerTomlGenerator() {
85
+ return this.generatorRegistry.get('wranglerTomlGenerator');
86
+ }
87
+ get domainsConfigGenerator() {
88
+ return this.generatorRegistry.get('domainsConfigGenerator');
89
+ }
90
+ get workerIndexGenerator() {
91
+ return this.generatorRegistry.get('workerIndexGenerator');
92
+ }
93
+ get serviceHandlersGenerator() {
94
+ return this.generatorRegistry.get('serviceHandlersGenerator');
95
+ }
96
+ get serviceMiddlewareGenerator() {
97
+ return this.generatorRegistry.get('serviceMiddlewareGenerator');
98
+ }
99
+ get serviceUtilsGenerator() {
100
+ return this.generatorRegistry.get('serviceUtilsGenerator');
101
+ }
102
+ get envExampleGenerator() {
103
+ return this.generatorRegistry.get('envExampleGenerator');
104
+ }
105
+ get productionEnvGenerator() {
106
+ return this.generatorRegistry.get('productionEnvGenerator');
107
+ }
108
+ get stagingEnvGenerator() {
109
+ return this.generatorRegistry.get('stagingEnvGenerator');
110
+ }
111
+ get developmentEnvGenerator() {
112
+ return this.generatorRegistry.get('developmentEnvGenerator');
113
+ }
114
+ get serviceSchemaGenerator() {
115
+ return this.generatorRegistry.get('serviceSchemaGenerator');
116
+ }
117
+ get deployScriptGenerator() {
118
+ return this.generatorRegistry.get('deployScriptGenerator');
119
+ }
120
+ get setupScriptGenerator() {
121
+ return this.generatorRegistry.get('setupScriptGenerator');
122
+ }
123
+ get healthCheckScriptGenerator() {
124
+ return this.generatorRegistry.get('healthCheckScriptGenerator');
125
+ }
126
+ get unitTestsGenerator() {
127
+ return this.generatorRegistry.get('unitTestsGenerator');
128
+ }
129
+ get integrationTestsGenerator() {
130
+ return this.generatorRegistry.get('integrationTestsGenerator');
131
+ }
132
+ get jestConfigGenerator() {
133
+ return this.generatorRegistry.get('jestConfigGenerator');
134
+ }
135
+ get eslintConfigGenerator() {
136
+ return this.generatorRegistry.get('eslintConfigGenerator');
137
+ }
138
+ get readmeGenerator() {
139
+ return this.generatorRegistry.get('readmeGenerator');
140
+ }
141
+ get apiDocsGenerator() {
142
+ return this.generatorRegistry.get('apiDocsGenerator');
143
+ }
144
+ get deploymentDocsGenerator() {
145
+ return this.generatorRegistry.get('deploymentDocsGenerator');
146
+ }
147
+ get configurationDocsGenerator() {
148
+ return this.generatorRegistry.get('configurationDocsGenerator');
149
+ }
150
+ get ciWorkflowGenerator() {
151
+ return this.generatorRegistry.get('ciWorkflowGenerator');
152
+ }
153
+ get deployWorkflowGenerator() {
154
+ return this.generatorRegistry.get('deployWorkflowGenerator');
155
+ }
156
+ get gitignoreGenerator() {
157
+ return this.generatorRegistry.get('gitignoreGenerator');
158
+ }
159
+ get dockerComposeGenerator() {
160
+ return this.generatorRegistry.get('dockerComposeGenerator');
161
+ }
162
+
163
+ // Dynamic proxy methods initialization (replaces ~300 lines of individual methods)
164
+ initializeProxyMethods() {
165
+ const generatorMappings = {
166
+ generatePackageJson: {
167
+ generator: 'packageJsonGenerator',
168
+ returnPath: 'package.json'
169
+ },
170
+ generateSiteConfig: {
171
+ generator: 'siteConfigGenerator',
172
+ returnContent: true
173
+ },
174
+ generateStaticSite: {
175
+ generator: 'staticSiteGenerator'
176
+ },
177
+ generateWranglerToml: {
178
+ generator: 'wranglerTomlGenerator',
179
+ returnPath: 'wrangler.toml'
180
+ },
181
+ generateDomainsConfig: {
182
+ generator: 'domainsConfigGenerator',
183
+ returnPath: 'config/domains.js'
184
+ },
185
+ generateWorkerIndex: {
186
+ generator: 'workerIndexGenerator',
187
+ returnPath: 'src/index.js'
188
+ },
189
+ generateServiceHandlers: {
190
+ generator: 'serviceHandlersGenerator',
191
+ returnPath: 'src/handlers.js'
192
+ },
193
+ generateServiceMiddleware: {
194
+ generator: 'serviceMiddlewareGenerator',
195
+ returnPath: 'src/middleware.js'
196
+ },
197
+ generateServiceUtils: {
198
+ generator: 'serviceUtilsGenerator',
199
+ returnPath: 'src/utils.js'
200
+ },
201
+ generateEnvExample: {
202
+ generator: 'envExampleGenerator',
203
+ returnPath: '.env.example'
204
+ },
205
+ generateProductionEnv: {
206
+ generator: 'productionEnvGenerator',
207
+ returnPath: '.env.production'
208
+ },
209
+ generateStagingEnv: {
210
+ generator: 'stagingEnvGenerator',
211
+ returnPath: '.env.staging'
212
+ },
213
+ generateDevelopmentEnv: {
214
+ generator: 'developmentEnvGenerator',
215
+ returnPath: '.env.development'
216
+ },
217
+ generateServiceSchema: {
218
+ generator: 'serviceSchemaGenerator',
219
+ returnPath: 'config/schema.json'
220
+ },
221
+ generateDeployScript: {
222
+ generator: 'deployScriptGenerator',
223
+ returnPath: 'scripts/deploy.sh'
224
+ },
225
+ generateSetupScript: {
226
+ generator: 'setupScriptGenerator',
227
+ returnPath: 'scripts/setup.sh'
228
+ },
229
+ generateHealthCheckScript: {
230
+ generator: 'healthCheckScriptGenerator',
231
+ returnPath: 'scripts/health-check.js'
232
+ },
233
+ generateUnitTests: {
234
+ generator: 'unitTestsGenerator',
235
+ returnPath: 'test/unit.test.js'
236
+ },
237
+ generateIntegrationTests: {
238
+ generator: 'integrationTestsGenerator',
239
+ returnPath: 'test/integration.test.js'
240
+ },
241
+ generateJestConfig: {
242
+ generator: 'jestConfigGenerator',
243
+ returnPath: 'jest.config.js'
244
+ },
245
+ generateEslintConfig: {
246
+ generator: 'eslintConfigGenerator',
247
+ returnPath: 'eslint.config.js'
248
+ },
249
+ generateReadme: {
250
+ generator: 'readmeGenerator',
251
+ returnPath: 'README.md'
252
+ },
253
+ generateApiDocs: {
254
+ generator: 'apiDocsGenerator',
255
+ returnPath: 'docs/api.md'
256
+ },
257
+ generateDeploymentDocs: {
258
+ generator: 'deploymentDocsGenerator',
259
+ returnPath: 'docs/deployment.md'
260
+ },
261
+ generateConfigurationDocs: {
262
+ generator: 'configurationDocsGenerator',
263
+ returnPath: 'docs/configuration.md'
264
+ },
265
+ generateCiWorkflow: {
266
+ generator: 'ciWorkflowGenerator',
267
+ returnPath: '.github/workflows/ci.yml'
268
+ },
269
+ generateDeployWorkflow: {
270
+ generator: 'deployWorkflowGenerator',
271
+ returnPath: '.github/workflows/deploy.yml'
272
+ },
273
+ generateGitignore: {
274
+ generator: 'gitignoreGenerator',
275
+ returnPath: '.gitignore'
276
+ },
277
+ generateDockerCompose: {
278
+ generator: 'dockerComposeGenerator',
279
+ returnPath: 'docker-compose.yml'
280
+ }
281
+ };
282
+ Object.entries(generatorMappings).forEach(([methodName, config]) => {
283
+ // Only create proxy method if it doesn't already exist
284
+ if (!this[methodName]) {
285
+ this[methodName] = async function (...args) {
286
+ const context = this.buildContext(methodName, ...args);
287
+ const generator = this[config.generator];
288
+ const result = await generator.generate(context);
289
+
290
+ // Return content for methods that return content, otherwise return file path
291
+ if (config.returnContent) {
292
+ return result;
293
+ } else if (config.returnPath) {
294
+ const servicePath = args[2] || args[0]?.servicePath || this.outputDir;
295
+ return join(servicePath, config.returnPath);
296
+ } else {
297
+ // For methods that don't return specific content or paths, return the service path
298
+ return args[2] || args[0]?.servicePath || this.outputDir;
299
+ }
300
+ };
301
+ }
302
+ });
303
+ }
304
+
305
+ // Context builder for proxy methods
306
+ buildContext(methodName, ...args) {
307
+ // Special handling for generateSiteConfig
308
+ if (methodName === 'generateSiteConfig') {
309
+ return {
310
+ coreInputs: {
311
+ serviceType: args[0]
312
+ },
313
+ siteConfig: args[1] || {}
314
+ };
315
+ }
316
+
317
+ // For most methods: (coreInputs, confirmedValues, servicePath)
318
+ return {
319
+ coreInputs: args[0],
320
+ confirmedValues: args[1],
321
+ servicePath: args[2]
322
+ };
52
323
  }
53
324
 
325
+ /**
326
+ * Generate complete service from core inputs and confirmed values
327
+ */
328
+
54
329
  /**
55
330
  * Generate complete service from core inputs and confirmed values
56
331
  */
@@ -97,3078 +372,76 @@ export class GenerationEngine {
97
372
  * Create the complete directory structure
98
373
  */
99
374
  createDirectoryStructure(servicePath) {
100
- const directories = ['src', 'src/config', 'src/worker', 'src/handlers', 'src/middleware', 'src/utils', 'src/schemas', 'scripts', 'test', 'test/unit', 'test/integration', 'docs', 'config', 'logs', '.github', '.github/workflows'];
101
- for (const dir of directories) {
102
- const fullPath = join(servicePath, dir);
103
- if (!existsSync(fullPath)) {
104
- mkdirSync(fullPath, {
105
- recursive: true
106
- });
107
- }
108
- }
375
+ return this.directoryStructureService.createStandardStructure(servicePath);
109
376
  }
110
377
 
111
378
  /**
112
379
  * Generate all configuration files
113
380
  */
114
381
  async generateAllFiles(coreInputs, confirmedValues, servicePath) {
115
- const generatedFiles = [];
116
-
117
- // Core configuration files
118
- generatedFiles.push(...this.generateCoreFiles(coreInputs, confirmedValues, servicePath));
119
-
120
- // Service-specific configuration files
121
- generatedFiles.push(...this.generateServiceSpecificFiles(coreInputs, confirmedValues, servicePath));
122
-
123
- // Environment and deployment files
124
- generatedFiles.push(...this.generateEnvironmentFiles(coreInputs, confirmedValues, servicePath));
125
-
126
- // Testing and quality assurance files
127
- generatedFiles.push(...this.generateTestingFiles(coreInputs, confirmedValues, servicePath));
128
-
129
- // Documentation files
130
- generatedFiles.push(...this.generateDocumentationFiles(coreInputs, confirmedValues, servicePath));
131
-
132
- // CI/CD and automation files
133
- generatedFiles.push(...this.generateAutomationFiles(coreInputs, confirmedValues, servicePath));
134
- return generatedFiles;
382
+ return await this.generationCoordinator.generateAllFiles(coreInputs, confirmedValues, servicePath);
135
383
  }
136
384
 
137
385
  /**
138
386
  * Generate core configuration files (package.json, wrangler.toml, etc.)
139
387
  */
140
- generateCoreFiles(coreInputs, confirmedValues, servicePath) {
141
- const files = [];
142
-
143
- // Use ServiceInitializer for proven package.json generation
144
- const serviceInitializer = new ServiceInitializer();
145
-
146
- // Generate package.json with proper dependencies
147
- const packageJsonContent = this.generatePackageJson(coreInputs, confirmedValues, servicePath);
148
- const packageJsonPath = join(servicePath, 'package.json');
149
- writeFileSync(packageJsonPath, packageJsonContent, 'utf8');
150
- files.push(packageJsonPath);
151
-
152
- // Generate wrangler.toml using ServiceInitializer's proven method
153
- const wranglerConfig = serviceInitializer.generateWranglerConfig(coreInputs.serviceName, {
154
- type: coreInputs.serviceType,
155
- env: coreInputs.environment
156
- }, {
157
- domains: [{
158
- domain: coreInputs.domainName,
159
- accountId: coreInputs.cloudflareAccountId,
160
- zoneId: coreInputs.cloudflareZoneId,
161
- name: `${coreInputs.serviceName}-${coreInputs.environment}`
162
- }]
163
- });
164
-
165
- // Write wrangler.toml
166
- const wranglerPath = join(servicePath, 'wrangler.toml');
167
- let wranglerContent = '';
168
- for (const [key, value] of Object.entries(wranglerConfig)) {
169
- if (key === 'wrangler.toml') {
170
- wranglerContent = value;
171
- } else {
172
- // Handle multi-domain configs if needed
173
- const configPath = join(servicePath, key);
174
- writeFileSync(configPath, value, 'utf8');
175
- files.push(configPath);
176
- }
177
- }
178
- if (wranglerContent) {
179
- writeFileSync(wranglerPath, wranglerContent, 'utf8');
180
- files.push(wranglerPath);
181
- }
182
-
183
- // Generate domains.js using ServiceInitializer
184
- const domainsContent = serviceInitializer.generateDomainsConfig(coreInputs.serviceName, {
185
- type: coreInputs.serviceType,
186
- env: coreInputs.environment
187
- }, {
188
- domains: [{
189
- domain: coreInputs.domainName,
190
- accountId: coreInputs.cloudflareAccountId,
191
- zoneId: coreInputs.cloudflareZoneId,
192
- name: `${coreInputs.serviceName}-${coreInputs.environment}`
193
- }]
194
- });
195
- const domainsPath = join(servicePath, 'src', 'config', 'domains.js');
196
- writeFileSync(domainsPath, domainsContent, 'utf8');
197
- files.push(domainsPath);
198
-
199
- // Generate worker index using existing method
200
- const workerPath = this.generateWorkerIndex(coreInputs, confirmedValues, servicePath);
201
- files.push(workerPath);
202
- return files;
388
+ async generateCoreFiles(coreInputs, confirmedValues, servicePath) {
389
+ return await this.generationCoordinator.generateCoreFiles(coreInputs, confirmedValues, servicePath);
203
390
  }
204
391
 
205
392
  /**
206
393
  * Generate service-specific configuration files
207
394
  */
208
- generateServiceSpecificFiles(coreInputs, confirmedValues, servicePath) {
209
- const files = [];
210
-
211
- // Generate service schema
212
- const schemaPath = this.generateServiceSchema(coreInputs, confirmedValues, servicePath);
213
- files.push(schemaPath);
214
-
215
- // Generate service handlers
216
- const handlersPath = this.generateServiceHandlers(coreInputs, confirmedValues, servicePath);
217
- files.push(handlersPath);
218
-
219
- // Generate service middleware
220
- const middlewarePath = this.generateServiceMiddleware(coreInputs, confirmedValues, servicePath);
221
- files.push(middlewarePath);
222
-
223
- // Generate service utils
224
- const utilsPath = this.generateServiceUtils(coreInputs, confirmedValues, servicePath);
225
- files.push(utilsPath);
226
- return files;
395
+ async generateServiceSpecificFiles(coreInputs, confirmedValues, servicePath) {
396
+ return await this.generationCoordinator.generateServiceSpecificFiles(coreInputs, confirmedValues, servicePath);
227
397
  }
228
398
 
229
399
  /**
230
400
  * Generate environment and deployment files
231
401
  */
232
- generateEnvironmentFiles(coreInputs, confirmedValues, servicePath) {
233
- const files = [];
234
-
235
- // scripts/deploy.ps1
236
- files.push(this.generateDeployScript(coreInputs, confirmedValues, servicePath));
237
-
238
- // scripts/setup.ps1
239
- files.push(this.generateSetupScript(coreInputs, confirmedValues, servicePath));
240
-
241
- // scripts/health-check.ps1
242
- files.push(this.generateHealthCheckScript(coreInputs, confirmedValues, servicePath));
243
-
244
- // config/production.env
245
- files.push(this.generateProductionEnv(coreInputs, confirmedValues, servicePath));
246
-
247
- // config/staging.env
248
- files.push(this.generateStagingEnv(coreInputs, confirmedValues, servicePath));
249
-
250
- // config/development.env
251
- files.push(this.generateDevelopmentEnv(coreInputs, confirmedValues, servicePath));
252
- return files;
402
+ async generateEnvironmentFiles(coreInputs, confirmedValues, servicePath) {
403
+ return await this.generationCoordinator.generateEnvironmentFiles(coreInputs, confirmedValues, servicePath);
253
404
  }
254
405
 
255
406
  /**
256
407
  * Generate testing and quality assurance files
257
408
  */
258
- generateTestingFiles(coreInputs, confirmedValues, servicePath) {
259
- const files = [];
260
-
261
- // test/unit/service.test.js
262
- files.push(this.generateUnitTests(coreInputs, confirmedValues, servicePath));
263
-
264
- // test/integration/service.integration.test.js
265
- files.push(this.generateIntegrationTests(coreInputs, confirmedValues, servicePath));
266
-
267
- // jest.config.js
268
- files.push(this.generateJestConfig(coreInputs, confirmedValues, servicePath));
269
-
270
- // .eslintrc.js
271
- files.push(this.generateEslintConfig(coreInputs, confirmedValues, servicePath));
272
- return files;
409
+ async generateTestingFiles(coreInputs, confirmedValues, servicePath) {
410
+ return await this.generationCoordinator.generateTestingFiles(coreInputs, confirmedValues, servicePath);
273
411
  }
274
412
 
275
413
  /**
276
414
  * Generate documentation files
277
415
  */
278
- generateDocumentationFiles(coreInputs, confirmedValues, servicePath) {
279
- const files = [];
280
-
281
- // README.md
282
- files.push(this.generateReadme(coreInputs, confirmedValues, servicePath));
283
-
284
- // docs/API.md
285
- files.push(this.generateApiDocs(coreInputs, confirmedValues, servicePath));
286
-
287
- // docs/DEPLOYMENT.md
288
- files.push(this.generateDeploymentDocs(coreInputs, confirmedValues, servicePath));
289
-
290
- // docs/CONFIGURATION.md
291
- files.push(this.generateConfigurationDocs(coreInputs, confirmedValues, servicePath));
292
- return files;
416
+ async generateDocumentationFiles(coreInputs, confirmedValues, servicePath) {
417
+ return await this.generationCoordinator.generateDocumentationFiles(coreInputs, confirmedValues, servicePath);
293
418
  }
294
419
 
295
420
  /**
296
421
  * Generate automation and CI/CD files
297
422
  */
298
- generateAutomationFiles(coreInputs, confirmedValues, servicePath) {
299
- const files = [];
300
-
301
- // .github/workflows/ci.yml
302
- files.push(this.generateCiWorkflow(coreInputs, confirmedValues, servicePath));
303
-
304
- // .github/workflows/deploy.yml
305
- files.push(this.generateDeployWorkflow(coreInputs, confirmedValues, servicePath));
306
-
307
- // .gitignore
308
- files.push(this.generateGitignore(coreInputs, confirmedValues, servicePath));
309
-
310
- // docker-compose.yml (for local development)
311
- files.push(this.generateDockerCompose(coreInputs, confirmedValues, servicePath));
312
- return files;
313
- }
314
-
315
- /**
316
- * Generate package.json
317
- */
318
- generatePackageJson(coreInputs, confirmedValues, servicePath) {
319
- const packageJson = {
320
- name: confirmedValues.packageName,
321
- version: confirmedValues.version,
322
- description: confirmedValues.description,
323
- main: "src/worker/index.js",
324
- type: "module",
325
- scripts: {
326
- // Development
327
- dev: "wrangler dev",
328
- // Testing
329
- test: "jest",
330
- "test:watch": "jest --watch",
331
- "test:coverage": "jest --coverage",
332
- // Deployment (cross-platform via framework)
333
- deploy: "clodo-service deploy",
334
- "deploy:dev": "node scripts/deploy.js development",
335
- "deploy:staging": "node scripts/deploy.js staging",
336
- "deploy:prod": "node scripts/deploy.js production",
337
- // Code Quality
338
- lint: "eslint src/ test/",
339
- "lint:fix": "eslint src/ test/ --fix",
340
- format: "prettier --write src/ test/",
341
- // Utilities
342
- validate: "clodo-service validate .",
343
- diagnose: "clodo-service diagnose .",
344
- build: "wrangler deploy --dry-run",
345
- clean: "rimraf dist/ coverage/"
346
- },
347
- dependencies: {
348
- "@tamyla/clodo-framework": "^2.0.20",
349
- "uuid": "^13.0.0",
350
- // Required for auth handlers
351
- "wrangler": "^3.0.0"
352
- },
353
- devDependencies: {
354
- "@types/jest": "^29.5.0",
355
- "@types/node": "^20.0.0",
356
- "eslint": "^8.54.0",
357
- "jest": "^29.7.0",
358
- "prettier": "^3.1.0",
359
- "rimraf": "^5.0.0"
360
- },
361
- author: confirmedValues.author,
362
- license: "MIT",
363
- repository: {
364
- type: "git",
365
- url: confirmedValues.gitRepositoryUrl
366
- },
367
- keywords: ["clodo-framework", coreInputs.serviceType, "cloudflare", "serverless"],
368
- engines: {
369
- node: ">=18.0.0"
370
- }
371
- };
372
- const filePath = join(servicePath, 'package.json');
373
- writeFileSync(filePath, JSON.stringify(packageJson, null, 2), 'utf8');
374
- return filePath;
375
- }
376
-
377
- /**
378
- * Generate wrangler.toml
379
- */
380
- generateWranglerToml(coreInputs, confirmedValues, servicePath) {
381
- const wranglerToml = `# Cloudflare Workers Configuration for ${confirmedValues.displayName}
382
- name = "${confirmedValues.workerName}"
383
- main = "src/worker/index.js"
384
- compatibility_date = "${new Date().toISOString().split('T')[0]}"
385
- compatibility_flags = ["nodejs_compat"]
386
-
387
- # Account configuration
388
- account_id = "${coreInputs.cloudflareAccountId}"
389
-
390
- # Environment configurations
391
- [env.development]
392
- name = "${confirmedValues.workerName}-dev"
393
-
394
- [env.staging]
395
- name = "${confirmedValues.workerName}-staging"
396
-
397
- [env.production]
398
- name = "${confirmedValues.workerName}"
399
-
400
- # Database bindings
401
- [[d1_databases]]
402
- binding = "DB"
403
- database_name = "${confirmedValues.databaseName}"
404
- database_id = "" # To be configured during setup
405
-
406
- # Environment variables
407
- [vars]
408
- SERVICE_NAME = "${coreInputs.serviceName}"
409
- SERVICE_TYPE = "${coreInputs.serviceType}"
410
- DOMAIN_NAME = "${coreInputs.domainName}"
411
- ENVIRONMENT = "${coreInputs.environment}"
412
- API_BASE_PATH = "${confirmedValues.apiBasePath}"
413
- HEALTH_CHECK_PATH = "${confirmedValues.healthCheckPath}"
414
-
415
- # Domain-specific variables
416
- PRODUCTION_URL = "${confirmedValues.productionUrl}"
417
- STAGING_URL = "${confirmedValues.stagingUrl}"
418
- DEVELOPMENT_URL = "${confirmedValues.developmentUrl}"
419
-
420
- # Feature flags
421
- ${Object.entries(confirmedValues.features).filter(([, enabled]) => enabled).map(([feature, enabled]) => `FEATURE_${feature.toUpperCase()} = ${enabled}`).join('\n')}
422
-
423
- # Custom environment variables (configure as needed)
424
- # CUSTOM_VAR = "value"
425
- `;
426
- const filePath = join(servicePath, 'wrangler.toml');
427
- writeFileSync(filePath, wranglerToml, 'utf8');
428
- return filePath;
429
- }
430
-
431
- /**
432
- * Generate domains.js configuration
433
- */
434
- generateDomainsConfig(coreInputs, confirmedValues, servicePath) {
435
- const domainsConfig = `import { createDomainConfigSchema } from '@tamyla/clodo-framework';
436
-
437
- /**
438
- * Domain configuration for ${confirmedValues.displayName}
439
- *
440
- * Generated by Clodo Framework GenerationEngine
441
- * Service Type: ${coreInputs.serviceType}
442
- * Generated: ${new Date().toISOString()}
443
- */
444
-
445
- export const domains = {
446
- '${coreInputs.serviceName}': {
447
- ...createDomainConfigSchema(),
448
- name: '${coreInputs.serviceName}',
449
- displayName: '${confirmedValues.displayName}',
450
- description: '${confirmedValues.description}',
451
- accountId: '${coreInputs.cloudflareAccountId}',
452
- zoneId: '${coreInputs.cloudflareZoneId}',
453
- domains: {
454
- production: '${confirmedValues.productionUrl}',
455
- staging: '${confirmedValues.stagingUrl}',
456
- development: '${confirmedValues.developmentUrl}'
457
- },
458
- services: [
459
- '${coreInputs.serviceName}'
460
- ],
461
- databases: [
462
- {
463
- name: '${confirmedValues.databaseName}',
464
- type: 'd1',
465
- binding: 'DB'
466
- }
467
- ],
468
- features: ${JSON.stringify(confirmedValues.features, null, 4)},
469
- metadata: {
470
- version: '${confirmedValues.version}',
471
- author: '${confirmedValues.author}',
472
- generatedAt: '${new Date().toISOString()}',
473
- frameworkVersion: '3.0.0',
474
- serviceType: '${coreInputs.serviceType}',
475
- environment: '${coreInputs.environment}'
476
- }
477
- }
478
- };
479
-
480
- export default domains;
481
- `;
482
- const filePath = join(servicePath, 'src', 'config', 'domains.js');
483
- writeFileSync(filePath, domainsConfig, 'utf8');
484
- return filePath;
485
- }
486
-
487
- /**
488
- * Generate worker index.js
489
- */
490
- generateWorkerIndex(coreInputs, confirmedValues, servicePath) {
491
- const workerIndex = `/**
492
- * ${confirmedValues.displayName} - Cloudflare Worker
493
- *
494
- * Generated by Clodo Framework GenerationEngine
495
- * Service Type: ${coreInputs.serviceType}
496
- */
497
-
498
- import { domains } from '../config/domains.js';
499
- import { createServiceHandlers } from '../handlers/service-handlers.js';
500
- import { createServiceMiddleware } from '../middleware/service-middleware.js';
501
-
502
- export default {
503
- async fetch(request, env, ctx) {
504
- try {
505
- // Get service configuration
506
- const serviceConfig = domains['${coreInputs.serviceName}'];
507
-
508
- // Apply middleware
509
- const middleware = createServiceMiddleware(serviceConfig, env);
510
- const processedRequest = await middleware.processRequest(request);
511
-
512
- // Route to appropriate handler
513
- const handlers = createServiceHandlers(serviceConfig, env);
514
- const response = await handlers.handleRequest(processedRequest, ctx);
515
-
516
- // Apply response middleware
517
- return await middleware.processResponse(response);
518
-
519
- } catch (error) {
520
- console.error('Worker error:', error);
521
-
522
- return new Response(JSON.stringify({
523
- error: 'Internal Server Error',
524
- message: error.message,
525
- timestamp: new Date().toISOString()
526
- }), {
527
- status: 500,
528
- headers: {
529
- 'Content-Type': 'application/json',
530
- 'X-Service': '${coreInputs.serviceName}',
531
- 'X-Version': '${confirmedValues.version}'
532
- }
533
- });
534
- }
535
- }
536
- };
537
- `;
538
- const filePath = join(servicePath, 'src', 'worker', 'index.js');
539
- writeFileSync(filePath, workerIndex, 'utf8');
540
- return filePath;
541
- }
542
-
543
- /**
544
- * Generate .env.example
545
- */
546
- generateEnvExample(coreInputs, confirmedValues, servicePath) {
547
- const envExample = `# ${confirmedValues.displayName} Environment Variables
548
- # Generated by Clodo Framework GenerationEngine
549
-
550
- # Cloudflare Configuration
551
- CLOUDFLARE_ACCOUNT_ID=${coreInputs.cloudflareAccountId}
552
- CLOUDFLARE_ZONE_ID=${coreInputs.cloudflareZoneId}
553
- CLOUDFLARE_API_TOKEN=${coreInputs.cloudflareToken}
554
-
555
- # Service Configuration
556
- SERVICE_NAME=${coreInputs.serviceName}
557
- SERVICE_TYPE=${coreInputs.serviceType}
558
- DOMAIN_NAME=${coreInputs.domainName}
559
- ENVIRONMENT=${coreInputs.environment}
560
-
561
- # URLs
562
- PRODUCTION_URL=${confirmedValues.productionUrl}
563
- STAGING_URL=${confirmedValues.stagingUrl}
564
- DEVELOPMENT_URL=${confirmedValues.developmentUrl}
565
- DOCUMENTATION_URL=${confirmedValues.documentationUrl}
566
-
567
- # API Configuration
568
- API_BASE_PATH=${confirmedValues.apiBasePath}
569
- HEALTH_CHECK_PATH=${confirmedValues.healthCheckPath}
570
-
571
- # Database Configuration
572
- DATABASE_NAME=${confirmedValues.databaseName}
573
-
574
- # Feature Flags
575
- ${Object.entries(confirmedValues.features).filter(([, enabled]) => enabled).map(([feature]) => `FEATURE_${feature.toUpperCase()}=true`).join('\n')}
576
-
577
- # Custom environment variables (uncomment and configure as needed)
578
- # CUSTOM_VAR=value
579
- # API_KEY=your-api-key-here
580
- # SECRET_KEY=your-secret-key-here
581
- `;
582
- const filePath = join(servicePath, '.env.example');
583
- writeFileSync(filePath, envExample, 'utf8');
584
- return filePath;
585
- }
586
-
587
- /**
588
- * Generate service schema
589
- */
590
- generateServiceSchema(coreInputs, confirmedValues, servicePath) {
591
- const schemaContent = `/**
592
- * ${confirmedValues.displayName} - Service Schema
593
- *
594
- * Generated by Clodo Framework GenerationEngine
595
- * Service Type: ${coreInputs.serviceType}
596
- */
597
-
598
- import { z } from 'zod';
599
-
600
- // Base service schema
601
- export const baseServiceSchema = z.object({
602
- id: z.string().uuid(),
603
- createdAt: z.date(),
604
- updatedAt: z.date(),
605
- version: z.string().default('${confirmedValues.version}')
606
- });
607
-
608
- // Service-specific schemas based on type
609
- ${this.generateServiceTypeSchemas(coreInputs.serviceType)}
610
-
611
- // Request/Response schemas
612
- export const healthCheckResponseSchema = z.object({
613
- status: z.enum(['healthy', 'unhealthy']),
614
- timestamp: z.string().datetime(),
615
- service: z.string(),
616
- version: z.string(),
617
- environment: z.string()
618
- });
619
-
620
- export const errorResponseSchema = z.object({
621
- error: z.string(),
622
- message: z.string(),
623
- timestamp: z.string().datetime(),
624
- service: z.string(),
625
- version: z.string()
626
- });
627
-
628
- // Validation helpers
629
- export function validateServiceRequest(data, schema) {
630
- try {
631
- return { success: true, data: schema.parse(data) };
632
- } catch (error) {
633
- return {
634
- success: false,
635
- error: error.errors.map(err => ({
636
- field: err.path.join('.'),
637
- message: err.message
638
- }))
639
- };
640
- }
641
- }
642
-
643
- export function createServiceResponse(data, schema) {
644
- try {
645
- return { success: true, data: schema.parse(data) };
646
- } catch (error) {
647
- throw new Error(\`Response validation failed: \${error.message}\`);
648
- }
649
- }
650
- `;
651
- const filePath = join(servicePath, 'src', 'schemas', 'service-schema.js');
652
- writeFileSync(filePath, schemaContent, 'utf8');
653
- return filePath;
423
+ async generateAutomationFiles(coreInputs, confirmedValues, servicePath) {
424
+ return await this.generationCoordinator.generateAutomationFiles(coreInputs, confirmedValues, servicePath);
654
425
  }
655
426
 
656
427
  /**
657
- * Generate service type specific schemas
428
+ * Create service manifest
658
429
  */
659
- generateServiceTypeSchemas(serviceType) {
660
- const schemas = {
661
- 'data-service': `
662
- export const dataItemSchema = z.object({
663
- id: z.string().uuid(),
664
- name: z.string().min(1).max(100),
665
- description: z.string().max(500).optional(),
666
- data: z.record(z.any()),
667
- tags: z.array(z.string()).optional(),
668
- status: z.enum(['active', 'inactive', 'archived']).default('active')
669
- });
670
-
671
- export const dataQuerySchema = z.object({
672
- limit: z.number().min(1).max(100).default(20),
673
- offset: z.number().min(0).default(0),
674
- search: z.string().optional(),
675
- filters: z.record(z.any()).optional(),
676
- sortBy: z.string().optional(),
677
- sortOrder: z.enum(['asc', 'desc']).default('asc')
678
- });`,
679
- 'auth-service': `
680
- export const userSchema = z.object({
681
- id: z.string().uuid(),
682
- email: z.string().email(),
683
- username: z.string().min(3).max(50),
684
- displayName: z.string().min(1).max(100),
685
- roles: z.array(z.string()),
686
- isActive: z.boolean().default(true),
687
- lastLogin: z.date().optional(),
688
- emailVerified: z.boolean().default(false)
689
- });
690
-
691
- export const authTokenSchema = z.object({
692
- token: z.string(),
693
- type: z.enum(['access', 'refresh']),
694
- expiresAt: z.date(),
695
- userId: z.string().uuid(),
696
- scopes: z.array(z.string())
697
- });`,
698
- 'content-service': `
699
- export const contentItemSchema = z.object({
700
- id: z.string().uuid(),
701
- title: z.string().min(1).max(200),
702
- content: z.string(),
703
- contentType: z.enum(['article', 'page', 'media', 'document']),
704
- slug: z.string().min(1).max(100),
705
- author: z.string(),
706
- published: z.boolean().default(false),
707
- publishedAt: z.date().optional(),
708
- tags: z.array(z.string()),
709
- metadata: z.record(z.any())
710
- });
711
-
712
- export const mediaAssetSchema = z.object({
713
- id: z.string().uuid(),
714
- filename: z.string(),
715
- originalName: z.string(),
716
- mimeType: z.string(),
717
- size: z.number(),
718
- url: z.string(),
719
- thumbnailUrl: z.string().optional(),
720
- altText: z.string().optional()
721
- });`,
722
- 'api-gateway': `
723
- export const apiRouteSchema = z.object({
724
- path: z.string().regex(/^\\/.*/),
725
- method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']),
726
- targetService: z.string(),
727
- targetPath: z.string(),
728
- rateLimit: z.number().optional(),
729
- authentication: z.boolean().default(false),
730
- authorization: z.array(z.string()).optional()
731
- });
732
-
733
- export const apiMetricsSchema = z.object({
734
- route: z.string(),
735
- method: z.string(),
736
- responseTime: z.number(),
737
- statusCode: z.number(),
738
- timestamp: z.date(),
739
- userAgent: z.string().optional(),
740
- ipAddress: z.string().optional()
741
- });`,
742
- 'generic': `
743
- export const genericItemSchema = z.object({
744
- id: z.string().uuid(),
745
- type: z.string(),
746
- data: z.record(z.any()),
747
- metadata: z.record(z.any()).optional()
748
- });`
749
- };
750
- return schemas[serviceType] || schemas.generic;
430
+ createServiceManifest(coreInputs, confirmedValues, generatedFiles) {
431
+ return this.serviceManifestGenerator.createManifest(coreInputs, confirmedValues, generatedFiles);
751
432
  }
752
433
 
753
434
  /**
754
- * Generate service handlers
435
+ * Categorize generated files
755
436
  */
756
- generateServiceHandlers(coreInputs, confirmedValues, servicePath) {
757
- const handlersContent = `/**
758
- * ${confirmedValues.displayName} - Service Handlers
759
- *
760
- * Generated by Clodo Framework GenerationEngine
761
- * Service Type: ${coreInputs.serviceType}
762
- */
763
-
764
- import { healthCheckResponseSchema, errorResponseSchema } from '../schemas/service-schema.js';
765
-
766
- export function createServiceHandlers(serviceConfig, env) {
767
- return {
768
- async handleRequest(request, ctx) {
769
- const url = new URL(request.url);
770
- const path = url.pathname;
771
-
772
- // Health check endpoint
773
- if (path === '${confirmedValues.healthCheckPath}') {
774
- return this.handleHealthCheck(request, serviceConfig);
775
- }
776
-
777
- // API routes
778
- if (path.startsWith('${confirmedValues.apiBasePath}')) {
779
- return this.handleApiRequest(request, ctx, serviceConfig, env);
780
- }
781
-
782
- // Default 404 response
783
- return new Response(JSON.stringify({
784
- error: 'Not Found',
785
- message: \`Endpoint not found: \${path}\`,
786
- availableEndpoints: [
787
- '${confirmedValues.healthCheckPath}',
788
- '${confirmedValues.apiBasePath}/*'
789
- ]
790
- }), {
791
- status: 404,
792
- headers: { 'Content-Type': 'application/json' }
793
- });
794
- },
795
-
796
- async handleHealthCheck(request, serviceConfig) {
797
- try {
798
- // Perform health checks
799
- const healthStatus = await this.performHealthChecks(serviceConfig, env);
800
-
801
- const response = {
802
- status: healthStatus.overall === 'healthy' ? 'healthy' : 'unhealthy',
803
- timestamp: new Date().toISOString(),
804
- service: serviceConfig.name,
805
- version: '${confirmedValues.version}',
806
- environment: '${coreInputs.environment}',
807
- checks: healthStatus.checks
808
- };
809
-
810
- return new Response(JSON.stringify(response), {
811
- status: healthStatus.overall === 'healthy' ? 200 : 503,
812
- headers: { 'Content-Type': 'application/json' }
813
- });
814
- } catch (error) {
815
- return new Response(JSON.stringify({
816
- status: 'unhealthy',
817
- timestamp: new Date().toISOString(),
818
- service: serviceConfig.name,
819
- error: error.message
820
- }), {
821
- status: 503,
822
- headers: { 'Content-Type': 'application/json' }
823
- });
824
- }
825
- },
826
-
827
- async handleApiRequest(request, ctx, serviceConfig, env) {
828
- try {
829
- const url = new URL(request.url);
830
- const path = url.pathname.replace('${confirmedValues.apiBasePath}', '');
831
-
832
- // Route to service-specific handlers
833
- switch (request.method) {
834
- case 'GET':
835
- return this.handleGet(path, request, ctx, serviceConfig, env);
836
- case 'POST':
837
- return this.handlePost(path, request, ctx, serviceConfig, env);
838
- case 'PUT':
839
- return this.handlePut(path, request, ctx, serviceConfig, env);
840
- case 'DELETE':
841
- return this.handleDelete(path, request, ctx, serviceConfig, env);
842
- default:
843
- return new Response(JSON.stringify({
844
- error: 'Method Not Allowed',
845
- message: \`Method \${request.method} not supported\`
846
- }), {
847
- status: 405,
848
- headers: { 'Content-Type': 'application/json' }
849
- });
850
- }
851
- } catch (error) {
852
- return new Response(JSON.stringify({
853
- error: 'Internal Server Error',
854
- message: error.message,
855
- timestamp: new Date().toISOString()
856
- }), {
857
- status: 500,
858
- headers: { 'Content-Type': 'application/json' }
859
- });
860
- }
861
- },
862
-
863
- async performHealthChecks(serviceConfig, env) {
864
- const checks = [];
865
-
866
- // Database connectivity check
867
- try {
868
- ${confirmedValues.features.database ? `
869
- // Check database connection
870
- const dbCheck = await env.DB.prepare('SELECT 1 as health_check').first();
871
- checks.push({
872
- name: 'database',
873
- status: dbCheck ? 'healthy' : 'unhealthy',
874
- responseTime: Date.now()
875
- });` : `
876
- checks.push({
877
- name: 'database',
878
- status: 'disabled',
879
- message: 'Database not configured for this service type'
880
- });`}
881
- } catch (error) {
882
- checks.push({
883
- name: 'database',
884
- status: 'unhealthy',
885
- error: error.message
886
- });
887
- }
888
-
889
- // Service configuration check
890
- checks.push({
891
- name: 'configuration',
892
- status: serviceConfig ? 'healthy' : 'unhealthy',
893
- message: serviceConfig ? 'Service configuration loaded' : 'Service configuration missing'
894
- });
895
-
896
- // Overall health status
897
- const overall = checks.every(check => check.status === 'healthy' || check.status === 'disabled')
898
- ? 'healthy' : 'unhealthy';
899
-
900
- return { overall, checks };
901
- },
902
-
903
- // Placeholder handlers - implement based on service type
904
- async handleGet(path, request, ctx, serviceConfig, env) {
905
- return new Response(JSON.stringify({
906
- message: 'GET handler not implemented',
907
- path,
908
- service: serviceConfig.name,
909
- timestamp: new Date().toISOString()
910
- }), {
911
- headers: { 'Content-Type': 'application/json' }
912
- });
913
- },
914
-
915
- async handlePost(path, request, ctx, serviceConfig, env) {
916
- return new Response(JSON.stringify({
917
- message: 'POST handler not implemented',
918
- path,
919
- service: serviceConfig.name,
920
- timestamp: new Date().toISOString()
921
- }), {
922
- headers: { 'Content-Type': 'application/json' }
923
- });
924
- },
925
-
926
- async handlePut(path, request, ctx, serviceConfig, env) {
927
- return new Response(JSON.stringify({
928
- message: 'PUT handler not implemented',
929
- path,
930
- service: serviceConfig.name,
931
- timestamp: new Date().toISOString()
932
- }), {
933
- headers: { 'Content-Type': 'application/json' }
934
- });
935
- },
936
-
937
- async handleDelete(path, request, ctx, serviceConfig, env) {
938
- return new Response(JSON.stringify({
939
- message: 'DELETE handler not implemented',
940
- path,
941
- service: serviceConfig.name,
942
- timestamp: new Date().toISOString()
943
- }), {
944
- headers: { 'Content-Type': 'application/json' }
945
- });
946
- }
947
- };
948
- }
949
- `;
950
- const filePath = join(servicePath, 'src', 'handlers', 'service-handlers.js');
951
- writeFileSync(filePath, handlersContent, 'utf8');
952
- return filePath;
437
+ categorizeFiles(files) {
438
+ return this.serviceManifestGenerator.categorizeFiles(files);
953
439
  }
954
440
 
955
441
  /**
956
- * Generate service middleware
957
- */
958
- generateServiceMiddleware(coreInputs, confirmedValues, servicePath) {
959
- const middlewareContent = `/**
960
- * ${confirmedValues.displayName} - Service Middleware
961
- *
962
- * Generated by Clodo Framework GenerationEngine
963
- * Service Type: ${coreInputs.serviceType}
964
- */
965
-
966
- export function createServiceMiddleware(serviceConfig, env) {
967
- return {
968
- async processRequest(request) {
969
- let processedRequest = request;
970
-
971
- // Add service context headers
972
- const headers = new Headers(request.headers);
973
- headers.set('X-Service', serviceConfig.name);
974
- headers.set('X-Version', '${confirmedValues.version}');
975
- headers.set('X-Environment', '${coreInputs.environment}');
976
- headers.set('X-Request-ID', crypto.randomUUID());
977
-
978
- // CORS headers for API requests
979
- if (request.url.includes('${confirmedValues.apiBasePath}')) {
980
- headers.set('Access-Control-Allow-Origin', '*');
981
- headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
982
- headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
983
- }
984
-
985
- ${confirmedValues.features.logging ? `
986
- // Request logging
987
- console.log(\`[\${new Date().toISOString()}] \${request.method} \${request.url}\`);` : ''}
988
-
989
- ${confirmedValues.features.rateLimiting ? `
990
- // Rate limiting (placeholder - implement based on requirements)
991
- // This would typically check request frequency and block if over limit` : ''}
992
-
993
- ${confirmedValues.features.authentication ? `
994
- // Authentication middleware (placeholder)
995
- // This would validate JWT tokens, API keys, etc.` : ''}
996
-
997
- ${confirmedValues.features.authorization ? `
998
- // Authorization middleware (placeholder)
999
- // This would check user permissions and roles` : ''}
1000
-
1001
- return new Request(request.url, {
1002
- ...request,
1003
- headers
1004
- });
1005
- },
1006
-
1007
- async processResponse(response) {
1008
- const headers = new Headers(response.headers);
1009
-
1010
- // Add standard response headers
1011
- headers.set('X-Service', serviceConfig.name);
1012
- headers.set('X-Version', '${confirmedValues.version}');
1013
- headers.set('X-Response-Time', Date.now().toString());
1014
-
1015
- ${confirmedValues.features.monitoring ? `
1016
- // Response monitoring
1017
- console.log(\`Response: \${response.status} (\${Date.now()}ms)\`);` : ''}
1018
-
1019
- ${confirmedValues.features.caching ? `
1020
- // Cache headers (placeholder - implement based on content type)
1021
- if (response.status === 200) {
1022
- headers.set('Cache-Control', 'public, max-age=300'); // 5 minutes
1023
- }` : ''}
1024
-
1025
- return new Response(response.body, {
1026
- ...response,
1027
- headers
1028
- });
1029
- }
1030
- };
1031
- }
1032
- `;
1033
- const filePath = join(servicePath, 'src', 'middleware', 'service-middleware.js');
1034
- writeFileSync(filePath, middlewareContent, 'utf8');
1035
- return filePath;
1036
- }
1037
-
1038
- /**
1039
- * Generate service utilities
1040
- */
1041
- generateServiceUtils(coreInputs, confirmedValues, servicePath) {
1042
- const utilsContent = `/**
1043
- * ${confirmedValues.displayName} - Service Utilities
1044
- *
1045
- * Generated by Clodo Framework GenerationEngine
1046
- * Service Type: ${coreInputs.serviceType}
1047
- */
1048
-
1049
- /**
1050
- * Utility functions for ${confirmedValues.displayName}
1051
- */
1052
-
1053
- // Database utilities
1054
- export class DatabaseUtils {
1055
- static async executeQuery(env, query, params = []) {
1056
- try {
1057
- const stmt = env.DB.prepare(query);
1058
- if (params.length > 0) {
1059
- return await stmt.bind(...params).all();
1060
- }
1061
- return await stmt.all();
1062
- } catch (error) {
1063
- console.error('Database query error:', error);
1064
- throw new Error(\`Database operation failed: \${error.message}\`);
1065
- }
1066
- }
1067
-
1068
- static async getById(env, table, id) {
1069
- const result = await this.executeQuery(
1070
- env,
1071
- \`SELECT * FROM \${table} WHERE id = ?\`,
1072
- [id]
1073
- );
1074
- return result.results[0] || null;
1075
- }
1076
-
1077
- static async create(env, table, data) {
1078
- const columns = Object.keys(data).join(', ');
1079
- const placeholders = Object.keys(data).map(() => '?').join(', ');
1080
- const values = Object.values(data);
1081
-
1082
- const result = await this.executeQuery(
1083
- env,
1084
- \`INSERT INTO \${table} (\${columns}) VALUES (\${placeholders})\`,
1085
- values
1086
- );
1087
-
1088
- return result.meta.last_row_id;
1089
- }
1090
-
1091
- static async update(env, table, id, data) {
1092
- const setClause = Object.keys(data).map(key => \`\${key} = ?\`).join(', ');
1093
- const values = [...Object.values(data), id];
1094
-
1095
- const result = await this.executeQuery(
1096
- env,
1097
- \`UPDATE \${table} SET \${setClause} WHERE id = ?\`,
1098
- values
1099
- );
1100
-
1101
- return result.meta.changes > 0;
1102
- }
1103
-
1104
- static async delete(env, table, id) {
1105
- const result = await this.executeQuery(
1106
- env,
1107
- \`DELETE FROM \${table} WHERE id = ?\`,
1108
- [id]
1109
- );
1110
-
1111
- return result.meta.changes > 0;
1112
- }
1113
- }
1114
-
1115
- // Validation utilities
1116
- export class ValidationUtils {
1117
- static isValidUUID(uuid) {
1118
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1119
- return uuidRegex.test(uuid);
1120
- }
1121
-
1122
- static isValidEmail(email) {
1123
- const emailRegex = /^[^@]+@[^@]+.[^@]+$/;
1124
- return emailRegex.test(email);
1125
- }
1126
-
1127
- static sanitizeString(str, maxLength = 1000) {
1128
- if (typeof str !== 'string') return '';
1129
- return str.trim().substring(0, maxLength);
1130
- }
1131
-
1132
- static validatePagination(limit = 20, offset = 0) {
1133
- const maxLimit = 100;
1134
- const sanitizedLimit = Math.min(Math.max(1, limit), maxLimit);
1135
- const sanitizedOffset = Math.max(0, offset);
1136
-
1137
- return { limit: sanitizedLimit, offset: sanitizedOffset };
1138
- }
1139
- }
1140
-
1141
- // Response utilities
1142
- export class ResponseUtils {
1143
- static createSuccessResponse(data, status = 200) {
1144
- return new Response(JSON.stringify({
1145
- success: true,
1146
- data,
1147
- timestamp: new Date().toISOString()
1148
- }), {
1149
- status,
1150
- headers: { 'Content-Type': 'application/json' }
1151
- });
1152
- }
1153
-
1154
- static createErrorResponse(error, status = 500, details = null) {
1155
- const errorResponse = {
1156
- success: false,
1157
- error: error.message || 'Internal Server Error',
1158
- timestamp: new Date().toISOString()
1159
- };
1160
-
1161
- if (details) {
1162
- errorResponse.details = details;
1163
- }
1164
-
1165
- return new Response(JSON.stringify(errorResponse), {
1166
- status,
1167
- headers: { 'Content-Type': 'application/json' }
1168
- });
1169
- }
1170
-
1171
- static createPaginatedResponse(data, pagination, status = 200) {
1172
- return new Response(JSON.stringify({
1173
- success: true,
1174
- data,
1175
- pagination: {
1176
- ...pagination,
1177
- hasMore: data.length === pagination.limit
1178
- },
1179
- timestamp: new Date().toISOString()
1180
- }), {
1181
- status,
1182
- headers: { 'Content-Type': 'application/json' }
1183
- });
1184
- }
1185
- }
1186
-
1187
- // Logging utilities
1188
- export class LoggingUtils {
1189
- static logRequest(request, context = {}) {
1190
- console.log(JSON.stringify({
1191
- timestamp: new Date().toISOString(),
1192
- level: 'info',
1193
- type: 'request',
1194
- method: request.method,
1195
- url: request.url,
1196
- userAgent: request.headers.get('User-Agent'),
1197
- ...context
1198
- }));
1199
- }
1200
-
1201
- static logError(error, context = {}) {
1202
- console.error(JSON.stringify({
1203
- timestamp: new Date().toISOString(),
1204
- level: 'error',
1205
- type: 'error',
1206
- message: error.message,
1207
- stack: error.stack,
1208
- ...context
1209
- }));
1210
- }
1211
-
1212
- static logPerformance(operation, startTime, context = {}) {
1213
- const duration = Date.now() - startTime;
1214
- console.log(JSON.stringify({
1215
- timestamp: new Date().toISOString(),
1216
- level: 'info',
1217
- type: 'performance',
1218
- operation,
1219
- duration,
1220
- ...context
1221
- }));
1222
- }
1223
- }
1224
-
1225
- // Feature flag utilities
1226
- export class FeatureUtils {
1227
- static isFeatureEnabled(featureName, serviceConfig) {
1228
- return serviceConfig.features && serviceConfig.features[featureName] === true;
1229
- }
1230
-
1231
- static getEnabledFeatures(serviceConfig) {
1232
- if (!serviceConfig.features) return [];
1233
- return Object.entries(serviceConfig.features)
1234
- .filter(([, enabled]) => enabled)
1235
- .map(([feature]) => feature);
1236
- }
1237
-
1238
- static getDisabledFeatures(serviceConfig) {
1239
- if (!serviceConfig.features) return [];
1240
- return Object.entries(serviceConfig.features)
1241
- .filter(([, enabled]) => !enabled)
1242
- .map(([feature]) => feature);
1243
- }
1244
- }
1245
- `;
1246
- const filePath = join(servicePath, 'src', 'utils', 'service-utils.js');
1247
- writeFileSync(filePath, utilsContent, 'utf8');
1248
- return filePath;
1249
- }
1250
-
1251
- /**
1252
- * Generate deployment script
1253
- */
1254
- generateDeployScript(coreInputs, confirmedValues, servicePath) {
1255
- const deployScript = `#!/usr/bin/env pwsh
1256
-
1257
- <#
1258
- .SYNOPSIS
1259
- Deploy ${confirmedValues.displayName} to Cloudflare
1260
-
1261
- .DESCRIPTION
1262
- Automated deployment script for ${confirmedValues.displayName}
1263
- Handles database setup, worker deployment, and environment configuration
1264
-
1265
- .PARAMETER Environment
1266
- Target environment (development, staging, production)
1267
-
1268
- .PARAMETER SkipTests
1269
- Skip running tests before deployment
1270
-
1271
- .EXAMPLE
1272
- .\\scripts\\deploy.ps1 -Environment production
1273
-
1274
- .EXAMPLE
1275
- .\\scripts\\deploy.ps1 -Environment staging -SkipTests
1276
- #>
1277
-
1278
- param(
1279
- [Parameter(Mandatory = $false)]
1280
- [ValidateSet('development', 'staging', 'production')]
1281
- [string]$Environment = 'development',
1282
-
1283
- [Parameter(Mandatory = $false)]
1284
- [switch]$SkipTests
1285
- )
1286
-
1287
- Write-Host "🚀 Deploying ${confirmedValues.displayName} to $Environment" -ForegroundColor Cyan
1288
-
1289
- # Load environment variables
1290
- if (Test-Path ".env") {
1291
- Write-Host "📄 Loading environment variables from .env" -ForegroundColor Gray
1292
- Get-Content ".env" | ForEach-Object {
1293
- if ($_ -match '^([^=]+)=(.*)$') {
1294
- $key = $matches[1]
1295
- $value = $matches[2]
1296
- [Environment]::SetEnvironmentVariable($key, $value)
1297
- }
1298
- }
1299
- }
1300
-
1301
- try {
1302
- # Run tests unless skipped
1303
- if (-not $SkipTests) {
1304
- Write-Host "🧪 Running tests..." -ForegroundColor Yellow
1305
- npm test
1306
- if ($LASTEXITCODE -ne 0) {
1307
- throw "Tests failed. Aborting deployment."
1308
- }
1309
- }
1310
-
1311
- # Lint code
1312
- Write-Host "🔍 Running linter..." -ForegroundColor Yellow
1313
- npm run lint
1314
- if ($LASTEXITCODE -ne 0) {
1315
- throw "Linting failed. Aborting deployment."
1316
- }
1317
-
1318
- # Deploy to Cloudflare
1319
- Write-Host "☁️ Deploying to Cloudflare Workers..." -ForegroundColor Yellow
1320
- npx wrangler deploy --env $Environment
1321
-
1322
- if ($LASTEXITCODE -ne 0) {
1323
- throw "Cloudflare deployment failed."
1324
- }
1325
-
1326
- # Run health check
1327
- Write-Host "🏥 Running health check..." -ForegroundColor Yellow
1328
- .\\scripts\\health-check.ps1 -Environment $Environment
1329
-
1330
- Write-Host "✅ Deployment completed successfully!" -ForegroundColor Green
1331
- Write-Host "🌐 Service URL: ${confirmedValues.productionUrl}" -ForegroundColor Cyan
1332
-
1333
- } catch {
1334
- Write-Host "❌ Deployment failed: $_" -ForegroundColor Red
1335
- exit 1
1336
- }
1337
- `;
1338
- const filePath = join(servicePath, 'scripts', 'deploy.ps1');
1339
- writeFileSync(filePath, deployScript, 'utf8');
1340
- return filePath;
1341
- }
1342
-
1343
- /**
1344
- * Generate setup script
1345
- */
1346
- generateSetupScript(coreInputs, confirmedValues, servicePath) {
1347
- const setupScript = `#!/usr/bin/env pwsh
1348
-
1349
- <#
1350
- .SYNOPSIS
1351
- Setup ${confirmedValues.displayName} environment
1352
-
1353
- .DESCRIPTION
1354
- Initializes the development environment for ${confirmedValues.displayName}
1355
- Sets up database, configures environment variables, and prepares for development
1356
-
1357
- .EXAMPLE
1358
- .\\scripts\\setup.ps1
1359
- #>
1360
-
1361
- Write-Host "🔧 Setting up ${confirmedValues.displayName} development environment" -ForegroundColor Cyan
1362
-
1363
- try {
1364
- # Check if .env exists
1365
- if (-not (Test-Path ".env")) {
1366
- Write-Host "📄 Creating .env file from template..." -ForegroundColor Yellow
1367
- Copy-Item ".env.example" ".env" -Force
1368
- Write-Host "⚠️ Please edit .env file with your actual values" -ForegroundColor Yellow
1369
- }
1370
-
1371
- # Install dependencies
1372
- Write-Host "📦 Installing dependencies..." -ForegroundColor Yellow
1373
- npm install
1374
-
1375
- # Create database (if configured)
1376
- ${confirmedValues.features.database ? `
1377
- Write-Host "🗄️ Setting up database..." -ForegroundColor Yellow
1378
- # Database setup would go here
1379
- Write-Host "⚠️ Database setup requires manual configuration" -ForegroundColor Yellow
1380
- ` : `
1381
- Write-Host "ℹ️ Database not required for this service type" -ForegroundColor Gray
1382
- `}
1383
-
1384
- # Run initial build
1385
- Write-Host "🔨 Running initial build..." -ForegroundColor Yellow
1386
- npm run build
1387
-
1388
- # Run tests
1389
- Write-Host "🧪 Running tests..." -ForegroundColor Yellow
1390
- npm test
1391
-
1392
- Write-Host "✅ Setup completed successfully!" -ForegroundColor Green
1393
- Write-Host "🚀 You can now run 'npm run dev' to start development" -ForegroundColor Cyan
1394
-
1395
- } catch {
1396
- Write-Host "❌ Setup failed: $_" -ForegroundColor Red
1397
- exit 1
1398
- }
1399
- `;
1400
- const filePath = join(servicePath, 'scripts', 'setup.ps1');
1401
- writeFileSync(filePath, setupScript, 'utf8');
1402
- return filePath;
1403
- }
1404
-
1405
- /**
1406
- * Generate health check script
1407
- */
1408
- generateHealthCheckScript(coreInputs, confirmedValues, servicePath) {
1409
- const healthCheckScript = `#!/usr/bin/env pwsh
1410
-
1411
- <#
1412
- .SYNOPSIS
1413
- Health check for ${confirmedValues.displayName}
1414
-
1415
- .DESCRIPTION
1416
- Performs health checks on ${confirmedValues.displayName} service
1417
- Tests endpoints, database connectivity, and overall service health
1418
-
1419
- .PARAMETER Environment
1420
- Target environment to check (development, staging, production)
1421
-
1422
- .EXAMPLE
1423
- .\\scripts\\health-check.ps1 -Environment production
1424
- #>
1425
-
1426
- param(
1427
- [Parameter(Mandatory = $false)]
1428
- [ValidateSet('development', 'staging', 'production')]
1429
- [string]$Environment = 'development'
1430
- )
1431
-
1432
- Write-Host "🏥 Running health checks for ${confirmedValues.displayName} ($Environment)" -ForegroundColor Cyan
1433
-
1434
- # Determine service URL based on environment
1435
- $serviceUrl = switch ($Environment) {
1436
- 'production' { "${confirmedValues.productionUrl}" }
1437
- 'staging' { "${confirmedValues.stagingUrl}" }
1438
- 'development' { "${confirmedValues.developmentUrl}" }
1439
- }
1440
-
1441
- Write-Host "🌐 Checking service at: $serviceUrl" -ForegroundColor Gray
1442
-
1443
- try {
1444
- # Health check endpoint
1445
- $healthUrl = "$serviceUrl${confirmedValues.healthCheckPath}"
1446
- Write-Host "🔍 Testing health endpoint: $healthUrl" -ForegroundColor Yellow
1447
-
1448
- $response = Invoke-RestMethod -Uri $healthUrl -Method GET -TimeoutSec 30
1449
- if ($response.status -eq 'healthy') {
1450
- Write-Host "✅ Health check passed" -ForegroundColor Green
1451
- } else {
1452
- Write-Host "❌ Health check failed: $($response | ConvertTo-Json)" -ForegroundColor Red
1453
- exit 1
1454
- }
1455
-
1456
- # API endpoint check
1457
- $apiUrl = "$serviceUrl${confirmedValues.apiBasePath}"
1458
- Write-Host "🔍 Testing API endpoint: $apiUrl" -ForegroundColor Yellow
1459
-
1460
- try {
1461
- $apiResponse = Invoke-WebRequest -Uri $apiUrl -Method GET -TimeoutSec 30
1462
- Write-Host "✅ API endpoint accessible (Status: $($apiResponse.StatusCode))" -ForegroundColor Green
1463
- } catch {
1464
- Write-Host "⚠️ API endpoint returned error (may be expected): $($_.Exception.Message)" -ForegroundColor Yellow
1465
- }
1466
-
1467
- Write-Host "✅ All health checks completed successfully!" -ForegroundColor Green
1468
-
1469
- } catch {
1470
- Write-Host "❌ Health check failed: $_" -ForegroundColor Red
1471
- exit 1
1472
- }
1473
- `;
1474
- const filePath = join(servicePath, 'scripts', 'health-check.ps1');
1475
- writeFileSync(filePath, healthCheckScript, 'utf8');
1476
- return filePath;
1477
- }
1478
-
1479
- /**
1480
- * Generate environment configuration files
1481
- */
1482
- generateProductionEnv(coreInputs, confirmedValues, servicePath) {
1483
- const envContent = `# Production Environment Configuration
1484
- # Generated by Clodo Framework GenerationEngine
1485
-
1486
- # Service Configuration
1487
- SERVICE_NAME=${coreInputs.serviceName}
1488
- SERVICE_TYPE=${coreInputs.serviceType}
1489
- ENVIRONMENT=production
1490
-
1491
- # URLs
1492
- PRODUCTION_URL=${confirmedValues.productionUrl}
1493
- STAGING_URL=${confirmedValues.stagingUrl}
1494
- DEVELOPMENT_URL=${confirmedValues.developmentUrl}
1495
-
1496
- # Cloudflare Configuration
1497
- CLOUDFLARE_ACCOUNT_ID=${coreInputs.cloudflareAccountId}
1498
- CLOUDFLARE_ZONE_ID=${coreInputs.cloudflareZoneId}
1499
-
1500
- # Database
1501
- DATABASE_NAME=${confirmedValues.databaseName}
1502
-
1503
- # Logging and Monitoring
1504
- LOG_LEVEL=warn
1505
- METRICS_ENABLED=true
1506
- ERROR_REPORTING_ENABLED=true
1507
- `;
1508
- const filePath = join(servicePath, 'config', 'production.env');
1509
- writeFileSync(filePath, envContent, 'utf8');
1510
- return filePath;
1511
- }
1512
- generateStagingEnv(coreInputs, confirmedValues, servicePath) {
1513
- const envContent = `# Staging Environment Configuration
1514
- # Generated by Clodo Framework GenerationEngine
1515
-
1516
- # Service Configuration
1517
- SERVICE_NAME=${coreInputs.serviceName}
1518
- SERVICE_TYPE=${coreInputs.serviceType}
1519
- ENVIRONMENT=staging
1520
-
1521
- # URLs
1522
- PRODUCTION_URL=${confirmedValues.productionUrl}
1523
- STAGING_URL=${confirmedValues.stagingUrl}
1524
- DEVELOPMENT_URL=${confirmedValues.developmentUrl}
1525
-
1526
- # Cloudflare Configuration
1527
- CLOUDFLARE_ACCOUNT_ID=${coreInputs.cloudflareAccountId}
1528
- CLOUDFLARE_ZONE_ID=${coreInputs.cloudflareZoneId}
1529
-
1530
- # Database
1531
- DATABASE_NAME=${confirmedValues.databaseName}
1532
-
1533
- # Logging and Monitoring
1534
- LOG_LEVEL=info
1535
- METRICS_ENABLED=true
1536
- ERROR_REPORTING_ENABLED=true
1537
- `;
1538
- const filePath = join(servicePath, 'config', 'staging.env');
1539
- writeFileSync(filePath, envContent, 'utf8');
1540
- return filePath;
1541
- }
1542
- generateDevelopmentEnv(coreInputs, confirmedValues, servicePath) {
1543
- const envContent = `# Development Environment Configuration
1544
- # Generated by Clodo Framework GenerationEngine
1545
-
1546
- # Service Configuration
1547
- SERVICE_NAME=${coreInputs.serviceName}
1548
- SERVICE_TYPE=${coreInputs.serviceType}
1549
- ENVIRONMENT=development
1550
-
1551
- # URLs
1552
- PRODUCTION_URL=${confirmedValues.productionUrl}
1553
- STAGING_URL=${confirmedValues.stagingUrl}
1554
- DEVELOPMENT_URL=${confirmedValues.developmentUrl}
1555
-
1556
- # Cloudflare Configuration
1557
- CLOUDFLARE_ACCOUNT_ID=${coreInputs.cloudflareAccountId}
1558
- CLOUDFLARE_ZONE_ID=${coreInputs.cloudflareZoneId}
1559
-
1560
- # Database
1561
- DATABASE_NAME=${confirmedValues.databaseName}
1562
-
1563
- # Logging and Monitoring
1564
- LOG_LEVEL=debug
1565
- METRICS_ENABLED=false
1566
- ERROR_REPORTING_ENABLED=false
1567
-
1568
- # Development settings
1569
- DEBUG_MODE=true
1570
- HOT_RELOAD=true
1571
- `;
1572
- const filePath = join(servicePath, 'config', 'development.env');
1573
- writeFileSync(filePath, envContent, 'utf8');
1574
- return filePath;
1575
- }
1576
-
1577
- /**
1578
- * Generate unit tests
1579
- */
1580
- generateUnitTests(coreInputs, confirmedValues, servicePath) {
1581
- const testContent = `/**
1582
- * ${confirmedValues.displayName} - Unit Tests
1583
- *
1584
- * Generated by Clodo Framework GenerationEngine
1585
- */
1586
-
1587
- import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
1588
- import { createServiceHandlers } from '../../src/handlers/service-handlers.js';
1589
- import { createServiceMiddleware } from '../../src/middleware/service-middleware.js';
1590
- import { domains } from '../../src/config/domains.js';
1591
-
1592
- describe('${confirmedValues.displayName} Service', () => {
1593
- let mockEnv;
1594
- let serviceConfig;
1595
-
1596
- beforeEach(() => {
1597
- // Mock environment
1598
- mockEnv = {
1599
- DB: {
1600
- prepare: jest.fn(() => ({
1601
- first: jest.fn().mockResolvedValue({ health_check: 1 }),
1602
- all: jest.fn().mockResolvedValue({ results: [], meta: {} })
1603
- }))
1604
- }
1605
- };
1606
-
1607
- serviceConfig = domains['${coreInputs.serviceName}'];
1608
- });
1609
-
1610
- describe('Health Check Handler', () => {
1611
- test('should return healthy status', async () => {
1612
- const handlers = createServiceHandlers(serviceConfig, mockEnv);
1613
- const request = new Request('http://localhost${confirmedValues.healthCheckPath}');
1614
-
1615
- const response = await handlers.handleHealthCheck(request, serviceConfig);
1616
- const data = await response.json();
1617
-
1618
- expect(response.status).toBe(200);
1619
- expect(data.status).toBe('healthy');
1620
- expect(data.service).toBe('${coreInputs.serviceName}');
1621
- expect(data.version).toBe('${confirmedValues.version}');
1622
- });
1623
-
1624
- test('should handle database errors gracefully', async () => {
1625
- const failingEnv = {
1626
- DB: {
1627
- prepare: jest.fn(() => ({
1628
- first: jest.fn().mockRejectedValue(new Error('Database connection failed'))
1629
- }))
1630
- }
1631
- };
1632
-
1633
- const handlers = createServiceHandlers(serviceConfig, failingEnv);
1634
- const request = new Request('http://localhost${confirmedValues.healthCheckPath}');
1635
-
1636
- const response = await handlers.handleHealthCheck(request, serviceConfig);
1637
- const data = await response.json();
1638
-
1639
- expect(response.status).toBe(200); // Health check still returns 200 but with unhealthy status
1640
- expect(data.status).toBe('unhealthy');
1641
- });
1642
- });
1643
-
1644
- describe('API Request Handler', () => {
1645
- test('should handle GET requests', async () => {
1646
- const handlers = createServiceHandlers(serviceConfig, mockEnv);
1647
- const request = new Request('http://localhost${confirmedValues.apiBasePath}/test', {
1648
- method: 'GET'
1649
- });
1650
-
1651
- const response = await handlers.handleApiRequest(request, {}, serviceConfig, mockEnv);
1652
- const data = await response.json();
1653
-
1654
- expect(response.status).toBe(200);
1655
- expect(data.message).toContain('GET handler not implemented');
1656
- });
1657
-
1658
- test('should handle POST requests', async () => {
1659
- const handlers = createServiceHandlers(serviceConfig, mockEnv);
1660
- const request = new Request('http://localhost${confirmedValues.apiBasePath}/test', {
1661
- method: 'POST'
1662
- });
1663
-
1664
- const response = await handlers.handleApiRequest(request, {}, serviceConfig, mockEnv);
1665
- const data = await response.json();
1666
-
1667
- expect(response.status).toBe(200);
1668
- expect(data.message).toContain('POST handler not implemented');
1669
- });
1670
-
1671
- test('should return 405 for unsupported methods', async () => {
1672
- const handlers = createServiceHandlers(serviceConfig, mockEnv);
1673
- const request = new Request('http://localhost${confirmedValues.apiBasePath}/test', {
1674
- method: 'PATCH'
1675
- });
1676
-
1677
- const response = await handlers.handleApiRequest(request, {}, serviceConfig, mockEnv);
1678
- const data = await response.json();
1679
-
1680
- expect(response.status).toBe(405);
1681
- expect(data.error).toBe('Method Not Allowed');
1682
- });
1683
- });
1684
-
1685
- describe('Middleware', () => {
1686
- test('should add service headers to requests', async () => {
1687
- const middleware = createServiceMiddleware(serviceConfig, mockEnv);
1688
- const request = new Request('http://localhost/test');
1689
-
1690
- const processedRequest = await middleware.processRequest(request);
1691
-
1692
- expect(processedRequest.headers.get('X-Service')).toBe('${coreInputs.serviceName}');
1693
- expect(processedRequest.headers.get('X-Version')).toBe('${confirmedValues.version}');
1694
- expect(processedRequest.headers.get('X-Environment')).toBe('${coreInputs.environment}');
1695
- expect(processedRequest.headers.get('X-Request-ID')).toBeDefined();
1696
- });
1697
-
1698
- test('should add CORS headers for API requests', async () => {
1699
- const middleware = createServiceMiddleware(serviceConfig, mockEnv);
1700
- const request = new Request('http://localhost${confirmedValues.apiBasePath}/test');
1701
-
1702
- const processedRequest = await middleware.processRequest(request);
1703
-
1704
- expect(processedRequest.headers.get('Access-Control-Allow-Origin')).toBe('*');
1705
- expect(processedRequest.headers.get('Access-Control-Allow-Methods')).toBe('GET, POST, PUT, DELETE, OPTIONS');
1706
- });
1707
- });
1708
-
1709
- describe('404 Handler', () => {
1710
- test('should return 404 for unknown endpoints', async () => {
1711
- const handlers = createServiceHandlers(serviceConfig, mockEnv);
1712
- const request = new Request('http://localhost/unknown-endpoint');
1713
-
1714
- const response = await handlers.handleRequest(request, {});
1715
- const data = await response.json();
1716
-
1717
- expect(response.status).toBe(404);
1718
- expect(data.error).toBe('Not Found');
1719
- expect(data.availableEndpoints).toContain('${confirmedValues.healthCheckPath}');
1720
- });
1721
- });
1722
- });
1723
- `;
1724
- const filePath = join(servicePath, 'test', 'unit', 'service.test.js');
1725
- writeFileSync(filePath, testContent, 'utf8');
1726
- return filePath;
1727
- }
1728
-
1729
- /**
1730
- * Generate integration tests
1731
- */
1732
- generateIntegrationTests(coreInputs, confirmedValues, servicePath) {
1733
- const integrationTestContent = `/**
1734
- * ${confirmedValues.displayName} - Integration Tests
1735
- *
1736
- * Generated by Clodo Framework GenerationEngine
1737
- */
1738
-
1739
- import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
1740
-
1741
- describe('${confirmedValues.displayName} Integration Tests', () => {
1742
- let testServer;
1743
- let baseUrl;
1744
-
1745
- beforeAll(async () => {
1746
- // Start test server (this would need to be implemented)
1747
- // testServer = await startTestServer();
1748
- // baseUrl = testServer.url;
1749
- baseUrl = 'http://localhost:8787'; // Placeholder
1750
- });
1751
-
1752
- afterAll(async () => {
1753
- // Stop test server
1754
- // await testServer.stop();
1755
- });
1756
-
1757
- describe('End-to-End Service Flow', () => {
1758
- test('complete service lifecycle', async () => {
1759
- // This would test the complete flow from request to response
1760
- // Including middleware, handlers, database operations, etc.
1761
-
1762
- expect(true).toBe(true); // Placeholder test
1763
- });
1764
- });
1765
-
1766
- describe('API Endpoints', () => {
1767
- test('health check endpoint', async () => {
1768
- const response = await fetch(\`\${baseUrl}${confirmedValues.healthCheckPath}\`);
1769
- const data = await response.json();
1770
-
1771
- expect(response.status).toBe(200);
1772
- expect(data.status).toBe('healthy');
1773
- expect(data.service).toBe('${coreInputs.serviceName}');
1774
- });
1775
-
1776
- test('API base path routing', async () => {
1777
- const response = await fetch(\`\${baseUrl}${confirmedValues.apiBasePath}\`);
1778
-
1779
- // Should not return 404 (service-specific routing would be implemented)
1780
- expect([200, 404]).toContain(response.status);
1781
- });
1782
- });
1783
-
1784
- describe('Database Integration', () => {
1785
- ${confirmedValues.features.database ? `
1786
- test('database connectivity', async () => {
1787
- // Test database operations
1788
- expect(true).toBe(true); // Placeholder
1789
- });
1790
-
1791
- test('CRUD operations', async () => {
1792
- // Test Create, Read, Update, Delete operations
1793
- expect(true).toBe(true); // Placeholder
1794
- });` : `
1795
- test.skip('database tests skipped - not enabled for this service type', () => {
1796
- expect(true).toBe(true);
1797
- });`}
1798
- });
1799
-
1800
- describe('Middleware Integration', () => {
1801
- test('request headers added', async () => {
1802
- const response = await fetch(\`\${baseUrl}${confirmedValues.healthCheckPath}\`);
1803
-
1804
- expect(response.headers.get('x-service')).toBe('${coreInputs.serviceName}');
1805
- expect(response.headers.get('x-version')).toBe('${confirmedValues.version}');
1806
- });
1807
-
1808
- ${confirmedValues.features.authentication ? `
1809
- test('authentication middleware', async () => {
1810
- // Test authentication requirements
1811
- expect(true).toBe(true); // Placeholder
1812
- });` : ''}
1813
-
1814
- ${confirmedValues.features.authorization ? `
1815
- test('authorization middleware', async () => {
1816
- // Test authorization checks
1817
- expect(true).toBe(true); // Placeholder
1818
- });` : ''}
1819
- });
1820
-
1821
- describe('Error Handling', () => {
1822
- test('graceful error responses', async () => {
1823
- // Test error scenarios
1824
- expect(true).toBe(true); // Placeholder
1825
- });
1826
-
1827
- test('error logging', async () => {
1828
- // Test error logging functionality
1829
- expect(true).toBe(true); // Placeholder
1830
- });
1831
- });
1832
- });
1833
- `;
1834
- const filePath = join(servicePath, 'test', 'integration', 'service.integration.test.js');
1835
- writeFileSync(filePath, integrationTestContent, 'utf8');
1836
- return filePath;
1837
- }
1838
-
1839
- /**
1840
- * Generate Jest configuration
1841
- */
1842
- generateJestConfig(coreInputs, confirmedValues, servicePath) {
1843
- const jestConfig = `/** @type {import('jest').Config} */
1844
- export default {
1845
- testEnvironment: 'node',
1846
- testMatch: [
1847
- '<rootDir>/test/**/*.test.js'
1848
- ],
1849
- collectCoverageFrom: [
1850
- 'src/**/*.js',
1851
- '!src/worker/index.js' // Worker code runs in different environment
1852
- ],
1853
- coverageDirectory: 'coverage',
1854
- coverageReporters: ['text', 'lcov', 'html'],
1855
- coverageThreshold: {
1856
- global: {
1857
- branches: 70,
1858
- functions: 80,
1859
- lines: 80,
1860
- statements: 80
1861
- }
1862
- },
1863
- setupFilesAfterEnv: ['<rootDir>/test/setup.js'],
1864
- testTimeout: 10000,
1865
- verbose: true
1866
- };
1867
- `;
1868
- const filePath = join(servicePath, 'jest.config.js');
1869
- writeFileSync(filePath, jestConfig, 'utf8');
1870
- return filePath;
1871
- }
1872
-
1873
- /**
1874
- * Generate ESLint configuration
1875
- */
1876
- generateEslintConfig(coreInputs, confirmedValues, servicePath) {
1877
- const eslintConfig = `export default [
1878
- {
1879
- languageOptions: {
1880
- ecmaVersion: 2022,
1881
- sourceType: 'module',
1882
- globals: {
1883
- console: 'readonly',
1884
- process: 'readonly',
1885
- Buffer: 'readonly',
1886
- crypto: 'readonly',
1887
- fetch: 'readonly',
1888
- Request: 'readonly',
1889
- Response: 'readonly',
1890
- URL: 'readonly',
1891
- Headers: 'readonly'
1892
- }
1893
- },
1894
- rules: {
1895
- 'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
1896
- 'no-console': 'off', // Cloudflare Workers use console
1897
- 'prefer-const': 'error',
1898
- 'no-var': 'error',
1899
- 'object-shorthand': 'error',
1900
- 'prefer-arrow-callback': 'error'
1901
- }
1902
- }
1903
- ];
1904
- `;
1905
- const filePath = join(servicePath, '.eslintrc.js');
1906
- writeFileSync(filePath, eslintConfig, 'utf8');
1907
- return filePath;
1908
- }
1909
-
1910
- /**
1911
- * Generate README.md
1912
- */
1913
- generateReadme(coreInputs, confirmedValues, servicePath) {
1914
- const readmeContent = `# ${confirmedValues.displayName}
1915
-
1916
- ${confirmedValues.description}
1917
-
1918
- ## 🚀 Quick Start
1919
-
1920
- \\\`\\\`\\\`bash
1921
- # Setup development environment
1922
- .\\\\scripts\\\\setup.ps1
1923
-
1924
- # Start development server
1925
- npm run dev
1926
-
1927
- # Run tests
1928
- npm test
1929
-
1930
- # Deploy to production
1931
- .\\\\scripts\\\\deploy.ps1 -Environment production
1932
- \\\`\\\`\\\`
1933
-
1934
- ## 📋 Features
1935
-
1936
- ${Object.entries(confirmedValues.features).filter(([, enabled]) => enabled).map(([feature]) => `- ✅ ${feature.replace(/([A-Z])/g, ' $1').toLowerCase()}`).join('\n')}
1937
-
1938
- ## 🏗️ Architecture
1939
-
1940
- This service is built with the **Clodo Framework** and follows a three-tier architecture:
1941
-
1942
- 1. **Input Collection**: Collects and validates service requirements
1943
- 2. **Smart Confirmations**: Generates and confirms derived configuration values
1944
- 3. **Automated Generation**: Creates all necessary configuration files and components
1945
-
1946
- ## 📁 Project Structure
1947
-
1948
- \`\`\`
1949
- ${coreInputs.serviceName}/
1950
- ├── src/
1951
- │ ├── config/
1952
- │ │ └── domains.js # Domain configuration
1953
- │ ├── worker/
1954
- │ │ └── index.js # Cloudflare Worker entry point
1955
- │ ├── handlers/
1956
- │ │ └── service-handlers.js # Request handlers
1957
- │ ├── middleware/
1958
- │ │ └── service-middleware.js # Request/response middleware
1959
- │ ├── schemas/
1960
- │ │ └── service-schema.js # Data validation schemas
1961
- │ └── utils/
1962
- │ └── service-utils.js # Utility functions
1963
- ├── scripts/
1964
- │ ├── deploy.ps1 # Deployment script
1965
- │ ├── setup.ps1 # Environment setup
1966
- │ └── health-check.ps1 # Health monitoring
1967
- ├── test/
1968
- │ ├── unit/ # Unit tests
1969
- │ └── integration/ # Integration tests
1970
- ├── config/ # Environment configurations
1971
- ├── docs/ # Documentation
1972
- └── wrangler.toml # Cloudflare Workers config
1973
- \`\`\`
1974
-
1975
- ## 🔧 Configuration
1976
-
1977
- ### Environment Variables
1978
-
1979
- Copy \`.env.example\` to \`.env\` and configure:
1980
-
1981
- \`\`\`bash
1982
- # Cloudflare Configuration
1983
- CLOUDFLARE_ACCOUNT_ID=your_account_id
1984
- CLOUDFLARE_ZONE_ID=your_zone_id
1985
- CLOUDFLARE_API_TOKEN=your_api_token
1986
-
1987
- # Service Configuration
1988
- SERVICE_NAME=${coreInputs.serviceName}
1989
- SERVICE_TYPE=${coreInputs.serviceType}
1990
- DOMAIN_NAME=${coreInputs.domainName}
1991
- ENVIRONMENT=${coreInputs.environment}
1992
- \`\`\`
1993
-
1994
- ### Service URLs
1995
-
1996
- - **Production**: ${confirmedValues.productionUrl}
1997
- - **Staging**: ${confirmedValues.stagingUrl}
1998
- - **Development**: ${confirmedValues.developmentUrl}
1999
- - **Documentation**: ${confirmedValues.documentationUrl}
2000
-
2001
- ## 🧪 Testing
2002
-
2003
- \`\`\`bash
2004
- # Run all tests
2005
- npm test
2006
-
2007
- # Run with coverage
2008
- npm run test:coverage
2009
-
2010
- # Run integration tests only
2011
- npm test -- --testPathPattern=integration
2012
- \`\`\`
2013
-
2014
- ## 🚀 Deployment
2015
-
2016
- ### Development
2017
-
2018
- \`\`\`bash
2019
- npm run dev
2020
- \`\`\`
2021
-
2022
- ### Staging
2023
-
2024
- \`\`\`bash
2025
- .\\scripts\\deploy.ps1 -Environment staging
2026
- \`\`\`
2027
-
2028
- ### Production
2029
-
2030
- \`\`\`bash
2031
- .\\scripts\\deploy.ps1 -Environment production
2032
- \`\`\`
2033
-
2034
- ## 🏥 Health Checks
2035
-
2036
- \`\`\`bash
2037
- # Check service health
2038
- .\\scripts\\health-check.ps1 -Environment production
2039
- \`\`\`
2040
-
2041
- Health check endpoint: \`${confirmedValues.healthCheckPath}\`
2042
-
2043
- ## 📚 API Documentation
2044
-
2045
- API Base Path: \`${confirmedValues.apiBasePath}\`
2046
-
2047
- See [API Documentation](./docs/API.md) for detailed endpoint information.
2048
-
2049
- ## 🤝 Contributing
2050
-
2051
- 1. Fork the repository
2052
- 2. Create a feature branch
2053
- 3. Make your changes
2054
- 4. Add tests
2055
- 5. Submit a pull request
2056
-
2057
- ## 📄 License
2058
-
2059
- ${confirmedValues.author} - Generated by Clodo Framework v3.0.0
2060
-
2061
- ## 🔗 Links
2062
-
2063
- - **Repository**: ${confirmedValues.gitRepositoryUrl}
2064
- - **Documentation**: ${confirmedValues.documentationUrl}
2065
- - **Health Check**: ${confirmedValues.productionUrl}${confirmedValues.healthCheckPath}
2066
- `;
2067
- const filePath = join(servicePath, 'README.md');
2068
- writeFileSync(filePath, readmeContent, 'utf8');
2069
- return filePath;
2070
- }
2071
-
2072
- /**
2073
- * Generate API documentation
2074
- */
2075
- generateApiDocs(coreInputs, confirmedValues, servicePath) {
2076
- const apiDocsContent = `# ${confirmedValues.displayName} API Documentation
2077
-
2078
- ## Overview
2079
-
2080
- ${confirmedValues.description}
2081
-
2082
- **Base URL**: ${confirmedValues.productionUrl}
2083
- **API Base Path**: ${confirmedValues.apiBasePath}
2084
- **Version**: ${confirmedValues.version}
2085
-
2086
- ## Authentication
2087
-
2088
- ${confirmedValues.features.authentication ? 'This service requires authentication. Include your API key in the request headers:\n\n' + '```\nAuthorization: Bearer YOUR_API_KEY\n```' : 'This service does not require authentication.'}
2089
-
2090
- ## Endpoints
2091
-
2092
- ### Health Check
2093
-
2094
- **GET** ${confirmedValues.healthCheckPath}
2095
-
2096
- Check the health status of the service.
2097
-
2098
- **Response:**
2099
- \`\`\`json
2100
- {
2101
- "status": "healthy",
2102
- "timestamp": "2024-01-01T00:00:00.000Z",
2103
- "service": "${coreInputs.serviceName}",
2104
- "version": "${confirmedValues.version}",
2105
- "environment": "${coreInputs.environment}",
2106
- "checks": [
2107
- {
2108
- "name": "database",
2109
- "status": "healthy"
2110
- },
2111
- {
2112
- "name": "configuration",
2113
- "status": "healthy"
2114
- }
2115
- ]
2116
- }
2117
- \`\`\`
2118
-
2119
- ### API Endpoints
2120
-
2121
- **Base Path**: ${confirmedValues.apiBasePath}
2122
-
2123
- ${this.generateApiEndpointsForType(coreInputs.serviceType, coreInputs, confirmedValues)}
2124
-
2125
- ## Error Responses
2126
-
2127
- All error responses follow this format:
2128
-
2129
- \`\`\`json
2130
- {
2131
- "success": false,
2132
- "error": "Error message",
2133
- "timestamp": "2024-01-01T00:00:00.000Z"
2134
- }
2135
- \`\`\`
2136
-
2137
- ### Common HTTP Status Codes
2138
-
2139
- - **200**: Success
2140
- - **400**: Bad Request
2141
- - **401**: Unauthorized
2142
- - **403**: Forbidden
2143
- - **404**: Not Found
2144
- - **500**: Internal Server Error
2145
-
2146
- ## Rate Limiting
2147
-
2148
- ${confirmedValues.features.rateLimiting ? 'This service implements rate limiting. Please respect the following limits:\n\n' + '- 1000 requests per hour for authenticated users\n' + '- 100 requests per hour for anonymous users' : 'This service does not implement rate limiting.'}
2149
-
2150
- ## Data Formats
2151
-
2152
- All requests and responses use JSON format.
2153
-
2154
- ### Request Headers
2155
-
2156
- \`\`\`
2157
- Content-Type: application/json
2158
- Authorization: Bearer YOUR_API_KEY (if required)
2159
- \`\`\`
2160
-
2161
- ### Response Headers
2162
-
2163
- \`\`\`
2164
- Content-Type: application/json
2165
- X-Service: ${coreInputs.serviceName}
2166
- X-Version: ${confirmedValues.version}
2167
- X-Response-Time: 150
2168
- \`\`\`
2169
- `;
2170
- const filePath = join(servicePath, 'docs', 'API.md');
2171
- writeFileSync(filePath, apiDocsContent, 'utf8');
2172
- return filePath;
2173
- }
2174
-
2175
- /**
2176
- * Generate API endpoints based on service type
2177
- */
2178
- generateApiEndpointsForType(serviceType, coreInputs, confirmedValues) {
2179
- const endpoints = {
2180
- 'data-service': `
2181
- #### List Items
2182
- **GET** /items
2183
-
2184
- Retrieve a paginated list of items.
2185
-
2186
- **Query Parameters:**
2187
- - \`limit\` (optional): Number of items per page (default: 20, max: 100)
2188
- - \`offset\` (optional): Number of items to skip (default: 0)
2189
- - \`search\` (optional): Search query string
2190
- - \`filters\` (optional): JSON object with filter criteria
2191
-
2192
- **Response:**
2193
- \`\`\`json
2194
- {
2195
- "success": true,
2196
- "data": [...],
2197
- "pagination": {
2198
- "limit": 20,
2199
- "offset": 0,
2200
- "total": 150,
2201
- "hasMore": true
2202
- }
2203
- }
2204
- \`\`\`
2205
-
2206
- #### Create Item
2207
- **POST** /items
2208
-
2209
- Create a new item.
2210
-
2211
- **Request Body:**
2212
- \`\`\`json
2213
- {
2214
- "name": "Item Name",
2215
- "description": "Item description",
2216
- "data": {}
2217
- }
2218
- \`\`\`
2219
-
2220
- #### Get Item
2221
- **GET** /items/{id}
2222
-
2223
- Retrieve a specific item by ID.
2224
-
2225
- #### Update Item
2226
- **PUT** /items/{id}
2227
-
2228
- Update an existing item.
2229
-
2230
- #### Delete Item
2231
- **DELETE** /items/{id}
2232
-
2233
- Delete an item.
2234
- `,
2235
- 'auth-service': `
2236
- #### Register User
2237
- **POST** /auth/register
2238
-
2239
- Register a new user account.
2240
-
2241
- **Request Body:**
2242
- \`\`\`json
2243
- {
2244
- "email": "user@example.com",
2245
- "username": "username",
2246
- "password": "password"
2247
- }
2248
- \`\`\`
2249
-
2250
- #### Login
2251
- **POST** /auth/login
2252
-
2253
- Authenticate a user and receive access tokens.
2254
-
2255
- **Request Body:**
2256
- \`\`\`json
2257
- {
2258
- "email": "user@example.com",
2259
- "password": "password"
2260
- }
2261
- \`\`\`
2262
-
2263
- #### Get Profile
2264
- **GET** /auth/profile
2265
-
2266
- Get the current user's profile information.
2267
-
2268
- #### Update Profile
2269
- **PUT** /auth/profile
2270
-
2271
- Update the current user's profile.
2272
-
2273
- #### Logout
2274
- **POST** /auth/logout
2275
-
2276
- Invalidate the current user's session.
2277
- `,
2278
- 'content-service': `
2279
- #### List Content
2280
- **GET** /content
2281
-
2282
- Retrieve a list of content items.
2283
-
2284
- #### Create Content
2285
- **POST** /content
2286
-
2287
- Create new content.
2288
-
2289
- **Request Body:**
2290
- \`\`\`json
2291
- {
2292
- "title": "Content Title",
2293
- "content": "Content body",
2294
- "contentType": "article",
2295
- "tags": ["tag1", "tag2"]
2296
- }
2297
- \`\`\`
2298
-
2299
- #### Get Content
2300
- **GET** /content/{id}
2301
-
2302
- Retrieve specific content by ID.
2303
-
2304
- #### Update Content
2305
- **PUT** /content/{id}
2306
-
2307
- Update existing content.
2308
-
2309
- #### Delete Content
2310
- **DELETE** /content/{id}
2311
-
2312
- Delete content.
2313
-
2314
- #### Upload Media
2315
- **POST** /media/upload
2316
-
2317
- Upload media files.
2318
- `,
2319
- 'api-gateway': `
2320
- #### Route Request
2321
- **ANY** /*
2322
-
2323
- All requests are routed through the API gateway.
2324
-
2325
- **Headers:**
2326
- - \`X-Target-Service\`: Target service name
2327
- - \`X-Target-Path\`: Path on target service
2328
-
2329
- #### Get Routes
2330
- **GET** /routes
2331
-
2332
- List all configured routes.
2333
-
2334
- #### Health Status
2335
- **GET** /status
2336
-
2337
- Get gateway health and route status.
2338
- `,
2339
- 'generic': `
2340
- #### Service Info
2341
- **GET** /info
2342
-
2343
- Get service information and capabilities.
2344
-
2345
- **Response:**
2346
- \`\`\`json
2347
- {
2348
- "success": true,
2349
- "data": {
2350
- "name": "${coreInputs.serviceName}",
2351
- "type": "${coreInputs.serviceType}",
2352
- "version": "${confirmedValues.version}",
2353
- "features": ${JSON.stringify(Object.keys(confirmedValues.features).filter(key => confirmedValues.features[key]), null, 4)}
2354
- }
2355
- }
2356
- \`\`\`
2357
- `
2358
- };
2359
- return endpoints[serviceType] || endpoints.generic;
2360
- }
2361
-
2362
- /**
2363
- * Generate deployment documentation
2364
- */
2365
- generateDeploymentDocs(coreInputs, confirmedValues, servicePath) {
2366
- const deploymentDocsContent = `# ${confirmedValues.displayName} - Deployment Guide
2367
-
2368
- ## Overview
2369
-
2370
- This guide covers deploying ${confirmedValues.displayName} to different environments using the Clodo Framework.
2371
-
2372
- ## Environments
2373
-
2374
- ### Development
2375
- - **URL**: ${confirmedValues.developmentUrl}
2376
- - **Environment**: development
2377
- - **Configuration**: \`config/development.env\`
2378
-
2379
- ### Staging
2380
- - **URL**: ${confirmedValues.stagingUrl}
2381
- - **Environment**: staging
2382
- - **Configuration**: \`config/staging.env\`
2383
-
2384
- ### Production
2385
- - **URL**: ${confirmedValues.productionUrl}
2386
- - **Environment**: production
2387
- - **Configuration**: \`config/production.env\`
2388
-
2389
- ## Prerequisites
2390
-
2391
- - Node.js 18+
2392
- - Cloudflare account with Workers enabled
2393
- - Wrangler CLI installed
2394
- - PowerShell (for deployment scripts)
2395
-
2396
- ## Initial Setup
2397
-
2398
- 1. **Clone and setup**:
2399
- \`\`\`bash
2400
- git clone ${confirmedValues.gitRepositoryUrl}
2401
- cd ${coreInputs.serviceName}
2402
- .\\scripts\\setup.ps1
2403
- \`\`\`
2404
-
2405
- 2. **Configure environment**:
2406
- Edit \`.env\` with your Cloudflare credentials:
2407
- \`\`\`bash
2408
- CLOUDFLARE_ACCOUNT_ID=your_account_id
2409
- CLOUDFLARE_ZONE_ID=your_zone_id
2410
- CLOUDFLARE_API_TOKEN=your_api_token
2411
- \`\`\`
2412
-
2413
- 3. **Setup database** (if enabled):
2414
- ${confirmedValues.features.database ? `
2415
- Create a Cloudflare D1 database and update \`wrangler.toml\`:
2416
- \`\`\`toml
2417
- [[d1_databases]]
2418
- binding = "DB"
2419
- database_name = "${confirmedValues.databaseName}"
2420
- database_id = "your_database_id"
2421
- \`\`\`
2422
- ` : 'Database not required for this service type.'}
2423
-
2424
- ## Development Deployment
2425
-
2426
- \`\`\`bash
2427
- # Start local development server
2428
- npm run dev
2429
-
2430
- # Server will be available at http://localhost:8787
2431
- \`\`\`
2432
-
2433
- ## Staging Deployment
2434
-
2435
- \`\`\`bash
2436
- # Deploy to staging
2437
- .\\scripts\\deploy.ps1 -Environment staging
2438
-
2439
- # Run health checks
2440
- .\\scripts\\health-check.ps1 -Environment staging
2441
- \`\`\`
2442
-
2443
- ## Production Deployment
2444
-
2445
- \`\`\`bash
2446
- # Deploy to production
2447
- .\\scripts\\deploy.ps1 -Environment production
2448
-
2449
- # Verify deployment
2450
- .\\scripts\\health-check.ps1 -Environment production
2451
- \`\`\`
2452
-
2453
- ## Automated Deployment
2454
-
2455
- ### GitHub Actions
2456
-
2457
- The service includes GitHub Actions workflows for automated deployment:
2458
-
2459
- - **CI**: Runs on every push to main branch
2460
- - **Deploy**: Deploys to staging on successful CI
2461
- - **Release**: Deploys to production on tag creation
2462
-
2463
- ### Manual CI/CD
2464
-
2465
- \`\`\`bash
2466
- # Run full CI pipeline locally
2467
- npm run lint
2468
- npm test
2469
- npm run build
2470
-
2471
- # Deploy if all checks pass
2472
- .\\scripts\\deploy.ps1 -Environment production
2473
- \`\`\`
2474
-
2475
- ## Monitoring and Health Checks
2476
-
2477
- ### Health Check Endpoint
2478
-
2479
- \`\`\`bash
2480
- curl ${confirmedValues.productionUrl}${confirmedValues.healthCheckPath}
2481
- \`\`\`
2482
-
2483
- ### Automated Health Monitoring
2484
-
2485
- The deployment scripts include automated health checks. For production monitoring, consider:
2486
-
2487
- - Cloudflare Analytics
2488
- - External monitoring services
2489
- - Log aggregation tools
2490
-
2491
- ## Rollback Strategy
2492
-
2493
- ### Quick Rollback
2494
-
2495
- \`\`\`bash
2496
- # Deploy previous version
2497
- wrangler deploy --env production
2498
-
2499
- # Or redeploy from git
2500
- git checkout previous-version
2501
- npm run deploy
2502
- \`\`\`
2503
-
2504
- ### Database Rollback
2505
-
2506
- ${confirmedValues.features.database ? `
2507
- If database schema changes need rollback:
2508
-
2509
- 1. Restore from backup
2510
- 2. Run migration rollback scripts
2511
- 3. Update wrangler.toml if needed
2512
- ` : 'No database rollback required for this service type.'}
2513
-
2514
- ## Troubleshooting
2515
-
2516
- ### Common Issues
2517
-
2518
- 1. **Deployment fails with authentication error**
2519
- - Check Cloudflare API token permissions
2520
- - Verify account ID and zone ID
2521
-
2522
- 2. **Health check fails**
2523
- - Check database connectivity
2524
- - Verify environment variables
2525
- - Review worker logs
2526
-
2527
- 3. **API returns 500 errors**
2528
- - Check worker logs in Cloudflare dashboard
2529
- - Verify service configuration
2530
- - Test locally first
2531
-
2532
- ### Logs and Debugging
2533
-
2534
- \`\`\`bash
2535
- # View worker logs
2536
- wrangler tail
2537
-
2538
- # Check deployment status
2539
- wrangler deployments list
2540
-
2541
- # View environment info
2542
- wrangler whoami
2543
- \`\`\`
2544
-
2545
- ## Security Considerations
2546
-
2547
- - Store secrets in Cloudflare Workers secrets, not environment variables
2548
- - Use HTTPS for all production endpoints
2549
- - Implement proper authentication and authorization
2550
- - Regularly rotate API tokens
2551
- - Monitor for unusual activity
2552
-
2553
- ## Performance Optimization
2554
-
2555
- - Enable caching where appropriate
2556
- - Use appropriate database indexes
2557
- - Monitor response times
2558
- - Optimize bundle size
2559
- - Consider edge deployment locations
2560
- `;
2561
- const filePath = join(servicePath, 'docs', 'DEPLOYMENT.md');
2562
- writeFileSync(filePath, deploymentDocsContent, 'utf8');
2563
- return filePath;
2564
- }
2565
-
2566
- /**
2567
- * Generate configuration documentation
2568
- */
2569
- generateConfigurationDocs(coreInputs, confirmedValues, servicePath) {
2570
- const configDocsContent = `# ${confirmedValues.displayName} - Configuration Guide
2571
-
2572
- ## Overview
2573
-
2574
- ${confirmedValues.displayName} is configured using multiple layers of configuration files and environment variables.
2575
-
2576
- ## Configuration Hierarchy
2577
-
2578
- 1. **Environment Variables** (.env) - Runtime secrets and environment-specific values
2579
- 2. **Service Configuration** (src/config/domains.js) - Service-specific settings
2580
- 3. **Worker Configuration** (wrangler.toml) - Cloudflare Workers deployment settings
2581
- 4. **Package Configuration** (package.json) - Node.js package settings
2582
-
2583
- ## Environment Variables
2584
-
2585
- ### Required Variables
2586
-
2587
- \`\`\`bash
2588
- # Cloudflare Configuration
2589
- CLOUDFLARE_ACCOUNT_ID=${coreInputs.cloudflareAccountId}
2590
- CLOUDFLARE_ZONE_ID=${coreInputs.cloudflareZoneId}
2591
- CLOUDFLARE_API_TOKEN=your_api_token
2592
-
2593
- # Service Configuration
2594
- SERVICE_NAME=${coreInputs.serviceName}
2595
- SERVICE_TYPE=${coreInputs.serviceType}
2596
- DOMAIN_NAME=${coreInputs.domainName}
2597
- ENVIRONMENT=${coreInputs.environment}
2598
- \`\`\`
2599
-
2600
- ### Optional Variables
2601
-
2602
- \`\`\`bash
2603
- # URLs (override defaults)
2604
- PRODUCTION_URL=${confirmedValues.productionUrl}
2605
- STAGING_URL=${confirmedValues.stagingUrl}
2606
- DEVELOPMENT_URL=${confirmedValues.developmentUrl}
2607
- DOCUMENTATION_URL=${confirmedValues.documentationUrl}
2608
-
2609
- # API Configuration
2610
- API_BASE_PATH=${confirmedValues.apiBasePath}
2611
- HEALTH_CHECK_PATH=${confirmedValues.healthCheckPath}
2612
-
2613
- # Database
2614
- DATABASE_NAME=${confirmedValues.databaseName}
2615
-
2616
- # Logging and Monitoring
2617
- LOG_LEVEL=info
2618
- METRICS_ENABLED=true
2619
- ERROR_REPORTING_ENABLED=true
2620
-
2621
- # Custom Variables
2622
- CUSTOM_VAR=value
2623
- \`\`\`
2624
-
2625
- ## Service Configuration (domains.js)
2626
-
2627
- Located at \`src/config/domains.js\`, this file contains service-specific configuration:
2628
-
2629
- \`\`\`javascript
2630
- export const domains = {
2631
- '${coreInputs.serviceName}': {
2632
- name: '${coreInputs.serviceName}',
2633
- displayName: '${confirmedValues.displayName}',
2634
- description: '${confirmedValues.description}',
2635
- accountId: process.env.CLOUDFLARE_ACCOUNT_ID,
2636
- zoneId: process.env.CLOUDFLARE_ZONE_ID,
2637
- domains: {
2638
- production: '${confirmedValues.productionUrl}',
2639
- staging: '${confirmedValues.stagingUrl}',
2640
- development: '${confirmedValues.developmentUrl}'
2641
- },
2642
- services: [
2643
- '${coreInputs.serviceName}'
2644
- ],
2645
- databases: [
2646
- {
2647
- name: '${confirmedValues.databaseName}',
2648
- type: 'd1',
2649
- binding: 'DB'
2650
- }
2651
- ],
2652
- features: ${JSON.stringify(confirmedValues.features, null, 4)},
2653
- metadata: {
2654
- version: '${confirmedValues.version}',
2655
- author: '${confirmedValues.author}',
2656
- generatedAt: '${new Date().toISOString()}',
2657
- frameworkVersion: '3.0.0',
2658
- serviceType: '${coreInputs.serviceType}',
2659
- environment: '${coreInputs.environment}'
2660
- }
2661
- }
2662
- };
2663
- \`\`\`
2664
-
2665
- ## Worker Configuration (wrangler.toml)
2666
-
2667
- Cloudflare Workers configuration with environment-specific settings:
2668
-
2669
- \`\`\`toml
2670
- name = "${confirmedValues.workerName}"
2671
- main = "src/worker/index.js"
2672
- compatibility_date = "${new Date().toISOString().split('T')[0]}"
2673
- compatibility_flags = ["nodejs_compat"]
2674
-
2675
- # Environment configurations
2676
- [env.development]
2677
- name = "${confirmedValues.workerName}-dev"
2678
-
2679
- [env.staging]
2680
- name = "${confirmedValues.workerName}-staging"
2681
-
2682
- [env.production]
2683
- name = "${confirmedValues.workerName}"
2684
-
2685
- # Database bindings
2686
- [[d1_databases]]
2687
- binding = "DB"
2688
- database_name = "${confirmedValues.databaseName}"
2689
-
2690
- # Environment variables
2691
- [vars]
2692
- SERVICE_NAME = "${coreInputs.serviceName}"
2693
- SERVICE_TYPE = "${coreInputs.serviceType}"
2694
- DOMAIN_NAME = "${coreInputs.domainName}"
2695
- ENVIRONMENT = "${coreInputs.environment}"
2696
- API_BASE_PATH = "${confirmedValues.apiBasePath}"
2697
- HEALTH_CHECK_PATH = "${confirmedValues.healthCheckPath}"
2698
-
2699
- # Domain-specific variables
2700
- PRODUCTION_URL = "${confirmedValues.productionUrl}"
2701
- STAGING_URL = "${confirmedValues.stagingUrl}"
2702
- DEVELOPMENT_URL = "${confirmedValues.developmentUrl}"
2703
-
2704
- # Feature flags
2705
- ${Object.entries(confirmedValues.features).filter(([, enabled]) => enabled).map(([feature, enabled]) => `FEATURE_${feature.toUpperCase()} = ${enabled}`).join('\n')}
2706
-
2707
- # Custom environment variables (configure as needed)
2708
- # CUSTOM_VAR = "value"
2709
- \`\`\`
2710
-
2711
- ## Feature Flags
2712
-
2713
- The service supports the following feature flags:
2714
-
2715
- ${Object.entries(confirmedValues.features).map(([feature, enabled]) => `- **${feature}**: ${enabled ? '✅ Enabled' : '❌ Disabled'}`).join('\n')}
2716
-
2717
- ### Feature Descriptions
2718
-
2719
- - **logging**: Request/response logging
2720
- - **monitoring**: Performance monitoring and metrics
2721
- - **errorReporting**: Error tracking and reporting
2722
- - **metrics**: Application metrics collection
2723
- - **healthChecks**: Health check endpoints
2724
- ${confirmedValues.features.database ? '- **database**: Database operations and connectivity\n' : ''}
2725
- ${confirmedValues.features.authentication ? '- **authentication**: User authentication\n' : ''}
2726
- ${confirmedValues.features.authorization ? '- **authorization**: Access control and permissions\n' : ''}
2727
- ${confirmedValues.features.search ? '- **search**: Search functionality\n' : ''}
2728
- ${confirmedValues.features.filtering ? '- **filtering**: Data filtering capabilities\n' : ''}
2729
- ${confirmedValues.features.pagination ? '- **pagination**: Paginated responses\n' : ''}
2730
- ${confirmedValues.features.caching ? '- **caching**: Response caching\n' : ''}
2731
- ${confirmedValues.features.backup ? '- **backup**: Data backup functionality\n' : ''}
2732
-
2733
- ## Environment-Specific Configuration
2734
-
2735
- ### Development
2736
- - Full debugging enabled
2737
- - Local database connections
2738
- - Hot reload enabled
2739
- - Less strict validation
2740
-
2741
- ### Staging
2742
- - Production-like settings
2743
- - Separate database
2744
- - Full feature set enabled
2745
- - Error reporting enabled
2746
-
2747
- ### Production
2748
- - Optimized settings
2749
- - Production database
2750
- - Security hardening
2751
- - Full monitoring enabled
2752
-
2753
- ## Configuration Validation
2754
-
2755
- The service validates configuration on startup:
2756
-
2757
- 1. **Environment Variables**: Required variables present and valid
2758
- 2. **Service Configuration**: domains.js structure and values
2759
- 3. **Worker Configuration**: wrangler.toml syntax and bindings
2760
- 4. **Feature Compatibility**: Feature flags compatible with service type
2761
-
2762
- ## Runtime Configuration
2763
-
2764
- Some configuration can be changed at runtime:
2765
-
2766
- - Environment variables (require restart)
2767
- - Feature flags (may require restart)
2768
- - Database connections (handled automatically)
2769
- - Logging levels (immediate effect)
2770
-
2771
- ## Security Considerations
2772
-
2773
- - Never commit secrets to version control
2774
- - Use Cloudflare Workers secrets for sensitive data
2775
- - Rotate API tokens regularly
2776
- - Limit feature access based on environment
2777
- - Validate all input data
2778
- - Use HTTPS for all production endpoints
2779
-
2780
- ## Troubleshooting Configuration Issues
2781
-
2782
- ### Common Problems
2783
-
2784
- 1. **Missing environment variables**
2785
- - Check .env file exists and is loaded
2786
- - Verify variable names match expectations
2787
-
2788
- 2. **Invalid Cloudflare credentials**
2789
- - Check account ID format (32 hex characters)
2790
- - Verify API token permissions
2791
- - Confirm zone ID is correct
2792
-
2793
- 3. **Database connection issues**
2794
- - Verify D1 database exists
2795
- - Check database ID in wrangler.toml
2796
- - Confirm database binding name
2797
-
2798
- 4. **Feature flag conflicts**
2799
- - Some features require others to be enabled
2800
- - Check service type compatibility
2801
-
2802
- ### Debugging Configuration
2803
-
2804
- \`\`\`bash
2805
- # Check environment variables
2806
- node -e "console.log(process.env)"
2807
-
2808
- # Validate service configuration
2809
- node -e "import('./src/config/domains.js').then(config => console.log(JSON.stringify(config, null, 2)))"
2810
-
2811
- # Test wrangler configuration
2812
- wrangler dev --dry-run
2813
- \`\`\`
2814
- `;
2815
- const filePath = join(servicePath, 'docs', 'CONFIGURATION.md');
2816
- writeFileSync(filePath, configDocsContent, 'utf8');
2817
- return filePath;
2818
- }
2819
-
2820
- /**
2821
- * Generate CI workflow
2822
- */
2823
- generateCiWorkflow(coreInputs, confirmedValues, servicePath) {
2824
- const ciWorkflow = `name: CI
2825
-
2826
- on:
2827
- push:
2828
- branches: [ main, master ]
2829
- pull_request:
2830
- branches: [ main, master ]
2831
-
2832
- jobs:
2833
- test:
2834
- runs-on: ubuntu-latest
2835
-
2836
- steps:
2837
- - uses: actions/checkout@v4
2838
-
2839
- - name: Setup Node.js
2840
- uses: actions/setup-node@v4
2841
- with:
2842
- node-version: '18'
2843
- cache: 'npm'
2844
-
2845
- - name: Install dependencies
2846
- run: npm ci
2847
-
2848
- - name: Lint code
2849
- run: npm run lint
2850
-
2851
- - name: Run tests
2852
- run: npm test
2853
-
2854
- - name: Build
2855
- run: npm run build
2856
-
2857
- - name: Upload coverage reports
2858
- uses: codecov/codecov-action@v3
2859
- with:
2860
- file: ./coverage/lcov.info
2861
- `;
2862
- const filePath = join(servicePath, '.github', 'workflows', 'ci.yml');
2863
- writeFileSync(filePath, ciWorkflow, 'utf8');
2864
- return filePath;
2865
- }
2866
-
2867
- /**
2868
- * Generate deploy workflow
2869
- */
2870
- generateDeployWorkflow(coreInputs, confirmedValues, servicePath) {
2871
- const deployWorkflow = `name: Deploy
2872
-
2873
- on:
2874
- push:
2875
- branches: [ main, master ]
2876
- workflow_run:
2877
- workflows: ["CI"]
2878
- types:
2879
- - completed
2880
-
2881
- jobs:
2882
- deploy-staging:
2883
- if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
2884
- runs-on: ubuntu-latest
2885
- environment: staging
2886
-
2887
- steps:
2888
- - uses: actions/checkout@v4
2889
-
2890
- - name: Setup Node.js
2891
- uses: actions/setup-node@v4
2892
- with:
2893
- node-version: '18'
2894
- cache: 'npm'
2895
-
2896
- - name: Install dependencies
2897
- run: npm ci
2898
-
2899
- - name: Deploy to staging
2900
- run: npx wrangler deploy --env staging
2901
- env:
2902
- CLOUDFLARE_API_TOKEN: \${{ secrets.CLOUDFLARE_API_TOKEN }}
2903
- CLOUDFLARE_ACCOUNT_ID: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
2904
-
2905
- deploy-production:
2906
- if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
2907
- runs-on: ubuntu-latest
2908
- environment: production
2909
-
2910
- steps:
2911
- - uses: actions/checkout@v4
2912
-
2913
- - name: Setup Node.js
2914
- uses: actions/setup-node@v4
2915
- with:
2916
- node-version: '18'
2917
- cache: 'npm'
2918
-
2919
- - name: Install dependencies
2920
- run: npm ci
2921
-
2922
- - name: Deploy to production
2923
- run: npx wrangler deploy --env production
2924
- env:
2925
- CLOUDFLARE_API_TOKEN: \${{ secrets.CLOUDFLARE_API_TOKEN }}
2926
- CLOUDFLARE_ACCOUNT_ID: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
2927
- `;
2928
- const filePath = join(servicePath, '.github', 'workflows', 'deploy.yml');
2929
- writeFileSync(filePath, deployWorkflow, 'utf8');
2930
- return filePath;
2931
- }
2932
-
2933
- /**
2934
- * Generate .gitignore
2935
- */
2936
- generateGitignore(coreInputs, confirmedValues, servicePath) {
2937
- const gitignoreContent = `# Dependencies
2938
- node_modules/
2939
- npm-debug.log*
2940
- yarn-debug.log*
2941
- yarn-error.log*
2942
-
2943
- # Environment variables
2944
- .env
2945
- .env.local
2946
- .env.development.local
2947
- .env.test.local
2948
- .env.production.local
2949
-
2950
- # Build outputs
2951
- dist/
2952
- build/
2953
- coverage/
2954
-
2955
- # Logs
2956
- logs/
2957
- *.log
2958
- npm-debug.log*
2959
- yarn-debug.log*
2960
- yarn-error.log*
2961
- lerna-debug.log*
2962
-
2963
- # Runtime data
2964
- pids/
2965
- *.pid
2966
- *.seed
2967
- *.pid.lock
2968
-
2969
- # Coverage directory used by tools like istanbul
2970
- coverage/
2971
- *.lcov
2972
-
2973
- # nyc test coverage
2974
- .nyc_output/
2975
-
2976
- # Dependency directories
2977
- jspm_packages/
2978
-
2979
- # Optional npm cache directory
2980
- .npm
2981
-
2982
- # Optional eslint cache
2983
- .eslintcache
2984
-
2985
- # Microbundle cache
2986
- .rpt2_cache/
2987
- .rts2_cache_cjs/
2988
- .rts2_cache_es/
2989
- .rts2_cache_umd/
2990
-
2991
- # Optional REPL history
2992
- .node_repl_history
2993
-
2994
- # Output of 'npm pack'
2995
- *.tgz
2996
-
2997
- # Yarn Integrity file
2998
- .yarn-integrity
2999
-
3000
- # parcel-bundler cache (https://parceljs.org/)
3001
- .cache
3002
- .parcel-cache
3003
-
3004
- # Next.js build / generate output
3005
- .next
3006
-
3007
- # Nuxt.js build / generate output
3008
- .nuxt
3009
- dist
3010
-
3011
- # Gatsby files
3012
- .cache/
3013
- public
3014
-
3015
- # Storybook build outputs
3016
- .out
3017
- .storybook-out
3018
-
3019
- # Temporary folders
3020
- tmp/
3021
- temp/
3022
-
3023
- # Editor directories and files
3024
- .vscode/*
3025
- !.vscode/extensions.json
3026
- .idea
3027
- .DS_Store
3028
- *.suo
3029
- *.ntvs*
3030
- *.njsproj
3031
- *.sln
3032
- *.sw?
3033
-
3034
- # Cloudflare
3035
- .wrangler/
3036
- `;
3037
- const filePath = join(servicePath, '.gitignore');
3038
- writeFileSync(filePath, gitignoreContent, 'utf8');
3039
- return filePath;
3040
- }
3041
-
3042
- /**
3043
- * Generate docker-compose.yml
3044
- */
3045
- generateDockerCompose(coreInputs, confirmedValues, servicePath) {
3046
- const dockerComposeContent = `version: '3.8'
3047
-
3048
- services:
3049
- ${coreInputs.serviceName}:
3050
- build:
3051
- context: .
3052
- dockerfile: Dockerfile
3053
- ports:
3054
- - "8787:8787"
3055
- environment:
3056
- - NODE_ENV=development
3057
- - SERVICE_NAME=${coreInputs.serviceName}
3058
- - SERVICE_TYPE=${coreInputs.serviceType}
3059
- - ENVIRONMENT=development
3060
- volumes:
3061
- - .:/app
3062
- - /app/node_modules
3063
- command: npm run dev
3064
-
3065
- ${coreInputs.serviceName}-db:
3066
- image: cloudflare/d1
3067
- ports:
3068
- - "8788:8787"
3069
- environment:
3070
- - DATABASE_NAME=${confirmedValues.databaseName}
3071
- volumes:
3072
- - .wrangler:/data
3073
- `;
3074
- const filePath = join(servicePath, 'docker-compose.yml');
3075
- writeFileSync(filePath, dockerComposeContent, 'utf8');
3076
- return filePath;
3077
- }
3078
-
3079
- /**
3080
- * Create service manifest
3081
- */
3082
- createServiceManifest(coreInputs, confirmedValues, generatedFiles) {
3083
- return {
3084
- manifestVersion: '1.0.0',
3085
- frameworkVersion: '3.0.0',
3086
- generatedAt: new Date().toISOString(),
3087
- service: {
3088
- name: coreInputs.serviceName,
3089
- displayName: confirmedValues.displayName,
3090
- description: confirmedValues.description,
3091
- type: coreInputs.serviceType,
3092
- version: confirmedValues.version,
3093
- author: confirmedValues.author
3094
- },
3095
- configuration: {
3096
- coreInputs,
3097
- confirmedValues,
3098
- urls: {
3099
- production: confirmedValues.productionUrl,
3100
- staging: confirmedValues.stagingUrl,
3101
- development: confirmedValues.developmentUrl,
3102
- documentation: confirmedValues.documentationUrl
3103
- },
3104
- api: {
3105
- basePath: confirmedValues.apiBasePath,
3106
- healthCheckPath: confirmedValues.healthCheckPath
3107
- },
3108
- cloudflare: {
3109
- accountId: coreInputs.cloudflareAccountId,
3110
- zoneId: coreInputs.cloudflareZoneId,
3111
- workerName: confirmedValues.workerName,
3112
- databaseName: confirmedValues.databaseName
3113
- },
3114
- features: confirmedValues.features
3115
- },
3116
- files: {
3117
- total: generatedFiles.length,
3118
- list: generatedFiles.map(file => relative(process.cwd(), file)),
3119
- byCategory: this.categorizeFiles(generatedFiles)
3120
- },
3121
- metadata: {
3122
- generationEngine: 'GenerationEngine v1.0.0',
3123
- tier: 'Tier 3 - Automated Generation',
3124
- checksum: this.generateChecksum(generatedFiles)
3125
- }
3126
- };
3127
- }
3128
-
3129
- /**
3130
- * Categorize generated files
3131
- */
3132
- categorizeFiles(files) {
3133
- const categories = {
3134
- core: [],
3135
- service: [],
3136
- environment: [],
3137
- testing: [],
3138
- documentation: [],
3139
- automation: []
3140
- };
3141
- files.forEach(file => {
3142
- const relativePath = relative(process.cwd(), file);
3143
- if (relativePath.includes('package.json') || relativePath.includes('wrangler.toml') || relativePath.includes('.env')) {
3144
- categories.core.push(relativePath);
3145
- } else if (relativePath.includes('src/')) {
3146
- categories.service.push(relativePath);
3147
- } else if (relativePath.includes('config/') || relativePath.includes('scripts/')) {
3148
- categories.environment.push(relativePath);
3149
- } else if (relativePath.includes('test/') || relativePath.includes('jest.config.js') || relativePath.includes('.eslintrc.js')) {
3150
- categories.testing.push(relativePath);
3151
- } else if (relativePath.includes('docs/') || relativePath.includes('README.md')) {
3152
- categories.documentation.push(relativePath);
3153
- } else if (relativePath.includes('.github/') || relativePath.includes('.gitignore') || relativePath.includes('docker-compose.yml')) {
3154
- categories.automation.push(relativePath);
3155
- }
3156
- });
3157
- return categories;
3158
- }
3159
-
3160
- /**
3161
- * Generate checksum for verification
442
+ * Generate checksum for verification
3162
443
  */
3163
444
  generateChecksum(files) {
3164
- // Simple checksum based on file count and names
3165
- const fileString = files.map(f => relative(process.cwd(), f)).sort().join('');
3166
- let hash = 0;
3167
- for (let i = 0; i < fileString.length; i++) {
3168
- const char = fileString.charCodeAt(i);
3169
- hash = (hash << 5) - hash + char;
3170
- hash = hash & hash; // Convert to 32-bit integer
3171
- }
3172
- return Math.abs(hash).toString(16);
445
+ return this.serviceManifestGenerator.generateChecksum(files);
3173
446
  }
3174
447
  }