From 91120091a3fce0657ddb89c50ea2865a815000cd Mon Sep 17 00:00:00 2001 From: dswbx Date: Fri, 19 Sep 2025 11:28:04 +0200 Subject: [PATCH] feat: add fallback redirect for cloudflare image optimization plugin Introduced `fallbackRedirect` option to enable a redirect to the original image if image optimization fails. Added logging for platform proxy usage and adjusted `beforeBuild` to handle undefined `app`. Minor improvements and process termination for clear command flow. --- app/src/adapter/cloudflare/proxy.ts | 3 +++ app/src/adapter/index.ts | 4 +++- app/src/cli/commands/types/types.ts | 2 ++ .../plugins/cloudflare/image-optimization.plugin.ts | 12 ++++++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app/src/adapter/cloudflare/proxy.ts b/app/src/adapter/cloudflare/proxy.ts index 938a2ab..0ae3a37 100644 --- a/app/src/adapter/cloudflare/proxy.ts +++ b/app/src/adapter/cloudflare/proxy.ts @@ -7,6 +7,7 @@ import { } from "bknd/adapter/cloudflare"; import type { GetPlatformProxyOptions, PlatformProxy } from "wrangler"; import process from "node:process"; +import { $console } from "bknd/utils"; export type WithPlatformProxyOptions = { /** @@ -25,6 +26,8 @@ export function withPlatformProxy( typeof opts?.useProxy === "boolean" ? opts.useProxy : process.env.PROXY === "1"; let proxy: PlatformProxy | undefined; + $console.log("Using cloudflare platform proxy"); + async function getEnv(env?: Env): Promise { if (use_proxy) { if (!proxy) { diff --git a/app/src/adapter/index.ts b/app/src/adapter/index.ts index 0ee5e0c..461a8d4 100644 --- a/app/src/adapter/index.ts +++ b/app/src/adapter/index.ts @@ -15,7 +15,7 @@ import type { Manifest } from "vite"; export type BkndConfig = CreateAppConfig & { app?: Omit | ((args: Args) => MaybePromise, "app">>); onBuilt?: (app: App) => MaybePromise; - beforeBuild?: (app: App, registries?: typeof $registries) => MaybePromise; + beforeBuild?: (app?: App, registries?: typeof $registries) => MaybePromise; buildConfig?: Parameters[0]; }; @@ -57,6 +57,8 @@ export async function createAdapterApp { + await config.beforeBuild?.(undefined, $registries); + const appConfig = await makeConfig(config, args); if (!appConfig.connection || !Connection.isConnection(appConfig.connection)) { let connection: Connection | undefined; diff --git a/app/src/cli/commands/types/types.ts b/app/src/cli/commands/types/types.ts index b545d61..ebadf35 100644 --- a/app/src/cli/commands/types/types.ts +++ b/app/src/cli/commands/types/types.ts @@ -35,4 +35,6 @@ async function action({ await writeFile(outfile, et.toString()); console.info(`\nTypes written to ${c.cyan(outfile)}`); } + + process.exit(0); } diff --git a/app/src/plugins/cloudflare/image-optimization.plugin.ts b/app/src/plugins/cloudflare/image-optimization.plugin.ts index 0f330bd..0fc5090 100644 --- a/app/src/plugins/cloudflare/image-optimization.plugin.ts +++ b/app/src/plugins/cloudflare/image-optimization.plugin.ts @@ -49,6 +49,11 @@ export type CloudflareImageOptimizationOptions = { * @default public, max-age=31536000, immutable */ cacheControl?: string; + /** + * Whether to fallback to the original image if the image optimization fails + * @default false + */ + fallbackRedirect?: boolean; }; export function cloudflareImageOptimization({ @@ -57,6 +62,7 @@ export function cloudflareImageOptimization({ explain = false, defaultOptions = {}, fixedOptions = {}, + fallbackRedirect = false, }: CloudflareImageOptimizationOptions = {}): AppPlugin { const disallowedAccessUrls = ["/api", "/admin", "/api/plugin"]; if (disallowedAccessUrls.includes(accessUrl) || accessUrl.length < 2) { @@ -117,6 +123,12 @@ export function cloudflareImageOptimization({ // Returning fetch() with resizing options will pass through response with the resized image. const res = await fetch(imageRequest, { cf: { image: options as any } }); + + if (!res.ok && fallbackRedirect) { + // add redirect response to the original image + return new Response(null, { status: 307, headers: { Location: imageURL } }); + } + const headers = pickHeaders2(res.headers, [ "Content-Type", "Content-Length",