Skip to content

fix(nextjs): Make NextApiHandler type version-agnostic #5737

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 14, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions packages/nextjs/src/utils/withSentry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,26 @@ import {
stripUrlQueryAndFragment,
} from '@sentry/utils';
import * as domain from 'domain';
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';

// This is the same as the `NextApiHandler` type, except instead of having a return type of `void | Promise<void>`, it's
// only `Promise<void>`, because wrapped handlers are always async
export type WrappedNextApiHandler = (req: NextApiRequest, res: NextApiResponse) => Promise<void>;
import { NextApiRequest, NextApiResponse } from 'next';

// These are the same as the official `NextApiHandler` type, except
//
// a) The wrapped version returns only promises, because wrapped handlers are always async.
//
// b) Instead of having a return types based on `void` (Next < 12.1.6) or `unknown` (Next 12.1.6+), both the wrapped and
// unwrapped versions of the type have both. This doesn't matter to users, because they exist solely on one side of that
// version divide or the other. For us, though, it's entirely possible to have one version of Next installed in our
// local repo (as a dev dependency) and have another Next version installed in a test app which also has the local SDK
// linked in.
//
// In that case, if those two versions are on either side of the 12.1.6 divide, importing the official `NextApiHandler`
// type here would break the test app's build, because it would set up a situation in which the linked SDK's
// `withSentry` would refer to one version of the type (from the local repo's `node_modules`) while any typed handler in
// the test app would refer to the other version of the type (from the test app's `node_modules`). By using a custom
// version of the type compatible with both the old and new official versions, we can use any Next version we want in
// a test app without worrying about type errors.
type NextApiHandler = (req: NextApiRequest, res: NextApiResponse) => void | Promise<void> | unknown | Promise<unknown>;
export type WrappedNextApiHandler = (req: NextApiRequest, res: NextApiResponse) => Promise<void> | Promise<unknown>;

export type AugmentedNextApiResponse = NextApiResponse & {
__sentryTransaction?: Transaction;
Expand Down