Repository: trpc/trpc
File: packages/server/src/adapters/next-app-dir/nextAppDirCaller.ts (TypeScript)

Code before:
// FIXME: fix lint rule, this is ok
// eslint-disable-next-line no-restricted-imports
import type { ErrorHandlerOptions } from '../../unstable-core-do-not-import/procedure';
// FIXME: fix lint rule, this is ok
// eslint-disable-next-line no-restricted-imports
import type { CallerOverride } from '../../unstable-core-do-not-import/procedureBuilder';
// FIXME: fix lint rule, this is ok
// eslint-disable-next-line no-restricted-imports
import type {
  MaybePromise,
  Simplify,
} from '../../unstable-core-do-not-import/types';
import { formDataToObject } from './formDataToObject';
import { TRPCRedirectError } from './redirect';
import { rethrowNextErrors } from './rethrowNextErrors';

/**
 * Create a caller that works with Next.js React Server Components & Server Actions
 */
export function nextAppDirCaller<TContext, TMeta>(
  config: Simplify<
    {
      /**
       * Extract the path from the procedure metadata
       */
      pathExtractor?: (meta: TMeta) => string;
      /**
       * Transform form data to a `Record` before passing it to the procedure
       * @default true
       */
      normalizeFormData?: boolean;
      /**
       * Called when an error occurs in the handler
       */
      onError?: (opts: ErrorHandlerOptions<TContext>) => void;
    } & CreateContextCallback<TContext, () => MaybePromise<TContext>>
  >,
): CallerOverride<TContext> {
  const {
    normalizeFormData = true,

    // rethrowNextErrors = true
  } = config;
  const createContext = async (): Promise<TContext> => {
    return config?.createContext?.() ?? ({} as TContext);
  };
  return async (opts) => {
    const path = config.pathExtractor?.(opts._def.meta as TMeta) ?? '';
    const ctx: TContext = await createContext().catch((cause) => {
      const error = new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',

Review comment (refactor):
options object allow addition of more things in the future without breaking the API
```suggestion
      pathExtractor?: (opts: { meta: TMeta }) => string;
```

Code after:
// FIXME: fix lint rule, this is ok
// eslint-disable-next-line no-restricted-imports
import type { ErrorHandlerOptions } from '../../unstable-core-do-not-import/procedure';
// FIXME: fix lint rule, this is ok
// eslint-disable-next-line no-restricted-imports
import type { CallerOverride } from '../../unstable-core-do-not-import/procedureBuilder';
// FIXME: fix lint rule, this is ok
// eslint-disable-next-line no-restricted-imports
import type {
  MaybePromise,
  Simplify,
} from '../../unstable-core-do-not-import/types';
import { formDataToObject } from './formDataToObject';
import { TRPCRedirectError } from './redirect';
import { rethrowNextErrors } from './rethrowNextErrors';

/**
 * Create a caller that works with Next.js React Server Components & Server Actions
 */
export function nextAppDirCaller<TContext, TMeta>(
  config: Simplify<
    {
      /**
       * Extract the path from the procedure metadata
       */
      pathExtractor?: (opts: { meta: TMeta }) => string;
      /**
       * Transform form data to a `Record` before passing it to the procedure
       * @default true
       */
      normalizeFormData?: boolean;
      /**
       * Called when an error occurs in the handler
       */
      onError?: (opts: ErrorHandlerOptions<TContext>) => void;
    } & CreateContextCallback<TContext, () => MaybePromise<TContext>>
  >,
): CallerOverride<TContext> {
  const {
    normalizeFormData = true,

    // rethrowNextErrors = true
  } = config;
  const createContext = async (): Promise<TContext> => {
    return config?.createContext?.() ?? ({} as TContext);
  };
  return async (opts) => {
    const path =
      config.pathExtractor?.({ meta: opts._def.meta as TMeta }) ?? '';
    const ctx: TContext = await createContext().catch((cause) => {
      const error = new TRPCError({