UNPKG

@restnfeel/agentc-starter-kit

Version:

한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템

180 lines (149 loc) 5.03 kB
import { CDNProvider, CDNConfig, getCacheSettingsForMimeType, } from "../cdn-config"; export class CloudflareCDNProvider implements CDNProvider { private config: CDNConfig; private baseUrl: string; constructor(config: CDNConfig) { this.config = config; this.baseUrl = config.customDomain ? `https://${config.customDomain}` : config.endpoint; } async upload(file: Buffer, key: string, mimeType: string): Promise<string> { if (!this.config.enabled) { throw new Error("CDN is disabled"); } try { // Cloudflare R2 또는 Images API 사용 // 실제 구현에서는 Cloudflare API 사용 const uploadUrl = `${this.config.endpoint}/api/v1/media/${key}`; const response = await fetch(uploadUrl, { method: "PUT", headers: { Authorization: `Bearer ${this.config.accessKey}`, "Content-Type": mimeType, ...this.getCacheHeaders(mimeType), }, body: file, }); if (!response.ok) { throw new Error(`Upload failed: ${response.statusText}`); } return this.getUrl(key); } catch (error) { console.error("Cloudflare CDN upload error:", error); throw error; } } async delete(key: string): Promise<void> { if (!this.config.enabled) return; try { const deleteUrl = `${this.config.endpoint}/api/v1/media/${key}`; const response = await fetch(deleteUrl, { method: "DELETE", headers: { Authorization: `Bearer ${this.config.accessKey}`, }, }); if (!response.ok) { throw new Error(`Delete failed: ${response.statusText}`); } } catch (error) { console.error("Cloudflare CDN delete error:", error); throw error; } } async invalidate(keys: string[]): Promise<void> { if (!this.config.enabled || keys.length === 0) return; try { // Cloudflare Cache Purge API const purgeUrl = `https://api.cloudflare.com/client/v4/zones/${this.config.zone}/purge_cache`; const urls = keys.map((key) => this.getUrl(key)); const response = await fetch(purgeUrl, { method: "POST", headers: { Authorization: `Bearer ${this.config.accessKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ files: urls, }), }); if (!response.ok) { throw new Error(`Cache invalidation failed: ${response.statusText}`); } } catch (error) { console.error("Cloudflare CDN invalidate error:", error); throw error; } } getUrl(key: string): string { return `${this.baseUrl}/${key}`; } getCacheHeaders(mimeType: string): Record<string, string> { const cacheSettings = getCacheSettingsForMimeType(mimeType); return { "Cache-Control": `public, max-age=${cacheSettings.maxAge}, stale-while-revalidate=${cacheSettings.staleWhileRevalidate}, stale-if-error=${cacheSettings.staleIfError}`, "CDN-Cache-Control": `public, max-age=${cacheSettings.maxAge}`, "Cloudflare-CDN-Cache-Control": `public, max-age=${cacheSettings.maxAge}`, }; } // Cloudflare 특화 기능들 async getAnalytics(_startDate: Date, _endDate: Date) { try { const analyticsUrl = `https://api.cloudflare.com/client/v4/zones/${this.config.zone}/analytics/dashboard`; const response = await fetch(analyticsUrl, { method: "GET", headers: { Authorization: `Bearer ${this.config.accessKey}`, }, }); if (!response.ok) { throw new Error(`Analytics fetch failed: ${response.statusText}`); } return await response.json(); } catch (error) { console.error("Cloudflare analytics error:", error); return null; } } async optimizeImage( key: string, options: { width?: number; height?: number; format?: "webp" | "avif" | "auto"; quality?: number; } ) { // Cloudflare Images 최적화 옵션 const params = new URLSearchParams(); if (options.width) params.append("w", options.width.toString()); if (options.height) params.append("h", options.height.toString()); if (options.format) params.append("f", options.format); if (options.quality) params.append("q", options.quality.toString()); const optimizedUrl = `${this.getUrl(key)}?${params.toString()}`; return optimizedUrl; } async getZoneSettings() { try { const settingsUrl = `https://api.cloudflare.com/client/v4/zones/${this.config.zone}/settings`; const response = await fetch(settingsUrl, { method: "GET", headers: { Authorization: `Bearer ${this.config.accessKey}`, }, }); if (!response.ok) { throw new Error(`Settings fetch failed: ${response.statusText}`); } return await response.json(); } catch (error) { console.error("Cloudflare zone settings error:", error); return null; } } }