diff --git a/packages/astro/package.json b/packages/astro/package.json index 370cd8bee29d..4539479195a0 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -33,7 +33,7 @@ "require": "./build/cjs/index.server.js" }, "./middleware": { - "types": "./build/types/integration/middleware/index.types.d.ts", + "types": "./build/types/integration/middleware/index.d.ts", "node": "./build/esm/integration/middleware/index.js", "import": "./build/esm/integration/middleware/index.js", "require": "./build/cjs/integration/middleware/index.js" diff --git a/packages/astro/src/integration/middleware/index.ts b/packages/astro/src/integration/middleware/index.ts index 46c7ad9531b5..0208290c2733 100644 --- a/packages/astro/src/integration/middleware/index.ts +++ b/packages/astro/src/integration/middleware/index.ts @@ -1,6 +1,8 @@ -import type { MiddlewareResponseHandler } from 'astro'; import { handleRequest } from '../../server/middleware'; +type MiddlewareNext = () => Promise; +type MiddlewareHandler = (ctx: unknown, next: MiddlewareNext) => Promise | Response | Promise | void; + /** * This export is used by our integration to automatically add the middleware * to astro ^3.5.0 projects. @@ -10,6 +12,13 @@ import { handleRequest } from '../../server/middleware'; * middleware registration in our integration and manually add it in their own * `/src/middleware.js` file. */ -export const onRequest: MiddlewareResponseHandler = (ctx, next) => { - return handleRequest()(ctx, next); +export const onRequest: MiddlewareHandler = (ctx, next) => { + const middleware = handleRequest(); + + // `onRequest` deliberately uses framework-agnostic parameter types so the published + // `@sentry/astro/middleware` declaration does not reference Astro-version-specific types + // (e.g. `MiddlewareResponseHandler`, which is absent in some supported Astro versions). + // The handler returned by `handleRequest()` is typed against Astro's own types, so we cast + // back to its expected parameter types here – the runtime shapes are identical. + return middleware(ctx as Parameters[0], next as Parameters[1]); }; diff --git a/packages/astro/test/integration/middleware/index.test-d.ts b/packages/astro/test/integration/middleware/index.test-d.ts new file mode 100644 index 000000000000..5f482f98746e --- /dev/null +++ b/packages/astro/test/integration/middleware/index.test-d.ts @@ -0,0 +1,18 @@ +import { describe, expectTypeOf, it } from 'vitest'; +import { onRequest } from '../../../src/integration/middleware'; + +describe('Integration middleware types', () => { + // Regression test for #21413: the published `@sentry/astro/middleware` declaration must stay + // framework-agnostic. Typing `onRequest` against Astro-version-specific aliases (such as + // `MiddlewareResponseHandler`) made the public type depend on an export that is absent in some + // supported Astro versions. The assertions below fail on that previous typing and pass with the fix. + it('exposes onRequest as a framework-agnostic middleware handler', () => { + expectTypeOf(onRequest).toBeFunction(); + expectTypeOf(onRequest).parameters.toEqualTypeOf<[unknown, () => Promise]>(); + expectTypeOf(onRequest).returns.toEqualTypeOf | Response | Promise | void>(); + }); + + it('is callable with a minimal context and a zero-argument next', () => { + expectTypeOf(onRequest).toBeCallableWith({}, () => Promise.resolve(new Response())); + }); +}); diff --git a/packages/astro/test/integration/middleware/index.test.ts b/packages/astro/test/integration/middleware/index.test.ts index 2a63a66027e8..1ce7b8d8e9b9 100644 --- a/packages/astro/test/integration/middleware/index.test.ts +++ b/packages/astro/test/integration/middleware/index.test.ts @@ -24,7 +24,7 @@ describe('Integration middleware', () => { id: '123', }, }; - // @ts-expect-error - a partial ctx object is fine here + // `onRequest` accepts a framework-agnostic `ctx`, so a partial Astro context is fine here. const res = await onRequest(ctx, next); expect(res).toBeDefined();