diff --git a/.changeset/new-shirts-bake.md b/.changeset/new-shirts-bake.md new file mode 100644 index 000000000..fb25f3d76 --- /dev/null +++ b/.changeset/new-shirts-bake.md @@ -0,0 +1,5 @@ +--- +"@solidjs/start": minor +--- + +refactor middleware. mainly fix onResponse diff --git a/packages/start/src/middleware/index.ts b/packages/start/src/middleware/index.ts index 26d28e717..f23d08161 100644 --- a/packages/start/src/middleware/index.ts +++ b/packages/start/src/middleware/index.ts @@ -1,29 +1,22 @@ // @refresh skip -import type { H3Event, Middleware } from "h3"; +import { H3Event, type Middleware, onResponse } from "h3"; import { getFetchEvent } from "../server/fetchEvent.ts"; import type { FetchEvent } from "../server/types.ts"; -/** Function responsible for receiving an observable [operation]{@link Operation} and returning a [result]{@link OperationResult}. */ +export type MiddlewareFn = (event: FetchEvent) => unknown; -export type MiddlewareFn = (event: FetchEvent) => Promise | unknown; -/** This composes an array of Exchanges into a single ExchangeIO function */ - -export type RequestMiddleware = ( - event: FetchEvent, -) => Response | Promise | void | Promise | Promise; - -// copy-pasted from h3/dist/index.d.ts -type EventHandlerResponse = T | Promise; -type ResponseMiddlewareResponseParam = { body?: Awaited }; +// `unknown` because h3 allows any response type like string, json, etc. not just Response +export type RequestMiddleware = (event: FetchEvent) => unknown; export type ResponseMiddleware = ( event: FetchEvent, - response: ResponseMiddlewareResponseParam, -) => Response | Promise | void | Promise; + response: Response, +) => ReturnType[0]>; function wrapRequestMiddleware(onRequest: RequestMiddleware) { return async (h3Event: H3Event) => { + // h3 onRequest doesn't allow returning a response, but we will for backwards compatibility with start v1 const fetchEvent = getFetchEvent(h3Event); const response = await onRequest(fetchEvent); if (response) return response; @@ -31,27 +24,22 @@ function wrapRequestMiddleware(onRequest: RequestMiddleware) { } function wrapResponseMiddleware(onBeforeResponse: ResponseMiddleware): Middleware { - return async (h3Event, next) => { - const resp = await next(); - + return onResponse(async (response, h3Event) => { const fetchEvent = getFetchEvent(h3Event); - const mwResponse = await onBeforeResponse(fetchEvent, { - body: (resp as any)?.body, - }); + const mwResponse = await onBeforeResponse(fetchEvent, response.clone()); if (mwResponse) return mwResponse; - }; + }); } export function createMiddleware( - args: + args?: | { - /** @deprecated Use H3 `Middleware` */ onRequest?: RequestMiddleware | RequestMiddleware[] | undefined; - /** @deprecated Use H3 `Middleware` */ onBeforeResponse?: ResponseMiddleware | ResponseMiddleware[] | undefined; } | Middleware[], ): Middleware[] { + if (!args) return []; if (Array.isArray(args)) return args; const mw: Middleware[] = []; diff --git a/packages/start/src/server/handler.ts b/packages/start/src/server/handler.ts index d91453d93..0d8fa875e 100644 --- a/packages/start/src/server/handler.ts +++ b/packages/start/src/server/handler.ts @@ -21,7 +21,7 @@ export function createBaseHandler( options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise) = {}, ) { const handler = defineHandler({ - middleware: middleware.length ? middleware.map(decorateMiddleware) : undefined, + middleware: middleware?.length ? middleware.map(decorateMiddleware) : undefined, handler: decorateHandler(async (e: H3Event) => { const event = getRequestEvent()!; const url = new URL(event.request.url); diff --git a/packages/start/src/virtual.d.ts b/packages/start/src/virtual.d.ts index 53083c11d..e50aba8bc 100644 --- a/packages/start/src/virtual.d.ts +++ b/packages/start/src/virtual.d.ts @@ -23,5 +23,5 @@ declare module "solid-start:app" { declare module "solid-start:middleware" { type MaybeArray = T | Array; - export default Middleware as import("h3").Middleware[]; + export default Middleware as import("h3").Middleware[] | undefined; }