From b5d94a1ad944652a12ac57d2036a5e90564b54e9 Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:26:58 +0900 Subject: [PATCH 01/17] refactor: narrow middleware config without type assertion --- packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts b/packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts index 426fb2188..967da30b4 100644 --- a/packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts +++ b/packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts @@ -1,5 +1,4 @@ import logger from "@opennextjs/aws/logger.js"; -import type { ExternalMiddlewareConfig } from "@opennextjs/aws/types/open-next.js"; import type { OpenNextConfig } from "../../../api/config.js"; @@ -9,8 +8,9 @@ import type { OpenNextConfig } from "../../../api/config.js"; * @param config OpenNext configuration. */ export function ensureCloudflareConfig(config: OpenNextConfig) { - const mwIsMiddlewareExternal = config.middleware?.external === true; - const mwConfig = mwIsMiddlewareExternal ? (config.middleware as ExternalMiddlewareConfig) : undefined; + const { middleware } = config; + const mwConfig = middleware?.external === true ? middleware : undefined; + const mwIsMiddlewareExternal = mwConfig !== undefined; const requirements = { // Check for the default function From 1d24faf4323e8bc789152b77fce755ea3955c279 Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:33:14 +0900 Subject: [PATCH 02/17] refactor: remove unnecessary optional chaining --- .../src/cli/build/utils/ensure-cf-config.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts b/packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts index 967da30b4..7f23e9443 100644 --- a/packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts +++ b/packages/cloudflare/src/cli/build/utils/ensure-cf-config.ts @@ -14,19 +14,19 @@ export function ensureCloudflareConfig(config: OpenNextConfig) { const requirements = { // Check for the default function - dftUseCloudflareWrapper: config.default?.override?.wrapper === "cloudflare-node", - dftUseEdgeConverter: config.default?.override?.converter === "edge", - dftUseFetchProxy: config.default?.override?.proxyExternalRequest === "fetch", + dftUseCloudflareWrapper: config.default.override?.wrapper === "cloudflare-node", + dftUseEdgeConverter: config.default.override?.converter === "edge", + dftUseFetchProxy: config.default.override?.proxyExternalRequest === "fetch", dftMaybeUseCache: - config.default?.override?.incrementalCache === "dummy" || - typeof config.default?.override?.incrementalCache === "function", + config.default.override?.incrementalCache === "dummy" || + typeof config.default.override?.incrementalCache === "function", dftMaybeUseTagCache: - config.default?.override?.tagCache === "dummy" || - typeof config.default?.override?.incrementalCache === "function", + config.default.override?.tagCache === "dummy" || + typeof config.default.override?.incrementalCache === "function", dftMaybeUseQueue: - config.default?.override?.queue === "dummy" || - config.default?.override?.queue === "direct" || - typeof config.default?.override?.queue === "function", + config.default.override?.queue === "dummy" || + config.default.override?.queue === "direct" || + typeof config.default.override?.queue === "function", // Check for the middleware function mwIsMiddlewareExternal, mwUseCloudflareWrapper: mwConfig?.override?.wrapper === "cloudflare-edge", @@ -35,7 +35,7 @@ export function ensureCloudflareConfig(config: OpenNextConfig) { hasCryptoExternal: config.edgeExternals?.includes("node:crypto"), }; - if (config.default?.override?.queue === "direct") { + if (config.default.override?.queue === "direct") { logger.warn("The direct mode queue is not recommended for use in production."); } From b73989ad9d0872443fa960673a189fb42f80820e Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:34:45 +0900 Subject: [PATCH 03/17] refactor: remove unnecessary type assertion --- packages/cloudflare/src/cli/commands/skew-protection.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cloudflare/src/cli/commands/skew-protection.ts b/packages/cloudflare/src/cli/commands/skew-protection.ts index 4845f8a9d..cdf0a7a63 100644 --- a/packages/cloudflare/src/cli/commands/skew-protection.ts +++ b/packages/cloudflare/src/cli/commands/skew-protection.ts @@ -90,11 +90,11 @@ export async function getDeploymentMapping( process.exit(1); } - const apiToken = envVars.CF_WORKERS_SCRIPTS_API_TOKEN!; - const accountId = envVars.CF_ACCOUNT_ID!; + const apiToken = envVars.CF_WORKERS_SCRIPTS_API_TOKEN; + const accountId = envVars.CF_ACCOUNT_ID; const client = new Cloudflare({ apiToken }); - const scriptName = envVars.CF_WORKER_NAME!; + const scriptName = envVars.CF_WORKER_NAME; const deployedVersions = await listWorkerVersions(scriptName, { client, From a0123e714b3ab6cb628d5a28402c9908ff83757b Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:35:34 +0900 Subject: [PATCH 04/17] refactor: remove unnecessary optional chaining --- packages/cloudflare/src/cli/commands/skew-protection.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cloudflare/src/cli/commands/skew-protection.ts b/packages/cloudflare/src/cli/commands/skew-protection.ts index cdf0a7a63..148db1dea 100644 --- a/packages/cloudflare/src/cli/commands/skew-protection.ts +++ b/packages/cloudflare/src/cli/commands/skew-protection.ts @@ -99,9 +99,9 @@ export async function getDeploymentMapping( const deployedVersions = await listWorkerVersions(scriptName, { client, accountId, - maxNumberOfVersions: config.cloudflare?.skewProtection?.maxNumberOfVersions, - afterTimeMs: config.cloudflare?.skewProtection?.maxVersionAgeDays - ? Date.now() - config.cloudflare?.skewProtection?.maxVersionAgeDays * MS_PER_DAY + maxNumberOfVersions: config.cloudflare.skewProtection.maxNumberOfVersions, + afterTimeMs: config.cloudflare.skewProtection.maxVersionAgeDays + ? Date.now() - config.cloudflare.skewProtection.maxVersionAgeDays * MS_PER_DAY : undefined, }); From dd8cca0d788d13f5c3557f33f1f6648b1ff29ee8 Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:37:10 +0900 Subject: [PATCH 05/17] chore: fix unnecessary conditional lint warning --- packages/cloudflare/src/cli/commands/skew-protection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cloudflare/src/cli/commands/skew-protection.ts b/packages/cloudflare/src/cli/commands/skew-protection.ts index 148db1dea..e43bcaac1 100644 --- a/packages/cloudflare/src/cli/commands/skew-protection.ts +++ b/packages/cloudflare/src/cli/commands/skew-protection.ts @@ -257,7 +257,7 @@ export async function listWorkerVersions( } } } catch (e) { - if (e instanceof NotFoundError && e.status === 404) { + if (e instanceof NotFoundError) { // The worker has not been deployed before, no previous versions. return []; } From 060c1834b847d1f5a73dffc09e53ecb67d140653 Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:38:56 +0900 Subject: [PATCH 06/17] refactor: remove unnecessary optional chaining --- .../cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts b/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts index 50ab91b1c..af78ad20b 100644 --- a/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts +++ b/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts @@ -229,7 +229,7 @@ export class KVNextModeTagCache implements NextModeTagCache { * @returns request scoped in-memory cache for tag values, or undefined if ALS is not available. */ protected getItemsCache() { - const store = globalThis.__openNextAls?.getStore(); + const store = globalThis.__openNextAls.getStore(); return store?.requestCache.getOrCreate("kv-nextMode:tagItems"); } } From 98640e37bf4f2f0f9159851ae1c0373a98204971 Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:43:03 +0900 Subject: [PATCH 07/17] refactor: remove unnecessary nullish coalescing for revalidatedAt --- .../cloudflare/src/api/overrides/tag-cache/d1-next-tag-cache.ts | 2 +- .../src/api/overrides/tag-cache/do-sharded-tag-cache.ts | 2 +- .../cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cloudflare/src/api/overrides/tag-cache/d1-next-tag-cache.ts b/packages/cloudflare/src/api/overrides/tag-cache/d1-next-tag-cache.ts index e288c841e..3d2fa7877 100644 --- a/packages/cloudflare/src/api/overrides/tag-cache/d1-next-tag-cache.ts +++ b/packages/cloudflare/src/api/overrides/tag-cache/d1-next-tag-cache.ts @@ -163,7 +163,7 @@ export class D1NextModeTagCache implements NextModeTagCache { const row = rowsByKey.get(this.getCacheKey(tag)); const value: D1TagValue | null = row ? { - revalidatedAt: (row[1] as number) ?? 0, + revalidatedAt: row[1] as number, stale: (row[2] as number) ?? null, expire: (row[3] as number) ?? null, } diff --git a/packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts b/packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts index 26f4d222d..aef329d19 100644 --- a/packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts +++ b/packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts @@ -311,7 +311,7 @@ class ShardedDOTagCache implements NextModeTagCache { const data = parsed as TagData; return { tag, - revalidatedAt: data.revalidatedAt ?? 0, + revalidatedAt: data.revalidatedAt, stale: data.stale ?? null, expire: data.expire ?? null, }; diff --git a/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts b/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts index af78ad20b..1679689a6 100644 --- a/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts +++ b/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts @@ -22,7 +22,7 @@ type KVTagValue = | { revalidatedAt: number; stale?: number | null; expire?: number | null }; function getRevalidatedAt(value: KVTagValue): number { - return typeof value === "number" ? value : (value.revalidatedAt ?? 0); + return typeof value === "number" ? value : value.revalidatedAt; } function getStale(value: KVTagValue): number | null { From 63fd71fe86a9470c84d4058c51216b0c0980c99d Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:44:46 +0900 Subject: [PATCH 08/17] refactor: validate queue service binding before assignment Co-authored-by: Copilot --- packages/cloudflare/src/api/durable-objects/queue.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/cloudflare/src/api/durable-objects/queue.ts b/packages/cloudflare/src/api/durable-objects/queue.ts index c8b8f7a65..d5d92b3ac 100644 --- a/packages/cloudflare/src/api/durable-objects/queue.ts +++ b/packages/cloudflare/src/api/durable-objects/queue.ts @@ -40,9 +40,11 @@ export class DOQueueHandler extends DurableObject { constructor(ctx: DurableObjectState, env: CloudflareEnv) { super(ctx, env); - this.service = env.WORKER_SELF_REFERENCE!; // If there is no service binding, we throw an error because we can't revalidate without it - if (!this.service) throw new IgnorableError("No service binding for cache revalidation worker"); + if (!env.WORKER_SELF_REFERENCE) { + throw new IgnorableError("No service binding for cache revalidation worker"); + } + this.service = env.WORKER_SELF_REFERENCE; this.sql = ctx.storage.sql; this.maxRevalidations = env.NEXT_CACHE_DO_QUEUE_MAX_REVALIDATION From ee1498b8a382aa2dbeef35337e595d6fc848f39a Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:47:45 +0900 Subject: [PATCH 09/17] refactor: remove optional chaining for stdout and stderr in runWrangler --- packages/cloudflare/src/cli/commands/utils/run-wrangler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cloudflare/src/cli/commands/utils/run-wrangler.ts b/packages/cloudflare/src/cli/commands/utils/run-wrangler.ts index 6859b4097..d01d10271 100644 --- a/packages/cloudflare/src/cli/commands/utils/run-wrangler.ts +++ b/packages/cloudflare/src/cli/commands/utils/run-wrangler.ts @@ -131,8 +131,8 @@ export function runWrangler( ); const success = result.status === 0; - const stdout = result.stdout?.toString() ?? ""; - const stderr = result.stderr?.toString() ?? ""; + const stdout = result.stdout.toString(); + const stderr = result.stderr.toString(); if (!noLogs) { // When not piping logs, stderr is captured but should still be visible to the user From 74474bc42211a566ea46aa453f56c5f8cbfd79da Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:48:22 +0900 Subject: [PATCH 10/17] refactor: remove nullish coalescing for routes in generateBundle function --- .../cloudflare/src/cli/build/open-next/createServerBundle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cloudflare/src/cli/build/open-next/createServerBundle.ts b/packages/cloudflare/src/cli/build/open-next/createServerBundle.ts index c556b6026..ea0b2c52e 100644 --- a/packages/cloudflare/src/cli/build/open-next/createServerBundle.ts +++ b/packages/cloudflare/src/cli/build/open-next/createServerBundle.ts @@ -187,7 +187,7 @@ async function generateBundle( buildOutputPath: appBuildOutputPath, packagePath, outputDir: outputPath, - routes: fnOptions.routes ?? ["app/page.tsx"], + routes: fnOptions.routes, bundledNextServer: isBundled, }); From 71879ccb474ffa272eba8f32110f6a207f241cc8 Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Wed, 29 Apr 2026 06:22:27 +0900 Subject: [PATCH 11/17] fix: restore optional chaining for __openNextAls in KV tag cache --- .../cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts b/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts index 1679689a6..39f07732a 100644 --- a/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts +++ b/packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts @@ -229,7 +229,7 @@ export class KVNextModeTagCache implements NextModeTagCache { * @returns request scoped in-memory cache for tag values, or undefined if ALS is not available. */ protected getItemsCache() { - const store = globalThis.__openNextAls.getStore(); + const store = globalThis.__openNextAls?.getStore(); return store?.requestCache.getOrCreate("kv-nextMode:tagItems"); } } From eaf0fe0e198d2b15a6c7ef1bc2ed5b1db5335bcd Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:35:34 +0900 Subject: [PATCH 12/17] refactor: simplify stale and expire properties in cached tag value --- .../src/api/overrides/tag-cache/do-sharded-tag-cache.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts b/packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts index aef329d19..646d9fada 100644 --- a/packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts +++ b/packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts @@ -304,16 +304,16 @@ class ShardedDOTagCache implements NextModeTagCache { return { tag, revalidatedAt: parsed, - stale: parsed as number | null, - expire: null as number | null, + stale: parsed, + expire: null, }; } const data = parsed as TagData; return { tag, revalidatedAt: data.revalidatedAt, - stale: data.stale ?? null, - expire: data.expire ?? null, + stale: data.stale, + expire: data.expire, }; } catch (e) { debugCache("Error while parsing cached value", e); From e3d02ec7dd2b20bd4e967998fdbb3b3b19749c9f Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:40:02 +0900 Subject: [PATCH 13/17] refactor: remove redundant string from tag cache filter union --- .../src/api/overrides/tag-cache/tag-cache-filter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cloudflare/src/api/overrides/tag-cache/tag-cache-filter.ts b/packages/cloudflare/src/api/overrides/tag-cache/tag-cache-filter.ts index 239cea838..bb6adaf7d 100644 --- a/packages/cloudflare/src/api/overrides/tag-cache/tag-cache-filter.ts +++ b/packages/cloudflare/src/api/overrides/tag-cache/tag-cache-filter.ts @@ -11,7 +11,7 @@ interface WithFilterOptions { * @param tag The tag to filter. * @returns true if the tag should be forwarded, false otherwise. */ - filterFn: (tag: string | NextModeTagCacheWriteInput) => boolean; + filterFn: (tag: NextModeTagCacheWriteInput) => boolean; } /** @@ -69,7 +69,7 @@ export function withFilter({ tagCache, filterFn }: WithFilterOptions): NextModeT * This is used to filter out internal soft tags. * Can be used if `revalidatePath` is not used. */ -export function softTagFilter(tag: string | NextModeTagCacheWriteInput): boolean { +export function softTagFilter(tag: NextModeTagCacheWriteInput): boolean { if (typeof tag === "string") { return !tag.startsWith("_N_T_"); } From 8e6ecadb1df0306b90a2782d28693e197e3d5cbc Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:47:41 +0900 Subject: [PATCH 14/17] refactor: remove unnecessary optional chaining --- packages/cloudflare/src/api/overrides/internal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cloudflare/src/api/overrides/internal.ts b/packages/cloudflare/src/api/overrides/internal.ts index cc7c115d4..d0b7251b3 100644 --- a/packages/cloudflare/src/api/overrides/internal.ts +++ b/packages/cloudflare/src/api/overrides/internal.ts @@ -34,7 +34,7 @@ export function computeCacheKey(key: string, options: KeyOptions) { export function isPurgeCacheEnabled(): boolean { // The `?` is required at `openNextConfig?` or the Open Next build fails because of a type error - const cdnInvalidation = globalThis.openNextConfig?.default?.override?.cdnInvalidation; + const cdnInvalidation = globalThis.openNextConfig.default?.override?.cdnInvalidation; return cdnInvalidation !== undefined && cdnInvalidation !== "dummy"; } From 9314fd8dd9364623854c78910f6f921335b993ca Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:58:18 +0900 Subject: [PATCH 15/17] refactor: remove non-null assertions in image query parameter validators Replace `length` checks followed by `arr[0]!` with destructuring (`const [x, ...rest] = arr`) and `undefined` guards. TypeScript does not narrow indexed access from a length check, so the previous code needed `!`; the destructured form narrows naturally and is type-safe without assertions. Co-authored-by: Copilot --- .../cloudflare/src/cli/templates/images.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/cloudflare/src/cli/templates/images.ts b/packages/cloudflare/src/cli/templates/images.ts index 886be5e8a..993054ad8 100644 --- a/packages/cloudflare/src/cli/templates/images.ts +++ b/packages/cloudflare/src/cli/templates/images.ts @@ -486,14 +486,15 @@ type ErrorResult = { function validateUrlQueryParameter(requestURL: URL): ErrorResult | { url: string; static: boolean } { // There should be a single "url" parameter. const urls = requestURL.searchParams.getAll("url"); - if (urls.length < 1) { + const [url, ...rest] = urls; + if (url === undefined) { const result: ErrorResult = { ok: false, message: '"url" parameter is required', }; return result; } - if (urls.length > 1) { + if (rest.length > 0) { const result: ErrorResult = { ok: false, message: '"url" parameter cannot be an array', @@ -501,8 +502,6 @@ function validateUrlQueryParameter(requestURL: URL): ErrorResult | { url: string return result; } - const url = urls[0]!; - if (url.length > 3072) { const result: ErrorResult = { ok: false, @@ -574,21 +573,22 @@ function validateUrlQueryParameter(requestURL: URL): ErrorResult | { url: string */ function validateWidthQueryParameter(requestURL: URL): ErrorResult | number { const widthQueryValues = requestURL.searchParams.getAll("w"); - if (widthQueryValues.length < 1) { + const [widthQueryValue, ...rest] = widthQueryValues; + + if (widthQueryValue === undefined) { const result: ErrorResult = { ok: false, message: '"w" parameter (width) is required', }; return result; } - if (widthQueryValues.length > 1) { + if (rest.length > 0) { const result: ErrorResult = { ok: false, message: '"w" parameter (width) cannot be an array', }; return result; } - const widthQueryValue = widthQueryValues[0]!; if (!/^[0-9]+$/.test(widthQueryValue)) { const result: ErrorResult = { ok: false, @@ -624,21 +624,21 @@ function validateWidthQueryParameter(requestURL: URL): ErrorResult | number { */ function validateQualityQueryParameter(requestURL: URL): ErrorResult | number { const qualityQueryValues = requestURL.searchParams.getAll("q"); - if (qualityQueryValues.length < 1) { + const [qualityQueryValue, ...rest] = qualityQueryValues; + if (qualityQueryValue === undefined) { const result: ErrorResult = { ok: false, message: '"q" parameter (quality) is required', }; return result; } - if (qualityQueryValues.length > 1) { + if (rest.length > 0) { const result: ErrorResult = { ok: false, message: '"q" parameter (quality) cannot be an array', }; return result; } - const qualityQueryValue = qualityQueryValues[0]!; if (!/^[0-9]+$/.test(qualityQueryValue)) { const result: ErrorResult = { ok: false, From 48ba2c025bc9fe51c6cbe62471b011673f5b4149 Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Wed, 29 Apr 2026 08:13:35 +0900 Subject: [PATCH 16/17] refactor: replace non-null assertions with optional chaining in vercel-og font patch Co-authored-by: Copilot --- .../src/cli/build/patches/ast/patch-vercel-og-library.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/cloudflare/src/cli/build/patches/ast/patch-vercel-og-library.ts b/packages/cloudflare/src/cli/build/patches/ast/patch-vercel-og-library.ts index b37fa892c..9ef4dcc20 100644 --- a/packages/cloudflare/src/cli/build/patches/ast/patch-vercel-og-library.ts +++ b/packages/cloudflare/src/cli/build/patches/ast/patch-vercel-og-library.ts @@ -65,8 +65,10 @@ export function patchVercelOgLibrary(buildOpts: BuildOptions): boolean { writeFileSync(outputEdgePath, ast.commitEdits(edits)); if (matches.length > 0) { - const fontFileName = matches[0]!.getMatch("PATH")!.text(); - renameSync(path.join(outputDir, fontFileName), path.join(outputDir, `${fontFileName}.bin`)); + const fontFileName = matches[0]?.getMatch("PATH")?.text(); + if (fontFileName) { + renameSync(path.join(outputDir, fontFileName), path.join(outputDir, `${fontFileName}.bin`)); + } } } From 0c4098ba7947cb2d32d99b41d6fc9f60bb5bfe89 Mon Sep 17 00:00:00 2001 From: Akihiro Nagai <77012577+314systems@users.noreply.github.com> Date: Wed, 29 Apr 2026 08:26:50 +0900 Subject: [PATCH 17/17] refactor: improve date extraction logic in getLatestCompatDate function Co-authored-by: Copilot --- .../src/cli/utils/create-wrangler-config.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/cloudflare/src/cli/utils/create-wrangler-config.ts b/packages/cloudflare/src/cli/utils/create-wrangler-config.ts index 2d89e3e2c..582a16bcc 100644 --- a/packages/cloudflare/src/cli/utils/create-wrangler-config.ts +++ b/packages/cloudflare/src/cli/utils/create-wrangler-config.ts @@ -128,14 +128,18 @@ async function getLatestCompatDate(): Promise { // The format of the workerd version is `major.yyyymmdd.patch`. const match = latestWorkerdVersion.match(/\d+\.(\d{4})(\d{2})(\d{2})\.\d+/); - if (match) { - const [, year, month, day] = match; - const compatDate = `${year}-${month}-${day}`; + if (!match) { + return undefined; + } + const [, year, month, day] = match; + if (!year || !month || !day) { + return undefined; + } + const compatDate = `${year}-${month}-${day}`; - const currentDate = new Date().toISOString().slice(0, 10); + const currentDate = new Date().toISOString().slice(0, 10); - return compatDate < currentDate ? compatDate : currentDate; - } + return compatDate < currentDate ? compatDate : currentDate; } catch { /* empty */ }