// Name: Cloudflare Cache Manager // Description: Accepts a Cloudflare API token, lists websites, and purges cache (entire site or specific URLs). // Author: anjaneyasivan // GitHub: anjaneyasivan import "@johnlindquist/kit" const TOKEN = await env("CLOUDFLARE_API_TOKEN", { panel: md(`## Cloudflare API Token - Create a token at https://dash.cloudflare.com/profile/api-tokens - Recommended: Use a token with "Zone:Cache Purge" and "Zone:Read" permissions `), secret: true, }) const CF_API = "https://api.cloudflare.com/client/v4" async function fetchZones(): Promise<any[]> { const zones: any[] = [] let page = 1 const per_page = 50 while (true) { const { data } = await get(`${CF_API}/zones`, { params: { page, per_page }, headers: { Authorization: `Bearer ${TOKEN}` }, }) if (!data?.success) { throw new Error(data?.errors?.[0]?.message || "Failed to load zones") } zones.push(...(data.result || [])) const totalPages = data?.result_info?.total_pages || 1 if (page >= totalPages) break page++ } return zones } async function purgeEverything(zoneId: string) { const { data } = await post( `${CF_API}/zones/${zoneId}/purge_cache`, { purge_everything: true }, { headers: { Authorization: `Bearer ${TOKEN}` } } ) if (!data?.success) throw new Error(data?.errors?.[0]?.message || "Purge everything failed") } async function purgeUrls(zoneId: string, files: string[]) { const { data } = await post( `${CF_API}/zones/${zoneId}/purge_cache`, { files }, { headers: { Authorization: `Bearer ${TOKEN}` } } ) if (!data?.success) throw new Error(data?.errors?.[0]?.message || "Purge URLs failed") } try { const zones = await fetchZones() if (!zones.length) { await div(md(`No zones found for this token.`)) exit() } const zone = await arg("Select a Cloudflare site (zone)", zones.map(z => ({ name: z.name, value: z, description: `${z.account?.name || "No Account"} • Status: ${z.status} • ID: ${z.id}`, }))) const action = await arg("Choose purge type", [ { name: "Purge everything", value: "all", description: `Clear entire cache for ${zone.name}` }, { name: "Purge URLs…", value: "urls", description: `Clear cache for specific URLs` }, ]) if (action === "all") { const confirm = await arg({ placeholder: `Type YES to confirm purge of all cache for ${zone.name}`, strict: false, }) if (confirm !== "YES") { notify(`Cancelled purge for ${zone.name}`) exit() } setLoading(true) await purgeEverything(zone.id) setLoading(false) notify(`Purged all cache for ${zone.name}`) exit() } if (action === "urls") { const urlText = await editor({ value: "", language: "text", hint: `Enter one URL per line. You can paste multiple. Example: https://${zone.name}/ https://${zone.name}/about https://${zone.name}/assets/app.js`, shortcuts: [ { name: "Submit", key: `${cmd}+enter`, onPress: input => submit(input), bar: "right", }, ], }) const files = urlText .split(/[\r\n, ]+/) .map(s => s.trim()) .filter(Boolean) if (!files.length) { notify("No URLs provided. Nothing to purge.") exit() } setLoading(true) await purgeUrls(zone.id, files) setLoading(false) notify(`Purged ${files.length} URL(s) for ${zone.name}`) exit() } } catch (err: any) { setLoading(false) await div( md(`## Error ${err?.message || String(err)} `) ) exit(1) }