ronantakizawa/codereview-bench huggingface dataset:
Repository: trpc/trpc
File: packages/server/src/adapters/content-handlers/selectContentHandlerOrUnsupportedMediaType.ts (TypeScript)

Code before:
import { TRPCError } from '../../@trpc/server';
import type {
  BaseContentTypeHandler,
  HTTPHeaders,
} from '../../@trpc/server/http';

interface MinimalHandlerOpts {
  req: {
    headers: HTTPHeaders | Headers;
  };
}

export function selectContentHandlerOrUnsupportedMediaType<
  THandlerOpts extends MinimalHandlerOpts,
  THandler extends BaseContentTypeHandler<THandlerOpts>,
>(handlers: THandler[], opts: THandlerOpts) {
  const contentType = new Headers(opts.req.headers as HeadersInit).get(
    'content-type',
  );

  const error = new TRPCError({
    code: 'UNSUPPORTED_MEDIA_TYPE',
    message: `Invalid Content-Type header '${contentType}'. This request may not be supported by your tRPC Adapter, or possibly by tRPC at all`,
  });

  if (typeof contentType !== 'string') {
    return [undefined, error] as const;
  }

  const handler = handlers.find((handler) => handler.isMatch(contentType));
  if (!handler) {
    return [undefined, error] as const;
  }

  return [handler] as const;
}

Review comment (refactor):
This could probably only take `Headers` and do the conversion higher up, but that's a bigger refactor for another day

Code after:
import { TRPCError } from '../../@trpc/server';
import type {
  BaseContentTypeHandler,
  HTTPHeaders,
} from '../../@trpc/server/http';

interface MinimalHandlerOpts {
  req: {
    // TODO: This could probably only take Headers and do the conversion higher up,
    //       but that's a bigger refactor for another day
    headers: HTTPHeaders | Headers;
  };
}

export function selectContentHandlerOrUnsupportedMediaType<
  THandlerOpts extends MinimalHandlerOpts,
  THandler extends BaseContentTypeHandler<THandlerOpts>,
>(handlers: THandler[], opts: THandlerOpts) {
  const headers = new Headers(opts.req.headers as HeadersInit);
  const contentType = headers.get('content-type');

  if (contentType === null) {
    return [
      undefined,
      new TRPCError({
        code: 'UNSUPPORTED_MEDIA_TYPE',
        message:
          'No Content-Type header detected on the incoming request. This request may not be supported by your tRPC Adapter, or possibly by tRPC at all',
      }),
    ] as const;
  }

  const handler = handlers.find((handler) => handler.isMatch(headers));
  if (!handler) {
    return [
      undefined,
Repository: trpc/trpc
File: packages/server/src/adapters/content-handlers/selectContentHandlerOrUnsupportedMediaType.ts (TypeScript)

Code before:
import { TRPCError } from '../../@trpc/server';
import type {
  BaseContentTypeHandler,
  HTTPHeaders,
} from '../../@trpc/server/http';

interface MinimalHandlerOpts {
  req: {
    headers: HTTPHeaders | Headers;
  };
}

export function selectContentHandlerOrUnsupportedMediaType<
  THandlerOpts extends MinimalHandlerOpts,
  THandler extends BaseContentTypeHandler<THandlerOpts>,
>(handlers: THandler[], opts: THandlerOpts) {
  const contentType = new Headers(opts.req.headers as HeadersInit).get(
    'content-type',
  );

  const error = new TRPCError({
    code: 'UNSUPPORTED_MEDIA_TYPE',
    message: `Invalid Content-Type header '${contentType}'. This request may not be supported by your tRPC Adapter, or possibly by tRPC at all`,
  });

  if (typeof contentType !== 'string') {
    return [undefined, error] as const;
  }

  const handler = handlers.find((handler) => handler.isMatch(contentType));
  if (!handler) {
    return [undefined, error] as const;
  }

  return [handler] as const;
}


Review comment (suggestion):
this cast is fine, idk why it complains that you can't pass a `Record<string, string[]>` in ther...

![CleanShot 2024-04-21 at 11 02 14@2x](https://github.com/trpc/trpc/assets/51714798/2f16a832-aee6-4f47-a8f5-c3f13dd196ab)


Code after:
import { TRPCError } from '../../@trpc/server';
import type {
  BaseContentTypeHandler,
  HTTPHeaders,
} from '../../@trpc/server/http';

interface MinimalHandlerOpts {
  req: {
    // TODO: This could probably only take Headers and do the conversion higher up,
    //       but that's a bigger refactor for another day
    headers: HTTPHeaders | Headers;
  };
}

export function selectContentHandlerOrUnsupportedMediaType<
  THandlerOpts extends MinimalHandlerOpts,
  THandler extends BaseContentTypeHandler<THandlerOpts>,
>(handlers: THandler[], opts: THandlerOpts) {
  const headers = new Headers(opts.req.headers as HeadersInit);
  const contentType = headers.get('content-type');

  if (contentType === null) {
    return [
      undefined,
      new TRPCError({
        code: 'UNSUPPORTED_MEDIA_TYPE',
        message:
          'No Content-Type header detected on the incoming request. This request may not be supported by your tRPC Adapter, or possibly by tRPC at all',
      }),
    ] as const;
  }

  const handler = handlers.find((handler) => handler.isMatch(headers));
  if (!handler) {
    return [
      undefined,
      new TRPCError({
        code: 'UNSUPPORTED_MEDIA_TYPE',
        message: `Invalid Content-Type header '${contentType}'. This request may not be supported by your tRPC Adapter, or possibly by tRPC at all`,
      }),
    ] as const;
  }
Repository: trpc/trpc
File: packages/server/src/adapters/content-handlers/selectContentHandlerOrUnsupportedMediaType.ts (TypeScript)

Code before:
import { TRPCError } from '../../@trpc/server';
import type {
  BaseContentTypeHandler,
  HTTPHeaders,
} from '../../@trpc/server/http';

interface MinimalHandlerOpts {
  req: {
    headers: HTTPHeaders | Headers;
  };
}

export function selectContentHandlerOrUnsupportedMediaType<
  THandlerOpts extends MinimalHandlerOpts,
  THandler extends BaseContentTypeHandler<THandlerOpts>,
>(handlers: THandler[], opts: THandlerOpts) {
  const contentType = new Headers(opts.req.headers as HeadersInit).get(
    'content-type',
  );

  const error = new TRPCError({
    code: 'UNSUPPORTED_MEDIA_TYPE',
    message: `Invalid Content-Type header '${contentType}'. This request may not be supported by your tRPC Adapter, or possibly by tRPC at all`,
  });

  if (typeof contentType !== 'string') {
    return [undefined, error] as const;
  }

  const handler = handlers.find((handler) => handler.isMatch(contentType));
  if (!handler) {
    return [undefined, error] as const;
  }

  return [handler] as const;
}


Review comment (suggestion):
Maybe we should still only create this when we actually need it? Unnecessary to create it for every request

Code after:
import { TRPCError } from '../../@trpc/server';
import type {
  BaseContentTypeHandler,
  HTTPHeaders,
} from '../../@trpc/server/http';

interface MinimalHandlerOpts {
  req: {
    // TODO: This could probably only take Headers and do the conversion higher up,
    //       but that's a bigger refactor for another day
    headers: HTTPHeaders | Headers;
  };
}

export function selectContentHandlerOrUnsupportedMediaType<
  THandlerOpts extends MinimalHandlerOpts,
  THandler extends BaseContentTypeHandler<THandlerOpts>,
>(handlers: THandler[], opts: THandlerOpts) {
  const headers = new Headers(opts.req.headers as HeadersInit);
  const contentType = headers.get('content-type');

  if (contentType === null) {
    return [
      undefined,
      new TRPCError({
        code: 'UNSUPPORTED_MEDIA_TYPE',
        message:
          'No Content-Type header detected on the incoming request. This request may not be supported by your tRPC Adapter, or possibly by tRPC at all',
      }),
    ] as const;
  }

  const handler = handlers.find((handler) => handler.isMatch(headers));
  if (!handler) {
    return [
      undefined,
      new TRPCError({
        code: 'UNSUPPORTED_MEDIA_TYPE',
        message: `Invalid Content-Type header '${contentType}'. This request may not be supported by your tRPC Adapter, or possibly by tRPC at all`,
      }),
    ] as const;
  }

  return [handler] as const;
}
Repository: trpc/trpc
File: packages/server/src/unstable-core-do-not-import/http/types.ts (TypeScript)

Code before:
   * Add handler to be called before response is sent to the user
   * Useful for setting cache headers
   * @link https://trpc.io/docs/v11/caching
   */
  responseMeta?: ResponseMetaFn<TRouter>;
}

/** @internal */
export type ProcedureCall = {
  path: string;
};

/**
 * Information about the incoming request
 * @internal
 */
export type TRPCRequestInfo = {
  isBatchCall: boolean;
  calls: {
    path: string;
    /**
     * Read the raw input (deduped and memoized)
     */
    getRawInput: () => Promise<unknown>;
    /**
     * Get already parsed inputs - won't trigger reading the body or parsing the inputs
     */
    result: () => unknown;
  }[];
};

/**
 * Inner createContext function for `resolveResponse` used to forward `TRPCRequestInfo` to `createContext`
 * @internal
 */
export type ResolveHTTPRequestOptionsContextFn<TRouter extends AnyRouter> =
  (opts: { info: TRPCRequestInfo }) => Promise<inferRouterContext<TRouter>>;

interface HTTPErrorHandlerOptions<TRouter extends AnyRouter, TRequest>
  extends ErrorHandlerOptions<inferRouterContext<TRouter>> {
  req: TRequest;
}
/**
 * @internal
 */
export type HTTPErrorHandler<TRouter extends AnyRouter, TRequest> = (
  opts: HTTPErrorHandlerOptions<TRouter, TRequest>,
) => void;

/**
 * Base interface for any response handler

Review comment (suggestion):
```suggestion
     * Get already parsed input for the procedure - won't trigger reading the body or parsing the inputs
```

Code after:
   * Add handler to be called before response is sent to the user
   * Useful for setting cache headers
   * @link https://trpc.io/docs/v11/caching
   */
  responseMeta?: ResponseMetaFn<TRouter>;
}

interface TRPCRequestInfoProcedureCall {
  path: string;
  /**
   * Read the raw input (deduped and memoized)
   */
  getRawInput: () => Promise<unknown>;
  /**
   * Get already parsed inputs - won't trigger reading the body or parsing the inputs
   */
  result: () => unknown;
}

/**
 * Information about the incoming request
 * @public
 */
export interface TRPCRequestInfo {
  isBatchCall: boolean;
  calls: TRPCRequestInfoProcedureCall[];
}

/**
 * Inner createContext function for `resolveResponse` used to forward `TRPCRequestInfo` to `createContext`
 * @internal
 */
export type ResolveHTTPRequestOptionsContextFn<TRouter extends AnyRouter> =
  (opts: { info: TRPCRequestInfo }) => Promise<inferRouterContext<TRouter>>;

interface HTTPErrorHandlerOptions<TRouter extends AnyRouter, TRequest>
  extends ErrorHandlerOptions<inferRouterContext<TRouter>> {
  req: TRequest;
}
/**
 * @internal
 */
export type HTTPErrorHandler<TRouter extends AnyRouter, TRequest> = (
  opts: HTTPErrorHandlerOptions<TRouter, TRequest>,
) => void;

/**
 * Base interface for any response handler
 * @internal
 */
export interface BaseHandlerOptions<TRouter extends AnyRouter, TRequest> {
Repository: trpc/trpc
File: packages/tests/server/websockets.test.ts (TypeScript)

Code before:
    await ctx.close();
  });
});

describe('keep alive', () => {
  const keepAliveConfig = {
    pingMs: 2000,
    pongWaitMs: 5000,
  };
  test('pong is received', async () => {
    const ctx = factory({
      wssServer: {
        keepAlive: {
          enabled: true,
          ...keepAliveConfig,
        },
      },
    });
    const pongMock = vi.fn();
    const { wsClient, wss } = ctx;
    wss.on('connection', (ws) => {
      ws.on('pong', pongMock);
    });
    {
      expect(wsClient.connection).not.toBe(null);
      await waitMs(3500);
      await waitFor(() => {
        expect(pongMock).toHaveBeenCalled();
      });
    }
    await ctx.close();
  });
  test('no pong is received', async () => {
    const ctx = factory({
      wssServer: {
        keepAlive: {
          enabled: false,
          ...keepAliveConfig,
        },
      },
    });
    const pongMock = vi.fn();
    const { wsClient, wss } = ctx;
    wss.on('connection', (ws) => {
      ws.on('pong', pongMock);
    });
    {
      expect(wsClient.connection).not.toBe(null);
      await waitMs(3500);
      await waitFor(() => {
        expect(pongMock).not.toHaveBeenCalled();

Review comment (suggestion):
Please use [`useFakeTimers`](https://vitest.dev/guide/mocking.html#example) instead of real waiting so the test is snappy

Code after:
    await ctx.close();
  });
});

describe('keep alive', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });
  afterEach(() => {
    vi.useRealTimers();
  });
  function attachPongMock(wss: WebSocket.Server, pongMock: () => void) {
    return new Promise((resolve) => {
      wss.on('connection', (ws) => {
        ws.on('pong', pongMock);
        resolve(null);
      });
    });
  }
  test('pong message should be received', async () => {
    const pingMs = 2000;
    const pongWaitMs = 5000;
    const ctx = factory({
      wssServer: {
        keepAlive: {
          enabled: true,
          pingMs,
          pongWaitMs,
        },
      },
    });
    const pongMock = vi.fn();
    const { wsClient, wss } = ctx;
    await attachPongMock(wss, pongMock);
    {
      await vi.advanceTimersByTimeAsync(pingMs + pongWaitMs + 100);
      expect(wsClient.connection).not.toBe(null);
      expect(pongMock).toHaveBeenCalled();
    }
    await ctx.close();
  });
  test('no pong message should be received', async () => {
    const ctx = factory({});
    const pongMock = vi.fn();
    const { wsClient, wss } = ctx;
    await attachPongMock(wss, pongMock);
    {
      await vi.advanceTimersByTimeAsync(60000);
      expect(wsClient.connection).not.toBe(null);
      expect(pongMock).not.toHaveBeenCalled();
    }
Repository: trpc/trpc
File: packages/server/src/adapters/node-http/incomingMessageToRequest.ts (TypeScript)

Code before:
  req: IncomingMessageWithBody,
  opts: { maxBodySize: number | null },
) {
  type Value = Buffer | Uint8Array | string | null;
  let size = 0;
  const maxBodySize = opts.maxBodySize;
  let hasClosed = false;

  const stream = new ReadableStream<Value>({
    start(controller) {
      req.on('data', (chunk) => {
        size += chunk.length;
        if (maxBodySize != null && size > maxBodySize) {
          controller.error(
            new TRPCError({
              code: 'PAYLOAD_TOO_LARGE',
            }),
          );
          // an error is thrown if we try to close the controller after
          // erroring, so track the closure
          hasClosed = true;
          return;
        }
        controller.enqueue(chunk);
      });
      req.on('end', () => {
        if (hasClosed) {
          return;
        }
        hasClosed = true;
        controller.close();
      });
    },
    cancel() {
      req.destroy();
    },
  });

  return stream;
}

const bodyMethods = ['POST', 'PUT', 'PATCH'];
/**
 * Convert an [`IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage) to a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
 */
export function incomingMessageToRequest(
  req: http.IncomingMessage,
  opts: {
    /**
     * Max body size in bytes. If the body is larger than this, the request will be aborted
     */

Review comment (suggestion):
it doesn't really matter but this is tidier
```suggestion
      req.once('end', () => {
```

Code after:
  req: IncomingMessageWithBody,
  opts: { maxBodySize: number | null },
) {
  type Value = Buffer | Uint8Array | string | null;
  let size = 0;
  const maxBodySize = opts.maxBodySize;
  let hasClosed = false;

  const stream = new ReadableStream<Value>({
    start(controller) {
      req.on('data', (chunk) => {
        size += chunk.length;
        if (maxBodySize != null && size > maxBodySize) {
          controller.error(
            new TRPCError({
              code: 'PAYLOAD_TOO_LARGE',
            }),
          );
          // an error is thrown if we try to close the controller after
          // erroring, so track the closure
          hasClosed = true;
          return;
        }
        controller.enqueue(chunk);
      });
      req.once('end', () => {
        if (hasClosed) {
          return;
        }
        hasClosed = true;
        controller.close();
      });
    },
    cancel() {
      req.destroy();
    },
  });

  return stream;
}

const bodyMethods = ['POST', 'PUT', 'PATCH'];
/**
 * Convert an [`IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage) to a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
 */
export function incomingMessageToRequest(
  req: http.IncomingMessage,
  opts: {
    /**
     * Max body size in bytes. If the body is larger than this, the request will be aborted
     */
Repository: trpc/trpc
File: packages/react-query/src/shared/hooks/createHooksInternal.tsx (TypeScript)

Code before:
                trpc: {
                  ...ssrOpts?.trpc,
                  ...(shouldAbortOnUnmount
                    ? { signal: queryFunctionContext.signal }
                    : {}),
                },
              };

              const result = await client.query(
                ...getClientArgs(queryKey, actualOpts),
              );

              if (isAsyncIterable(result)) {
                const queryHash = hashKey(queryKey);

                const queryCache = queryClient.getQueryCache();

                const query = queryCache.build(queryClient, {
                  queryKey,
                  queryHash,
                });

                query.setState({
                  data: [],
                  status: 'pending',
                });

                const aggregate: unknown[] = [];
                for await (const value of result) {
                  aggregate.push(value);

                  query.setState({
                    data: [...aggregate],
                  });
                }
                return aggregate;
              }
              return result;
            },
      },
      queryClient,
    ) as UseTRPCQueryResult<unknown, TError>;

    hook.trpc = useHookResult({
      path,
    });

    return hook;
  }

  function useSuspenseQuery(

Review comment (suggestion):
Would love TkDodo's opinion on this. When I was trying to think of this DX I couldn't decide between the possible "is streaming" states
- `status: 'pending', fetchStatus: 'fetching', data: <defined>`
- `status: 'success', fetchStatus: 'fetching', data: <defined>`
- `status: 'success', fetchStatus: 'idle',     data: <defined>`

Code after:
                trpc: {
                  ...ssrOpts?.trpc,
                  ...(shouldAbortOnUnmount
                    ? { signal: queryFunctionContext.signal }
                    : {}),
                },
              };

              const result = await client.query(
                ...getClientArgs(queryKey, actualOpts),
              );

              if (isAsyncIterable(result)) {
                const queryCache = queryClient.getQueryCache();

                const query = queryCache.build(queryFunctionContext.queryKey, {
                  queryKey,
                });

                query.setState({
                  data: [],
                  status: 'success',
                });

                const aggregate: unknown[] = [];
                for await (const value of result) {
                  aggregate.push(value);

                  query.setState({
                    data: [...aggregate],
                  });
                }
                return aggregate;
              }
              return result;
            },
      },
      queryClient,
    ) as UseTRPCQueryResult<unknown, TError>;

    hook.trpc = useHookResult({
      path,
    });

    return hook;
  }

  function useSuspenseQuery(
    path: string[],
    input: unknown,
    opts?: UseTRPCSuspenseQueryOptions<unknown, unknown, TError>,
Repository: trpc/trpc
File: packages/server/src/adapters/next-app-dir/rethrowNextErrors.ts (TypeScript)

Code before:
import * as nextNavigation from 'next/navigation.js';
import type { TRPCError } from '../../@trpc/server';
import { TRPCRedirectError } from './redirect';

/**
 * @remarks The helpers from `next/dist/client/components/*` has been removed in Next.js 15.
 * Inlining them here instead...
 */
const REDIRECT_ERROR_CODE = 'NEXT_REDIRECT';
function isRedirectError(error: unknown) {
  if (
    typeof error !== 'object' ||
    error === null ||
    !('digest' in error) ||
    typeof error.digest !== 'string'
  ) {
    return false;
  }
  const [errorCode, type, destination, status] = error.digest.split(';', 4);
  const statusCode = Number(status);
  return (
    errorCode === REDIRECT_ERROR_CODE &&
    (type === 'replace' || type === 'push') &&
    typeof destination === 'string' &&
    !isNaN(statusCode)
  );

Review comment (suggestion):
without the `.js` we get this error:

![CleanShot 2024-06-01 at 14 35 03@2x](https://github.com/trpc/trpc/assets/51714798/f3509ba1-bfbd-4ac0-8298-77bf89eaa1a9)


Code after:
import * as nextNavigation from 'next/navigation.js';
import type { TRPCError } from '../../@trpc/server';
import { TRPCRedirectError } from './redirect';

/**
 * @remarks The helpers from `next/dist/client/components/*` has been removed in Next.js 15.
 * Inlining them here instead...
 * @see https://github.com/vercel/next.js/blob/5ae286ffd664e5c76841ed64f6e2da85a0835922/packages/next/src/client/components/redirect.ts#L97-L123
 */
const REDIRECT_ERROR_CODE = 'NEXT_REDIRECT';
function isRedirectError(error: unknown) {
  if (
    typeof error !== 'object' ||
    error === null ||
    !('digest' in error) ||
    typeof error.digest !== 'string'
  ) {
    return false;
  }
  const [errorCode, type, destination, status] = error.digest.split(';', 4);
  const statusCode = Number(status);
  return (
    errorCode === REDIRECT_ERROR_CODE &&
    (type === 'replace' || type === 'push') &&
    typeof destination === 'string' &&
    !isNaN(statusCode)