diff --git a/.changeset/slimy-turkeys-smoke.md b/.changeset/slimy-turkeys-smoke.md new file mode 100644 index 000000000..0d599cb9d --- /dev/null +++ b/.changeset/slimy-turkeys-smoke.md @@ -0,0 +1,5 @@ +--- +"@opennextjs/aws": patch +--- + +fix: middleware configuration type diff --git a/packages/open-next/src/adapters/middleware.ts b/packages/open-next/src/adapters/middleware.ts index 5f0985bf0..ff243d6de 100644 --- a/packages/open-next/src/adapters/middleware.ts +++ b/packages/open-next/src/adapters/middleware.ts @@ -1,4 +1,5 @@ import type { + ExternalMiddlewareConfig, InternalEvent, InternalResult, MiddlewareResult, @@ -30,22 +31,30 @@ const defaultHandler = async ( internalEvent: InternalEvent, options?: OpenNextHandlerOptions, ): Promise => { - const config = globalThis.openNextConfig.middleware; - const originResolver = await resolveOriginResolver(config?.originResolver); + // We know that the middleware is external when this adapter is used + const middlewareConfig = globalThis.openNextConfig + .middleware as ExternalMiddlewareConfig; + const originResolver = await resolveOriginResolver( + middlewareConfig?.originResolver, + ); const externalRequestProxy = await resolveProxyRequest( - config?.override?.proxyExternalRequest, + middlewareConfig?.override?.proxyExternalRequest, ); - const assetResolver = await resolveAssetResolver(config?.assetResolver); + const assetResolver = await resolveAssetResolver( + middlewareConfig?.assetResolver, + ); //#override includeCacheInMiddleware - globalThis.tagCache = await resolveTagCache(config?.override?.tagCache); + globalThis.tagCache = await resolveTagCache( + middlewareConfig?.override?.tagCache, + ); - globalThis.queue = await resolveQueue(config?.override?.queue); + globalThis.queue = await resolveQueue(middlewareConfig?.override?.queue); globalThis.incrementalCache = await resolveIncrementalCache( - config?.override?.incrementalCache, + middlewareConfig?.override?.incrementalCache, ); //#endOverride diff --git a/packages/open-next/src/build/generateOutput.ts b/packages/open-next/src/build/generateOutput.ts index 769e106e7..7d3b995e5 100644 --- a/packages/open-next/src/build/generateOutput.ts +++ b/packages/open-next/src/build/generateOutput.ts @@ -3,6 +3,7 @@ import path from "node:path"; import type { BaseOverride, DefaultOverrideOptions, + ExternalMiddlewareConfig, FunctionOptions, LazyLoadedOverride, OverrideOptions, @@ -164,14 +165,16 @@ export async function generateOutput(options: BuildOptions) { const edgeFunctions: OpenNextOutput["edgeFunctions"] = {}; const isExternalMiddleware = config.middleware?.external ?? false; if (isExternalMiddleware) { + const middlewareConfig = options.config + .middleware as ExternalMiddlewareConfig; edgeFunctions.middleware = { bundle: ".open-next/middleware", handler: "handler.handler", pathResolver: await extractOverrideName( "pattern-env", - config.middleware!.originResolver, + middlewareConfig.originResolver, ), - ...(await extractOverrideFn(config.middleware?.override)), + ...(await extractOverrideFn(middlewareConfig.override)), }; } // Add edge functions diff --git a/packages/open-next/src/build/validateConfig.ts b/packages/open-next/src/build/validateConfig.ts index ecb3cda19..c24bf276e 100644 --- a/packages/open-next/src/build/validateConfig.ts +++ b/packages/open-next/src/build/validateConfig.ts @@ -109,7 +109,9 @@ export function validateConfig(config: OpenNextConfig) { ); } validateFunctionOptions(config.imageOptimization ?? {}); - validateFunctionOptions(config.middleware ?? {}); + if (config.middleware?.external === true) { + validateFunctionOptions(config.middleware ?? {}); + } //@ts-expect-error - Revalidate custom wrapper type is different validateFunctionOptions(config.revalidate ?? {}); //@ts-expect-error - Warmer custom wrapper type is different diff --git a/packages/open-next/src/core/createGenericHandler.ts b/packages/open-next/src/core/createGenericHandler.ts index 1870b5033..f27819fd3 100644 --- a/packages/open-next/src/core/createGenericHandler.ts +++ b/packages/open-next/src/core/createGenericHandler.ts @@ -37,8 +37,11 @@ export async function createGenericHandler< ); globalThis.openNextConfig = config; - const override = config[handler.type] - ?.override as any as DefaultOverrideOptions; + const handlerConfig = config[handler.type]; + const override = + handlerConfig && "override" in handlerConfig + ? (handlerConfig.override as any as DefaultOverrideOptions) + : undefined; // From the config, we create the converter const converter = await resolveConverter(override?.converter); diff --git a/packages/open-next/src/core/resolve.ts b/packages/open-next/src/core/resolve.ts index f8ca6dacb..a86102a6c 100644 --- a/packages/open-next/src/core/resolve.ts +++ b/packages/open-next/src/core/resolve.ts @@ -1,6 +1,7 @@ import type { BaseEventOrResult, DefaultOverrideOptions, + ExternalMiddlewareConfig, InternalEvent, InternalResult, OpenNextConfig, @@ -105,9 +106,7 @@ export async function resolveImageLoader( * @__PURE__ */ export async function resolveOriginResolver( - originResolver: RemoveUndefined< - OpenNextConfig["middleware"] - >["originResolver"], + originResolver: RemoveUndefined["originResolver"], ) { if (typeof originResolver === "function") { return originResolver(); diff --git a/packages/open-next/src/types/open-next.ts b/packages/open-next/src/types/open-next.ts index 8de290285..210803468 100644 --- a/packages/open-next/src/types/open-next.ts +++ b/packages/open-next/src/types/open-next.ts @@ -363,20 +363,24 @@ export interface SplittedFunctionOptions extends FunctionOptions { patterns: string[]; } -export interface OpenNextConfig { - default: FunctionOptions; - functions?: Record; - +/** + * MiddlewareConfig that applies to both external and internal middlewares + * + * Note: this type is internal and included in both `ExternalMiddlewareConfig` and `InternalMiddlewareConfig` + */ +type CommonMiddlewareConfig = { /** - * Override the default middleware - * If you set this options, the middleware need to be deployed separately. - * It supports both edge and node runtime. - * @default undefined + * The assetResolver is used to resolve assets in the routing layer. + * + * @default "dummy" */ - middleware?: DefaultFunctionOptions & { - //We force the middleware to be a function - external: true; + assetResolver?: IncludedAssetResolver | LazyLoadedOverride; +}; +/** MiddlewareConfig that applies to external middlewares only */ +export type ExternalMiddlewareConfig = DefaultFunctionOptions & + CommonMiddlewareConfig & { + external: true; /** * The runtime used by next for the middleware. * @default "edge" @@ -400,15 +404,25 @@ export interface OpenNextConfig { originResolver?: | IncludedOriginResolver | LazyLoadedOverride; - - /** - * The assetResolver is used to resolve assets in the routing layer. - * - * @default "dummy" - */ - assetResolver?: IncludedAssetResolver | LazyLoadedOverride; }; +/** MiddlewareConfig that applies to internal middlewares only */ +export type InternalMiddlewareConfig = { + external: false; +} & CommonMiddlewareConfig; + +export interface OpenNextConfig { + default: FunctionOptions; + functions?: Record; + + /** + * Override the default middleware + * When `external` is true, the middleware need to be deployed separately. + * It supports both edge and node runtime. + * @default undefined - Which is equivalent to `external: false` + */ + middleware?: ExternalMiddlewareConfig | InternalMiddlewareConfig; + /** * Override the default warmer * By default, works for lambda only.