/** * Cloudflare Images Media Provider * * Provides integration with Cloudflare Images for image hosting and transformation. * * Features: * - Browse uploaded images * - Upload new images * - Delete images * - URL-based image transformations (resize, format conversion, etc.) * * @see https://developers.cloudflare.com/images/ */ import type { MediaProviderDescriptor } from "emdash/media"; /** * Cloudflare Images configuration */ export interface CloudflareImagesConfig { /** * Cloudflare Account ID (for API calls) * If not provided, reads from accountIdEnvVar at runtime */ accountId?: string; /** * Environment variable name containing the Account ID * @default "CF_ACCOUNT_ID" */ accountIdEnvVar?: string; /** * Cloudflare Images Account Hash (for delivery URLs) * This is different from the Account ID - find it in the Cloudflare dashboard * under Images > Overview > "Account Hash" * If not provided, reads from accountHashEnvVar at runtime */ accountHash?: string; /** * Environment variable name containing the Account Hash * @default "CF_IMAGES_ACCOUNT_HASH" */ accountHashEnvVar?: string; /** * API Token with Images permissions * If not provided, reads from apiTokenEnvVar at runtime * Should have "Cloudflare Images: Read" and "Cloudflare Images: Edit" permissions */ apiToken?: string; /** * Environment variable name containing the API token * @default "CF_IMAGES_TOKEN" */ apiTokenEnvVar?: string; /** * Custom delivery domain (optional) * If not specified, uses imagedelivery.net * @example "images.example.com" */ deliveryDomain?: string; /** * Default variant to use for display * @default "public" */ defaultVariant?: string; } // Cloudflare Images icon (inline SVG as data URL) const IMAGES_ICON = `data:image/svg+xml,${encodeURIComponent('')}`; /** * Cloudflare Images media provider * * @example * ```ts * import { cloudflareImages } from "@emdash-cms/cloudflare"; * * emdash({ * mediaProviders: [ * // Uses CF_ACCOUNT_ID and CF_IMAGES_TOKEN env vars by default * cloudflareImages({}), * * // Or with custom env var names * cloudflareImages({ * accountIdEnvVar: "MY_CF_ACCOUNT", * apiTokenEnvVar: "MY_CF_IMAGES_KEY", * }), * ], * }) * ``` */ export function cloudflareImages( config: CloudflareImagesConfig, ): MediaProviderDescriptor { return { id: "cloudflare-images", name: "Cloudflare Images", icon: IMAGES_ICON, entrypoint: "@emdash-cms/cloudflare/media/images-runtime", capabilities: { browse: true, search: false, // Images API doesn't support search upload: true, delete: true, }, config, }; }