import * as plugins from './cloudflare.plugins.js'; import { logger } from './cloudflare.logger.js'; import * as interfaces from './interfaces/index.js'; import type { CloudflareAccount } from './cloudflare.classes.account.js'; export class CloudflareZone { // Zone properties public id: string; public name: string; public status: interfaces.ICflareZone['status']; public paused: boolean; public type: interfaces.ICflareZone['type']; public development_mode: number; public name_servers: string[]; public original_name_servers: string[]; public original_registrar: string | null; public original_dnshost: string | null; public modified_on: string; public created_on: string; public activated_on: string; public meta: interfaces.ICflareZone['meta']; public owner: interfaces.ICflareZone['owner']; public account: interfaces.ICflareZone['account']; public permissions: string[]; public plan: interfaces.ICflareZone['plan']; private cfAccount?: CloudflareAccount; // Will be set when created through a manager /** * Create a CloudflareZone instance from an API object * @param apiObject Cloudflare Zone API object * @param cfAccount Optional Cloudflare account instance * @returns CloudflareZone instance */ public static createFromApiObject( apiObject: plugins.ICloudflareTypes['Zone'], cfAccount?: CloudflareAccount ): CloudflareZone { const cloudflareZone = new CloudflareZone(); Object.assign(cloudflareZone, apiObject); if (cfAccount) { cloudflareZone.cfAccount = cfAccount; } return cloudflareZone; } /** * Check if development mode is currently active * @returns True if development mode is active */ public isDevelopmentModeActive(): boolean { return this.development_mode > 0; } /** * Enable development mode for the zone * @param cfAccount Cloudflare account to use if not already set * @param duration Duration in seconds (default: 3 hours) * @returns Updated zone */ public async enableDevelopmentMode( cfAccount?: CloudflareAccount, duration: number = 10800 ): Promise { const account = cfAccount || this.cfAccount; if (!account) { throw new Error('CloudflareAccount is required to enable development mode'); } logger.log('info', `Enabling development mode for zone ${this.name}`); try { // The official client doesn't have a direct method for development mode // We'll use the request method for this specific case await account.request('PATCH', `/zones/${this.id}/settings/development_mode`, { value: 'on', time: duration }); this.development_mode = duration; return this; } catch (error) { logger.log('error', `Failed to enable development mode: ${error.message}`); throw error; } } /** * Disable development mode for the zone * @param cfAccount Cloudflare account to use if not already set * @returns Updated zone */ public async disableDevelopmentMode(cfAccount?: CloudflareAccount): Promise { const account = cfAccount || this.cfAccount; if (!account) { throw new Error('CloudflareAccount is required to disable development mode'); } logger.log('info', `Disabling development mode for zone ${this.name}`); try { // The official client doesn't have a direct method for development mode // We'll use the request method for this specific case await account.request('PATCH', `/zones/${this.id}/settings/development_mode`, { value: 'off' }); this.development_mode = 0; return this; } catch (error) { logger.log('error', `Failed to disable development mode: ${error.message}`); throw error; } } /** * Purge all cached content for this zone * @param cfAccount Cloudflare account to use if not already set * @returns True if successful */ public async purgeCache(cfAccount?: CloudflareAccount): Promise { const account = cfAccount || this.cfAccount; if (!account) { throw new Error('CloudflareAccount is required to purge cache'); } logger.log('info', `Purging all cache for zone ${this.name}`); try { await account.apiAccount.cache.purge({ zone_id: this.id, purge_everything: true }); return true; } catch (error) { logger.log('error', `Failed to purge cache: ${error.message}`); return false; } } /** * Purge specific URLs from the cache * @param urls Array of URLs to purge * @param cfAccount Cloudflare account to use if not already set * @returns True if successful */ public async purgeUrls(urls: string[], cfAccount?: CloudflareAccount): Promise { const account = cfAccount || this.cfAccount; if (!account) { throw new Error('CloudflareAccount is required to purge URLs'); } if (!urls.length) { return true; } logger.log('info', `Purging ${urls.length} URLs from cache for zone ${this.name}`); try { await account.apiAccount.cache.purge({ zone_id: this.id, files: urls }); return true; } catch (error) { logger.log('error', `Failed to purge URLs: ${error.message}`); return false; } } /** * Check if the zone is active * @returns True if the zone is active */ public isActive(): boolean { return this.status === 'active' && !this.paused; } /** * Check if the zone is using Cloudflare nameservers * @returns True if using Cloudflare nameservers */ public isUsingCloudflareNameservers(): boolean { // Check if original nameservers match current nameservers if (!this.original_name_servers || !this.name_servers) { return false; } // If they're different, and current nameservers are Cloudflare's return this.name_servers.some(ns => ns.includes('cloudflare')); } /** * Update zone settings * @param settings Settings to update * @param cfAccount Cloudflare account to use if not already set * @returns Updated zone */ public async updateSettings( settings: Partial<{ paused: boolean; plan: { id: string }; vanity_name_servers: string[]; type: 'full' | 'partial' | 'secondary'; }>, cfAccount?: CloudflareAccount ): Promise { const account = cfAccount || this.cfAccount; if (!account) { throw new Error('CloudflareAccount is required to update zone settings'); } logger.log('info', `Updating settings for zone ${this.name}`); try { // Use the request method instead of zones.edit to avoid type issues const response: { result: interfaces.ICflareZone } = await account.request( 'PATCH', `/zones/${this.id}`, settings ); Object.assign(this, response.result); return this; } catch (error) { logger.log('error', `Failed to update zone settings: ${error.message}`); throw error; } } }