@tamyla/clodo-framework 4.0.5 → 4.0.7

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 CHANGED
@@ -1,3 +1,23 @@
1
+ ## [4.0.7](https://github.com/tamylaa/clodo-framework/compare/v4.0.6...v4.0.7) (2025-12-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * correct dynamic import paths in interactive-validation.js ([acbadae](https://github.com/tamylaa/clodo-framework/commit/acbadaefc10cf7efab9dd263f7a40f8db18fccb4))
7
+ * correct import path in interactive-validation.js ([8355677](https://github.com/tamylaa/clodo-framework/commit/83556777a0faa1a85766c0bf4795428d8ba807e6))
8
+ * correct remaining dynamic import paths in interactive-validation.js ([837f0a4](https://github.com/tamylaa/clodo-framework/commit/837f0a48489dbde6b644944950232ec0f424639f))
9
+ * correct Windows PowerShell environment variable handling ([f3c5354](https://github.com/tamylaa/clodo-framework/commit/f3c535449f744a2448b4c1b7d98fc62853a8eaab))
10
+
11
+ ## [4.0.6](https://github.com/tamylaa/clodo-framework/compare/v4.0.5...v4.0.6) (2025-12-09)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * add null checks for enterprise deployment methods ([97c3237](https://github.com/tamylaa/clodo-framework/commit/97c32371e97f259f62a82e9f7cc393dab0def7ed))
17
+ * correct URL construction and export missing testing workflow ([19691e1](https://github.com/tamylaa/clodo-framework/commit/19691e1651b3f37762e0564ccbb939c7c22965ad))
18
+ * correct worker URL construction and prevent undefined errors ([5d94f4f](https://github.com/tamylaa/clodo-framework/commit/5d94f4f064d5264f18929a6d2bd0564b0bb5494a))
19
+ * remove duplicate export in InteractiveTestingWorkflow ([db710c2](https://github.com/tamylaa/clodo-framework/commit/db710c2342ac3fd41b73ffd01fdd83ce0e0256f1))
20
+
1
21
  ## [4.0.5](https://github.com/tamylaa/clodo-framework/compare/v4.0.4...v4.0.5) (2025-12-09)
2
22
 
3
23
 
@@ -171,12 +171,18 @@ export async function listWorkers(options = {}) {
171
171
 
172
172
  // Fallback to CLI-based operation
173
173
  try {
174
- const envVars = apiToken ? `CLOUDFLARE_API_TOKEN=${apiToken}` : '';
175
- const command = `${envVars} npx wrangler list`;
176
- const {
177
- stdout: list
178
- } = await executeWithRateLimit(command, 'workers');
179
- return list;
174
+ if (apiToken) {
175
+ const command = process.platform === 'win32' ? `powershell -Command "$env:CLOUDFLARE_API_TOKEN = '${apiToken}'; npx wrangler list"` : `CLOUDFLARE_API_TOKEN=${apiToken} npx wrangler list`;
176
+ const {
177
+ stdout: list
178
+ } = await executeWithRateLimit(command, 'workers');
179
+ return list;
180
+ } else {
181
+ const {
182
+ stdout: list
183
+ } = await executeWithRateLimit('npx wrangler list', 'workers');
184
+ return list;
185
+ }
180
186
  } catch (error) {
181
187
  throw new Error(`Failed to list workers: ${error.message}`);
182
188
  }
@@ -244,40 +250,40 @@ export async function deploySecret(key, value, env = 'production', options = {})
244
250
  }
245
251
 
246
252
  // Fallback to CLI-based operation with API token if available
247
- const envVars = apiToken ? `CLOUDFLARE_API_TOKEN=${apiToken}` : '';
248
- const command = process.platform === 'win32' ? `${envVars} powershell -Command "Write-Output '${value}' | npx wrangler secret put ${key} --env ${env}"` : `${envVars} echo "${value}" | npx wrangler secret put ${key} --env ${env}`;
249
- try {
250
- // Increase retries for secrets due to higher timeout likelihood
253
+ if (apiToken) {
254
+ const command = process.platform === 'win32' ? `powershell -Command "$env:CLOUDFLARE_API_TOKEN = '${apiToken}'; Write-Output '${value}' | npx wrangler secret put ${key} --env ${env}"` : `CLOUDFLARE_API_TOKEN=${apiToken} echo "${value}" | npx wrangler secret put ${key} --env ${env}`;
255
+ await executeWithRateLimit(command, 'workers', 5);
256
+ } else {
257
+ const command = process.platform === 'win32' ? `powershell -Command "Write-Output '${value}' | npx wrangler secret put ${key} --env ${env}"` : `echo "${value}" | npx wrangler secret put ${key} --env ${env}`;
251
258
  await executeWithRateLimit(command, 'workers', 5);
252
- } catch (error) {
253
- throw new Error(`Secret deployment failed: ${error.message}`);
254
259
  }
255
260
  }
256
261
  export async function deleteSecret(key, env = 'production', options = {}) {
257
262
  const {
258
263
  apiToken
259
264
  } = options;
260
- const envVars = apiToken ? `CLOUDFLARE_API_TOKEN=${apiToken}` : '';
261
- const command = `${envVars} npx wrangler secret delete ${key} --env ${env}`;
262
- try {
265
+ if (apiToken) {
266
+ const command = process.platform === 'win32' ? `powershell -Command "$env:CLOUDFLARE_API_TOKEN = '${apiToken}'; npx wrangler secret delete ${key} --env ${env}"` : `CLOUDFLARE_API_TOKEN=${apiToken} npx wrangler secret delete ${key} --env ${env}`;
263
267
  await executeWithRateLimit(command, 'workers');
264
- } catch (error) {
265
- throw new Error(`Secret deletion failed: ${error.message}`);
268
+ } else {
269
+ await executeWithRateLimit(`npx wrangler secret delete ${key} --env ${env}`, 'workers');
266
270
  }
267
271
  }
268
272
  export async function listSecrets(env = 'production', options = {}) {
269
273
  const {
270
274
  apiToken
271
275
  } = options;
272
- const envVars = apiToken ? `CLOUDFLARE_API_TOKEN=${apiToken}` : '';
273
- const command = `${envVars} npx wrangler secret list --env ${env}`;
274
- try {
276
+ if (apiToken) {
277
+ const command = process.platform === 'win32' ? `powershell -Command "$env:CLOUDFLARE_API_TOKEN = '${apiToken}'; npx wrangler secret list --env ${env}"` : `CLOUDFLARE_API_TOKEN=${apiToken} npx wrangler secret list --env ${env}`;
275
278
  const {
276
279
  stdout: list
277
280
  } = await executeWithRateLimit(command, 'workers');
278
281
  return list;
279
- } catch (error) {
280
- throw new Error(`Failed to list secrets: ${error.message}`);
282
+ } else {
283
+ const {
284
+ stdout: list
285
+ } = await executeWithRateLimit(`npx wrangler secret list --env ${env}`, 'workers');
286
+ return list;
281
287
  }
282
288
  }
283
289
  export async function listDatabases(options = {}) {
@@ -346,16 +352,26 @@ export async function createDatabase(name, options = {}) {
346
352
 
347
353
  // Fallback to CLI-based operation
348
354
  try {
349
- const envVars = apiToken ? `CLOUDFLARE_API_TOKEN=${apiToken}` : '';
350
- const command = `${envVars} npx wrangler d1 create ${name}`;
351
- const {
352
- stdout: output
353
- } = await executeWithRateLimit(command, 'd1');
354
- const idMatch = output.match(/database_id = "([^"]+)"/);
355
- if (!idMatch) {
356
- throw new Error('Could not extract database ID from creation output');
355
+ if (apiToken) {
356
+ const command = process.platform === 'win32' ? `powershell -Command "$env:CLOUDFLARE_API_TOKEN = '${apiToken}'; npx wrangler d1 create ${name}"` : `CLOUDFLARE_API_TOKEN=${apiToken} npx wrangler d1 create ${name}`;
357
+ const {
358
+ stdout: output
359
+ } = await executeWithRateLimit(command, 'd1');
360
+ const idMatch = output.match(/database_id = "([^"]+)"/);
361
+ if (!idMatch) {
362
+ throw new Error('Could not extract database ID from creation output');
363
+ }
364
+ return idMatch[1];
365
+ } else {
366
+ const {
367
+ stdout: output
368
+ } = await executeWithRateLimit(`npx wrangler d1 create ${name}`, 'd1');
369
+ const idMatch = output.match(/database_id = "([^"]+)"/);
370
+ if (!idMatch) {
371
+ throw new Error('Could not extract database ID from creation output');
372
+ }
373
+ return idMatch[1];
357
374
  }
358
- return idMatch[1];
359
375
  } catch (error) {
360
376
  throw new Error(`Database creation failed: ${error.message}`);
361
377
  }
@@ -364,12 +380,13 @@ export async function deleteDatabase(name, options = {}) {
364
380
  const {
365
381
  apiToken
366
382
  } = options;
367
- const envVars = apiToken ? `CLOUDFLARE_API_TOKEN=${apiToken}` : '';
368
- const command = `${envVars} npx wrangler d1 delete ${name} --skip-confirmation`;
369
- try {
383
+ if (apiToken) {
384
+ // For Windows PowerShell, set environment variable within the command
385
+ const command = process.platform === 'win32' ? `powershell -Command "$env:CLOUDFLARE_API_TOKEN = '${apiToken}'; npx wrangler d1 delete ${name} --skip-confirmation"` : `CLOUDFLARE_API_TOKEN=${apiToken} npx wrangler d1 delete ${name} --skip-confirmation`;
370
386
  await executeWithRateLimit(command, 'd1');
371
- } catch (error) {
372
- throw new Error(`Database deletion failed: ${error.message}`);
387
+ } else {
388
+ // No API token provided, use default wrangler auth
389
+ await executeWithRateLimit(`npx wrangler d1 delete ${name} --skip-confirmation`, 'd1');
373
390
  }
374
391
  }
375
392
  export async function runMigrations(databaseName, env = 'production', options = {}) {
@@ -380,9 +397,12 @@ export async function runMigrations(databaseName, env = 'production', options =
380
397
  try {
381
398
  await ensureMonitoringInitialized();
382
399
  const result = await errorRecovery.executeWithRecovery(async () => {
383
- const envVars = apiToken ? `CLOUDFLARE_API_TOKEN=${apiToken}` : '';
384
- const command = `${envVars} npx wrangler d1 migrations apply ${databaseName} --env ${env} --remote`;
385
- await executeWithRateLimit(command, 'd1');
400
+ if (apiToken) {
401
+ const command = process.platform === 'win32' ? `powershell -Command "$env:CLOUDFLARE_API_TOKEN = '${apiToken}'; npx wrangler d1 migrations apply ${databaseName} --env ${env} --remote"` : `CLOUDFLARE_API_TOKEN=${apiToken} npx wrangler d1 migrations apply ${databaseName} --env ${env} --remote`;
402
+ await executeWithRateLimit(command, 'd1');
403
+ } else {
404
+ await executeWithRateLimit(`npx wrangler d1 migrations apply ${databaseName} --env ${env} --remote`, 'd1');
405
+ }
386
406
  return true;
387
407
  }, {
388
408
  operationId: `runMigrations_${databaseName}_${env}`
@@ -78,7 +78,7 @@ export class InteractiveConfirmation {
78
78
  console.log('2. Run database migrations');
79
79
  console.log('3. Deploy Cloudflare Worker');
80
80
  console.log('4. Verify deployment health');
81
- if (config.deployment.runTests) {
81
+ if (config.deployment?.runTests) {
82
82
  console.log('5. Run integration tests');
83
83
  }
84
84
  }
@@ -147,11 +147,11 @@ export class InteractiveConfirmation {
147
147
  console.log(`šŸ“± Mode: ${config.deploymentMode}`);
148
148
  console.log(`⚔ Worker: ${config.worker.name}`);
149
149
  console.log(`šŸ”— URL: ${config.worker.url}`);
150
- console.log(`šŸ—„ļø Database: ${config.database.name} (${config.database.id})`);
151
- console.log(`šŸ”‘ Secrets: ${Object.keys(config.secrets.keys).length} configured`);
150
+ console.log(`šŸ—„ļø Database: ${config.database?.name || 'None'} (${config.database?.id || 'No ID'})`);
151
+ console.log(`šŸ”‘ Secrets: ${config.secrets?.keys ? Object.keys(config.secrets.keys).length : 0} configured`);
152
152
  console.log(`šŸ†” Deployment ID: ${deploymentState.deploymentId}`);
153
- console.log(`šŸ” Validation: ${config.deployment.validationLevel}`);
154
- console.log(`šŸ“‹ Audit: ${config.deployment.auditLevel}`);
153
+ console.log(`šŸ” Validation: ${config.deployment?.validationLevel || 'standard'}`);
154
+ console.log(`šŸ“‹ Audit: ${config.deployment?.auditLevel || 'basic'}`);
155
155
  }
156
156
 
157
157
  /**
@@ -168,7 +168,7 @@ export class InteractiveConfirmation {
168
168
  console.log('4. Configuration management');
169
169
  console.log('5. Cloudflare Worker deployment with D1 recovery');
170
170
  console.log('6. Deployment verification');
171
- if (config.deployment.runTests) {
171
+ if (config.deployment?.runTests) {
172
172
  console.log('7. Comprehensive integration tests');
173
173
  }
174
174
  console.log(`8. Audit logging and reporting`);
@@ -93,9 +93,9 @@ export class InteractiveDomainInfoGatherer {
93
93
  config.worker = config.worker || {};
94
94
  config.worker.name = `${config.domain}-data-service`;
95
95
 
96
- // Use account name from credentials for workers.dev subdomain
97
- const accountName = config.credentials?.accountName || 'tamylatrading';
98
- config.worker.url = `https://${config.worker.name}.${accountName}.workers.dev`;
96
+ // Use zone name from credentials for workers.dev subdomain
97
+ const zoneName = config.credentials?.zoneName || `${config.domain}.workers.dev`;
98
+ config.worker.url = `https://${config.worker.name}.${zoneName}`;
99
99
  console.log(`\nšŸ”§ Generated Configuration:`);
100
100
  console.log(` Worker Name: ${config.worker.name}`);
101
101
  console.log(` Worker URL: ${config.worker.url}`);
@@ -114,8 +114,8 @@ export class InteractiveDomainInfoGatherer {
114
114
  console.log(` šŸ”§ Using extracted name: ${customWorkerName}`);
115
115
  }
116
116
  config.worker.name = customWorkerName;
117
- const accountName = config.credentials?.accountName || 'tamylatrading';
118
- config.worker.url = `https://${config.worker.name}.${accountName}.workers.dev`;
117
+ const zoneName = config.credentials?.zoneName || `${config.domain}.workers.dev`;
118
+ config.worker.url = `https://${config.worker.name}.${zoneName}`;
119
119
  console.log(`\nāœ… Updated worker configuration`);
120
120
  }
121
121
  }
@@ -129,7 +129,7 @@ export class InteractiveValidationWorkflow {
129
129
  console.log('===========================');
130
130
  const {
131
131
  askChoice
132
- } = await import('../utils/prompt-utils.js');
132
+ } = await import('../../utils/interactive-prompts.js');
133
133
  const choice = await askChoice('How would you like to handle the existing worker?', ['šŸ”„ Overwrite/Update - Deploy new version (recommended)', 'šŸ“ Rename - Create with a different worker name', 'šŸ” Compare - Show differences before deciding', 'šŸ’¾ Backup & Update - Create backup before overwriting', 'āŒ Cancel - Stop deployment'], 0);
134
134
  switch (choice) {
135
135
  case 0:
@@ -140,7 +140,7 @@ export class InteractiveValidationWorkflow {
140
140
  // Rename
141
141
  const newName = await this.promptForNewWorkerName(config.worker.name);
142
142
  config.worker.name = newName;
143
- config.worker.url = `https://${newName}.${config.credentials?.zoneName || config.credentials?.accountName || 'tamylatrading.workers.dev'}`;
143
+ config.worker.url = `https://${newName}.${config.credentials?.zoneName || `${config.domain || 'clododev'}.workers.dev`}`;
144
144
  console.log(` āœ… Will deploy as new worker: ${newName}`);
145
145
  return true;
146
146
  case 2:
@@ -168,7 +168,7 @@ export class InteractiveValidationWorkflow {
168
168
  async promptForNewWorkerName(currentName) {
169
169
  const {
170
170
  askUser
171
- } = await import('../utils/prompt-utils.js');
171
+ } = await import('../../utils/interactive-prompts.js');
172
172
  let newName = await askUser(`Enter new worker name (current: ${currentName})`);
173
173
  newName = newName.trim();
174
174
  if (!newName) {
@@ -207,7 +207,7 @@ export class InteractiveValidationWorkflow {
207
207
  // This is a simplified comparison - in a real implementation,
208
208
  // you might fetch the existing worker's configuration
209
209
  console.log(` šŸ“‹ Existing Worker: ${config.worker.name}`);
210
- console.log(` 🌐 URL: https://${config.worker.name}.${config.credentials?.zoneName || config.credentials?.accountName || 'tamylatrading.workers.dev'}`);
210
+ console.log(` 🌐 URL: https://${config.worker.name}.${config.credentials?.zoneName || `${config.domain || 'clododev'}.workers.dev`}`);
211
211
  console.log(` šŸ“… Last deployed: Unknown (would need API call to check)`);
212
212
  console.log(` šŸ”§ Environment: ${config.environment || 'production'}`);
213
213
  console.log('\n šŸ“‹ New Deployment:');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamyla/clodo-framework",
3
- "version": "4.0.5",
3
+ "version": "4.0.7",
4
4
  "description": "Reusable framework for Clodo-style software architecture on Cloudflare Workers + D1",
5
5
  "type": "module",
6
6
  "sideEffects": [