@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.
- package/CHANGELOG.md +9 -0
- package/README.md +53 -0
- package/dist/bin/clodo-service.js +47 -15
- package/dist/bin/commands/deploy.js +115 -83
- package/dist/bin/commands/helpers/deployment-ui.js +138 -0
- package/dist/bin/commands/helpers/deployment-verification.js +251 -0
- package/dist/bin/commands/helpers/error-recovery.js +80 -0
- package/dist/bin/commands/helpers/resource-detection.js +113 -0
- package/dist/bin/commands/validate.js +1 -1
- package/dist/bin/security/security-cli.js +1 -1
- package/dist/bin/shared/cache/configuration-cache.js +82 -0
- package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
- package/dist/bin/shared/cloudflare/index.js +1 -1
- package/dist/bin/shared/cloudflare/ops.js +6 -4
- package/dist/bin/shared/config/ConfigurationManager.js +23 -1
- package/dist/bin/shared/config/command-config-manager.js +19 -3
- package/dist/bin/shared/config/index.js +1 -1
- package/dist/bin/shared/deployment/credential-collector.js +30 -7
- package/dist/bin/shared/deployment/index.js +2 -2
- package/dist/bin/shared/deployment/rollback-manager.js +4 -520
- package/dist/bin/shared/deployment/utilities/d1-error-recovery.js +177 -0
- package/dist/bin/shared/deployment/validator.js +40 -10
- package/dist/bin/shared/deployment/workflows/deployment-summary.js +214 -0
- package/dist/bin/shared/deployment/workflows/interactive-confirmation.js +188 -0
- package/dist/bin/shared/deployment/workflows/interactive-database-workflow.js +234 -0
- package/dist/bin/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
- package/dist/bin/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
- package/dist/bin/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
- package/dist/bin/shared/deployment/workflows/interactive-validation.js +218 -0
- package/dist/bin/shared/error-handling/error-classifier.js +46 -0
- package/dist/bin/shared/monitoring/health-checker.js +129 -1
- package/dist/bin/shared/monitoring/memory-manager.js +17 -6
- package/dist/bin/shared/routing/domain-router.js +1 -1
- package/dist/bin/shared/utils/deployment-validator.js +97 -0
- package/dist/bin/shared/utils/formatters.js +10 -0
- package/dist/bin/shared/utils/index.js +13 -1
- package/dist/bin/shared/utils/interactive-prompts.js +34 -18
- package/dist/bin/shared/utils/progress-manager.js +2 -2
- package/dist/bin/shared/utils/progress-spinner.js +53 -0
- package/dist/bin/shared/utils/sensitive-redactor.js +91 -0
- package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/patterns/insecure-patterns.js +1 -1
- package/dist/utils/constants.js +102 -0
- package/dist/utils/deployment/wrangler-config-manager.js +215 -48
- package/dist/utils/framework-config.js +2 -2
- package/dist/utils/interactive-prompts.js +10 -59
- package/package.json +16 -8
- package/dist/bin/clodo-service-old.js +0 -868
- package/dist/bin/clodo-service-test.js +0 -10
- package/dist/bin/commands/assess.js +0 -91
- package/dist/bin/commands/create.js +0 -77
- package/dist/bin/commands/diagnose.js +0 -83
- package/dist/bin/commands/helpers.js +0 -138
- package/dist/bin/commands/update.js +0 -75
- package/dist/bin/database/deployment-db-manager.js +0 -423
- package/dist/bin/database/enterprise-db-manager.js +0 -457
- package/dist/bin/database/wrangler-d1-manager.js +0 -685
- package/dist/bin/deployment/enterprise-deploy.js +0 -877
- package/dist/bin/deployment/master-deploy.js +0 -1376
- package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
- package/dist/bin/deployment/modules/DeploymentConfiguration.js +0 -395
- package/dist/bin/deployment/modules/DeploymentOrchestrator.js +0 -492
- package/dist/bin/deployment/modules/EnvironmentManager.js +0 -517
- package/dist/bin/deployment/modules/MonitoringIntegration.js +0 -560
- package/dist/bin/deployment/modules/ValidationManager.js +0 -342
- package/dist/bin/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
- package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
- package/dist/bin/deployment/orchestration/PortfolioOrchestrator.js +0 -273
- package/dist/bin/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
- package/dist/bin/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
- package/dist/bin/deployment/test-interactive-utils.js +0 -66
- package/dist/bin/portfolio/portfolio-manager.js +0 -487
- package/dist/bin/service-management/create-service.js +0 -122
- package/dist/bin/service-management/init-service.js +0 -79
- package/dist/config/customers.js +0 -623
- package/dist/config/domains.js +0 -186
- package/dist/config/index.js +0 -6
- package/dist/database/database-orchestrator.js +0 -795
- package/dist/database/index.js +0 -4
- package/dist/deployment/index.js +0 -11
- package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
- package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
- package/dist/deployment/orchestration/PortfolioOrchestrator.js +0 -273
- package/dist/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
- package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
- package/dist/deployment/orchestration/index.js +0 -17
- package/dist/deployment/rollback-manager.js +0 -36
- package/dist/deployment/wrangler-deployer.js +0 -640
- package/dist/handlers/GenericRouteHandler.js +0 -532
- package/dist/migration/MigrationAdapters.js +0 -562
- package/dist/modules/ModuleManager.js +0 -668
- package/dist/modules/security.js +0 -96
- package/dist/orchestration/cross-domain-coordinator.js +0 -1083
- package/dist/orchestration/index.js +0 -5
- package/dist/orchestration/modules/DeploymentCoordinator.js +0 -368
- package/dist/orchestration/modules/DomainResolver.js +0 -198
- package/dist/orchestration/modules/StateManager.js +0 -332
- package/dist/orchestration/multi-domain-orchestrator.js +0 -724
- package/dist/routing/EnhancedRouter.js +0 -158
- package/dist/schema/SchemaManager.js +0 -778
- package/dist/service-management/ConfirmationEngine.js +0 -412
- package/dist/service-management/ErrorTracker.js +0 -299
- package/dist/service-management/GenerationEngine.js +0 -447
- package/dist/service-management/InputCollector.js +0 -619
- package/dist/service-management/ServiceCreator.js +0 -265
- package/dist/service-management/ServiceInitializer.js +0 -453
- package/dist/service-management/ServiceOrchestrator.js +0 -633
- package/dist/service-management/generators/BaseGenerator.js +0 -233
- package/dist/service-management/generators/GeneratorRegistry.js +0 -254
- package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +0 -87
- package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +0 -106
- package/dist/service-management/generators/code/ServiceHandlersGenerator.js +0 -235
- package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +0 -116
- package/dist/service-management/generators/code/ServiceUtilsGenerator.js +0 -246
- package/dist/service-management/generators/code/WorkerIndexGenerator.js +0 -143
- package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +0 -101
- package/dist/service-management/generators/config/DomainsConfigGenerator.js +0 -175
- package/dist/service-management/generators/config/EnvExampleGenerator.js +0 -178
- package/dist/service-management/generators/config/ProductionEnvGenerator.js +0 -97
- package/dist/service-management/generators/config/StagingEnvGenerator.js +0 -97
- package/dist/service-management/generators/config/WranglerTomlGenerator.js +0 -238
- package/dist/service-management/generators/core/PackageJsonGenerator.js +0 -243
- package/dist/service-management/generators/core/SiteConfigGenerator.js +0 -115
- package/dist/service-management/generators/documentation/ApiDocsGenerator.js +0 -331
- package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +0 -294
- package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +0 -244
- package/dist/service-management/generators/documentation/ReadmeGenerator.js +0 -196
- package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +0 -190
- package/dist/service-management/generators/scripts/DeployScriptGenerator.js +0 -123
- package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +0 -101
- package/dist/service-management/generators/scripts/SetupScriptGenerator.js +0 -88
- package/dist/service-management/generators/service-types/StaticSiteGenerator.js +0 -342
- package/dist/service-management/generators/testing/EslintConfigGenerator.js +0 -85
- package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +0 -237
- package/dist/service-management/generators/testing/JestConfigGenerator.js +0 -72
- package/dist/service-management/generators/testing/UnitTestsGenerator.js +0 -277
- package/dist/service-management/generators/tooling/DockerComposeGenerator.js +0 -71
- package/dist/service-management/generators/tooling/GitignoreGenerator.js +0 -143
- package/dist/service-management/generators/utils/FileWriter.js +0 -179
- package/dist/service-management/generators/utils/PathResolver.js +0 -157
- package/dist/service-management/generators/utils/ServiceManifestGenerator.js +0 -111
- package/dist/service-management/generators/utils/TemplateEngine.js +0 -185
- package/dist/service-management/generators/utils/index.js +0 -18
- package/dist/service-management/handlers/ConfirmationHandler.js +0 -71
- package/dist/service-management/handlers/GenerationHandler.js +0 -80
- package/dist/service-management/handlers/InputHandler.js +0 -59
- package/dist/service-management/handlers/ValidationHandler.js +0 -203
- package/dist/service-management/index.js +0 -14
- package/dist/service-management/routing/DomainRouteMapper.js +0 -311
- package/dist/service-management/routing/RouteGenerator.js +0 -266
- package/dist/service-management/routing/WranglerRoutesBuilder.js +0 -273
- package/dist/service-management/routing/index.js +0 -14
- package/dist/service-management/services/DirectoryStructureService.js +0 -56
- package/dist/service-management/services/GenerationCoordinator.js +0 -208
- package/dist/service-management/services/GeneratorRegistry.js +0 -174
- package/dist/services/GenericDataService.js +0 -501
- package/dist/ui-structures/concepts/second-order-acquisition-strategy.md +0 -286
- package/dist/ui-structures/concepts/service-lifecycle-management.md +0 -150
- package/dist/ui-structures/concepts/service-manifest-guide.md +0 -309
- package/dist/ui-structures/concepts/three-tier-categorization-strategy.md +0 -231
- package/dist/ui-structures/creation/automated-generation-ui.json +0 -246
- package/dist/ui-structures/creation/core-inputs-ui.json +0 -217
- package/dist/ui-structures/creation/smart-confirmable-ui.json +0 -451
- package/dist/ui-structures/reference/absolutely-required-inputs.json +0 -315
- package/dist/ui-structures/reference/service-manifest-template.json +0 -342
- package/dist/version/VersionDetector.js +0 -723
- package/dist/worker/index.js +0 -4
- package/dist/worker/integration.js +0 -351
|
@@ -96,6 +96,192 @@ export class WranglerConfigManager {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Get customer config path based on zone name
|
|
101
|
+
* Maps zone names to customer config directories using conventions:
|
|
102
|
+
* - clodo.dev → config/customers/clodo/wrangler.toml
|
|
103
|
+
* - tamyla.com → config/customers/tamyla/wrangler.toml
|
|
104
|
+
* - wetechfounders.com → config/customers/wetechfounders/wrangler.toml
|
|
105
|
+
*
|
|
106
|
+
* @param {string} zoneName - Cloudflare zone name (domain)
|
|
107
|
+
* @returns {string} Path to customer config (may not exist yet)
|
|
108
|
+
*/
|
|
109
|
+
getCustomerConfigPath(zoneName) {
|
|
110
|
+
if (!zoneName) {
|
|
111
|
+
throw new Error('Zone name is required to get customer config path');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Extract base name from domain (e.g., clodo.dev → clodo)
|
|
115
|
+
const baseName = zoneName.split('.')[0];
|
|
116
|
+
|
|
117
|
+
// Return customer directory path based on base name
|
|
118
|
+
return join(this.projectRoot, 'config', 'customers', baseName, 'wrangler.toml');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Generate or update customer-specific wrangler.toml
|
|
123
|
+
* Creates a persistent config for the customer based on current deployment parameters
|
|
124
|
+
* This serves as deployment history and source of truth for reruns
|
|
125
|
+
*
|
|
126
|
+
* @param {string} zoneName - Cloudflare zone name (domain)
|
|
127
|
+
* @param {Object} params - Deployment parameters
|
|
128
|
+
* @param {string} params.accountId - Cloudflare account ID
|
|
129
|
+
* @param {string} params.environment - Deployment environment (production, staging, development)
|
|
130
|
+
* @returns {Promise<string>} Path to generated/updated customer config
|
|
131
|
+
*/
|
|
132
|
+
async generateCustomerConfig(zoneName, params = {}) {
|
|
133
|
+
const {
|
|
134
|
+
accountId,
|
|
135
|
+
environment = 'production'
|
|
136
|
+
} = params;
|
|
137
|
+
if (!zoneName) {
|
|
138
|
+
throw new Error('Zone name is required to generate customer config');
|
|
139
|
+
}
|
|
140
|
+
const customerConfigPath = this.getCustomerConfigPath(zoneName);
|
|
141
|
+
const customerDir = dirname(customerConfigPath);
|
|
142
|
+
if (this.dryRun) {
|
|
143
|
+
console.log(` 🔍 DRY RUN: Would generate/update customer config at ${customerConfigPath}`);
|
|
144
|
+
return customerConfigPath;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Ensure customer directory exists
|
|
148
|
+
await mkdir(customerDir, {
|
|
149
|
+
recursive: true
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Read existing config or start with current root config as template
|
|
153
|
+
let config;
|
|
154
|
+
try {
|
|
155
|
+
await access(customerConfigPath, constants.F_OK);
|
|
156
|
+
// Customer config exists - read and update it
|
|
157
|
+
const content = await readFile(customerConfigPath, 'utf-8');
|
|
158
|
+
config = parseToml(content);
|
|
159
|
+
if (this.verbose) {
|
|
160
|
+
console.log(` 📋 Updating existing customer config: ${customerConfigPath}`);
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
// Customer config doesn't exist - use root config as template
|
|
164
|
+
try {
|
|
165
|
+
config = await this.readConfig();
|
|
166
|
+
if (this.verbose) {
|
|
167
|
+
console.log(` 📋 Creating new customer config from root template: ${customerConfigPath}`);
|
|
168
|
+
}
|
|
169
|
+
} catch (readError) {
|
|
170
|
+
// No root config either - create minimal config
|
|
171
|
+
config = {
|
|
172
|
+
name: 'worker',
|
|
173
|
+
main: 'src/index.js',
|
|
174
|
+
compatibility_date: new Date().toISOString().split('T')[0],
|
|
175
|
+
env: {}
|
|
176
|
+
};
|
|
177
|
+
if (this.verbose) {
|
|
178
|
+
console.log(` 📋 Creating new minimal customer config: ${customerConfigPath}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Update account_id if provided
|
|
184
|
+
if (accountId) {
|
|
185
|
+
config.account_id = accountId;
|
|
186
|
+
console.log(` ✅ Set account_id to ${accountId} in customer config`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Update worker name based on zone
|
|
190
|
+
// Extract base service name and apply zone-based naming
|
|
191
|
+
const customerPrefix = zoneName.split('.')[0]; // clodo.dev → clodo
|
|
192
|
+
|
|
193
|
+
// Update root-level worker name
|
|
194
|
+
if (config.name) {
|
|
195
|
+
const baseName = config.name.replace(/^[^-]+-/, ''); // Remove existing prefix
|
|
196
|
+
const newWorkerName = `${customerPrefix}-${baseName}`;
|
|
197
|
+
config.name = newWorkerName;
|
|
198
|
+
console.log(` ✅ Set worker name to ${newWorkerName} in customer config`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Update SERVICE_DOMAIN in environment variables (all environments)
|
|
202
|
+
const updateServiceDomain = varsObj => {
|
|
203
|
+
if (varsObj && 'SERVICE_DOMAIN' in varsObj) {
|
|
204
|
+
varsObj.SERVICE_DOMAIN = customerPrefix;
|
|
205
|
+
console.log(` ✅ Set SERVICE_DOMAIN to ${customerPrefix}`);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// Update top-level vars if they exist
|
|
210
|
+
if (config.vars) {
|
|
211
|
+
updateServiceDomain(config.vars);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Ensure environment section exists
|
|
215
|
+
if (environment !== 'production') {
|
|
216
|
+
if (!config.env) {
|
|
217
|
+
config.env = {};
|
|
218
|
+
}
|
|
219
|
+
if (!config.env[environment]) {
|
|
220
|
+
config.env[environment] = {
|
|
221
|
+
name: config.name || 'worker'
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Update worker name and SERVICE_DOMAIN in all environment sections
|
|
227
|
+
if (config.env) {
|
|
228
|
+
for (const [envName, envConfig] of Object.entries(config.env)) {
|
|
229
|
+
if (envConfig.name) {
|
|
230
|
+
const baseName = envConfig.name.replace(/^[^-]+-/, ''); // Remove existing prefix
|
|
231
|
+
envConfig.name = `${customerPrefix}-${baseName}`;
|
|
232
|
+
console.log(` ✅ Set [env.${envName}] worker name to ${envConfig.name}`);
|
|
233
|
+
}
|
|
234
|
+
if (envConfig.vars) {
|
|
235
|
+
updateServiceDomain(envConfig.vars);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Write customer config
|
|
241
|
+
const tomlContent = stringifyToml(config);
|
|
242
|
+
await writeFile(customerConfigPath, tomlContent, 'utf-8');
|
|
243
|
+
console.log(` ✅ Customer config saved: ${customerConfigPath}`);
|
|
244
|
+
return customerConfigPath;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Copy customer-specific wrangler.toml to root (ephemeral working copy)
|
|
249
|
+
* This implements the architecture where:
|
|
250
|
+
* - config/customers/{customer}/wrangler.toml = source of truth (versioned)
|
|
251
|
+
* - wrangler.toml (root) = ephemeral working copy (reflects last deployment)
|
|
252
|
+
*
|
|
253
|
+
* @param {string} customerConfigPath - Path to customer's wrangler.toml
|
|
254
|
+
* @returns {Promise<void>}
|
|
255
|
+
*/
|
|
256
|
+
async copyCustomerConfig(customerConfigPath) {
|
|
257
|
+
if (!customerConfigPath) {
|
|
258
|
+
throw new Error('Customer config path is required');
|
|
259
|
+
}
|
|
260
|
+
if (this.dryRun) {
|
|
261
|
+
console.log(` 🔍 DRY RUN: Would copy ${customerConfigPath} → ${this.configPath}`);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
// Read customer config
|
|
266
|
+
const customerContent = await readFile(customerConfigPath, 'utf-8');
|
|
267
|
+
if (this.verbose) {
|
|
268
|
+
console.log(` 📋 Copying customer config: ${customerConfigPath}`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Write to root wrangler.toml (ephemeral working copy)
|
|
272
|
+
await mkdir(dirname(this.configPath), {
|
|
273
|
+
recursive: true
|
|
274
|
+
});
|
|
275
|
+
await writeFile(this.configPath, customerContent, 'utf-8');
|
|
276
|
+
console.log(` ✅ Copied customer config to root wrangler.toml`);
|
|
277
|
+
} catch (error) {
|
|
278
|
+
if (error.code === 'ENOENT') {
|
|
279
|
+
throw new Error(`Customer config not found: ${customerConfigPath}`);
|
|
280
|
+
}
|
|
281
|
+
throw new Error(`Failed to copy customer config: ${error.message}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
99
285
|
/**
|
|
100
286
|
* Set account_id in wrangler.toml
|
|
101
287
|
* @param {string} accountId - Cloudflare account ID
|
|
@@ -186,44 +372,31 @@ export class WranglerConfigManager {
|
|
|
186
372
|
database_name: databaseName,
|
|
187
373
|
database_id: databaseId
|
|
188
374
|
};
|
|
189
|
-
if (environment === 'production') {
|
|
190
|
-
// Add to top-level d1_databases array
|
|
191
|
-
if (!config.d1_databases) {
|
|
192
|
-
config.d1_databases = [];
|
|
193
|
-
}
|
|
194
375
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
config.env[environment] = {
|
|
211
|
-
name: config.name || 'worker'
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
if (!config.env[environment].d1_databases) {
|
|
215
|
-
config.env[environment].d1_databases = [];
|
|
216
|
-
}
|
|
376
|
+
// Always add to environment-specific section for consistency
|
|
377
|
+
// This ensures database bindings are scoped to their environment
|
|
378
|
+
if (!config.env) {
|
|
379
|
+
config.env = {};
|
|
380
|
+
}
|
|
381
|
+
if (!config.env[environment]) {
|
|
382
|
+
// Create environment section with proper name
|
|
383
|
+
const envName = environment === 'production' ? `${config.name}-prod` : config.name || 'worker';
|
|
384
|
+
config.env[environment] = {
|
|
385
|
+
name: envName
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
if (!config.env[environment].d1_databases) {
|
|
389
|
+
config.env[environment].d1_databases = [];
|
|
390
|
+
}
|
|
217
391
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
392
|
+
// Check if binding already exists
|
|
393
|
+
const existingIndex = config.env[environment].d1_databases.findIndex(db => db.binding === binding || db.database_name === databaseName);
|
|
394
|
+
if (existingIndex >= 0) {
|
|
395
|
+
console.log(` 🔄 Updating existing database binding`);
|
|
396
|
+
config.env[environment].d1_databases[existingIndex] = dbBinding;
|
|
397
|
+
} else {
|
|
398
|
+
console.log(` ➕ Adding new database binding`);
|
|
399
|
+
config.env[environment].d1_databases.push(dbBinding);
|
|
227
400
|
}
|
|
228
401
|
await this.writeConfig(config);
|
|
229
402
|
console.log(` ✅ D1 database binding added successfully`);
|
|
@@ -239,18 +412,12 @@ export class WranglerConfigManager {
|
|
|
239
412
|
async removeDatabaseBinding(environment, bindingOrName) {
|
|
240
413
|
const config = await this.readConfig();
|
|
241
414
|
let removed = false;
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
} else {
|
|
249
|
-
if (config.env?.[environment]?.d1_databases) {
|
|
250
|
-
const initialLength = config.env[environment].d1_databases.length;
|
|
251
|
-
config.env[environment].d1_databases = config.env[environment].d1_databases.filter(db => db.binding !== bindingOrName && db.database_name !== bindingOrName);
|
|
252
|
-
removed = config.env[environment].d1_databases.length < initialLength;
|
|
253
|
-
}
|
|
415
|
+
|
|
416
|
+
// Always remove from environment-specific section
|
|
417
|
+
if (config.env?.[environment]?.d1_databases) {
|
|
418
|
+
const initialLength = config.env[environment].d1_databases.length;
|
|
419
|
+
config.env[environment].d1_databases = config.env[environment].d1_databases.filter(db => db.binding !== bindingOrName && db.database_name !== bindingOrName);
|
|
420
|
+
removed = config.env[environment].d1_databases.length < initialLength;
|
|
254
421
|
}
|
|
255
422
|
if (removed) {
|
|
256
423
|
await this.writeConfig(config);
|
|
@@ -45,7 +45,7 @@ export class FrameworkConfig {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// Return null instead of throwing - will use default config
|
|
48
|
-
|
|
48
|
+
// Note: This is expected behavior - services don't need their own config
|
|
49
49
|
return null;
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -54,8 +54,8 @@ export class FrameworkConfig {
|
|
|
54
54
|
*/
|
|
55
55
|
loadConfig() {
|
|
56
56
|
// If no config file found, return default configuration
|
|
57
|
+
// This is normal - services use framework defaults unless they need custom settings
|
|
57
58
|
if (!this.configPath) {
|
|
58
|
-
console.log('📋 Using default framework configuration');
|
|
59
59
|
return this.getDefaultConfig();
|
|
60
60
|
}
|
|
61
61
|
try {
|
|
@@ -98,64 +98,15 @@ export function showProgress(message, steps = ['⏳', '⚡', '✅']) {
|
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
100
|
* Ask for sensitive input (like API tokens) with hidden input
|
|
101
|
-
*
|
|
101
|
+
* Uses inquirer for better paste support and robust input handling
|
|
102
102
|
*/
|
|
103
|
-
export function askPassword(question) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// Hide input for sensitive data
|
|
113
|
-
if (process.stdin.isTTY) {
|
|
114
|
-
process.stdin.setRawMode(true);
|
|
115
|
-
}
|
|
116
|
-
process.stdin.resume();
|
|
117
|
-
let password = '';
|
|
118
|
-
const onData = char => {
|
|
119
|
-
const charCode = char[0];
|
|
120
|
-
if (charCode === 13 || charCode === 10) {
|
|
121
|
-
// Enter key (CR or LF)
|
|
122
|
-
// Restore original state BEFORE resolving
|
|
123
|
-
if (process.stdin.isTTY) {
|
|
124
|
-
process.stdin.setRawMode(wasRaw || false);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Important: Resume stdin so readline can use it
|
|
128
|
-
if (!wasPaused) {
|
|
129
|
-
process.stdin.resume();
|
|
130
|
-
} else {
|
|
131
|
-
process.stdin.pause();
|
|
132
|
-
}
|
|
133
|
-
process.stdin.removeListener('data', onData);
|
|
134
|
-
process.stdout.write('\n');
|
|
135
|
-
|
|
136
|
-
// Small delay to let stdin stabilize before next readline operation
|
|
137
|
-
setTimeout(() => resolve(password), 50);
|
|
138
|
-
} else if (charCode === 127 || charCode === 8) {
|
|
139
|
-
// Backspace
|
|
140
|
-
if (password.length > 0) {
|
|
141
|
-
password = password.slice(0, -1);
|
|
142
|
-
process.stdout.write('\b \b');
|
|
143
|
-
}
|
|
144
|
-
} else if (charCode === 3) {
|
|
145
|
-
// Ctrl+C
|
|
146
|
-
// Restore state and exit gracefully
|
|
147
|
-
if (process.stdin.isTTY) {
|
|
148
|
-
process.stdin.setRawMode(wasRaw || false);
|
|
149
|
-
}
|
|
150
|
-
process.stdin.removeListener('data', onData);
|
|
151
|
-
process.stdout.write('\n');
|
|
152
|
-
process.exit(0);
|
|
153
|
-
} else if (charCode >= 32 && charCode <= 126) {
|
|
154
|
-
// Printable characters
|
|
155
|
-
password += char.toString();
|
|
156
|
-
process.stdout.write('*');
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
process.stdin.on('data', onData);
|
|
160
|
-
});
|
|
103
|
+
export async function askPassword(question) {
|
|
104
|
+
const inquirer = (await import('inquirer')).default;
|
|
105
|
+
const answers = await inquirer.prompt([{
|
|
106
|
+
type: 'password',
|
|
107
|
+
name: 'password',
|
|
108
|
+
message: question,
|
|
109
|
+
mask: '*'
|
|
110
|
+
}]);
|
|
111
|
+
return answers.password;
|
|
161
112
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamyla/clodo-framework",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.22",
|
|
4
4
|
"description": "Reusable framework for Clodo-style software architecture on Cloudflare Workers + D1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -43,15 +43,22 @@
|
|
|
43
43
|
},
|
|
44
44
|
"bin": {
|
|
45
45
|
"clodo-service": "./dist/bin/clodo-service.js",
|
|
46
|
-
"clodo-create-service": "./dist/bin/service-management/create-service.js",
|
|
47
|
-
"clodo-init-service": "./dist/bin/service-management/init-service.js",
|
|
48
46
|
"clodo-security": "./dist/bin/security/security-cli.js"
|
|
49
47
|
},
|
|
50
48
|
"publishConfig": {
|
|
51
49
|
"access": "public"
|
|
52
50
|
},
|
|
53
51
|
"files": [
|
|
54
|
-
"dist",
|
|
52
|
+
"dist/!(bin)",
|
|
53
|
+
"dist/bin/clodo-service.js",
|
|
54
|
+
"dist/bin/commands/deploy.js",
|
|
55
|
+
"dist/bin/commands/validate.js",
|
|
56
|
+
"dist/bin/commands/helpers/",
|
|
57
|
+
"dist/bin/shared/",
|
|
58
|
+
"dist/bin/security/",
|
|
59
|
+
"dist/bin/service-management/",
|
|
60
|
+
"dist/security/",
|
|
61
|
+
"dist/utils/",
|
|
55
62
|
"types",
|
|
56
63
|
"templates",
|
|
57
64
|
"ui-structures",
|
|
@@ -64,11 +71,11 @@
|
|
|
64
71
|
"LICENSE"
|
|
65
72
|
],
|
|
66
73
|
"scripts": {
|
|
67
|
-
"build": "npm run prebuild && babel src/ --out-dir dist/ && babel bin/ --out-dir dist/bin/ --ignore 'bin/**/*.test.js' && node -e \"const fs=require('fs'); fs.cpSync('ui-structures', 'dist/ui-structures', {recursive: true});\" && npm run postbuild",
|
|
68
|
-
"build:ci": "npm run prebuild:ci && babel src/ --out-dir dist/ && babel bin/ --out-dir dist/bin/ --ignore 'bin/**/*.test.js' && node -e \"const fs=require('fs'); fs.cpSync('ui-structures', 'dist/ui-structures', {recursive: true});\" && npm run postbuild",
|
|
74
|
+
"build": "npm run prebuild && babel src/ --out-dir dist/ && babel bin/ --out-dir dist/bin/ --ignore 'bin/**/*.test.js' && node -e \"const fs=require('fs'); fs.cpSync('ui-structures', 'dist/ui-structures', {recursive: true}); fs.cpSync('config', 'dist/config', {recursive: true});\" && npm run postbuild",
|
|
75
|
+
"build:ci": "npm run prebuild:ci && babel src/ --out-dir dist/ && babel bin/ --out-dir dist/bin/ --ignore 'bin/**/*.test.js' && node -e \"const fs=require('fs'); fs.cpSync('ui-structures', 'dist/ui-structures', {recursive: true}); fs.cpSync('config', 'dist/config', {recursive: true});\" && npm run postbuild",
|
|
69
76
|
"prebuild": "npm run clean && npm run type-check",
|
|
70
77
|
"prebuild:ci": "npm run clean && npm run type-check",
|
|
71
|
-
"postbuild": "npm run check:bundle && npm run check:imports",
|
|
78
|
+
"postbuild": "npm run check:bundle && npm run check:imports && node scripts/utilities/fix-dist-imports.js",
|
|
72
79
|
"clean": "rimraf dist",
|
|
73
80
|
"clean:generated": "rimraf generated",
|
|
74
81
|
"clean:all": "npm run clean && npm run clean:generated",
|
|
@@ -147,6 +154,7 @@
|
|
|
147
154
|
"@iarna/toml": "^2.2.5",
|
|
148
155
|
"chalk": "^5.3.0",
|
|
149
156
|
"commander": "^11.0.0",
|
|
157
|
+
"inquirer": "^12.10.0",
|
|
150
158
|
"uuid": "^13.0.0",
|
|
151
159
|
"wrangler": ">=3.0.0"
|
|
152
160
|
},
|
|
@@ -157,7 +165,7 @@
|
|
|
157
165
|
"@babel/preset-env": "^7.23.0",
|
|
158
166
|
"@semantic-release/changelog": "^6.0.3",
|
|
159
167
|
"@semantic-release/git": "^10.0.1",
|
|
160
|
-
"@types/node": "^20.19.
|
|
168
|
+
"@types/node": "^20.19.24",
|
|
161
169
|
"babel-plugin-transform-import-meta": "^2.3.3",
|
|
162
170
|
"cross-env": "^10.1.0",
|
|
163
171
|
"eslint": "^8.54.0",
|