@trpc/next
Version:
1 lines • 11 kB
Source Map (JSON)
{"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"}