diff --git a/.changeset/fix-onoriginrequest-async-signature.md b/.changeset/fix-onoriginrequest-async-signature.md new file mode 100644 index 0000000..bc8c991 --- /dev/null +++ b/.changeset/fix-onoriginrequest-async-signature.md @@ -0,0 +1,16 @@ +--- +"@bunny.net/edgescript-sdk": patch +--- + +`onOriginRequest`'s old `Promise | Promise` signature +doesn't accept `async` callbacks returning a mix of the two: TS infers +`Promise` for them, which is a supertype the narrower +union won't accept. Flagged in #63 and partially fixed in #64 (which only +touched the ambient declaration). + +Widen both hooks, with sync returns too: + +* `onOriginRequest`: `(ctx) => Request | Response | Promise` +* `onOriginResponse`: `(ctx) => Response | Promise` + +Same shape as `ServerHandler`, strictly wider, nothing breaks. diff --git a/libs/bunny-sdk/src/net/serve.test.ts b/libs/bunny-sdk/src/net/serve.test.ts new file mode 100644 index 0000000..170bc08 --- /dev/null +++ b/libs/bunny-sdk/src/net/serve.test.ts @@ -0,0 +1,51 @@ +// Type-level tests for the middleware signatures on `servePullZone`. +// The callbacks below are typechecked but never invoked — these +// exist purely to ensure the public signatures accept all the shapes +// documented in the JSDoc. If any stop typechecking, it's a regression. + +import type * as Http from "./serve.ts"; + +type OnRequest = Parameters[0]; +type OnResponse = Parameters[0]; + +// Async arrow with mixed Request / Response returns — async-flattening +// produces `Promise`. Used to fail under the previous +// `Promise | Promise` signature. +const _asyncMixed: OnRequest = async (ctx) => { + if (ctx.request.headers.get("upgrade") === "websocket") { + return new Response(null, { status: 426 }); + } + return new Request(ctx.request); +}; + +// Plain function returning `Promise.resolve(...)` — the classic workaround. +const _promiseResolve: OnRequest = (ctx) => { + if (ctx.request.headers.get("x-block") === "1") { + return Promise.resolve(new Response(null, { status: 403 })); + } + return Promise.resolve(new Request(ctx.request)); +}; + +// Sync returns — mirrors the `ServerHandler` pattern. +const _sync: OnRequest = (ctx) => { + if (ctx.request.headers.get("x-fast-path") === "1") { + return new Response("ok"); + } + return new Request(ctx.request); +}; + +// `onOriginResponse` accepts sync and async too. +const _resSync: OnResponse = (ctx) => ctx.response; +const _resAsync: OnResponse = async (ctx) => { + ctx.response.headers.set("Via", "Custom"); + return ctx.response; +}; + +test("middleware type signatures accept sync, async, and mixed returns", () => { + // Silence unused-var warnings; the real check is at compile time. + expect(typeof _asyncMixed).toBe("function"); + expect(typeof _promiseResolve).toBe("function"); + expect(typeof _sync).toBe("function"); + expect(typeof _resSync).toBe("function"); + expect(typeof _resAsync).toBe("function"); +}); diff --git a/libs/bunny-sdk/src/net/serve.ts b/libs/bunny-sdk/src/net/serve.ts index bdb594d..2aa7d54 100644 --- a/libs/bunny-sdk/src/net/serve.ts +++ b/libs/bunny-sdk/src/net/serve.ts @@ -136,7 +136,7 @@ export type PullZoneHandler = { onOriginRequest: ( middleware: ( ctx: OriginRequestContext, - ) => Promise | Promise, + ) => Request | Response | Promise, ) => PullZoneHandler; /** @@ -145,7 +145,7 @@ export type PullZoneHandler = { onOriginResponse: ( middleware: ( ctx: OriginResponseContext, - ) => Promise, + ) => Response | Promise, ) => PullZoneHandler; }; @@ -234,12 +234,12 @@ function servePullZone( const onOriginRequestMiddleware: Array< ( ctx: OriginRequestContext, - ) => Promise | Promise | undefined + ) => Request | Response | Promise | undefined > = []; const onOriginResponseMiddleware: Array< ( ctx: OriginResponseContext, - ) => Promise | undefined + ) => Response | Promise | undefined > = []; const platform = internal_getPlatform(); diff --git a/libs/bunny-sdk/types/bunny.d.ts b/libs/bunny-sdk/types/bunny.d.ts index 18314fa..323985f 100644 --- a/libs/bunny-sdk/types/bunny.d.ts +++ b/libs/bunny-sdk/types/bunny.d.ts @@ -14,10 +14,10 @@ declare namespace Bunny { registerMiddlewares: (middlewares: { onOriginRequest: Array<( ctx: { request: Request }, - ) => Promise | Promise | undefined> + ) => Request | Response | Promise | undefined> onOriginResponse: Array<( ctx: { request: Request, response: Response }, - ) => Promise | Promise | undefined> + ) => Response | Promise | undefined> }) => void, };