@trpc/next 11.22.1 → 11.22.2-canary.11.4427f0bea

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -36,14 +36,6 @@ pnpm add @trpc/next @trpc/react-query @tanstack/react-query
36
36
  bun add @trpc/next @trpc/react-query @tanstack/react-query
37
37
  ```
38
38
 
39
- ## AI Agents
40
-
41
- If you use an AI coding agent, install tRPC skills for better code generation:
42
-
43
- ```bash
44
- npx @tanstack/intent@latest install
45
- ```
46
-
47
39
  ## Basic Example
48
40
 
49
41
  Setup tRPC in `utils/trpc.ts`.
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { a as WithTRPCSSROptions, i as WithTRPCNoSSROptions, n as TRPCPrepassProps, o as withTRPC, r as WithTRPCConfig, t as TRPCPrepassHelper } from "./withTRPC-DywCxFfq.cjs";
1
+ import { a as WithTRPCSSROptions, i as WithTRPCNoSSROptions, n as TRPCPrepassProps, o as withTRPC, r as WithTRPCConfig, t as TRPCPrepassHelper } from "./withTRPC-Cr10aYRv.cjs";
2
2
  import { AnyRouter, ProtectedIntersection } from "@trpc/server/unstable-core-do-not-import";
3
3
  import { CreateReactUtils, DecorateRouterRecord, TRPCUseQueries, TRPCUseSuspenseQueries } from "@trpc/react-query/shared";
4
- import { NextPageContext } from "next/types";
4
+ import { NextPageContext } from "next/types.js";
5
5
  //#region src/createTRPCNext.d.ts
6
6
  /**
7
7
  * @internal
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { a as WithTRPCSSROptions, i as WithTRPCNoSSROptions, n as TRPCPrepassProps, o as withTRPC, r as WithTRPCConfig, t as TRPCPrepassHelper } from "./withTRPC-BchtyodQ.mjs";
1
+ import { a as WithTRPCSSROptions, i as WithTRPCNoSSROptions, n as TRPCPrepassProps, o as withTRPC, r as WithTRPCConfig, t as TRPCPrepassHelper } from "./withTRPC-CxGgngCY.mjs";
2
2
  import { CreateReactUtils, DecorateRouterRecord, TRPCUseQueries, TRPCUseSuspenseQueries } from "@trpc/react-query/shared";
3
3
  import { AnyRouter, ProtectedIntersection } from "@trpc/server/unstable-core-do-not-import";
4
- import { NextPageContext } from "next/types";
4
+ import { NextPageContext } from "next/types.js";
5
5
  //#region src/createTRPCNext.d.ts
6
6
  /**
7
7
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/withTRPC.tsx","../src/createTRPCNext.tsx"],"sourcesContent":["/**\n * Heavily based on urql's ssr\n * https://github.com/FormidableLabs/urql/blob/main/packages/next-urql/src/with-urql-client.ts\n */\nimport type { DehydratedState, QueryClient } from '@tanstack/react-query';\nimport { HydrationBoundary, QueryClientProvider } from '@tanstack/react-query';\nimport type {\n CreateTRPCClientOptions,\n TRPCClient,\n TRPCClientError,\n TRPCUntypedClient,\n} from '@trpc/client';\nimport type { CoercedTransformerParameters } from '@trpc/client/unstable-internals';\nimport {\n getTransformer,\n type TransformerOptions,\n} from '@trpc/client/unstable-internals';\nimport type {\n CreateTRPCReactOptions,\n CreateTRPCReactQueryClientConfig,\n} from '@trpc/react-query/shared';\nimport { createRootHooks, getQueryClient } from '@trpc/react-query/shared';\nimport type {\n AnyRouter,\n Dict,\n inferClientTypes,\n ResponseMeta,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type {\n AppContextType,\n AppPropsType,\n NextComponentType,\n NextPageContext,\n} from 'next/dist/shared/lib/utils';\nimport type { NextRouter } from 'next/router';\nimport React, { useState } from 'react';\n\nexport type WithTRPCConfig<TRouter extends AnyRouter> =\n CreateTRPCClientOptions<TRouter> &\n CreateTRPCReactQueryClientConfig & {\n abortOnUnmount?: boolean;\n };\n\ntype WithTRPCOptions<TRouter extends AnyRouter> =\n CreateTRPCReactOptions<TRouter> & {\n config: (info: { ctx?: NextPageContext }) => WithTRPCConfig<TRouter>;\n } & TransformerOptions<inferClientTypes<TRouter>>;\n\nexport type TRPCPrepassHelper = (opts: {\n parent: WithTRPCSSROptions<AnyRouter>;\n WithTRPC: NextComponentType<any, any, any>;\n AppOrPage: NextComponentType<any, any, any>;\n}) => void;\nexport type WithTRPCSSROptions<TRouter extends AnyRouter> =\n WithTRPCOptions<TRouter> & {\n /**\n * If you enable this, you also need to add a `ssrPrepass`-prop\n * @see https://trpc.io/docs/client/nextjs/ssr\n */\n ssr:\n true | ((opts: { ctx: NextPageContext }) => boolean | Promise<boolean>);\n responseMeta?: (opts: {\n ctx: NextPageContext;\n clientErrors: TRPCClientError<TRouter>[];\n }) => ResponseMeta;\n /**\n * use `import { ssrPrepass } from '@trpc/next/ssrPrepass'`\n * @see https://trpc.io/docs/client/nextjs/ssr\n */\n ssrPrepass: TRPCPrepassHelper;\n };\n\nexport type WithTRPCNoSSROptions<TRouter extends AnyRouter> =\n WithTRPCOptions<TRouter> & {\n ssr?: false;\n };\n\nexport type TRPCPrepassProps<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext = NextPageContext,\n> = {\n config: WithTRPCConfig<TRouter>;\n queryClient: QueryClient;\n trpcClient: TRPCUntypedClient<TRouter> | TRPCClient<TRouter>;\n ssrState: 'prepass';\n ssrContext: TSSRContext;\n};\n\nexport function withTRPC<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext = NextPageContext,\n>(opts: WithTRPCNoSSROptions<TRouter> | WithTRPCSSROptions<TRouter>) {\n const { config: getClientConfig } = opts;\n const transformer = getTransformer(\n (opts as CoercedTransformerParameters).transformer,\n );\n\n type $PrepassProps = TRPCPrepassProps<TRouter, TSSRContext>;\n return (AppOrPage: NextComponentType<any, any, any>): NextComponentType => {\n const trpc = createRootHooks<TRouter, TSSRContext>(opts);\n\n const WithTRPC = (\n props: AppPropsType<NextRouter, any> & {\n trpc?: $PrepassProps;\n },\n ) => {\n const [prepassProps] = useState(() => {\n if (props.trpc) {\n return props.trpc;\n }\n\n const config = getClientConfig({});\n const queryClient = getQueryClient(config);\n const trpcClient = trpc.createClient(config);\n\n return {\n abortOnUnmount: config.abortOnUnmount,\n queryClient,\n trpcClient,\n ssrState: opts.ssr ? ('mounting' as const) : (false as const),\n ssrContext: null,\n };\n });\n\n const { queryClient, trpcClient, ssrState, ssrContext } = prepassProps;\n\n // allow normal components to be wrapped, not just app/pages\n const trpcState = props.pageProps?.trpcState;\n\n const hydratedState: DehydratedState | undefined = React.useMemo(() => {\n if (!trpcState) {\n return trpcState;\n }\n\n return transformer.input.deserialize(trpcState);\n }, [trpcState]);\n\n return (\n <trpc.Provider\n abortOnUnmount={(prepassProps as any).abortOnUnmount ?? false}\n client={trpcClient}\n queryClient={queryClient}\n ssrState={ssrState}\n ssrContext={ssrContext}\n >\n <QueryClientProvider client={queryClient}>\n <HydrationBoundary state={hydratedState}>\n <AppOrPage {...props} />\n </HydrationBoundary>\n </QueryClientProvider>\n </trpc.Provider>\n );\n };\n\n if (opts.ssr) {\n opts.ssrPrepass({\n parent: opts,\n AppOrPage,\n WithTRPC,\n });\n } else if (AppOrPage.getInitialProps) {\n // Allow combining `getServerSideProps` and `getInitialProps`\n\n WithTRPC.getInitialProps = async (appOrPageCtx: AppContextType) => {\n // Determine if we are wrapping an App component or a Page component.\n const isApp = !!appOrPageCtx.Component;\n\n // Run the wrapped component's getInitialProps function.\n let pageProps: Dict<unknown> = {};\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const originalProps = await AppOrPage.getInitialProps!(\n appOrPageCtx as any,\n );\n const originalPageProps = isApp\n ? (originalProps.pageProps ?? {})\n : originalProps;\n\n pageProps = {\n ...originalPageProps,\n ...pageProps,\n };\n const getAppTreeProps = (props: Dict<unknown>) =>\n isApp ? { pageProps: props } : props;\n\n return getAppTreeProps(pageProps);\n };\n }\n\n const displayName = AppOrPage.displayName ?? AppOrPage.name ?? 'Component';\n WithTRPC.displayName = `withTRPC(${displayName})`;\n\n return WithTRPC as any;\n };\n}\n","/* istanbul ignore file -- @preserve */\n// We're testing this through E2E-testing\nimport type {\n CreateReactUtils,\n DecorateRouterRecord,\n TRPCUseQueries,\n TRPCUseSuspenseQueries,\n} from '@trpc/react-query/shared';\nimport {\n createReactDecoration,\n createReactQueryUtils,\n createRootHooks,\n} from '@trpc/react-query/shared';\nimport type {\n AnyRouter,\n ProtectedIntersection,\n} from '@trpc/server/unstable-core-do-not-import';\nimport { createFlatProxy } from '@trpc/server/unstable-core-do-not-import';\nimport type { NextPageContext } from 'next/types';\nimport { useMemo } from 'react';\nimport type { WithTRPCNoSSROptions, WithTRPCSSROptions } from './withTRPC';\nimport { withTRPC } from './withTRPC';\n\n/**\n * @internal\n */\nexport interface CreateTRPCNextBase<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext,\n> {\n /**\n * @deprecated renamed to `useUtils` and will be removed in a future tRPC version\n *\n * @see https://trpc.io/docs/v11/client/react/useUtils\n */\n useContext(): CreateReactUtils<TRouter, TSSRContext>;\n /**\n * @see https://trpc.io/docs/v11/client/react/useUtils\n */\n useUtils(): CreateReactUtils<TRouter, TSSRContext>;\n withTRPC: ReturnType<typeof withTRPC<TRouter, TSSRContext>>;\n useQueries: TRPCUseQueries<TRouter>;\n useSuspenseQueries: TRPCUseSuspenseQueries<TRouter>;\n}\n\n/**\n * @internal\n */\nexport type CreateTRPCNext<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext,\n> = ProtectedIntersection<\n CreateTRPCNextBase<TRouter, TSSRContext>,\n DecorateRouterRecord<\n TRouter['_def']['_config']['$types'],\n TRouter['_def']['record']\n >\n>;\n\nexport function createTRPCNext<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext = NextPageContext,\n>(\n opts: WithTRPCNoSSROptions<TRouter> | WithTRPCSSROptions<TRouter>,\n): CreateTRPCNext<TRouter, TSSRContext> {\n const hooks = createRootHooks<TRouter, TSSRContext>(opts);\n\n // TODO: maybe set TSSRContext to `never` when using `WithTRPCNoSSROptions`\n const _withTRPC = withTRPC(opts);\n\n const proxy = createReactDecoration(hooks) as DecorateRouterRecord<\n TRouter['_def']['_config']['$types'],\n TRouter['_def']['record']\n >;\n\n return createFlatProxy((key) => {\n if (key === 'useContext' || key === 'useUtils') {\n return () => {\n const context = hooks.useUtils();\n // create a stable reference of the utils context\n return useMemo(() => {\n return (createReactQueryUtils as any)(context);\n }, [context]);\n };\n }\n\n if (key === 'useQueries') {\n return hooks.useQueries;\n }\n\n if (key === 'useSuspenseQueries') {\n return hooks.useSuspenseQueries;\n }\n\n if (key === 'withTRPC') {\n return _withTRPC;\n }\n\n return proxy[key];\n });\n}\n"],"mappings":";;;;;;;AAwFA,SAAgB,SAGd,MAAmE;CACnE,MAAM,EAAE,QAAQ,oBAAoB;CACpC,MAAM,cAAc,eACjB,KAAsC,WACzC;CAGA,QAAQ,cAAmE;;EACzE,MAAM,OAAO,gBAAsC,IAAI;EAEvD,MAAM,YACJ,UAGG;;GACH,MAAM,CAAC,gBAAgB,eAAe;IACpC,IAAI,MAAM,MACR,OAAO,MAAM;IAGf,MAAM,SAAS,gBAAgB,CAAC,CAAC;IACjC,MAAM,cAAc,eAAe,MAAM;IACzC,MAAM,aAAa,KAAK,aAAa,MAAM;IAE3C,OAAO;KACL,gBAAgB,OAAO;KACvB;KACA;KACA,UAAU,KAAK,MAAO,aAAwB;KAC9C,YAAY;IACd;GACF,CAAC;GAED,MAAM,EAAE,aAAa,YAAY,UAAU,eAAe;GAG1D,MAAM,aAAA,mBAAY,MAAM,eAAA,QAAA,qBAAA,KAAA,IAAA,KAAA,IAAA,iBAAW;GAEnC,MAAM,gBAA6C,MAAM,cAAc;IACrE,IAAI,CAAC,WACH,OAAO;IAGT,OAAO,YAAY,MAAM,YAAY,SAAS;GAChD,GAAG,CAAC,SAAS,CAAC;GAEd,OACE,sBAAA,cAAC,KAAK,UAAN;IACE,iBAAA,kBAAiB,aAAqB,oBAAA,QAAA,oBAAA,KAAA,IAAA,kBAAkB;IACxD,QAAQ;IACK;IACH;IACE;GAOC,GALb,sBAAA,cAAC,qBAAD,EAAqB,QAAQ,YAIR,GAHnB,sBAAA,cAAC,mBAAD,EAAmB,OAAO,cAEP,GADjB,sBAAA,cAAC,WAAc,KAAQ,CACN,CACA,CACR;EAEnB;EAEA,IAAI,KAAK,KACP,KAAK,WAAW;GACd,QAAQ;GACR;GACA;EACF,CAAC;OACI,IAAI,UAAU,iBAGnB,SAAS,kBAAkB,OAAO,iBAAiC;;GAEjE,MAAM,QAAQ,CAAC,CAAC,aAAa;GAG7B,IAAI,YAA2B,CAAC;GAEhC,MAAM,gBAAgB,MAAM,UAAU,gBACpC,YACF;GACA,MAAM,oBAAoB,SAAA,wBACrB,cAAc,eAAA,QAAA,0BAAA,KAAA,IAAA,wBAAa,CAAC,IAC7B;GAEJ,YAAA,eAAA,eAAA,CAAA,GACK,iBAAA,GACA,SACL;GACA,MAAM,mBAAmB,UACvB,QAAQ,EAAE,WAAW,MAAM,IAAI;GAEjC,OAAO,gBAAgB,SAAS;EAClC;EAIF,SAAS,cAAc,aAAA,QAAA,wBADH,UAAU,iBAAA,QAAA,0BAAA,KAAA,IAAA,wBAAe,UAAU,UAAA,QAAA,SAAA,KAAA,IAAA,OAAQ,YAChB;EAE/C,OAAO;CACT;AACF;;;;ACtIA,SAAgB,eAId,MACsC;CACtC,MAAM,QAAQ,gBAAsC,IAAI;CAGxD,MAAM,YAAY,SAAS,IAAI;CAE/B,MAAM,QAAQ,sBAAsB,KAAK;CAKzC,OAAO,iBAAiB,QAAQ;EAC9B,IAAI,QAAQ,gBAAgB,QAAQ,YAClC,aAAa;GACX,MAAM,UAAU,MAAM,SAAS;GAE/B,OAAO,cAAc;IACnB,OAAQ,sBAA8B,OAAO;GAC/C,GAAG,CAAC,OAAO,CAAC;EACd;EAGF,IAAI,QAAQ,cACV,OAAO,MAAM;EAGf,IAAI,QAAQ,sBACV,OAAO,MAAM;EAGf,IAAI,QAAQ,YACV,OAAO;EAGT,OAAO,MAAM;CACf,CAAC;AACH"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/withTRPC.tsx","../src/createTRPCNext.tsx"],"sourcesContent":["/**\n * Heavily based on urql's ssr\n * https://github.com/FormidableLabs/urql/blob/main/packages/next-urql/src/with-urql-client.ts\n */\nimport type { DehydratedState, QueryClient } from '@tanstack/react-query';\nimport { HydrationBoundary, QueryClientProvider } from '@tanstack/react-query';\nimport type {\n CreateTRPCClientOptions,\n TRPCClient,\n TRPCClientError,\n TRPCUntypedClient,\n} from '@trpc/client';\nimport type { CoercedTransformerParameters } from '@trpc/client/unstable-internals';\nimport {\n getTransformer,\n type TransformerOptions,\n} from '@trpc/client/unstable-internals';\nimport type {\n CreateTRPCReactOptions,\n CreateTRPCReactQueryClientConfig,\n} from '@trpc/react-query/shared';\nimport { createRootHooks, getQueryClient } from '@trpc/react-query/shared';\nimport type {\n AnyRouter,\n Dict,\n inferClientTypes,\n ResponseMeta,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type {\n AppContextType,\n AppPropsType,\n NextComponentType,\n NextPageContext,\n} from 'next/dist/shared/lib/utils.js';\nimport type { NextRouter } from 'next/router';\nimport React, { useState } from 'react';\n\nexport type WithTRPCConfig<TRouter extends AnyRouter> =\n CreateTRPCClientOptions<TRouter> &\n CreateTRPCReactQueryClientConfig & {\n abortOnUnmount?: boolean;\n };\n\ntype WithTRPCOptions<TRouter extends AnyRouter> =\n CreateTRPCReactOptions<TRouter> & {\n config: (info: { ctx?: NextPageContext }) => WithTRPCConfig<TRouter>;\n } & TransformerOptions<inferClientTypes<TRouter>>;\n\nexport type TRPCPrepassHelper = (opts: {\n parent: WithTRPCSSROptions<AnyRouter>;\n WithTRPC: NextComponentType<any, any, any>;\n AppOrPage: NextComponentType<any, any, any>;\n}) => void;\nexport type WithTRPCSSROptions<TRouter extends AnyRouter> =\n WithTRPCOptions<TRouter> & {\n /**\n * If you enable this, you also need to add a `ssrPrepass`-prop\n * @see https://trpc.io/docs/client/nextjs/ssr\n */\n ssr:\n true | ((opts: { ctx: NextPageContext }) => boolean | Promise<boolean>);\n responseMeta?: (opts: {\n ctx: NextPageContext;\n clientErrors: TRPCClientError<TRouter>[];\n }) => ResponseMeta;\n /**\n * use `import { ssrPrepass } from '@trpc/next/ssrPrepass'`\n * @see https://trpc.io/docs/client/nextjs/ssr\n */\n ssrPrepass: TRPCPrepassHelper;\n };\n\nexport type WithTRPCNoSSROptions<TRouter extends AnyRouter> =\n WithTRPCOptions<TRouter> & {\n ssr?: false;\n };\n\nexport type TRPCPrepassProps<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext = NextPageContext,\n> = {\n config: WithTRPCConfig<TRouter>;\n queryClient: QueryClient;\n trpcClient: TRPCUntypedClient<TRouter> | TRPCClient<TRouter>;\n ssrState: 'prepass';\n ssrContext: TSSRContext;\n};\n\nexport function withTRPC<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext = NextPageContext,\n>(opts: WithTRPCNoSSROptions<TRouter> | WithTRPCSSROptions<TRouter>) {\n const { config: getClientConfig } = opts;\n const transformer = getTransformer(\n (opts as CoercedTransformerParameters).transformer,\n );\n\n type $PrepassProps = TRPCPrepassProps<TRouter, TSSRContext>;\n return (AppOrPage: NextComponentType<any, any, any>): NextComponentType => {\n const trpc = createRootHooks<TRouter, TSSRContext>(opts);\n\n const WithTRPC = (\n props: AppPropsType<NextRouter, any> & {\n trpc?: $PrepassProps;\n },\n ) => {\n const [prepassProps] = useState(() => {\n if (props.trpc) {\n return props.trpc;\n }\n\n const config = getClientConfig({});\n const queryClient = getQueryClient(config);\n const trpcClient = trpc.createClient(config);\n\n return {\n abortOnUnmount: config.abortOnUnmount,\n queryClient,\n trpcClient,\n ssrState: opts.ssr ? ('mounting' as const) : (false as const),\n ssrContext: null,\n };\n });\n\n const { queryClient, trpcClient, ssrState, ssrContext } = prepassProps;\n\n // allow normal components to be wrapped, not just app/pages\n const trpcState = props.pageProps?.trpcState;\n\n const hydratedState: DehydratedState | undefined = React.useMemo(() => {\n if (!trpcState) {\n return trpcState;\n }\n\n return transformer.input.deserialize(trpcState);\n }, [trpcState]);\n\n return (\n <trpc.Provider\n abortOnUnmount={(prepassProps as any).abortOnUnmount ?? false}\n client={trpcClient}\n queryClient={queryClient}\n ssrState={ssrState}\n ssrContext={ssrContext}\n >\n <QueryClientProvider client={queryClient}>\n <HydrationBoundary state={hydratedState}>\n <AppOrPage {...props} />\n </HydrationBoundary>\n </QueryClientProvider>\n </trpc.Provider>\n );\n };\n\n if (opts.ssr) {\n opts.ssrPrepass({\n parent: opts,\n AppOrPage,\n WithTRPC,\n });\n } else if (AppOrPage.getInitialProps) {\n // Allow combining `getServerSideProps` and `getInitialProps`\n\n WithTRPC.getInitialProps = async (appOrPageCtx: AppContextType) => {\n // Determine if we are wrapping an App component or a Page component.\n const isApp = !!appOrPageCtx.Component;\n\n // Run the wrapped component's getInitialProps function.\n let pageProps: Dict<unknown> = {};\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const originalProps = await AppOrPage.getInitialProps!(\n appOrPageCtx as any,\n );\n const originalPageProps = isApp\n ? (originalProps.pageProps ?? {})\n : originalProps;\n\n pageProps = {\n ...originalPageProps,\n ...pageProps,\n };\n const getAppTreeProps = (props: Dict<unknown>) =>\n isApp ? { pageProps: props } : props;\n\n return getAppTreeProps(pageProps);\n };\n }\n\n const displayName = AppOrPage.displayName ?? AppOrPage.name ?? 'Component';\n WithTRPC.displayName = `withTRPC(${displayName})`;\n\n return WithTRPC as any;\n };\n}\n","/* istanbul ignore file -- @preserve */\n// We're testing this through E2E-testing\nimport type {\n CreateReactUtils,\n DecorateRouterRecord,\n TRPCUseQueries,\n TRPCUseSuspenseQueries,\n} from '@trpc/react-query/shared';\nimport {\n createReactDecoration,\n createReactQueryUtils,\n createRootHooks,\n} from '@trpc/react-query/shared';\nimport type {\n AnyRouter,\n ProtectedIntersection,\n} from '@trpc/server/unstable-core-do-not-import';\nimport { createFlatProxy } from '@trpc/server/unstable-core-do-not-import';\nimport type { NextPageContext } from 'next/types.js';\nimport { useMemo } from 'react';\nimport type { WithTRPCNoSSROptions, WithTRPCSSROptions } from './withTRPC';\nimport { withTRPC } from './withTRPC';\n\n/**\n * @internal\n */\nexport interface CreateTRPCNextBase<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext,\n> {\n /**\n * @deprecated renamed to `useUtils` and will be removed in a future tRPC version\n *\n * @see https://trpc.io/docs/v11/client/react/useUtils\n */\n useContext(): CreateReactUtils<TRouter, TSSRContext>;\n /**\n * @see https://trpc.io/docs/v11/client/react/useUtils\n */\n useUtils(): CreateReactUtils<TRouter, TSSRContext>;\n withTRPC: ReturnType<typeof withTRPC<TRouter, TSSRContext>>;\n useQueries: TRPCUseQueries<TRouter>;\n useSuspenseQueries: TRPCUseSuspenseQueries<TRouter>;\n}\n\n/**\n * @internal\n */\nexport type CreateTRPCNext<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext,\n> = ProtectedIntersection<\n CreateTRPCNextBase<TRouter, TSSRContext>,\n DecorateRouterRecord<\n TRouter['_def']['_config']['$types'],\n TRouter['_def']['record']\n >\n>;\n\nexport function createTRPCNext<\n TRouter extends AnyRouter,\n TSSRContext extends NextPageContext = NextPageContext,\n>(\n opts: WithTRPCNoSSROptions<TRouter> | WithTRPCSSROptions<TRouter>,\n): CreateTRPCNext<TRouter, TSSRContext> {\n const hooks = createRootHooks<TRouter, TSSRContext>(opts);\n\n // TODO: maybe set TSSRContext to `never` when using `WithTRPCNoSSROptions`\n const _withTRPC = withTRPC(opts);\n\n const proxy = createReactDecoration(hooks) as DecorateRouterRecord<\n TRouter['_def']['_config']['$types'],\n TRouter['_def']['record']\n >;\n\n return createFlatProxy((key) => {\n if (key === 'useContext' || key === 'useUtils') {\n return () => {\n const context = hooks.useUtils();\n // create a stable reference of the utils context\n return useMemo(() => {\n return (createReactQueryUtils as any)(context);\n }, [context]);\n };\n }\n\n if (key === 'useQueries') {\n return hooks.useQueries;\n }\n\n if (key === 'useSuspenseQueries') {\n return hooks.useSuspenseQueries;\n }\n\n if (key === 'withTRPC') {\n return _withTRPC;\n }\n\n return proxy[key];\n });\n}\n"],"mappings":";;;;;;;AAwFA,SAAgB,SAGd,MAAmE;CACnE,MAAM,EAAE,QAAQ,oBAAoB;CACpC,MAAM,cAAc,eACjB,KAAsC,WACzC;CAGA,QAAQ,cAAmE;;EACzE,MAAM,OAAO,gBAAsC,IAAI;EAEvD,MAAM,YACJ,UAGG;;GACH,MAAM,CAAC,gBAAgB,eAAe;IACpC,IAAI,MAAM,MACR,OAAO,MAAM;IAGf,MAAM,SAAS,gBAAgB,CAAC,CAAC;IACjC,MAAM,cAAc,eAAe,MAAM;IACzC,MAAM,aAAa,KAAK,aAAa,MAAM;IAE3C,OAAO;KACL,gBAAgB,OAAO;KACvB;KACA;KACA,UAAU,KAAK,MAAO,aAAwB;KAC9C,YAAY;IACd;GACF,CAAC;GAED,MAAM,EAAE,aAAa,YAAY,UAAU,eAAe;GAG1D,MAAM,aAAA,mBAAY,MAAM,eAAA,QAAA,qBAAA,KAAA,IAAA,KAAA,IAAA,iBAAW;GAEnC,MAAM,gBAA6C,MAAM,cAAc;IACrE,IAAI,CAAC,WACH,OAAO;IAGT,OAAO,YAAY,MAAM,YAAY,SAAS;GAChD,GAAG,CAAC,SAAS,CAAC;GAEd,OACE,sBAAA,cAAC,KAAK,UAAN;IACE,iBAAA,kBAAiB,aAAqB,oBAAA,QAAA,oBAAA,KAAA,IAAA,kBAAkB;IACxD,QAAQ;IACK;IACH;IACE;GAOC,GALb,sBAAA,cAAC,qBAAD,EAAqB,QAAQ,YAIR,GAHnB,sBAAA,cAAC,mBAAD,EAAmB,OAAO,cAEP,GADjB,sBAAA,cAAC,WAAc,KAAQ,CACN,CACA,CACR;EAEnB;EAEA,IAAI,KAAK,KACP,KAAK,WAAW;GACd,QAAQ;GACR;GACA;EACF,CAAC;OACI,IAAI,UAAU,iBAGnB,SAAS,kBAAkB,OAAO,iBAAiC;;GAEjE,MAAM,QAAQ,CAAC,CAAC,aAAa;GAG7B,IAAI,YAA2B,CAAC;GAEhC,MAAM,gBAAgB,MAAM,UAAU,gBACpC,YACF;GACA,MAAM,oBAAoB,SAAA,wBACrB,cAAc,eAAA,QAAA,0BAAA,KAAA,IAAA,wBAAa,CAAC,IAC7B;GAEJ,YAAA,eAAA,eAAA,CAAA,GACK,iBAAA,GACA,SACL;GACA,MAAM,mBAAmB,UACvB,QAAQ,EAAE,WAAW,MAAM,IAAI;GAEjC,OAAO,gBAAgB,SAAS;EAClC;EAIF,SAAS,cAAc,aAAA,QAAA,wBADH,UAAU,iBAAA,QAAA,0BAAA,KAAA,IAAA,wBAAe,UAAU,UAAA,QAAA,SAAA,KAAA,IAAA,OAAQ,YAChB;EAE/C,OAAO;CACT;AACF;;;;ACtIA,SAAgB,eAId,MACsC;CACtC,MAAM,QAAQ,gBAAsC,IAAI;CAGxD,MAAM,YAAY,SAAS,IAAI;CAE/B,MAAM,QAAQ,sBAAsB,KAAK;CAKzC,OAAO,iBAAiB,QAAQ;EAC9B,IAAI,QAAQ,gBAAgB,QAAQ,YAClC,aAAa;GACX,MAAM,UAAU,MAAM,SAAS;GAE/B,OAAO,cAAc;IACnB,OAAQ,sBAA8B,OAAO;GAC/C,GAAG,CAAC,OAAO,CAAC;EACd;EAGF,IAAI,QAAQ,cACV,OAAO,MAAM;EAGf,IAAI,QAAQ,sBACV,OAAO,MAAM;EAGf,IAAI,QAAQ,YACV,OAAO;EAGT,OAAO,MAAM;CACf,CAAC;AACH"}
@@ -1,4 +1,4 @@
1
- import { t as TRPCPrepassHelper } from "./withTRPC-DywCxFfq.cjs";
1
+ import { t as TRPCPrepassHelper } from "./withTRPC-Cr10aYRv.cjs";
2
2
  //#region src/ssrPrepass.d.ts
3
3
  export declare const ssrPrepass: TRPCPrepassHelper;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { t as TRPCPrepassHelper } from "./withTRPC-BchtyodQ.mjs";
1
+ import { t as TRPCPrepassHelper } from "./withTRPC-CxGgngCY.mjs";
2
2
  //#region src/ssrPrepass.d.ts
3
3
  export declare const ssrPrepass: TRPCPrepassHelper;
4
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"ssrPrepass.mjs","names":[],"sources":["../src/ssrPrepass.ts"],"sourcesContent":["/**\n * Heavily based on urql's ssr\n * https://github.com/FormidableLabs/urql/blob/main/packages/next-urql/src/with-urql-client.ts\n */\nimport type { DehydratedState } from '@tanstack/react-query';\nimport { dehydrate } from '@tanstack/react-query';\nimport { createTRPCUntypedClient } from '@trpc/client';\nimport type { TRPCClientError, TRPCClientErrorLike } from '@trpc/client';\nimport type { CoercedTransformerParameters } from '@trpc/client/unstable-internals';\nimport { getTransformer } from '@trpc/client/unstable-internals';\nimport { getQueryClient } from '@trpc/react-query/shared';\nimport type {\n AnyRouter,\n Dict,\n Maybe,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type {\n AppContextType,\n NextPageContext,\n} from 'next/dist/shared/lib/utils';\nimport { createElement } from 'react';\nimport type { TRPCPrepassHelper, TRPCPrepassProps } from './withTRPC';\n\nfunction transformQueryOrMutationCacheErrors<\n TState extends\n DehydratedState['mutations'][0] | DehydratedState['queries'][0],\n>(result: TState): TState {\n const error = result.state.error as Maybe<TRPCClientError<any>>;\n if (error instanceof Error && error.name === 'TRPCClientError') {\n const newError: TRPCClientErrorLike<any> = {\n message: error.message,\n data: error.data,\n shape: error.shape,\n };\n return {\n ...result,\n state: {\n ...result.state,\n error: newError,\n },\n };\n }\n return result;\n}\n\nexport const ssrPrepass: TRPCPrepassHelper = (opts) => {\n const { parent, WithTRPC, AppOrPage } = opts;\n type $PrepassProps = TRPCPrepassProps<AnyRouter, any>;\n\n const transformer = getTransformer(\n (parent as CoercedTransformerParameters).transformer,\n );\n WithTRPC.getInitialProps = async (appOrPageCtx: AppContextType) => {\n const shouldSsr = async () => {\n if (typeof window !== 'undefined') {\n return false;\n }\n if (typeof parent.ssr === 'function') {\n try {\n return await parent.ssr({ ctx: appOrPageCtx.ctx });\n } catch {\n return false;\n }\n }\n return parent.ssr;\n };\n const ssrEnabled = await shouldSsr();\n const AppTree = appOrPageCtx.AppTree;\n\n // Determine if we are wrapping an App component or a Page component.\n const isApp = !!appOrPageCtx.Component;\n const ctx: NextPageContext = isApp\n ? appOrPageCtx.ctx\n : (appOrPageCtx as any as NextPageContext);\n\n // Run the wrapped component's getInitialProps function.\n let pageProps: Dict<unknown> = {};\n if (AppOrPage.getInitialProps) {\n const originalProps = await AppOrPage.getInitialProps(\n appOrPageCtx as any,\n );\n const originalPageProps = isApp\n ? (originalProps.pageProps ?? {})\n : originalProps;\n\n pageProps = {\n ...originalPageProps,\n ...pageProps,\n };\n }\n const getAppTreeProps = (props: Record<string, unknown>) =>\n isApp ? { pageProps: props } : props;\n\n if (typeof window !== 'undefined' || !ssrEnabled) {\n return getAppTreeProps(pageProps);\n }\n\n const config = parent.config({ ctx });\n const trpcClient = createTRPCUntypedClient(config);\n const queryClient = getQueryClient(config);\n\n const trpcProp: $PrepassProps = {\n config,\n trpcClient,\n queryClient,\n ssrState: 'prepass',\n ssrContext: ctx,\n };\n const prepassProps = {\n pageProps,\n trpc: trpcProp,\n };\n\n const reactDomServer = await import('react-dom/server');\n\n // Run the prepass step on AppTree. This will run all trpc queries on the server.\n // multiple prepass ensures that we can do batching on the server\n while (true) {\n // render full tree\n reactDomServer.renderToString(createElement(AppTree, prepassProps));\n if (!queryClient.isFetching()) {\n // the render didn't cause the queryClient to fetch anything\n break;\n }\n\n // wait until the query cache has settled it's promises\n await new Promise<void>((resolve) => {\n const unsub = queryClient.getQueryCache().subscribe((event) => {\n if (event?.query.getObserversCount() === 0) {\n resolve();\n unsub();\n }\n });\n });\n }\n const dehydratedCache = dehydrate(queryClient, {\n shouldDehydrateQuery(query) {\n // filter out queries that are marked as trpc: { ssr: false } or are not enabled, but make sure errors are dehydrated\n const isExcludedFromSSr =\n query.state.fetchStatus === 'idle' &&\n query.state.status === 'pending';\n return !isExcludedFromSSr;\n },\n });\n // since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects\n const dehydratedCacheWithErrors = {\n ...dehydratedCache,\n queries: dehydratedCache.queries.map(transformQueryOrMutationCacheErrors),\n mutations: dehydratedCache.mutations.map(\n transformQueryOrMutationCacheErrors,\n ),\n };\n\n // dehydrate query client's state and add it to the props\n pageProps['trpcState'] = transformer.input.serialize(\n dehydratedCacheWithErrors,\n );\n\n const appTreeProps = getAppTreeProps(pageProps);\n\n const meta =\n parent.responseMeta?.({\n ctx,\n clientErrors: [...dehydratedCache.queries, ...dehydratedCache.mutations]\n .map((v) => v.state.error)\n .flatMap((err) =>\n err instanceof Error && err.name === 'TRPCClientError'\n ? [err as TRPCClientError<AnyRouter>]\n : [],\n ),\n }) ?? {};\n\n for (const [key, value] of Object.entries(meta.headers ?? {})) {\n if (typeof value === 'string') {\n ctx.res?.setHeader(key, value);\n }\n }\n if (meta.status && ctx.res) {\n ctx.res.statusCode = meta.status;\n }\n\n return appTreeProps;\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ssrPrepass.mjs","names":[],"sources":["../src/ssrPrepass.ts"],"sourcesContent":["/**\n * Heavily based on urql's ssr\n * https://github.com/FormidableLabs/urql/blob/main/packages/next-urql/src/with-urql-client.ts\n */\nimport type { DehydratedState } from '@tanstack/react-query';\nimport { dehydrate } from '@tanstack/react-query';\nimport { createTRPCUntypedClient } from '@trpc/client';\nimport type { TRPCClientError, TRPCClientErrorLike } from '@trpc/client';\nimport type { CoercedTransformerParameters } from '@trpc/client/unstable-internals';\nimport { getTransformer } from '@trpc/client/unstable-internals';\nimport { getQueryClient } from '@trpc/react-query/shared';\nimport type {\n AnyRouter,\n Dict,\n Maybe,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type {\n AppContextType,\n NextPageContext,\n} from 'next/dist/shared/lib/utils.js';\nimport { createElement } from 'react';\nimport type { TRPCPrepassHelper, TRPCPrepassProps } from './withTRPC';\n\nfunction transformQueryOrMutationCacheErrors<\n TState extends\n DehydratedState['mutations'][0] | DehydratedState['queries'][0],\n>(result: TState): TState {\n const error = result.state.error as Maybe<TRPCClientError<any>>;\n if (error instanceof Error && error.name === 'TRPCClientError') {\n const newError: TRPCClientErrorLike<any> = {\n message: error.message,\n data: error.data,\n shape: error.shape,\n };\n return {\n ...result,\n state: {\n ...result.state,\n error: newError,\n },\n };\n }\n return result;\n}\n\nexport const ssrPrepass: TRPCPrepassHelper = (opts) => {\n const { parent, WithTRPC, AppOrPage } = opts;\n type $PrepassProps = TRPCPrepassProps<AnyRouter, any>;\n\n const transformer = getTransformer(\n (parent as CoercedTransformerParameters).transformer,\n );\n WithTRPC.getInitialProps = async (appOrPageCtx: AppContextType) => {\n const shouldSsr = async () => {\n if (typeof window !== 'undefined') {\n return false;\n }\n if (typeof parent.ssr === 'function') {\n try {\n return await parent.ssr({ ctx: appOrPageCtx.ctx });\n } catch {\n return false;\n }\n }\n return parent.ssr;\n };\n const ssrEnabled = await shouldSsr();\n const AppTree = appOrPageCtx.AppTree;\n\n // Determine if we are wrapping an App component or a Page component.\n const isApp = !!appOrPageCtx.Component;\n const ctx: NextPageContext = isApp\n ? appOrPageCtx.ctx\n : (appOrPageCtx as any as NextPageContext);\n\n // Run the wrapped component's getInitialProps function.\n let pageProps: Dict<unknown> = {};\n if (AppOrPage.getInitialProps) {\n const originalProps = await AppOrPage.getInitialProps(\n appOrPageCtx as any,\n );\n const originalPageProps = isApp\n ? (originalProps.pageProps ?? {})\n : originalProps;\n\n pageProps = {\n ...originalPageProps,\n ...pageProps,\n };\n }\n const getAppTreeProps = (props: Record<string, unknown>) =>\n isApp ? { pageProps: props } : props;\n\n if (typeof window !== 'undefined' || !ssrEnabled) {\n return getAppTreeProps(pageProps);\n }\n\n const config = parent.config({ ctx });\n const trpcClient = createTRPCUntypedClient(config);\n const queryClient = getQueryClient(config);\n\n const trpcProp: $PrepassProps = {\n config,\n trpcClient,\n queryClient,\n ssrState: 'prepass',\n ssrContext: ctx,\n };\n const prepassProps = {\n pageProps,\n trpc: trpcProp,\n };\n\n const reactDomServer = await import('react-dom/server');\n\n // Run the prepass step on AppTree. This will run all trpc queries on the server.\n // multiple prepass ensures that we can do batching on the server\n while (true) {\n // render full tree\n reactDomServer.renderToString(createElement(AppTree, prepassProps));\n if (!queryClient.isFetching()) {\n // the render didn't cause the queryClient to fetch anything\n break;\n }\n\n // wait until the query cache has settled it's promises\n await new Promise<void>((resolve) => {\n const unsub = queryClient.getQueryCache().subscribe((event) => {\n if (event?.query.getObserversCount() === 0) {\n resolve();\n unsub();\n }\n });\n });\n }\n const dehydratedCache = dehydrate(queryClient, {\n shouldDehydrateQuery(query) {\n // filter out queries that are marked as trpc: { ssr: false } or are not enabled, but make sure errors are dehydrated\n const isExcludedFromSSr =\n query.state.fetchStatus === 'idle' &&\n query.state.status === 'pending';\n return !isExcludedFromSSr;\n },\n });\n // since error instances can't be serialized, let's make them into `TRPCClientErrorLike`-objects\n const dehydratedCacheWithErrors = {\n ...dehydratedCache,\n queries: dehydratedCache.queries.map(transformQueryOrMutationCacheErrors),\n mutations: dehydratedCache.mutations.map(\n transformQueryOrMutationCacheErrors,\n ),\n };\n\n // dehydrate query client's state and add it to the props\n pageProps['trpcState'] = transformer.input.serialize(\n dehydratedCacheWithErrors,\n );\n\n const appTreeProps = getAppTreeProps(pageProps);\n\n const meta =\n parent.responseMeta?.({\n ctx,\n clientErrors: [...dehydratedCache.queries, ...dehydratedCache.mutations]\n .map((v) => v.state.error)\n .flatMap((err) =>\n err instanceof Error && err.name === 'TRPCClientError'\n ? [err as TRPCClientError<AnyRouter>]\n : [],\n ),\n }) ?? {};\n\n for (const [key, value] of Object.entries(meta.headers ?? {})) {\n if (typeof value === 'string') {\n ctx.res?.setHeader(key, value);\n }\n }\n if (meta.status && ctx.res) {\n ctx.res.statusCode = meta.status;\n }\n\n return appTreeProps;\n };\n};\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import { QueryClient } from "@tanstack/react-query";
1
+ import { CreateTRPCClientOptions, TRPCClient, TRPCClientError, TRPCUntypedClient } from "@trpc/client";
2
+ import { AnyRouter, ResponseMeta, inferClientTypes } from "@trpc/server/unstable-core-do-not-import";
2
3
  import { TransformerOptions } from "@trpc/client/unstable-internals";
4
+ import { QueryClient } from "@tanstack/react-query";
3
5
  import { CreateTRPCReactOptions, CreateTRPCReactQueryClientConfig } from "@trpc/react-query/shared";
4
- import { AnyRouter, ResponseMeta, inferClientTypes } from "@trpc/server/unstable-core-do-not-import";
5
- import { CreateTRPCClientOptions, TRPCClient, TRPCClientError, TRPCUntypedClient } from "@trpc/client";
6
- import { NextComponentType, NextPageContext } from "next/dist/shared/lib/utils";
6
+ import { NextComponentType, NextPageContext } from "next/dist/shared/lib/utils.js";
7
7
  //#region src/withTRPC.d.ts
8
8
  type WithTRPCConfig<TRouter extends AnyRouter> = CreateTRPCClientOptions<TRouter> & CreateTRPCReactQueryClientConfig & {
9
9
  abortOnUnmount?: boolean;
@@ -49,4 +49,4 @@ type TRPCPrepassProps<TRouter extends AnyRouter, TSSRContext extends NextPageCon
49
49
  declare function withTRPC<TRouter extends AnyRouter, TSSRContext extends NextPageContext = NextPageContext>(opts: WithTRPCNoSSROptions<TRouter> | WithTRPCSSROptions<TRouter>): (AppOrPage: NextComponentType<any, any, any>) => NextComponentType;
50
50
  //#endregion
51
51
  export { WithTRPCSSROptions as a, WithTRPCNoSSROptions as i, TRPCPrepassProps as n, withTRPC as o, WithTRPCConfig as r, TRPCPrepassHelper as t };
52
- //# sourceMappingURL=withTRPC-BchtyodQ.d.mts.map
52
+ //# sourceMappingURL=withTRPC-Cr10aYRv.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"withTRPC-DywCxFfq.d.cts","names":[],"sources":["../src/withTRPC.tsx"],"mappings":";;;;;;;KAqCY,eAAe,gBAAgB,aACzC,wBAAwB,WACtB;EACE;;KAGD,gBAAgB,gBAAgB,aACnC,uBAAuB;EACrB,SAAS;IAAQ,MAAM;QAAsB,eAAe;IAC1D,mBAAmB,iBAAiB;KAE9B,qBAAqB;EAC/B,QAAQ,mBAAmB;EAC3B,UAAU;EACV,WAAW;;KAED,mBAAmB,gBAAgB,aAC7C,gBAAgB;;;;;EAKd,cACW;IAAQ,KAAK;kBAAgC;EACxD,gBAAgB;IACd,KAAK;IACL,cAAc,gBAAgB;QAC1B;;;;;EAKN,YAAY;;KAGJ,qBAAqB,gBAAgB,aAC/C,gBAAgB;EACd;;KAGQ,iBACV,gBAAgB,WAChB,oBAAoB,kBAAkB;EAEtC,QAAQ,eAAe;EACvB,aAAa;EACb,YAAY,kBAAkB,WAAW,WAAW;EACpD;EACA,YAAY;;iBAGE,SACd,gBAAgB,WAChB,oBAAoB,kBAAkB,iBACtC,MAAM,qBAAqB,WAAW,mBAAmB,YAAQ,WAO9C,qCAAmC"}
1
+ {"version":3,"file":"withTRPC-Cr10aYRv.d.cts","names":[],"sources":["../src/withTRPC.tsx"],"mappings":";;;;;;;KAqCY,eAAe,gBAAgB,aACzC,wBAAwB,WACtB;EACE;;KAGD,gBAAgB,gBAAgB,aACnC,uBAAuB;EACrB,SAAS;IAAQ,MAAM;QAAsB,eAAe;IAC1D,mBAAmB,iBAAiB;KAE9B,qBAAqB;EAC/B,QAAQ,mBAAmB;EAC3B,UAAU;EACV,WAAW;;KAED,mBAAmB,gBAAgB,aAC7C,gBAAgB;;;;;EAKd,cACW;IAAQ,KAAK;kBAAgC;EACxD,gBAAgB;IACd,KAAK;IACL,cAAc,gBAAgB;QAC1B;;;;;EAKN,YAAY;;KAGJ,qBAAqB,gBAAgB,aAC/C,gBAAgB;EACd;;KAGQ,iBACV,gBAAgB,WAChB,oBAAoB,kBAAkB;EAEtC,QAAQ,eAAe;EACvB,aAAa;EACb,YAAY,kBAAkB,WAAW,WAAW;EACpD;EACA,YAAY;;iBAGE,SACd,gBAAgB,WAChB,oBAAoB,kBAAkB,iBACtC,MAAM,qBAAqB,WAAW,mBAAmB,YAAQ,WAO9C,qCAAmC"}
@@ -1,9 +1,9 @@
1
- import { CreateTRPCClientOptions, TRPCClient, TRPCClientError, TRPCUntypedClient } from "@trpc/client";
2
- import { AnyRouter, ResponseMeta, inferClientTypes } from "@trpc/server/unstable-core-do-not-import";
3
- import { TransformerOptions } from "@trpc/client/unstable-internals";
4
1
  import { QueryClient } from "@tanstack/react-query";
2
+ import { TransformerOptions } from "@trpc/client/unstable-internals";
5
3
  import { CreateTRPCReactOptions, CreateTRPCReactQueryClientConfig } from "@trpc/react-query/shared";
6
- import { NextComponentType, NextPageContext } from "next/dist/shared/lib/utils";
4
+ import { AnyRouter, ResponseMeta, inferClientTypes } from "@trpc/server/unstable-core-do-not-import";
5
+ import { CreateTRPCClientOptions, TRPCClient, TRPCClientError, TRPCUntypedClient } from "@trpc/client";
6
+ import { NextComponentType, NextPageContext } from "next/dist/shared/lib/utils.js";
7
7
  //#region src/withTRPC.d.ts
8
8
  type WithTRPCConfig<TRouter extends AnyRouter> = CreateTRPCClientOptions<TRouter> & CreateTRPCReactQueryClientConfig & {
9
9
  abortOnUnmount?: boolean;
@@ -49,4 +49,4 @@ type TRPCPrepassProps<TRouter extends AnyRouter, TSSRContext extends NextPageCon
49
49
  declare function withTRPC<TRouter extends AnyRouter, TSSRContext extends NextPageContext = NextPageContext>(opts: WithTRPCNoSSROptions<TRouter> | WithTRPCSSROptions<TRouter>): (AppOrPage: NextComponentType<any, any, any>) => NextComponentType;
50
50
  //#endregion
51
51
  export { WithTRPCSSROptions as a, WithTRPCNoSSROptions as i, TRPCPrepassProps as n, withTRPC as o, WithTRPCConfig as r, TRPCPrepassHelper as t };
52
- //# sourceMappingURL=withTRPC-DywCxFfq.d.cts.map
52
+ //# sourceMappingURL=withTRPC-CxGgngCY.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"withTRPC-BchtyodQ.d.mts","names":[],"sources":["../src/withTRPC.tsx"],"mappings":";;;;;;;KAqCY,eAAe,gBAAgB,aACzC,wBAAwB,WACtB;EACE;;KAGD,gBAAgB,gBAAgB,aACnC,uBAAuB;EACrB,SAAS;IAAQ,MAAM;QAAsB,eAAe;IAC1D,mBAAmB,iBAAiB;KAE9B,qBAAqB;EAC/B,QAAQ,mBAAmB;EAC3B,UAAU;EACV,WAAW;;KAED,mBAAmB,gBAAgB,aAC7C,gBAAgB;;;;;EAKd,cACW;IAAQ,KAAK;kBAAgC;EACxD,gBAAgB;IACd,KAAK;IACL,cAAc,gBAAgB;QAC1B;;;;;EAKN,YAAY;;KAGJ,qBAAqB,gBAAgB,aAC/C,gBAAgB;EACd;;KAGQ,iBACV,gBAAgB,WAChB,oBAAoB,kBAAkB;EAEtC,QAAQ,eAAe;EACvB,aAAa;EACb,YAAY,kBAAkB,WAAW,WAAW;EACpD;EACA,YAAY;;iBAGE,SACd,gBAAgB,WAChB,oBAAoB,kBAAkB,iBACtC,MAAM,qBAAqB,WAAW,mBAAmB,YAAQ,WAO9C,qCAAmC"}
1
+ {"version":3,"file":"withTRPC-CxGgngCY.d.mts","names":[],"sources":["../src/withTRPC.tsx"],"mappings":";;;;;;;KAqCY,eAAe,gBAAgB,aACzC,wBAAwB,WACtB;EACE;;KAGD,gBAAgB,gBAAgB,aACnC,uBAAuB;EACrB,SAAS;IAAQ,MAAM;QAAsB,eAAe;IAC1D,mBAAmB,iBAAiB;KAE9B,qBAAqB;EAC/B,QAAQ,mBAAmB;EAC3B,UAAU;EACV,WAAW;;KAED,mBAAmB,gBAAgB,aAC7C,gBAAgB;;;;;EAKd,cACW;IAAQ,KAAK;kBAAgC;EACxD,gBAAgB;IACd,KAAK;IACL,cAAc,gBAAgB;QAC1B;;;;;EAKN,YAAY;;KAGJ,qBAAqB,gBAAgB,aAC/C,gBAAgB;EACd;;KAGQ,iBACV,gBAAgB,WAChB,oBAAoB,kBAAkB;EAEtC,QAAQ,eAAe;EACvB,aAAa;EACb,YAAY,kBAAkB,WAAW,WAAW;EACpD;EACA,YAAY;;iBAGE,SACd,gBAAgB,WAChB,oBAAoB,kBAAkB,iBACtC,MAAM,qBAAqB,WAAW,mBAAmB,YAAQ,WAO9C,qCAAmC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@trpc/next",
4
- "version": "11.22.1",
4
+ "version": "11.22.2-canary.11.4427f0bea",
5
5
  "description": "The tRPC Next.js library",
6
6
  "author": "KATT",
7
7
  "license": "MIT",
@@ -100,16 +100,13 @@
100
100
  "app-dir",
101
101
  "ssrPrepass",
102
102
  "!**/*.test.*",
103
- "!**/__tests__",
104
- "skills",
105
- "!skills/_artifacts",
106
- "bin"
103
+ "!**/__tests__"
107
104
  ],
108
105
  "peerDependencies": {
109
106
  "@tanstack/react-query": "^5.59.15",
110
- "@trpc/client": "11.22.1",
111
- "@trpc/react-query": "11.22.1",
112
- "@trpc/server": "11.22.1",
107
+ "@trpc/client": "11.22.2-canary.11.4427f0bea",
108
+ "@trpc/react-query": "11.22.2-canary.11.4427f0bea",
109
+ "@trpc/server": "11.22.2-canary.11.4427f0bea",
113
110
  "next": "*",
114
111
  "react": ">=16.8.0",
115
112
  "react-dom": ">=16.8.0",
@@ -124,11 +121,10 @@
124
121
  }
125
122
  },
126
123
  "devDependencies": {
127
- "@tanstack/intent": "^0.0.27",
128
124
  "@tanstack/react-query": "^5.80.3",
129
- "@trpc/client": "11.22.1",
130
- "@trpc/react-query": "11.22.1",
131
- "@trpc/server": "11.22.1",
125
+ "@trpc/client": "11.22.2-canary.11.4427f0bea",
126
+ "@trpc/react-query": "11.22.2-canary.11.4427f0bea",
127
+ "@trpc/server": "11.22.2-canary.11.4427f0bea",
132
128
  "@types/express": "^5.0.0",
133
129
  "@types/node": "^24.13.4",
134
130
  "@types/react": "^19.1.0",
@@ -149,11 +145,5 @@
149
145
  "funding": [
150
146
  "https://trpc.io/sponsor"
151
147
  ],
152
- "keywords": [
153
- "tanstack-intent"
154
- ],
155
- "bin": {
156
- "intent": "./bin/intent.js"
157
- },
158
- "gitHead": "708753ff1383c47c5f765694978db1000a86ee36"
148
+ "gitHead": "4427f0bea4ceca48f3e15125e858ab9adddf3f3b"
159
149
  }
@@ -16,7 +16,7 @@ import type {
16
16
  ProtectedIntersection,
17
17
  } from '@trpc/server/unstable-core-do-not-import';
18
18
  import { createFlatProxy } from '@trpc/server/unstable-core-do-not-import';
19
- import type { NextPageContext } from 'next/types';
19
+ import type { NextPageContext } from 'next/types.js';
20
20
  import { useMemo } from 'react';
21
21
  import type { WithTRPCNoSSROptions, WithTRPCSSROptions } from './withTRPC';
22
22
  import { withTRPC } from './withTRPC';
package/src/ssrPrepass.ts CHANGED
@@ -17,7 +17,7 @@ import type {
17
17
  import type {
18
18
  AppContextType,
19
19
  NextPageContext,
20
- } from 'next/dist/shared/lib/utils';
20
+ } from 'next/dist/shared/lib/utils.js';
21
21
  import { createElement } from 'react';
22
22
  import type { TRPCPrepassHelper, TRPCPrepassProps } from './withTRPC';
23
23
 
package/src/withTRPC.tsx CHANGED
@@ -31,7 +31,7 @@ import type {
31
31
  AppPropsType,
32
32
  NextComponentType,
33
33
  NextPageContext,
34
- } from 'next/dist/shared/lib/utils';
34
+ } from 'next/dist/shared/lib/utils.js';
35
35
  import type { NextRouter } from 'next/router';
36
36
  import React, { useState } from 'react';
37
37
 
package/bin/intent.js DELETED
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env node
2
- // Auto-generated by @tanstack/intent setup
3
- // Exposes the intent end-user CLI for consumers of this library.
4
- // Commit this file, then add to your package.json:
5
- // "bin": { "intent": "./bin/intent.js" }
6
- try {
7
- await import('@tanstack/intent/intent-library');
8
- } catch (e) {
9
- if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
10
- console.error('@tanstack/intent is not installed.');
11
- console.error('');
12
- console.error('Install it as a dev dependency:');
13
- console.error(' npm add -D @tanstack/intent');
14
- console.error('');
15
- console.error('Or run directly:');
16
- console.error(' npx @tanstack/intent@latest list');
17
- process.exit(1);
18
- }
19
- throw e;
20
- }
@@ -1,429 +0,0 @@
1
- ---
2
- name: nextjs-app-router
3
- description: >
4
- Full end-to-end tRPC setup for Next.js App Router. Covers route handler
5
- with fetchRequestHandler (GET + POST exports), TRPCProvider with
6
- QueryClientProvider, createTRPCOptionsProxy for RSC prefetching,
7
- HydrateClient/HydrationBoundary for hydration, useSuspenseQuery
8
- for Suspense, and server-side callers.
9
- type: framework
10
- library: trpc
11
- framework: react
12
- library_version: '11.16.0'
13
- requires:
14
- - server-setup
15
- - client-setup
16
- - react-query-setup
17
- - adapter-fetch
18
- sources:
19
- - www/docs/client/nextjs/overview.mdx
20
- - www/docs/client/tanstack-react-query/server-components.mdx
21
- - www/docs/server/adapters/nextjs.md
22
- - examples/next-prisma-starter/
23
- - examples/next-sse-chat/
24
- ---
25
-
26
- This skill builds on [server-setup], [client-setup], [react-query-setup], and [adapter-fetch]. Read them first for foundational concepts.
27
-
28
- # tRPC -- Next.js App Router
29
-
30
- ## File Structure
31
-
32
- ```
33
- .
34
- ├── app
35
- │ ├── api/trpc/[trpc]
36
- │ │ └── route.ts # tRPC HTTP handler
37
- │ ├── layout.tsx # mount TRPCReactProvider
38
- │ ├── page.tsx # server component (prefetch)
39
- │ └── client-greeting.tsx # client component (consume)
40
- ├── trpc
41
- │ ├── init.ts # initTRPC, createTRPCContext
42
- │ ├── routers
43
- │ │ └── _app.ts # main app router, AppRouter type
44
- │ ├── query-client.ts # shared QueryClient factory
45
- │ ├── client.tsx # client hooks & TRPCReactProvider
46
- │ └── server.tsx # server-side proxy & helpers
47
- └── ...
48
- ```
49
-
50
- ## Setup
51
-
52
- ### 1. Install
53
-
54
- ```sh
55
- npm install @trpc/server @trpc/client @trpc/tanstack-react-query @tanstack/react-query zod server-only client-only
56
- ```
57
-
58
- ### 2. Server init and context
59
-
60
- ```ts title="trpc/init.ts"
61
- import { initTRPC } from '@trpc/server';
62
-
63
- export const createTRPCContext = async (opts: { headers: Headers }) => {
64
- return { userId: 'user_123' };
65
- };
66
-
67
- const t = initTRPC
68
- .context<Awaited<ReturnType<typeof createTRPCContext>>>()
69
- .create();
70
-
71
- export const createTRPCRouter = t.router;
72
- export const createCallerFactory = t.createCallerFactory;
73
- export const baseProcedure = t.procedure;
74
- ```
75
-
76
- ### 3. Define the router
77
-
78
- ```ts title="trpc/routers/_app.ts"
79
- import { z } from 'zod';
80
- import { baseProcedure, createTRPCRouter } from '../init';
81
-
82
- export const appRouter = createTRPCRouter({
83
- hello: baseProcedure
84
- .input(z.object({ text: z.string() }))
85
- .query(({ input }) => ({
86
- greeting: `hello ${input.text}`,
87
- })),
88
- });
89
-
90
- export type AppRouter = typeof appRouter;
91
- ```
92
-
93
- ### 4. Route handler (API endpoint)
94
-
95
- ```ts title="app/api/trpc/[trpc]/route.ts"
96
- import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
97
- import { createTRPCContext } from '../../../../trpc/init';
98
- import { appRouter } from '../../../../trpc/routers/_app';
99
-
100
- const handler = (req: Request) =>
101
- fetchRequestHandler({
102
- endpoint: '/api/trpc',
103
- req,
104
- router: appRouter,
105
- createContext: () => createTRPCContext({ headers: req.headers }),
106
- });
107
-
108
- export { handler as GET, handler as POST };
109
- ```
110
-
111
- ### 5. QueryClient factory
112
-
113
- ```ts title="trpc/query-client.ts"
114
- import {
115
- defaultShouldDehydrateQuery,
116
- QueryClient,
117
- } from '@tanstack/react-query';
118
-
119
- export function makeQueryClient() {
120
- return new QueryClient({
121
- defaultOptions: {
122
- queries: {
123
- staleTime: 30 * 1000,
124
- },
125
- dehydrate: {
126
- shouldDehydrateQuery: (query) =>
127
- defaultShouldDehydrateQuery(query) ||
128
- query.state.status === 'pending',
129
- },
130
- },
131
- });
132
- }
133
- ```
134
-
135
- If using a data transformer (e.g., superjson), add `dehydrate.serializeData` and `hydrate.deserializeData` here.
136
-
137
- ### 6. Client provider (client component)
138
-
139
- ```tsx title="trpc/client.tsx"
140
- 'use client';
141
-
142
- import type { QueryClient } from '@tanstack/react-query';
143
- import { QueryClientProvider } from '@tanstack/react-query';
144
- import { createTRPCClient, httpBatchLink } from '@trpc/client';
145
- import { createTRPCContext } from '@trpc/tanstack-react-query';
146
- import { useState } from 'react';
147
- import { makeQueryClient } from './query-client';
148
- import type { AppRouter } from './routers/_app';
149
-
150
- export const { TRPCProvider, useTRPC, useTRPCClient } =
151
- createTRPCContext<AppRouter>();
152
-
153
- let browserQueryClient: QueryClient;
154
- function getQueryClient() {
155
- if (typeof window === 'undefined') {
156
- return makeQueryClient();
157
- }
158
- if (!browserQueryClient) browserQueryClient = makeQueryClient();
159
- return browserQueryClient;
160
- }
161
-
162
- function getUrl() {
163
- const base = (() => {
164
- if (typeof window !== 'undefined') return '';
165
- if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
166
- return 'http://localhost:3000';
167
- })();
168
- return `${base}/api/trpc`;
169
- }
170
-
171
- export function TRPCReactProvider(props: { children: React.ReactNode }) {
172
- const queryClient = getQueryClient();
173
-
174
- const [trpcClient] = useState(() =>
175
- createTRPCClient<AppRouter>({
176
- links: [
177
- httpBatchLink({
178
- url: getUrl(),
179
- }),
180
- ],
181
- }),
182
- );
183
-
184
- return (
185
- <QueryClientProvider client={queryClient}>
186
- <TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
187
- {props.children}
188
- </TRPCProvider>
189
- </QueryClientProvider>
190
- );
191
- }
192
- ```
193
-
194
- ### 7. Server-side proxy (server component)
195
-
196
- ```tsx title="trpc/server.tsx"
197
- import 'server-only';
198
- import { dehydrate, HydrationBoundary } from '@tanstack/react-query';
199
- import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query';
200
- import type { TRPCQueryOptions } from '@trpc/tanstack-react-query';
201
- import { headers } from 'next/headers';
202
- import { cache } from 'react';
203
- import { createTRPCContext } from './init';
204
- import { makeQueryClient } from './query-client';
205
- import { appRouter } from './routers/_app';
206
-
207
- export const getQueryClient = cache(makeQueryClient);
208
-
209
- export const trpc = createTRPCOptionsProxy({
210
- ctx: async () =>
211
- createTRPCContext({
212
- headers: await headers(),
213
- }),
214
- router: appRouter,
215
- queryClient: getQueryClient,
216
- });
217
-
218
- export function HydrateClient(props: { children: React.ReactNode }) {
219
- const queryClient = getQueryClient();
220
- return (
221
- <HydrationBoundary state={dehydrate(queryClient)}>
222
- {props.children}
223
- </HydrationBoundary>
224
- );
225
- }
226
-
227
- export function prefetch<T extends ReturnType<TRPCQueryOptions<any>>>(
228
- queryOptions: T,
229
- ) {
230
- const queryClient = getQueryClient();
231
- if (queryOptions.queryKey[1]?.type === 'infinite') {
232
- void queryClient.prefetchInfiniteQuery(queryOptions as any);
233
- } else {
234
- void queryClient.prefetchQuery(queryOptions);
235
- }
236
- }
237
- ```
238
-
239
- ### 8. Mount provider in layout
240
-
241
- ```tsx title="app/layout.tsx"
242
- import { TRPCReactProvider } from '../trpc/client';
243
-
244
- export default function RootLayout({
245
- children,
246
- }: {
247
- children: React.ReactNode;
248
- }) {
249
- return (
250
- <html lang="en">
251
- <body>
252
- <TRPCReactProvider>{children}</TRPCReactProvider>
253
- </body>
254
- </html>
255
- );
256
- }
257
- ```
258
-
259
- ## Core Patterns
260
-
261
- ### Prefetch in server component, consume in client component
262
-
263
- ```tsx title="app/page.tsx"
264
- import { HydrateClient, prefetch, trpc } from '../trpc/server';
265
- import { ClientGreeting } from './client-greeting';
266
-
267
- export default async function Home() {
268
- prefetch(trpc.hello.queryOptions({ text: 'world' }));
269
-
270
- return (
271
- <HydrateClient>
272
- <ClientGreeting />
273
- </HydrateClient>
274
- );
275
- }
276
- ```
277
-
278
- ```tsx title="app/client-greeting.tsx"
279
- 'use client';
280
-
281
- import { useQuery } from '@tanstack/react-query';
282
- import { useTRPC } from '../trpc/client';
283
-
284
- export function ClientGreeting() {
285
- const trpc = useTRPC();
286
- const greeting = useQuery(trpc.hello.queryOptions({ text: 'world' }));
287
- if (!greeting.data) return <div>Loading...</div>;
288
- return <div>{greeting.data.greeting}</div>;
289
- }
290
- ```
291
-
292
- ### Suspense with prefetch
293
-
294
- ```tsx title="app/page.tsx"
295
- import { Suspense } from 'react';
296
- import { ErrorBoundary } from 'react-error-boundary';
297
- import { HydrateClient, prefetch, trpc } from '../trpc/server';
298
- import { ClientGreeting } from './client-greeting';
299
-
300
- export default async function Home() {
301
- prefetch(trpc.hello.queryOptions({ text: 'world' }));
302
-
303
- return (
304
- <HydrateClient>
305
- <ErrorBoundary fallback={<div>Something went wrong</div>}>
306
- <Suspense fallback={<div>Loading...</div>}>
307
- <ClientGreeting />
308
- </Suspense>
309
- </ErrorBoundary>
310
- </HydrateClient>
311
- );
312
- }
313
- ```
314
-
315
- ```tsx title="app/client-greeting.tsx"
316
- 'use client';
317
-
318
- import { useSuspenseQuery } from '@tanstack/react-query';
319
- import { useTRPC } from '../trpc/client';
320
-
321
- export function ClientGreeting() {
322
- const trpc = useTRPC();
323
- const { data } = useSuspenseQuery(trpc.hello.queryOptions({ text: 'world' }));
324
- return <div>{data.greeting}</div>;
325
- }
326
- ```
327
-
328
- ### Direct server caller (data needed on server only)
329
-
330
- ```tsx title="trpc/server.tsx"
331
- // Add to existing server.tsx
332
- export const caller = appRouter.createCaller(async () =>
333
- createTRPCContext({ headers: await headers() }),
334
- );
335
- ```
336
-
337
- ```tsx title="app/page.tsx"
338
- import { caller } from '../trpc/server';
339
-
340
- export default async function Home() {
341
- const greeting = await caller.hello({ text: 'world' });
342
- return <div>{greeting.greeting}</div>;
343
- }
344
- ```
345
-
346
- Note: `caller` results are not stored in the query cache. They cannot hydrate to client components. Use `prefetchQuery` if client components also need the data.
347
-
348
- ### fetchQuery for data on server AND client
349
-
350
- ```tsx title="app/page.tsx"
351
- import { getQueryClient, HydrateClient, trpc } from '../trpc/server';
352
- import { ClientGreeting } from './client-greeting';
353
-
354
- export default async function Home() {
355
- const queryClient = getQueryClient();
356
- const greeting = await queryClient.fetchQuery(
357
- trpc.hello.queryOptions({ text: 'world' }),
358
- );
359
-
360
- // Use greeting on the server
361
- console.log(greeting.greeting);
362
-
363
- return (
364
- <HydrateClient>
365
- <ClientGreeting />
366
- </HydrateClient>
367
- );
368
- }
369
- ```
370
-
371
- ## Common Mistakes
372
-
373
- ### Not exporting both GET and POST from route handler
374
-
375
- Next.js App Router route handlers must export named `GET` and `POST` functions. Missing either causes queries or mutations to return 405 Method Not Allowed.
376
-
377
- ```ts
378
- // WRONG
379
- export default function handler(req: Request) { ... }
380
-
381
- // CORRECT
382
- const handler = (req: Request) =>
383
- fetchRequestHandler({ req, router: appRouter, endpoint: '/api/trpc', createContext });
384
- export { handler as GET, handler as POST };
385
- ```
386
-
387
- ### Creating a singleton QueryClient for SSR
388
-
389
- In server components, each request needs its own `QueryClient` instance. A singleton leaks data between requests.
390
-
391
- ```ts
392
- // WRONG
393
- const queryClient = new QueryClient(); // shared across requests!
394
-
395
- // CORRECT
396
- export const getQueryClient = cache(makeQueryClient);
397
- ```
398
-
399
- The `cache()` wrapper from React ensures the same `QueryClient` is reused within a single request but a new one is created for each new request.
400
-
401
- ### Missing dehydrate/shouldDehydrateQuery config
402
-
403
- RSC hydration requires `shouldDehydrateQuery` to include pending queries so that prefetched-but-not-yet-resolved promises can stream to the client. Without this, prefetched queries may not appear in the hydrated state.
404
-
405
- ```ts
406
- // WRONG
407
- new QueryClient(); // default shouldDehydrateQuery skips pending
408
-
409
- // CORRECT
410
- new QueryClient({
411
- defaultOptions: {
412
- dehydrate: {
413
- shouldDehydrateQuery: (query) =>
414
- defaultShouldDehydrateQuery(query) || query.state.status === 'pending',
415
- },
416
- },
417
- });
418
- ```
419
-
420
- ### Suspense query failure crashes entire page during SSR
421
-
422
- If a query fails during SSR with `useSuspenseQuery`, the entire page crashes. Error Boundaries only catch errors on the client side. For critical pages, either handle errors server-side before rendering, or use `useQuery` (non-suspense) which allows graceful degradation.
423
-
424
- ## See Also
425
-
426
- - [react-query-setup] -- TanStack React Query setup, queryOptions/mutationOptions factories
427
- - [adapter-fetch] -- fetchRequestHandler for edge/serverless runtimes
428
- - [server-setup] -- initTRPC, routers, procedures, context
429
- - [nextjs-pages-router] -- if maintaining a Pages Router project alongside App Router
@@ -1,386 +0,0 @@
1
- ---
2
- name: nextjs-pages-router
3
- description: >
4
- Set up tRPC in Next.js Pages Router with createNextApiHandler,
5
- createTRPCNext, withTRPC HOC, SSR via ssr option and ssrPrepass,
6
- SSG via createServerSideHelpers with getStaticProps, and
7
- server-side helpers for getServerSideProps prefetching.
8
- type: framework
9
- library: trpc
10
- framework: react
11
- library_version: '11.16.0'
12
- requires:
13
- - server-setup
14
- - client-setup
15
- sources:
16
- - www/docs/client/nextjs/overview.mdx
17
- - www/docs/server/adapters/nextjs.md
18
- - examples/next-prisma-starter/
19
- ---
20
-
21
- This skill builds on [server-setup] and [client-setup]. Read them first for foundational concepts.
22
-
23
- # tRPC -- Next.js Pages Router
24
-
25
- ## File Structure
26
-
27
- ```
28
- .
29
- ├── src
30
- │ ├── pages
31
- │ │ ├── _app.tsx # withTRPC() HOC
32
- │ │ ├── api/trpc
33
- │ │ │ └── [trpc].ts # tRPC API handler
34
- │ │ └── index.tsx # page using tRPC hooks
35
- │ ├── server
36
- │ │ ├── routers
37
- │ │ │ └── _app.ts # main app router
38
- │ │ ├── context.ts # createContext
39
- │ │ └── trpc.ts # initTRPC, procedure helpers
40
- │ └── utils
41
- │ └── trpc.ts # createTRPCNext, hooks
42
- └── ...
43
- ```
44
-
45
- ## Setup
46
-
47
- ### 1. Install
48
-
49
- ```sh
50
- npm install @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query zod
51
- ```
52
-
53
- ### 2. Server init
54
-
55
- ```ts title="server/trpc.ts"
56
- import { initTRPC } from '@trpc/server';
57
-
58
- const t = initTRPC.create();
59
-
60
- export const router = t.router;
61
- export const procedure = t.procedure;
62
- ```
63
-
64
- ### 3. Define the router
65
-
66
- ```ts title="server/routers/_app.ts"
67
- import { z } from 'zod';
68
- import { procedure, router } from '../trpc';
69
-
70
- export const appRouter = router({
71
- hello: procedure.input(z.object({ text: z.string() })).query(({ input }) => ({
72
- greeting: `hello ${input.text}`,
73
- })),
74
- });
75
-
76
- export type AppRouter = typeof appRouter;
77
- ```
78
-
79
- ### 4. API handler
80
-
81
- ```ts title="pages/api/trpc/[trpc].ts"
82
- import { createNextApiHandler } from '@trpc/server/adapters/next';
83
- import { appRouter } from '../../../server/routers/_app';
84
-
85
- export default createNextApiHandler({
86
- router: appRouter,
87
- createContext: () => ({}),
88
- });
89
- ```
90
-
91
- ### 5. Create tRPC hooks
92
-
93
- ```ts title="utils/trpc.ts"
94
- import { httpBatchLink } from '@trpc/client';
95
- import { createTRPCNext } from '@trpc/next';
96
- import type { AppRouter } from '../server/routers/_app';
97
-
98
- function getBaseUrl() {
99
- if (typeof window !== 'undefined') return '';
100
- if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
101
- return `http://localhost:${process.env.PORT ?? 3000}`;
102
- }
103
-
104
- export const trpc = createTRPCNext<AppRouter>({
105
- config() {
106
- return {
107
- links: [
108
- httpBatchLink({
109
- url: `${getBaseUrl()}/api/trpc`,
110
- }),
111
- ],
112
- };
113
- },
114
- ssr: false,
115
- });
116
- ```
117
-
118
- ### 6. Wrap app with withTRPC HOC
119
-
120
- ```tsx title="pages/_app.tsx"
121
- import type { AppType } from 'next/app';
122
- import { trpc } from '../utils/trpc';
123
-
124
- const MyApp: AppType = ({ Component, pageProps }) => {
125
- return <Component {...pageProps} />;
126
- };
127
-
128
- export default trpc.withTRPC(MyApp);
129
- ```
130
-
131
- ### 7. Use hooks in pages
132
-
133
- ```tsx title="pages/index.tsx"
134
- import { trpc } from '../utils/trpc';
135
-
136
- export default function IndexPage() {
137
- const hello = trpc.hello.useQuery({ text: 'client' });
138
- if (!hello.data) return <div>Loading...</div>;
139
- return <p>{hello.data.greeting}</p>;
140
- }
141
- ```
142
-
143
- ## Core Patterns
144
-
145
- ### SSR with ssr: true
146
-
147
- Enable SSR to prefetch all queries on the server automatically. Requires `ssrPrepass` and forwarding client headers.
148
-
149
- ```ts title="utils/trpc.ts"
150
- import { httpBatchLink } from '@trpc/client';
151
- import { createTRPCNext } from '@trpc/next';
152
- import { ssrPrepass } from '@trpc/next/ssrPrepass';
153
- import type { AppRouter } from '../server/routers/_app';
154
-
155
- function getBaseUrl() {
156
- if (typeof window !== 'undefined') return '';
157
- if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
158
- return `http://localhost:${process.env.PORT ?? 3000}`;
159
- }
160
-
161
- export const trpc = createTRPCNext<AppRouter>({
162
- ssr: true,
163
- ssrPrepass,
164
- config({ ctx }) {
165
- if (typeof window !== 'undefined') {
166
- return {
167
- links: [httpBatchLink({ url: '/api/trpc' })],
168
- };
169
- }
170
- return {
171
- links: [
172
- httpBatchLink({
173
- url: `${getBaseUrl()}/api/trpc`,
174
- headers() {
175
- if (!ctx?.req?.headers) return {};
176
- return { cookie: ctx.req.headers.cookie };
177
- },
178
- }),
179
- ],
180
- };
181
- },
182
- });
183
- ```
184
-
185
- ### SSG with createServerSideHelpers and getStaticProps
186
-
187
- ```tsx title="pages/posts/[id].tsx"
188
- import { createServerSideHelpers } from '@trpc/react-query/server';
189
- import type {
190
- GetStaticPaths,
191
- GetStaticPropsContext,
192
- InferGetStaticPropsType,
193
- } from 'next';
194
- import superjson from 'superjson';
195
- import { appRouter } from '../../server/routers/_app';
196
- import { trpc } from '../../utils/trpc';
197
-
198
- export async function getStaticProps(
199
- context: GetStaticPropsContext<{ id: string }>,
200
- ) {
201
- const helpers = createServerSideHelpers({
202
- router: appRouter,
203
- ctx: {},
204
- transformer: superjson,
205
- });
206
- const id = context.params?.id as string;
207
-
208
- await helpers.post.byId.prefetch({ id });
209
-
210
- return {
211
- props: {
212
- trpcState: helpers.dehydrate(),
213
- id,
214
- },
215
- revalidate: 1,
216
- };
217
- }
218
-
219
- export const getStaticPaths: GetStaticPaths = async () => {
220
- return { paths: [], fallback: 'blocking' };
221
- };
222
-
223
- export default function PostPage(
224
- props: InferGetStaticPropsType<typeof getStaticProps>,
225
- ) {
226
- const { id } = props;
227
- const postQuery = trpc.post.byId.useQuery({ id });
228
-
229
- if (postQuery.status !== 'success') return <>Loading...</>;
230
- return <h1>{postQuery.data.title}</h1>;
231
- }
232
- ```
233
-
234
- ### Server-side helpers with getServerSideProps
235
-
236
- ```tsx title="pages/posts/[id].tsx"
237
- import { createServerSideHelpers } from '@trpc/react-query/server';
238
- import type {
239
- GetServerSidePropsContext,
240
- InferGetServerSidePropsType,
241
- } from 'next';
242
- import superjson from 'superjson';
243
- import { appRouter } from '../../server/routers/_app';
244
- import { trpc } from '../../utils/trpc';
245
-
246
- export async function getServerSideProps(
247
- context: GetServerSidePropsContext<{ id: string }>,
248
- ) {
249
- const helpers = createServerSideHelpers({
250
- router: appRouter,
251
- ctx: {},
252
- transformer: superjson,
253
- });
254
- const id = context.params?.id as string;
255
-
256
- await helpers.post.byId.prefetch({ id });
257
-
258
- return {
259
- props: {
260
- trpcState: helpers.dehydrate(),
261
- id,
262
- },
263
- };
264
- }
265
-
266
- export default function PostPage(
267
- props: InferGetServerSidePropsType<typeof getServerSideProps>,
268
- ) {
269
- const { id } = props;
270
- const postQuery = trpc.post.byId.useQuery({ id });
271
-
272
- if (postQuery.status !== 'success') return <>Loading...</>;
273
- return <h1>{postQuery.data.title}</h1>;
274
- }
275
- ```
276
-
277
- ### SSR response caching
278
-
279
- ```ts title="utils/trpc.ts"
280
- import { httpBatchLink } from '@trpc/client';
281
- import { createTRPCNext } from '@trpc/next';
282
- import { ssrPrepass } from '@trpc/next/ssrPrepass';
283
- import type { AppRouter } from '../server/routers/_app';
284
-
285
- export const trpc = createTRPCNext<AppRouter>({
286
- ssr: true,
287
- ssrPrepass,
288
- config() {
289
- return {
290
- links: [httpBatchLink({ url: '/api/trpc' })],
291
- };
292
- },
293
- responseMeta(opts) {
294
- const { clientErrors } = opts;
295
- if (clientErrors.length) {
296
- return { status: clientErrors[0].data?.httpStatus ?? 500 };
297
- }
298
- const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
299
- return {
300
- headers: new Headers([
301
- [
302
- 'cache-control',
303
- `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,
304
- ],
305
- ]),
306
- };
307
- },
308
- });
309
- ```
310
-
311
- ### CORS on the API handler
312
-
313
- ```ts title="pages/api/trpc/[trpc].ts"
314
- import { createNextApiHandler } from '@trpc/server/adapters/next';
315
- import type { NextApiRequest, NextApiResponse } from 'next';
316
- import { appRouter } from '../../../server/routers/_app';
317
-
318
- const nextApiHandler = createNextApiHandler({
319
- router: appRouter,
320
- createContext: () => ({}),
321
- });
322
-
323
- export default async function handler(
324
- req: NextApiRequest,
325
- res: NextApiResponse,
326
- ) {
327
- res.setHeader('Access-Control-Allow-Origin', '*');
328
- res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST');
329
- res.setHeader('Access-Control-Allow-Headers', '*');
330
-
331
- if (req.method === 'OPTIONS') {
332
- res.writeHead(200);
333
- return res.end();
334
- }
335
-
336
- return nextApiHandler(req, res);
337
- }
338
- ```
339
-
340
- ### Limiting batch size with maxBatchSize
341
-
342
- ```ts title="pages/api/trpc/[trpc].ts"
343
- import { createNextApiHandler } from '@trpc/server/adapters/next';
344
- import { appRouter } from '../../../server/routers/_app';
345
-
346
- export default createNextApiHandler({
347
- router: appRouter,
348
- createContext: () => ({}),
349
- maxBatchSize: 10,
350
- });
351
- ```
352
-
353
- Requests batching more than `maxBatchSize` operations are rejected with a `400 Bad Request` error. Set `maxItems` on your client's `httpBatchLink` to the same value to avoid exceeding the limit.
354
-
355
- ## Common Mistakes
356
-
357
- ### Using ssr: true without understanding implications
358
-
359
- Enabling `ssr: true` imports `react-dom` and runs `ssrPrepass` on every request, rendering the component tree repeatedly until no queries are fetching. This adds latency and server load. For better control, keep `ssr: false` (the default) and use `createServerSideHelpers` in `getServerSideProps` or `getStaticProps` to selectively prefetch only the queries you need.
360
-
361
- ### SSR prepass renders multiple times
362
-
363
- The SSR prepass loop re-renders the component tree repeatedly until all queries resolve. This is by design but causes performance issues with expensive renders. Keep SSR-rendered pages lightweight, or switch to selective prefetching with server-side helpers.
364
-
365
- ### Mixing App Router and Pages Router patterns
366
-
367
- App Router uses `fetchRequestHandler`, `createTRPCOptionsProxy`, and `@trpc/tanstack-react-query`. Pages Router uses `createNextApiHandler`, `createTRPCNext`, and `@trpc/next`/`@trpc/react-query`. Applying App Router patterns (like `HydrationBoundary` or `prefetchQuery`) in Pages Router, or vice versa, produces non-functional code.
368
-
369
- ### Forgetting to return trpcState from getStaticProps/getServerSideProps
370
-
371
- When using `createServerSideHelpers`, you must return `trpcState: helpers.dehydrate()` in props. Without this, the prefetched data is lost and queries re-fetch on the client.
372
-
373
- ```ts
374
- // WRONG
375
- return { props: { id } }; // missing trpcState!
376
-
377
- // CORRECT
378
- return { props: { trpcState: helpers.dehydrate(), id } };
379
- ```
380
-
381
- ## See Also
382
-
383
- - [server-setup] -- initTRPC, routers, procedures, context
384
- - [client-setup] -- vanilla tRPC client, links configuration
385
- - [nextjs-app-router] -- if migrating to or starting with App Router
386
- - [react-query-classic-migration] -- migrating from @trpc/react-query to @trpc/tanstack-react-query