@tamyla/clodo-framework 3.1.21 → 3.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +53 -0
  3. package/dist/bin/clodo-service.js +47 -15
  4. package/dist/bin/commands/deploy.js +115 -83
  5. package/dist/bin/commands/helpers/deployment-ui.js +138 -0
  6. package/dist/bin/commands/helpers/deployment-verification.js +251 -0
  7. package/dist/bin/commands/helpers/error-recovery.js +80 -0
  8. package/dist/bin/commands/helpers/resource-detection.js +113 -0
  9. package/dist/bin/commands/validate.js +1 -1
  10. package/dist/bin/security/security-cli.js +1 -1
  11. package/dist/bin/shared/cache/configuration-cache.js +82 -0
  12. package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
  13. package/dist/bin/shared/cloudflare/index.js +1 -1
  14. package/dist/bin/shared/cloudflare/ops.js +6 -4
  15. package/dist/bin/shared/config/ConfigurationManager.js +23 -1
  16. package/dist/bin/shared/config/command-config-manager.js +19 -3
  17. package/dist/bin/shared/config/index.js +1 -1
  18. package/dist/bin/shared/deployment/credential-collector.js +30 -7
  19. package/dist/bin/shared/deployment/index.js +2 -2
  20. package/dist/bin/shared/deployment/rollback-manager.js +4 -520
  21. package/dist/bin/shared/deployment/utilities/d1-error-recovery.js +177 -0
  22. package/dist/bin/shared/deployment/validator.js +40 -10
  23. package/dist/bin/shared/deployment/workflows/deployment-summary.js +214 -0
  24. package/dist/bin/shared/deployment/workflows/interactive-confirmation.js +188 -0
  25. package/dist/bin/shared/deployment/workflows/interactive-database-workflow.js +234 -0
  26. package/dist/bin/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
  27. package/dist/bin/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
  28. package/dist/bin/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
  29. package/dist/bin/shared/deployment/workflows/interactive-validation.js +218 -0
  30. package/dist/bin/shared/error-handling/error-classifier.js +46 -0
  31. package/dist/bin/shared/monitoring/health-checker.js +129 -1
  32. package/dist/bin/shared/monitoring/memory-manager.js +17 -6
  33. package/dist/bin/shared/routing/domain-router.js +1 -1
  34. package/dist/bin/shared/utils/deployment-validator.js +97 -0
  35. package/dist/bin/shared/utils/formatters.js +10 -0
  36. package/dist/bin/shared/utils/index.js +13 -1
  37. package/dist/bin/shared/utils/interactive-prompts.js +34 -18
  38. package/dist/bin/shared/utils/progress-manager.js +2 -2
  39. package/dist/bin/shared/utils/progress-spinner.js +53 -0
  40. package/dist/bin/shared/utils/sensitive-redactor.js +91 -0
  41. package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
  42. package/dist/security/index.js +1 -1
  43. package/dist/security/patterns/insecure-patterns.js +1 -1
  44. package/dist/utils/constants.js +102 -0
  45. package/dist/utils/deployment/wrangler-config-manager.js +215 -48
  46. package/dist/utils/framework-config.js +2 -2
  47. package/dist/utils/interactive-prompts.js +10 -59
  48. package/package.json +16 -8
  49. package/dist/bin/clodo-service-old.js +0 -868
  50. package/dist/bin/clodo-service-test.js +0 -10
  51. package/dist/bin/commands/assess.js +0 -91
  52. package/dist/bin/commands/create.js +0 -77
  53. package/dist/bin/commands/diagnose.js +0 -83
  54. package/dist/bin/commands/helpers.js +0 -138
  55. package/dist/bin/commands/update.js +0 -75
  56. package/dist/bin/database/deployment-db-manager.js +0 -423
  57. package/dist/bin/database/enterprise-db-manager.js +0 -457
  58. package/dist/bin/database/wrangler-d1-manager.js +0 -685
  59. package/dist/bin/deployment/enterprise-deploy.js +0 -877
  60. package/dist/bin/deployment/master-deploy.js +0 -1376
  61. package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
  62. package/dist/bin/deployment/modules/DeploymentConfiguration.js +0 -395
  63. package/dist/bin/deployment/modules/DeploymentOrchestrator.js +0 -492
  64. package/dist/bin/deployment/modules/EnvironmentManager.js +0 -517
  65. package/dist/bin/deployment/modules/MonitoringIntegration.js +0 -560
  66. package/dist/bin/deployment/modules/ValidationManager.js +0 -342
  67. package/dist/bin/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
  68. package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  69. package/dist/bin/deployment/orchestration/PortfolioOrchestrator.js +0 -273
  70. package/dist/bin/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
  71. package/dist/bin/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
  72. package/dist/bin/deployment/test-interactive-utils.js +0 -66
  73. package/dist/bin/portfolio/portfolio-manager.js +0 -487
  74. package/dist/bin/service-management/create-service.js +0 -122
  75. package/dist/bin/service-management/init-service.js +0 -79
  76. package/dist/config/customers.js +0 -623
  77. package/dist/config/domains.js +0 -186
  78. package/dist/config/index.js +0 -6
  79. package/dist/database/database-orchestrator.js +0 -795
  80. package/dist/database/index.js +0 -4
  81. package/dist/deployment/index.js +0 -11
  82. package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
  83. package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  84. package/dist/deployment/orchestration/PortfolioOrchestrator.js +0 -273
  85. package/dist/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
  86. package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
  87. package/dist/deployment/orchestration/index.js +0 -17
  88. package/dist/deployment/rollback-manager.js +0 -36
  89. package/dist/deployment/wrangler-deployer.js +0 -640
  90. package/dist/handlers/GenericRouteHandler.js +0 -532
  91. package/dist/migration/MigrationAdapters.js +0 -562
  92. package/dist/modules/ModuleManager.js +0 -668
  93. package/dist/modules/security.js +0 -96
  94. package/dist/orchestration/cross-domain-coordinator.js +0 -1083
  95. package/dist/orchestration/index.js +0 -5
  96. package/dist/orchestration/modules/DeploymentCoordinator.js +0 -368
  97. package/dist/orchestration/modules/DomainResolver.js +0 -198
  98. package/dist/orchestration/modules/StateManager.js +0 -332
  99. package/dist/orchestration/multi-domain-orchestrator.js +0 -724
  100. package/dist/routing/EnhancedRouter.js +0 -158
  101. package/dist/schema/SchemaManager.js +0 -778
  102. package/dist/service-management/ConfirmationEngine.js +0 -412
  103. package/dist/service-management/ErrorTracker.js +0 -299
  104. package/dist/service-management/GenerationEngine.js +0 -447
  105. package/dist/service-management/InputCollector.js +0 -619
  106. package/dist/service-management/ServiceCreator.js +0 -265
  107. package/dist/service-management/ServiceInitializer.js +0 -453
  108. package/dist/service-management/ServiceOrchestrator.js +0 -633
  109. package/dist/service-management/generators/BaseGenerator.js +0 -233
  110. package/dist/service-management/generators/GeneratorRegistry.js +0 -254
  111. package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +0 -87
  112. package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +0 -106
  113. package/dist/service-management/generators/code/ServiceHandlersGenerator.js +0 -235
  114. package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +0 -116
  115. package/dist/service-management/generators/code/ServiceUtilsGenerator.js +0 -246
  116. package/dist/service-management/generators/code/WorkerIndexGenerator.js +0 -143
  117. package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +0 -101
  118. package/dist/service-management/generators/config/DomainsConfigGenerator.js +0 -175
  119. package/dist/service-management/generators/config/EnvExampleGenerator.js +0 -178
  120. package/dist/service-management/generators/config/ProductionEnvGenerator.js +0 -97
  121. package/dist/service-management/generators/config/StagingEnvGenerator.js +0 -97
  122. package/dist/service-management/generators/config/WranglerTomlGenerator.js +0 -238
  123. package/dist/service-management/generators/core/PackageJsonGenerator.js +0 -243
  124. package/dist/service-management/generators/core/SiteConfigGenerator.js +0 -115
  125. package/dist/service-management/generators/documentation/ApiDocsGenerator.js +0 -331
  126. package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +0 -294
  127. package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +0 -244
  128. package/dist/service-management/generators/documentation/ReadmeGenerator.js +0 -196
  129. package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +0 -190
  130. package/dist/service-management/generators/scripts/DeployScriptGenerator.js +0 -123
  131. package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +0 -101
  132. package/dist/service-management/generators/scripts/SetupScriptGenerator.js +0 -88
  133. package/dist/service-management/generators/service-types/StaticSiteGenerator.js +0 -342
  134. package/dist/service-management/generators/testing/EslintConfigGenerator.js +0 -85
  135. package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +0 -237
  136. package/dist/service-management/generators/testing/JestConfigGenerator.js +0 -72
  137. package/dist/service-management/generators/testing/UnitTestsGenerator.js +0 -277
  138. package/dist/service-management/generators/tooling/DockerComposeGenerator.js +0 -71
  139. package/dist/service-management/generators/tooling/GitignoreGenerator.js +0 -143
  140. package/dist/service-management/generators/utils/FileWriter.js +0 -179
  141. package/dist/service-management/generators/utils/PathResolver.js +0 -157
  142. package/dist/service-management/generators/utils/ServiceManifestGenerator.js +0 -111
  143. package/dist/service-management/generators/utils/TemplateEngine.js +0 -185
  144. package/dist/service-management/generators/utils/index.js +0 -18
  145. package/dist/service-management/handlers/ConfirmationHandler.js +0 -71
  146. package/dist/service-management/handlers/GenerationHandler.js +0 -80
  147. package/dist/service-management/handlers/InputHandler.js +0 -59
  148. package/dist/service-management/handlers/ValidationHandler.js +0 -203
  149. package/dist/service-management/index.js +0 -14
  150. package/dist/service-management/routing/DomainRouteMapper.js +0 -311
  151. package/dist/service-management/routing/RouteGenerator.js +0 -266
  152. package/dist/service-management/routing/WranglerRoutesBuilder.js +0 -273
  153. package/dist/service-management/routing/index.js +0 -14
  154. package/dist/service-management/services/DirectoryStructureService.js +0 -56
  155. package/dist/service-management/services/GenerationCoordinator.js +0 -208
  156. package/dist/service-management/services/GeneratorRegistry.js +0 -174
  157. package/dist/services/GenericDataService.js +0 -501
  158. package/dist/ui-structures/concepts/second-order-acquisition-strategy.md +0 -286
  159. package/dist/ui-structures/concepts/service-lifecycle-management.md +0 -150
  160. package/dist/ui-structures/concepts/service-manifest-guide.md +0 -309
  161. package/dist/ui-structures/concepts/three-tier-categorization-strategy.md +0 -231
  162. package/dist/ui-structures/creation/automated-generation-ui.json +0 -246
  163. package/dist/ui-structures/creation/core-inputs-ui.json +0 -217
  164. package/dist/ui-structures/creation/smart-confirmable-ui.json +0 -451
  165. package/dist/ui-structures/reference/absolutely-required-inputs.json +0 -315
  166. package/dist/ui-structures/reference/service-manifest-template.json +0 -342
  167. package/dist/version/VersionDetector.js +0 -723
  168. package/dist/worker/index.js +0 -4
  169. package/dist/worker/integration.js +0 -351
@@ -1,640 +0,0 @@
1
- import { spawn } from 'child_process';
2
- import { execSync } from 'child_process';
3
- import fs from 'fs';
4
- import path from 'path';
5
- import { WranglerD1Manager } from "../../dist/bin/database/wrangler-d1-manager.js";
6
-
7
- /**
8
- * WranglerDeployer - Executes actual Cloudflare Workers deployments using wrangler CLI
9
- * Provides integration between Clodo Framework orchestration and wrangler deployment
10
- *
11
- * Now integrated with WranglerD1Manager for comprehensive D1 database operations
12
- */
13
- export class WranglerDeployer {
14
- constructor(options = {}) {
15
- this.cwd = options.cwd || process.cwd();
16
- this.configPath = options.configPath || 'wrangler.toml';
17
- this.timeout = options.timeout || 300000; // 5 minutes
18
- this.maxRetries = options.maxRetries || 1;
19
- this.environment = options.environment || this.detectEnvironment();
20
- this.serviceInfo = options.serviceInfo || this.discoverServiceInfo();
21
-
22
- // Initialize D1 manager for database operations
23
- this.d1Manager = new WranglerD1Manager({
24
- cwd: this.cwd,
25
- timeout: 60000 // 1 minute for D1 operations
26
- });
27
- }
28
-
29
- /**
30
- * Detect deployment environment from various sources
31
- * @returns {string} Detected environment
32
- */
33
- detectEnvironment() {
34
- // Priority: explicit option > env var > git branch > default
35
- if (process.env.NODE_ENV) return process.env.NODE_ENV;
36
- if (process.env.ENVIRONMENT) return process.env.ENVIRONMENT;
37
- if (process.env.CF_PAGES_BRANCH) return process.env.CF_PAGES_BRANCH;
38
-
39
- // Try to detect from git branch
40
- try {
41
- const branch = execSync('git rev-parse --abbrev-ref HEAD', {
42
- cwd: this.cwd
43
- }).toString().trim();
44
- if (branch === 'main' || branch === 'master') return 'production';
45
- if (branch === 'develop' || branch === 'dev') return 'development';
46
- if (branch.includes('staging')) return 'staging';
47
- return 'development';
48
- } catch {
49
- return 'development';
50
- }
51
- }
52
-
53
- /**
54
- * Discover service information from project files
55
- * @returns {Object} Service information
56
- */
57
- discoverServiceInfo() {
58
- const info = {
59
- name: null,
60
- version: null,
61
- domain: null,
62
- accountId: null
63
- };
64
- try {
65
- // Read package.json
66
- const packagePath = path.join(this.cwd, 'package.json');
67
- if (fs.existsSync(packagePath)) {
68
- const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
69
- info.name = packageJson.name;
70
- info.version = packageJson.version;
71
- }
72
-
73
- // Read environment variables
74
- info.accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
75
- info.domain = process.env.SERVICE_DOMAIN || process.env.DOMAIN;
76
-
77
- // Try to read from wrangler config
78
- const configPath = path.join(this.cwd, 'wrangler.toml');
79
- if (fs.existsSync(configPath)) {
80
- const content = fs.readFileSync(configPath, 'utf8');
81
- const accountMatch = content.match(/account_id\s*=\s*["']([^"']+)["']/);
82
- if (accountMatch) {
83
- info.accountId = info.accountId || accountMatch[1];
84
- }
85
- }
86
- } catch (error) {
87
- // Ignore discovery errors
88
- }
89
- return info;
90
- }
91
-
92
- /**
93
- * Deploy worker to specified environment with intelligent configuration discovery
94
- * @param {string} environment - Environment to deploy to (production, staging, development)
95
- * @param {Object} options - Additional deployment options
96
- * @returns {Promise<Object>} Deployment result with URL and metadata
97
- */
98
- async deploy(environment = 'production', options = {}) {
99
- const startTime = Date.now();
100
- try {
101
- console.log(` 🚀 Executing wrangler deploy --env ${environment}`);
102
-
103
- // Discover deployment configuration intelligently
104
- const deployConfig = await this.discoverDeploymentConfig(environment);
105
-
106
- // Build wrangler command arguments based on discovered config
107
- const args = await this.buildWranglerCommand(environment, deployConfig, options);
108
- console.log(` 📋 Command: npx ${args.join(' ')}`);
109
- console.log(` 📁 Config: ${deployConfig.configPath}`);
110
- console.log(` 🌍 Environment: ${environment}`);
111
-
112
- // Execute wrangler command
113
- const result = await this.executeWranglerCommand(args, {
114
- cwd: this.cwd,
115
- timeout: this.timeout
116
- });
117
- const duration = Date.now() - startTime;
118
- if (result.success) {
119
- // Extract deployment URL with enhanced parsing
120
- const deploymentUrl = this.extractDeploymentUrl(result.output, deployConfig);
121
- console.log(` ✅ Deployment successful in ${duration}ms`);
122
- console.log(` 🌐 URL: ${deploymentUrl}`);
123
- return {
124
- success: true,
125
- url: deploymentUrl,
126
- environment,
127
- duration,
128
- deploymentId: this.generateDeploymentId(),
129
- output: result.output,
130
- config: deployConfig,
131
- timestamp: new Date().toISOString()
132
- };
133
- } else {
134
- console.error(` ❌ Deployment failed after ${duration}ms`);
135
- console.error(` Error: ${result.error}`);
136
- throw new Error(`Wrangler deployment failed: ${result.error}`);
137
- }
138
- } catch (error) {
139
- const duration = Date.now() - startTime;
140
- console.error(` ❌ Deployment error after ${duration}ms: ${error.message}`);
141
- throw new Error(`Deployment failed: ${error.message}`);
142
- }
143
- }
144
-
145
- /**
146
- * Execute wrangler command and capture output
147
- * @param {Array<string>} args - Command arguments
148
- * @param {Object} options - Execution options
149
- * @returns {Promise<Object>} Command execution result
150
- */
151
- async executeWranglerCommand(args, options = {}) {
152
- return new Promise((resolve, reject) => {
153
- const child = spawn('npx', args, {
154
- cwd: options.cwd || this.cwd,
155
- stdio: ['inherit', 'pipe', 'pipe'],
156
- shell: true,
157
- timeout: options.timeout || this.timeout
158
- });
159
- let stdout = '';
160
- let stderr = '';
161
- child.stdout.on('data', data => {
162
- const output = data.toString();
163
- stdout += output;
164
- console.log(` ${output.trim()}`);
165
- });
166
- child.stderr.on('data', data => {
167
- const output = data.toString();
168
- stderr += output;
169
- console.error(` ${output.trim()}`);
170
- });
171
- child.on('close', code => {
172
- const success = code === 0;
173
- resolve({
174
- success,
175
- code,
176
- output: stdout,
177
- error: stderr,
178
- fullOutput: stdout + stderr
179
- });
180
- });
181
- child.on('error', error => {
182
- reject(new Error(`Failed to execute wrangler: ${error.message}`));
183
- });
184
-
185
- // Handle timeout
186
- if (options.timeout) {
187
- setTimeout(() => {
188
- child.kill('SIGTERM');
189
- reject(new Error(`Wrangler command timed out after ${options.timeout}ms`));
190
- }, options.timeout);
191
- }
192
- });
193
- }
194
-
195
- /**
196
- * Extract deployment URL from wrangler output with intelligent parsing
197
- * @param {string} output - Wrangler command output
198
- * @param {Object} config - Deployment configuration
199
- * @returns {string|null} Deployment URL or null if not found
200
- */
201
- extractDeploymentUrl(output, config) {
202
- // Strategy 1: Look for explicit URL patterns in output
203
- const urlPatterns = [/https:\/\/[^\s\n]+/g, /Deployed to:\s*(https:\/\/[^\s\n]+)/i, /Your worker has been deployed to:\s*(https:\/\/[^\s\n]+)/i, /Worker URL:\s*(https:\/\/[^\s\n]+)/i, /Available at:\s*(https:\/\/[^\s\n]+)/i];
204
- for (const pattern of urlPatterns) {
205
- const matches = output.match(pattern);
206
- if (matches && matches.length > 0) {
207
- for (const match of matches) {
208
- const url = match.replace(/^.*?https:\/\//, 'https://').split(/[>\s\n]/)[0];
209
- if (url.startsWith('https://') && this.isValidDeploymentUrl(url, config)) {
210
- return url;
211
- }
212
- }
213
- }
214
- }
215
-
216
- // Strategy 2: Use routes from config if available
217
- if (config.routes && config.routes.length > 0) {
218
- for (const route of config.routes) {
219
- if (route.startsWith('https://')) {
220
- return route;
221
- }
222
- }
223
- }
224
-
225
- // Strategy 3: Construct URL from worker name
226
- if (config.workerName) {
227
- // Check if it's already a full domain
228
- if (config.workerName.includes('.')) {
229
- return `https://${config.workerName}`;
230
- }
231
-
232
- // Construct workers.dev URL
233
- return `https://${config.workerName}.workers.dev`;
234
- }
235
-
236
- // Strategy 4: Fallback URL construction from environment and output
237
- const lines = output.split('\n');
238
- for (const line of lines) {
239
- if (line.includes('https://') && (line.includes('.workers.dev') || line.includes(config.environment) || line.includes('deployed'))) {
240
- const urlMatch = line.match(/https:\/\/[^\s\n>]+/);
241
- if (urlMatch) {
242
- return urlMatch[0];
243
- }
244
- }
245
- }
246
- return null;
247
- }
248
-
249
- /**
250
- * Validate if a URL is a likely deployment URL
251
- * @param {string} url - URL to validate
252
- * @param {Object} config - Deployment config
253
- * @returns {boolean} True if URL appears valid for deployment
254
- */
255
- isValidDeploymentUrl(url, config) {
256
- try {
257
- const urlObj = new URL(url);
258
-
259
- // Must be HTTPS
260
- if (urlObj.protocol !== 'https:') return false;
261
-
262
- // Should be workers.dev or custom domain
263
- const hostname = urlObj.hostname;
264
- return hostname.includes('.workers.dev') || hostname.includes('.dev') || hostname.includes(config.environment) || config.workerName && hostname.includes(config.workerName);
265
- } catch {
266
- return false;
267
- }
268
- }
269
-
270
- /**
271
- * Generate unique deployment ID
272
- * @returns {string} Unique deployment identifier
273
- */
274
- generateDeploymentId() {
275
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
276
- const random = Math.random().toString(36).substring(2, 8);
277
- return `deploy-${timestamp}-${random}`;
278
- }
279
-
280
- /**
281
- * Intelligently discover deployment configuration for the given environment
282
- * @param {string} environment - Target environment
283
- * @returns {Promise<Object>} Discovered configuration
284
- */
285
- async discoverDeploymentConfig(environment) {
286
- const config = {
287
- configPath: null,
288
- hasEnvironmentConfig: false,
289
- workerName: null,
290
- routes: [],
291
- environment
292
- };
293
-
294
- // Strategy 1: Check for environment-specific wrangler.toml
295
- const envConfigPath = path.join(this.cwd, 'config', 'wrangler.toml');
296
- if (fs.existsSync(envConfigPath)) {
297
- config.configPath = 'config/wrangler.toml';
298
- config.hasEnvironmentConfig = true;
299
- try {
300
- // Try to parse basic config info (without TOML dependency)
301
- const content = fs.readFileSync(envConfigPath, 'utf8');
302
- config.workerName = this.extractWorkerNameFromConfig(content);
303
- config.routes = this.extractRoutesFromConfig(content);
304
- } catch (error) {
305
- console.warn(` ⚠️ Could not parse config file: ${error.message}`);
306
- }
307
- }
308
-
309
- // Strategy 2: Check for root wrangler.toml
310
- if (!config.configPath) {
311
- const rootConfigPath = path.join(this.cwd, 'wrangler.toml');
312
- if (fs.existsSync(rootConfigPath)) {
313
- config.configPath = 'wrangler.toml';
314
- try {
315
- const content = fs.readFileSync(rootConfigPath, 'utf8');
316
- config.workerName = this.extractWorkerNameFromConfig(content);
317
- config.routes = this.extractRoutesFromConfig(content);
318
-
319
- // Check if root config has environment-specific sections
320
- config.hasEnvironmentConfig = content.includes(`[env.${environment}]`);
321
- } catch (error) {
322
- console.warn(` ⚠️ Could not parse root config: ${error.message}`);
323
- }
324
- }
325
- }
326
-
327
- // Strategy 3: Fallback to package.json for worker name
328
- if (!config.workerName) {
329
- try {
330
- const packagePath = path.join(this.cwd, 'package.json');
331
- if (fs.existsSync(packagePath)) {
332
- const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
333
- config.workerName = packageJson.name;
334
- }
335
- } catch (error) {
336
- // Ignore package.json parsing errors
337
- }
338
- }
339
- return config;
340
- }
341
-
342
- /**
343
- * Build wrangler command arguments based on discovered configuration
344
- * @param {string} environment - Target environment
345
- * @param {Object} config - Discovered configuration
346
- * @param {Object} options - Additional options
347
- * @returns {Promise<Array<string>>} Command arguments
348
- */
349
- async buildWranglerCommand(environment, config, options = {}) {
350
- const args = ['wrangler', 'deploy'];
351
-
352
- // Add config path if not default
353
- if (config.configPath && config.configPath !== 'wrangler.toml') {
354
- args.push('--config', config.configPath);
355
- }
356
-
357
- // Add environment flag based on configuration
358
- if (config.hasEnvironmentConfig) {
359
- args.push('--env', environment);
360
- } else if (environment !== 'production') {
361
- // For non-production without explicit env config, still try
362
- args.push('--env', environment);
363
- }
364
-
365
- // Add deployment options
366
- if (options.dryRun) {
367
- args.push('--dry-run');
368
- }
369
- if (options.legacyAssets) {
370
- args.push('--legacy-assets');
371
- }
372
-
373
- // Add environment variables from process.env that might be relevant
374
- const envVars = this.extractRelevantEnvironmentVars(environment);
375
- Object.entries(envVars).forEach(([key, value]) => {
376
- if (value) {
377
- args.push('--var', `${key}:${value}`);
378
- }
379
- });
380
-
381
- // Add any environment-specific overrides from options
382
- if (options.vars) {
383
- Object.entries(options.vars).forEach(([key, value]) => {
384
- args.push('--var', `${key}:${value}`);
385
- });
386
- }
387
- return args;
388
- }
389
-
390
- /**
391
- * Extract worker name from wrangler config content (basic parsing)
392
- * @param {string} content - Config file content
393
- * @returns {string|null} Worker name or null
394
- */
395
- extractWorkerNameFromConfig(content) {
396
- const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
397
- return nameMatch ? nameMatch[1] : null;
398
- }
399
-
400
- /**
401
- * Extract routes from wrangler config content
402
- * @param {string} content - Config file content
403
- * @returns {Array<string>} Routes
404
- */
405
- extractRoutesFromConfig(content) {
406
- const routes = [];
407
- const routeMatches = content.match(/route\s*=\s*["']([^"']+)["']/g);
408
- if (routeMatches) {
409
- routeMatches.forEach(match => {
410
- const routeMatch = match.match(/route\s*=\s*["']([^"']+)["']/);
411
- if (routeMatch) {
412
- routes.push(routeMatch[1]);
413
- }
414
- });
415
- }
416
- return routes;
417
- }
418
-
419
- /**
420
- * Extract relevant environment variables for deployment
421
- * @param {string} environment - Target environment
422
- * @returns {Object} Relevant environment variables
423
- */
424
- extractRelevantEnvironmentVars(environment) {
425
- const relevantVars = {};
426
-
427
- // Cloudflare-specific variables
428
- const cfVars = ['CLOUDFLARE_ACCOUNT_ID', 'CLOUDFLARE_ZONE_ID', 'CLOUDFLARE_API_TOKEN', 'CF_API_TOKEN', 'CF_ACCOUNT_ID'];
429
- cfVars.forEach(varName => {
430
- if (process.env[varName]) {
431
- relevantVars[varName] = process.env[varName];
432
- }
433
- });
434
-
435
- // Service-specific variables
436
- const serviceVars = ['SERVICE_DOMAIN', 'SERVICE_NAME', 'NODE_ENV', 'ENVIRONMENT', 'LOG_LEVEL', 'CORS_ORIGINS', 'DATA_SERVICE_URL', 'AUTH_SERVICE_URL', 'CONTENT_STORE_SERVICE_URL', 'FRONTEND_URL', 'MAGIC_LINK_EXPIRY_MINUTES', 'RATE_LIMIT_WINDOW_MS', 'RATE_LIMIT_MAX', 'MAX_FILE_SIZE', 'ALLOWED_FILE_TYPES', 'SKIP_WEBHOOK_AUTH'];
437
- serviceVars.forEach(varName => {
438
- if (process.env[varName]) {
439
- relevantVars[varName] = process.env[varName];
440
- }
441
- });
442
-
443
- // Environment-specific variables
444
- const envSpecificVars = [`${environment.toUpperCase()}_URL`, `${environment.toUpperCase()}_DOMAIN`, `CF_${environment.toUpperCase()}_TOKEN`];
445
- envSpecificVars.forEach(varName => {
446
- if (process.env[varName]) {
447
- relevantVars[varName] = process.env[varName];
448
- }
449
- });
450
- return relevantVars;
451
- }
452
-
453
- /**
454
- * Validate wrangler installation and configuration with intelligent discovery
455
- * @param {string} environment - Environment to validate for
456
- * @returns {Promise<Object>} Validation result with detailed configuration info
457
- */
458
- async validateWranglerSetup(environment = 'production') {
459
- try {
460
- console.log(' 🔍 Validating wrangler setup...');
461
-
462
- // Check if wrangler is available
463
- const versionResult = await this.executeWranglerCommand(['wrangler', '--version']);
464
- if (!versionResult.success) {
465
- return {
466
- valid: false,
467
- error: 'Wrangler CLI not found or not working',
468
- details: versionResult.error
469
- };
470
- }
471
-
472
- // Discover deployment configuration
473
- const deployConfig = await this.discoverDeploymentConfig(environment);
474
- if (!deployConfig.configPath) {
475
- return {
476
- valid: false,
477
- error: 'No wrangler configuration found',
478
- details: 'Expected wrangler.toml or config/wrangler.toml',
479
- suggestions: ['Run: wrangler init', 'Create wrangler.toml in project root', 'Create config/wrangler.toml for environment-specific config']
480
- };
481
- }
482
-
483
- // Validate authentication
484
- const authResult = await this.executeWranglerCommand(['wrangler', 'whoami']);
485
- if (!authResult.success) {
486
- return {
487
- valid: false,
488
- error: 'Wrangler authentication failed',
489
- details: 'You need to login to Cloudflare',
490
- suggestions: ['Run: wrangler auth login', 'Or set CLOUDFLARE_API_TOKEN environment variable']
491
- };
492
- }
493
-
494
- // Extract account information
495
- const accountInfo = this.extractAccountInfo(authResult.output);
496
-
497
- // Validate configuration can be parsed
498
- const configValidation = await this.validateWranglerConfig(deployConfig, environment);
499
-
500
- // Validate D1 database bindings using D1Manager
501
- const d1Validation = await this.d1Manager.validateD1Bindings(deployConfig);
502
- const overallValid = configValidation.valid && d1Validation.valid;
503
- return {
504
- valid: overallValid,
505
- version: versionResult.output.trim(),
506
- config: deployConfig,
507
- account: accountInfo,
508
- configValidation,
509
- d1Validation,
510
- authenticated: true,
511
- ready: overallValid
512
- };
513
- } catch (error) {
514
- return {
515
- valid: false,
516
- error: error.message
517
- };
518
- }
519
- }
520
-
521
- /**
522
- * Extract account information from wrangler whoami output
523
- * @param {string} output - wrangler whoami output
524
- * @returns {Object} Account information
525
- */
526
- extractAccountInfo(output) {
527
- const info = {};
528
-
529
- // Extract email
530
- const emailMatch = output.match(/(\S+@\S+\.\S+)/);
531
- if (emailMatch) {
532
- info.email = emailMatch[1];
533
- }
534
-
535
- // Extract account name/id
536
- const accountMatch = output.match(/Account:\s*([^\n]+)/i);
537
- if (accountMatch) {
538
- info.account = accountMatch[1].trim();
539
- }
540
- return info;
541
- }
542
-
543
- /**
544
- * Validate wrangler configuration for the given environment
545
- * @param {Object} config - Deployment configuration
546
- * @param {string} environment - Target environment
547
- * @returns {Promise<Object>} Configuration validation result
548
- */
549
- async validateWranglerConfig(config, environment) {
550
- try {
551
- const args = ['wrangler', 'deploy', '--dry-run'];
552
- if (config.configPath && config.configPath !== 'wrangler.toml') {
553
- args.push('--config', config.configPath);
554
- }
555
- if (config.hasEnvironmentConfig) {
556
- args.push('--env', environment);
557
- }
558
- const result = await this.executeWranglerCommand(args);
559
- return {
560
- valid: result.success,
561
- error: result.success ? null : result.error,
562
- warnings: this.extractConfigWarnings(result.output)
563
- };
564
- } catch (error) {
565
- return {
566
- valid: false,
567
- error: error.message
568
- };
569
- }
570
- }
571
-
572
- /**
573
- * Extract configuration warnings from wrangler output
574
- * @param {string} output - Wrangler output
575
- * @returns {Array<string>} Warning messages
576
- */
577
- extractConfigWarnings(output) {
578
- const warnings = [];
579
- const lines = output.split('\n');
580
- for (const line of lines) {
581
- if (line.includes('Warning') || line.includes('warning') || line.includes('WARN') || line.includes('⚠️')) {
582
- warnings.push(line.trim());
583
- }
584
- }
585
- return warnings;
586
- }
587
-
588
- /**
589
- * Handle D1 binding errors with interactive recovery options (delegated to D1Manager)
590
- * @param {string} error - Error message
591
- * @param {Object} context - Error context
592
- * @returns {Promise<Object>} Recovery result
593
- */
594
- async handleD1BindingError(error, context = {}) {
595
- return await this.d1Manager.handleD1BindingError(error, context);
596
- }
597
-
598
- /**
599
- * Validate D1 bindings using D1Manager (delegated)
600
- */
601
- async validateD1Bindings(deployConfig) {
602
- return await this.d1Manager.validateD1Bindings(deployConfig);
603
- }
604
-
605
- /**
606
- * Extract D1 bindings using D1Manager (delegated)
607
- */
608
- extractD1Bindings(configContent) {
609
- return this.d1Manager.extractD1Bindings(configContent);
610
- }
611
-
612
- /**
613
- * Check D1 database existence using D1Manager (delegated)
614
- */
615
- async checkD1DatabaseExists(nameOrId) {
616
- return await this.d1Manager.checkD1DatabaseExists(nameOrId);
617
- }
618
-
619
- /**
620
- * Secret management methods
621
- *
622
- * NOTE: For secret management operations, use the Cloudflare ops module:
623
- *
624
- * import { deploySecret, listSecrets, deleteSecret } from '../bin/shared/cloudflare/ops.js';
625
- *
626
- * The ops.js module provides:
627
- * - deploySecret(key, value, env)
628
- * - listSecrets(env)
629
- * - deleteSecret(key, env)
630
- *
631
- * With built-in:
632
- * - Rate limiting
633
- * - Error recovery
634
- * - Production monitoring
635
- * - Retry logic
636
- *
637
- * This avoids code duplication and ensures consistent secret handling across the framework.
638
- */
639
- }
640
- export default WranglerDeployer;