import * as plugins from './cloudflare.plugins.js'; import { CloudflareAccount } from './cloudflare.classes.account.js'; import { CloudflareWorker } from './cloudflare.classes.worker.js'; import { logger } from './cloudflare.logger.js'; export class WorkerManager { public cfAccount: CloudflareAccount; constructor(cfAccountArg: CloudflareAccount) { this.cfAccount = cfAccountArg; } /** * Creates a new worker or updates an existing one * @param workerName Name of the worker * @param workerScript JavaScript content of the worker * @returns CloudflareWorker instance for the created/updated worker */ public async createWorker(workerName: string, workerScript: string): Promise { if (!this.cfAccount.preselectedAccountId) { throw new Error('No account selected. Please select it first on the account.'); } try { // Use the official client to create/update the worker await this.cfAccount.apiAccount.workers.scripts.content.update(workerName, { account_id: this.cfAccount.preselectedAccountId, "CF-WORKER-BODY-PART": workerScript, metadata: {} }); // Create a new worker instance const worker = new CloudflareWorker(this); worker.id = workerName; worker.script = workerScript; // Initialize the worker and get its routes try { await worker.getRoutes(); } catch (routeError) { logger.log('warn', `Failed to get routes for worker ${workerName}: ${routeError.message}`); // Continue anyway since the worker was created } return worker; } catch (error) { logger.log('error', `Failed to create worker ${workerName}: ${error.message}`); throw error; } } /** * Get a worker by name * @param workerName Name of the worker to retrieve * @returns CloudflareWorker instance or undefined if not found */ public async getWorker(workerName: string): Promise { if (!this.cfAccount.preselectedAccountId) { throw new Error('No account selected. Please select it first on the account.'); } try { // Get the worker script using the official client const workerScript = await this.cfAccount.apiAccount.workers.scripts.get(workerName, { account_id: this.cfAccount.preselectedAccountId }); // Create a new worker instance const worker = new CloudflareWorker(this); worker.id = workerName; // Save script content if available if (workerScript && typeof workerScript === 'object') { Object.assign(worker, workerScript); } // Initialize the worker and get its routes try { await worker.getRoutes(); } catch (routeError) { logger.log('warn', `Failed to get routes for worker ${workerName}: ${routeError.message}`); // Continue anyway since we found the worker } return worker; } catch (error) { logger.log('warn', `Worker '${workerName}' not found: ${error.message}`); return undefined; } } /** * Lists all worker scripts * @returns Array of worker scripts */ public async listWorkerScripts() { if (!this.cfAccount.preselectedAccountId) { throw new Error('No account selected. Please select it first on the account.'); } try { // Collect all scripts using the new client's async iterator const workerScripts: plugins.ICloudflareTypes['Script'][] = []; try { for await (const script of this.cfAccount.apiAccount.workers.scripts.list({ account_id: this.cfAccount.preselectedAccountId, })) { workerScripts.push(script); } logger.log('info', `Found ${workerScripts.length} worker scripts`); return workerScripts; } catch (error) { logger.log('warn', `Error while listing workers with async iterator: ${error.message}`); // Try alternative approach if the async iterator fails const result = await this.cfAccount.apiAccount.workers.scripts.list({ account_id: this.cfAccount.preselectedAccountId, }) as any; // Check if the result has a 'result' property (older API response format) if (result && result.result && Array.isArray(result.result)) { logger.log('info', `Found ${result.result.length} worker scripts using direct result`); return result.result; } } logger.log('warn', 'Could not retrieve worker scripts'); return []; } catch (error) { logger.log('error', `Failed to list worker scripts: ${error.message}`); return []; } } /** * Deletes a worker script * @param workerName Name of the worker to delete * @returns True if deletion was successful */ public async deleteWorker(workerName: string): Promise { if (!this.cfAccount.preselectedAccountId) { throw new Error('No account selected. Please select it first on the account.'); } try { await this.cfAccount.apiAccount.workers.scripts.delete(workerName, { account_id: this.cfAccount.preselectedAccountId }); logger.log('info', `Worker '${workerName}' deleted successfully`); return true; } catch (error) { logger.log('error', `Failed to delete worker '${workerName}': ${error.message}`); return false; } } }