{"version":3,"file":"ssrPrepass.mjs","names":["result: TState","newError: TRPCClientErrorLike<any>","ssrPrepass: TRPCPrepassHelper","appOrPageCtx: AppContextType","ctx: NextPageContext","pageProps: Dict<unknown>","props: Record<string, unknown>","trpcProp: $PrepassProps"],"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]\n    | 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":";;;;;;;;;AAuBA,SAAS,oCAIPA,QAAwB;CACxB,MAAM,QAAQ,OAAO,MAAM;AAC3B,KAAI,iBAAiB,SAAS,MAAM,SAAS,mBAAmB;EAC9D,MAAMC,WAAqC;GACzC,SAAS,MAAM;GACf,MAAM,MAAM;GACZ,OAAO,MAAM;EACd;AACD,iFACK,eACH,+EACK,OAAO,cACV,OAAO;CAGZ;AACD,QAAO;AACR;AAED,MAAaC,aAAgC,CAAC,SAAS;CACrD,MAAM,EAAE,QAAQ,UAAU,WAAW,GAAG;CAGxC,MAAM,cAAc,eACjB,OAAwC,YAC1C;AACD,UAAS,kBAAkB,OAAOC,iBAAiC;;EACjE,MAAM,YAAY,YAAY;AAC5B,cAAW,WAAW,YACpB,QAAO;AAET,cAAW,OAAO,QAAQ,WACxB,KAAI;AACF,WAAO,MAAM,OAAO,IAAI,EAAE,KAAK,aAAa,IAAK,EAAC;GACnD,kBAAO;AACN,WAAO;GACR;AAEH,UAAO,OAAO;EACf;EACD,MAAM,aAAa,MAAM,WAAW;EACpC,MAAM,UAAU,aAAa;EAG7B,MAAM,UAAU,aAAa;EAC7B,MAAMC,MAAuB,QACzB,aAAa,MACZ;EAGL,IAAIC,YAA2B,CAAE;AACjC,MAAI,UAAU,iBAAiB;;GAC7B,MAAM,gBAAgB,MAAM,UAAU,gBACpC,aACD;GACD,MAAM,oBAAoB,iCACrB,cAAc,kFAAa,CAAE,IAC9B;AAEJ,uFACK,oBACA;EAEN;EACD,MAAM,kBAAkB,CAACC,UACvB,QAAQ,EAAE,WAAW,MAAO,IAAG;AAEjC,aAAW,WAAW,gBAAgB,WACpC,QAAO,gBAAgB,UAAU;EAGnC,MAAM,SAAS,OAAO,OAAO,EAAE,IAAK,EAAC;EACrC,MAAM,aAAa,wBAAwB,OAAO;EAClD,MAAM,cAAc,eAAe,OAAO;EAE1C,MAAMC,WAA0B;GAC9B;GACA;GACA;GACA,UAAU;GACV,YAAY;EACb;EACD,MAAM,eAAe;GACnB;GACA,MAAM;EACP;EAED,MAAM,iBAAiB,MAAM,OAAO;AAIpC,SAAO,MAAM;AAEX,kBAAe,eAAe,cAAc,SAAS,aAAa,CAAC;AACnE,QAAK,YAAY,YAAY,CAE3B;AAIF,SAAM,IAAI,QAAc,CAAC,YAAY;IACnC,MAAM,QAAQ,YAAY,eAAe,CAAC,UAAU,CAAC,UAAU;AAC7D,wDAAI,MAAO,MAAM,mBAAmB,MAAK,GAAG;AAC1C,eAAS;AACT,aAAO;KACR;IACF,EAAC;GACH;EACF;EACD,MAAM,kBAAkB,UAAU,aAAa,EAC7C,qBAAqB,OAAO;GAE1B,MAAM,oBACJ,MAAM,MAAM,gBAAgB,UAC5B,MAAM,MAAM,WAAW;AACzB,WAAQ;EACT,EACF,EAAC;EAEF,MAAM,oGACD;GACH,SAAS,gBAAgB,QAAQ,IAAI,oCAAoC;GACzE,WAAW,gBAAgB,UAAU,IACnC,oCACD;;AAIH,YAAU,eAAe,YAAY,MAAM,UACzC,0BACD;EAED,MAAM,eAAe,gBAAgB,UAAU;EAE/C,MAAM,wDACJ,OAAO,sEAAP,mCAAsB;GACpB;GACA,cAAc,CAAC,GAAG,gBAAgB,SAAS,GAAG,gBAAgB,SAAU,EACrE,IAAI,CAAC,MAAM,EAAE,MAAM,MAAM,CACzB,QAAQ,CAAC,QACR,eAAe,SAAS,IAAI,SAAS,oBACjC,CAAC,GAAkC,IACnC,CAAE,EACP;EACJ,EAAC,uEAAI,CAAE;AAEV,OAAK,MAAM,CAAC,KAAK,MAAM,IAAI,OAAO,yBAAQ,KAAK,gEAAW,CAAE,EAAC,CAC3D,YAAW,UAAU,UAAU;;AAC7B,mBAAI,wCAAJ,SAAS,UAAU,KAAK,MAAM;EAC/B;AAEH,MAAI,KAAK,UAAU,IAAI,IACrB,KAAI,IAAI,aAAa,KAAK;AAG5B,SAAO;CACR;AACF"}