\r\n \u003C/ZodParser>\r\n \u003C/query>\r\n \u003Cquery name=\"getUser\">\r\n \u003CProtectedProcedure>\r\n \u003CGetUserProcedure />\r\n \u003C/ProtectedProcedure>\r\n \u003C/query>\r\n \u003C/router>\r\n \u003C/SessionContext.Provider>\r\n );\r\n});\r\n```\r\n\r\nLet's break this down.\r\n\r\n# Rendering\r\nEach request corresponds to a render. Only those procedures requested will be run on each render.\r\n```ts\r\nconst AppRouter = withTRPC(() => {\r\n // ...\r\n});\r\n```\r\nThe `withTRPC` function wrapper is necessary to get `req` and `res`.\r\n\r\n# Context\r\nAll context will be done like React:\r\n```tsx\r\nconst SessionContext = createContext();\r\n\r\nconst AppRouter = withTRPC(() => {\r\n const { req, res } = useTrpcRequestContext();\r\n const session = useMemo(() => getServerAuthSession(req, res), []);\r\n\r\n return (\r\n // session will be passed down to all procedures\r\n \u003CSessionContext.Provider value={session}>\r\n {/* ... */}\r\n \u003C/SessionContext.Provider>\r\n );\r\n});\r\n```\r\n\r\n# Middleware\r\nReact already has a composition pattern so we can just hook into that for middleware:\r\n```ts\r\nconst ProtectedProcedure = (props: { children: ReactNode }) => {\r\n // session passed down from `SessionContext.Provider`\r\n const session = useContext(UserContext);\r\n\r\n // bail out if no user\r\n if (!session || !session.user) {\r\n throw new TRPCError({ code: \"UNAUTHORIZED\" });\r\n }\r\n\r\n return (\r\n \u003CUserContext.Provider value={session.user}>\r\n {props.children}\r\n \u003C/UserContext.Provider>\r\n );\r\n};\r\n```\r\n\r\n# Procedures\r\nThere are a few internal JSX elements for declaring procedures: `query`, `mutation`, and `subscription`, all which require the procedure name.\r\n```ts\r\n// this is the actual resolver for the procedure\r\nconst GreetingProcedure = () => {\r\n // automatically typed (call it a gift from God)\r\n const { name } = useArgsContext\u003C{ name: string }>();\r\n\r\n return `Hello ${name}`;\r\n};\r\n\r\nconst AppRouter = withTRPC(() => {\r\n return (\r\n \u003Crouter>\r\n {/* this marks the procedure as a query in the router tree */}\r\n \u003Cquery name=\"greeting\">\r\n \u003CGreetingProcedure />\r\n \u003C/query>\r\n \u003C/router>\r\n );\r\n});\r\n```\r\n\r\n## Input Validation\r\n```ts\r\nconst GreetingProcedure = () => {\r\n const { name } = useArgsContext();\r\n\r\n return `Hello ${name}`;\r\n};\r\n\r\nconst AppRouter = withTRPC(() => {\r\n return (\r\n \u003Crouter>\r\n \u003Cquery name=\"greeting\">\r\n {/* this parses the input data from the request and passes it on using the internal ArgsContext */}\r\n \u003CZodParser schema={z.object({ name: z.string() })}>\r\n \u003CGreetingProcedure />\r\n \u003C/ZodParser>\r\n \u003C/query>\r\n \u003C/router>\r\n );\r\n});\r\n```\r\n\r\n\r\n# Router\r\nRouters and procedures can be nested like any other JSX element:\r\n```ts\r\nconst AppRouter = withTRPC(() => {\r\n return (\r\n \u003Crouter>\r\n \u003Cquery name=\"greeting\">\r\n \u003CGreetingProcedure />\r\n \u003C/query>\r\n {/* everything under this router will be mounted at user.* */}\r\n \u003Crouter name=\"user\">\r\n {/* this mutation is mounted at user.createUser */}\r\n \u003Cmutation name=\"createUser\">\r\n \u003CZodParser schema={z.object({ name: z.string(), age: z.number() })}>\r\n \u003CCreateUserMutation />\r\n \u003C/ZodParser>\r\n \u003C/mutation>\r\n \u003C/router>\r\n \u003C/router>\r\n );\r\n});\r\n```\r\n\r\n### Describe alternate solutions\r\n\r\nMaybe Svelte or Vue could offer better syntax and typesafety 🧐\r\n\r\n### Additional information\r\n\r\n_No response_\r\n\r\n### 👨👧👦 Contributing\r\n\r\n- [X] 🙋♂️ Yes, I'd be down to file a PR implementing this feature!",[2905],{"name":2906,"color":2907},"RFC","78B062",4124,"[RFC]: tRPC Server JSX API","2023-04-21T18:01:53Z","https://github.com/trpc/trpc/issues/4124",0.6810172,{"description":2914,"labels":2915,"number":2919,"owner":2868,"repository":2868,"state":2878,"title":2920,"updated_at":2921,"url":2922,"score":2923},"Some recommendations for improvements to the API:\r\n\r\n- I don't really see any reason to split up `@trpc/server` and `@trpc/client`. I think they should be merged into a single `trpc` module. It makes the out-of-the-box experience so much cleaner.\r\n- Then the `@trpc` scope can be used for specific plugins/adapters etc. You could publish the Express adapter as `@trpc/express` for instance. That would also let you properly specify all the requisite peerDependencies (which I don't believe are specified using the current `@trpc/server/adapters/express` approach since it doesn't have its own package.json.\r\n- I think `import * as` imports are a bad user experience. I submitted a PR with a solution.\r\n- Simplify the function names: `createTRPCClient` => `createClient`, `createNextApiHandler` => `createHandler`, `CreateNextContextOptions` => `ContextOptions`. It should be standard across adapters. It's obvious that a function called `createHandler` imported from `\"@trpc/server/adapters/next\"` is creating a Next.js API handler. It doesn't need to be in the name.\r\n- The adapters should export a `createContext` function that can automatically type `opts` with the necessary types.\r\n- I think all requests (queries and mutations) should get served from a single URL. The `path` can be added as an additional query parameter for queries and in the `body` for mutations. This would also simplify the Next/Express adapters (no need for a catchall API route).\r\n\r\n\r\nLess important:\r\n\r\nI think there should be a way of manually typing the input of a resolver without passing a validator into `input`. This is easy to do if the resolver functions had two parameters instead of one. I have this working on a local branch (type inference still works the same).\r\n\r\nI propose this syntax/convention:\r\n\r\n```ts\r\nconst router = trpc.router\u003CContext>().query('test', {\r\n resolve(input: number, req) {\r\n return input;\r\n },\r\n });\r\n```\r\n\r\nThe `req` variable above if of type `{ ctx: TContext, type: ProcedureType }`. This leaves the door open to future API expansion, as `req` can act like a catchall for any additional properties we want to pass into resolvers. ",[2916],{"name":2917,"color":2918},"💬 discussion","4B318A",211,"API recommendations","2021-04-12T21:57:33Z","https://github.com/trpc/trpc/issues/211",0.68250686,{"description":2925,"labels":2926,"number":2928,"owner":2868,"repository":2868,"state":2878,"title":2929,"updated_at":2930,"url":2931,"score":2932},"## Problem\r\n\r\nCurrently, it's possible to use the old client APIs to call the new ways of defining routers and procedures and the other way around. This creates quite a heavy load on TypeScript performance as we flatten all procedures on the router, whether it's used or not.\r\n\r\nSeeing that we are stepping away from string literals, this is an undesirable bottleneck & makes tRPC slower.\r\n\r\n## Proposed solution\r\n\r\n- Procedures defined with old way (i.e. `trpc.router().query('oldProc', { resolve: () => '..' )`) should **not** be callable through a proxy, and **only** with the legacy string literals\r\n- Procedures defined with new way, (i.e. `t.router({ newProc: t.query(() => '..') })`), should not be callable **except through a proxy**\r\n\r\n## Implications\r\n\r\n- Proxy will be the only way to call things in the default tRPC clients\r\n- People who want to support environments [which can't support `Proxy`](https://caniuse.com/#search=Proxy) will need another tRPC client *(TBD if we make one of those ourselves)*\r\n- We need to change the way we define interop mode on the client\r\n- We will deprecate `createTRPCClient` & `createReactQueryHooks` in favor of proxy-based APIs\r\n- We will need to define interop clients or make the current clients automatically expose a `.proxy` object\r\n- This **should not** make incremental migration from v9->v10 harder\r\n\r\n\r\n## Proposed APIs\r\n\r\nGiven the following backend:\r\n\r\n```ts\r\nconst t = initTRPC()();\r\nconst legacyRouter = trpc\r\n .router()\r\n .query('legacyProc', {\r\n input: z.string().optional(),\r\n resolve({ input }) {\r\n return `hello ${input ?? 'world'}`;\r\n },\r\n })\r\nconst newAppRouter = t.router({\r\n newProc: t.procedure.query(() => \"I am just a test, I don't know! \"),\r\n});\r\nconst appRouter = t.mergeRouters(legacyRouter.interop(), newAppRouter);\r\n```\r\n\r\n### `@trpc/client`\r\n\r\n**New way of creating a client:**\r\n```ts\r\n// Create new client\r\nconst client = createTRPCProxyClient\u003CAppRouter>({ \r\n url: 'http://localhost:3001',\r\n})\r\n\r\n// Usage:\r\nclient.newProc.query();\r\n```\r\n\r\n**Interop:**\r\n\r\n```ts\r\n// Will show deprecation error\r\nconst client = createTRPCClient\u003CAppRouter>({\r\n url: 'http://localhost:3001',\r\n})\r\n\r\n// Expose a proxy prop automatically:\r\nconst proxy = client.proxy;\r\n\r\n// ✅ These calls will work\r\nproxy.newProc.query();\r\nclient.query('legacyProc');\r\n\r\n// ❌ These will now show TypeScript error\r\nproxy.legacyProc.query();\r\nclient.query('newProc');\r\n```\r\n\r\n### `@trpc/react`\r\n\r\n**New default way of creating a client:**\r\n\r\n```tsx\r\nconst trpc = createTRPCReact\u003CAppRouter>();\r\n\r\n// Calls:\r\ntrpc.newProc.useQuery();\r\n```\r\n\r\n**Interop:**\r\n\r\n```tsx\r\nconst trpc = createReactQueryHooks\u003CAppRouter>();\r\n\r\nconst proxy = trpc.proxy;\r\n\r\n// ✅ These calls will work\r\nproxy.newProc.useQuery();\r\ntrpc.useQuery(['legacyProc']);\r\n\r\n// ❌ These will now show TypeScript error\r\nproxy.legacyProc.useQuery();\r\ntrpc.useQuery(['newProc']);\r\n```\r\n",[2927],{"name":2906,"color":2907},2311,"[v10] Make interop non-proxy string literals & and new proxy calls mutually exclusive","2022-10-04T00:18:25Z","https://github.com/trpc/trpc/issues/2311",0.683163,{"description":2934,"labels":2935,"number":2945,"owner":2868,"repository":2868,"state":2878,"title":2946,"updated_at":2947,"url":2948,"score":2949},"So. We're making a new major. \r\n\r\n\r\n\r\n\r\n\r\n## Goals\r\n\r\n- **More ergonomic API for creating procedures** and building out your backend\r\n- **CMD+Click** from your frontend and jump straight into the backend procedure. This will work with `react-query` as well!\r\n- **Better scaling** than the current structure - the TypeScript server starts choking a bit when you get close to 100 procedures in your backend\r\n- **Fully backward compatible** for the 99% use-case with a migration path which you can do incrementally. \r\n\r\n\r\n## Todos\r\n\r\n> **Important for contributors:** All of the work here is related to the [`next`](https://github.com/trpc/trpc/tree/next) branch.\r\n\r\n\r\nTracked in https://github.com/orgs/trpc/projects/1\r\n\r\n- [x] New Router API\r\n - [x] Tracked in [trpc/v10-playground](https://github.com/trpc/v10-playground) - the current winning proposal is https://github.com/trpc/v10-playground/pull/33\r\n - [x] Error formatting in new API - [`formatError()`](https://trpc.io/docs/error-formatting)-equivalent. \r\n - [x] `meta`-equivalent\r\n - [x] Maybe we need a `createRootRouter()` that additionally accepts `{ transformer: X, formatError: Y}`\r\n - [x] Implement new API in tRPC\r\n - [x] Make old routers compatible (`.legacy()` at the end to transform them to the new version)\r\n- [x] New client API with backward compatibility \r\n - Maybe old can be `client.query('postById', input, options)` whilst new stuff can be `client.queries.postById({ input, ...options})`\r\n- [x] New react-query API with backward compat\r\n- [ ] Make actual issues for all of these\r\n- [x] Add all old projects in a folder (copy/paste `examples/*` to `examples/.test` so we can track breaking changes easily and make sure we remain backward compatible for a long time\r\n- [ ] Rewrite `TRPCClient` to be functional instead of a class but reuse the same interface\r\n- [ ] Write a migration guide\r\n - [ ] New router API\r\n - [ ] New links\r\n- [x] Move transformers back to `runtime` to make it backward compatible\r\n- [ ] Explore: Add [`stripInternal`](https://www.typescriptlang.org/tsconfig#stripInternal)-flag\r\n- [x] Simplify HTTP-responses\r\n- [x] New links architecture (#1366)\r\n- [ ] Refactor observables implementation to have `unknown` errors or make it guaranteed to be `TRPCClientError` of some sort. \r\n- [ ] Make transformers dynamically opt-in similar to how a batch request is indicated by `?batch=1` maybe a transformed request could be `?transform=1` or `transform=TRANSFORMER_NAME`?\r\n- [ ] Write a blog post about new major and API.\r\n- [ ] \"Marketing\"? Hype video, new website, etc\r\n- [ ] Decide on structure for react-query integration\r\n- [ ] Add old website on `www/`-docs as `v9.trpc.io`\r\n - [ ] Link it in Docusaurus\r\n - [ ] Make sure we have deployment for a \"v9\"-branch\r\n\r\n### Stretch\r\n\r\n- [ ] Add DTO for clients without transformers - #1694\r\n- [x] #1597\r\n- [x] New Subscriptions API (nice to have) - #1596 \r\n- [ ] `trpc.output.snapshot()` https://github.com/trpc/trpc/issues/3435\r\n\r\n\r\n\r\n\r\n\r\n\u003Cdetails>\u003Csummary>Old notes\u003C/summary>\r\n\r\n## Definite\r\n\r\n- [x] Remove official support for node `12.x`\r\n - [x] Remove E2E-test for 12.x\r\n - [x] Change `tsconfig` build target\r\n- [ ] Add official support for node `16.x`\r\n- [ ] Add `stripInternal`-flag\r\n- [x] Remove all `@deprecated` stuff\r\n - [x] Remove `LegacyRouter` introduced in #915\r\n - [ ] [...]\r\n- [x] New links architecture (#1366)\r\n- [ ] Move official support for `react-query` `3` to `4`\r\n- [ ] Simplify HTTP-responses\r\n - [ ] From `{ id:null, result: {type: 'data', data: x } }` -> `{ result: { data: x } }`\r\n - [ ] maybe remove `id: null` from HTTP responses?\r\n- [ ] Migration guides for all changed parts\r\n - [ ] New Links\r\n\r\n\r\n## Maybe ❓ \r\n\r\n> Feedback please!\r\n\r\n\r\n- [x] Optimize so router inference only needs to be done once? #1218 \r\n- [ ] ~Update so procedures needs to return `{ data: x }` instead of just `x` so we could add metadata and potentially discriminated union of `{ data: x } | { error: y }` ~\r\n- [x] Decide: \r\n - Pipe-based rather than object resolvers? `{ input: z.string(), resolve({input}) {}}` -> `t.pipe(t.input(z.string), ({input}) => \r\n - Chained resolvers\r\n- [x] Plan how to deal with degrading typescript performance when approaching ~100 procedures (there are no runtime issues, but the DX slows down) \r\n- [ ] Turn `client.query` result into `[ output, { meta } ]`\r\n- [ ] New `useQuery()` API that expects suspense as default - See this gist: https://gist.github.com/KATT/aa1ad532d6e57520b942f657569e1505\r\n- [ ] Refactor `@trpc/server` to easier work with CloudFlare-workers etc (#1375)\r\n- [ ] Collaborate with Blitz.js? https://github.com/blitz-js/blitz/discussions/3083#discussioncomment-1841427\r\n- [ ] https://jsonapi.org/format/\r\n\r\n### Transformers\r\n\r\n- [x] Turn transformers into a link on the client (#1366)\r\n- [ ] Revert above and put transformers back to runtime 😬 \r\n- [ ] ~Turn transformers into a middleware on the server~\r\n- [ ] Make transformers dynamically opt-in similar to how a batch request is indicated by `?batch=1` maybe a transformed request could be `?transform=1` or `transform=TRANSFORMER_NAME`?\r\n\r\n### Misc\r\n\r\n- [ ] Rename `@trpc/react/ssg` -> `@trpc/react/ssr` & `createSSGHelpers` -> `createServerSideHelpers` (or something, as it is often used in `getServerSideProps()` as well as `getStaticProps()`)\r\n\r\n## Open questions\r\n\r\n- Should we continue to follow OpenRPC?\r\n- Any changes that could make tRPC easier to support stuff like Svelte/Vue?\r\n- Any changes that could make tRPC stricter support stuff like AWS Lambdas? (Already is doable to do Lambdas but through an Express->Lambda converter) #882 \r\n- Ideas?\r\n\r\n\r\n\r\n\u003C/details>",[2936,2939,2942],{"name":2937,"color":2938},"🙏 review please","A7356F",{"name":2940,"color":2941},"💸 Get paid!","c2e0c6",{"name":2943,"color":2944},"next-major/definite","5319E7",887,"[RFC] Next major overview","2022-12-19T22:11:47Z","https://github.com/trpc/trpc/issues/887",0.68340564,{"description":2951,"labels":2952,"number":2953,"owner":2868,"repository":2868,"state":2878,"title":2954,"updated_at":2955,"url":2956,"score":2957},"### Describe the feature you'd like to request\r\n\r\nWhen defining routers which have common interfaces, it can be helpful to also define common UI which just needs to be informed about the particular route it will be using. For instance:\r\n\r\n```tsx\r\n// Route structure like: { foo: { create, update, list, delete }, bar: { create, update, list, delete } }\r\nconst trpc = createTRPCReact \r\n\r\ntype CrudRoute = typeof trpc.bar\r\n\r\nfunction MyComponent({ route }: { route: CrudRoute }) {\r\n const createMutation = route.create.useMutation()\r\n const listQuery = route.delete.useQuery({ /* paging params */ })\r\n\r\n return /* ui */\r\n}\r\n\r\nfunction MyScreen() {\r\n // We then pass a route which matches the interface but isn't the one the type was derived from\r\n // Error because the query key does not match!\r\n return \u003CMyComponent route={trpc.foo} />\r\n}\r\n```\r\n\r\nCurrently for even the most basic example, this doesn't work because `DecoratedProcedureRecord` calculates `TPath` based on the full path to a procedure name and down the type chain into react query's `TQueryKey` on `QueryObserverOptions`. TPath/TQueryKey is important type information of course.\r\n\r\nIt would be helpful to have some type utilities provided which can extract the abstract type information from a Route/Procedure and produce a type which can be used for polymorphism. The design of this I'm not too sure as fairly complex cases might exist where parameter/return types may vary slightly but have some common underlying interface.\r\n\r\n### Describe the solution you'd like to see\r\n\r\nA proof of concept for the simple use case (where the underlying interface of the procedures is identical) looks like this:\r\n\r\n```tsx\r\nimport { AnyProcedure, AnyRouter, ProcedureRouterRecord } from '@trpc/server'\r\nimport {\r\n DecoratedProcedureRecord,\r\n DecorateProcedure,\r\n} from '@trpc/react-query/dist/shared'\r\n\r\ntype AbstractDecoratedProcedureRecord\u003C\r\n TProcedures extends ProcedureRouterRecord,\r\n TFlags\r\n> = {\r\n [TKey in keyof TProcedures]: TProcedures[TKey] extends AnyRouter\r\n ? AbstractDecoratedProcedureRecord\u003C\r\n TProcedures[TKey]['_def']['record'],\r\n TFlags\r\n >\r\n : TProcedures[TKey] extends AnyProcedure\r\n ? DecorateProcedure\u003CTProcedures[TKey], TFlags, any>\r\n : never\r\n}\r\n\r\n/**\r\n * Given a tRPC react route, calculates the abstract type so that similar interfaces can be passed polymorphically\r\n *\r\n * Ie. For: `trpc.routeA.routeB = { procA, procB }`\r\n * Usage: `AbstractProcedureRecord\u003Ctypeof trpc.routeA.routeB>`\r\n */\r\nexport type AbstractProcedureRecord\u003C\r\n T extends DecoratedProcedureRecord\u003Cany, any, any>\r\n> = T extends DecoratedProcedureRecord\u003Cinfer TProcedures, infer TFlags, any>\r\n ? AbstractDecoratedProcedureRecord\u003CTProcedures, TFlags>\r\n : never\r\n\r\n//\r\n// Usage\r\n//\r\n\r\nimport { trpc } from './react-client/api'\r\n\r\nexport type RouteDef = BaseProcedureRecord\u003C\r\n typeof trpc.foo\r\n>\r\n\r\n// Now any matching interface can be assigned polymorphically\r\nconst r1: RouteDef = trpc.foo\r\nconst r2: RouteDef = trpc.bar\r\n```\r\n\r\n### Describe alternate solutions\r\n\r\nThere is a lot more to this, the above solution may not work where routes don't have the exact same interface. The full solution might involve taking the recursive union of an arbitrary number of route types which could get hairy\r\n\r\n```\r\ntype AbstractProcedureRecord\u003CT1, T2, T3, ...TEtc> = /* calculate the common abstract type */\r\n```\r\n\r\nOr less hackily, maybe a way to actually define an interface which a Router must implement on the API side, and then provide an API to use these interfaces alongside the React Client library\r\n\r\n### Additional information\r\n\r\n_No response_\r\n\r\n### 👨👧👦 Contributing\r\n\r\n- [x] 🙋♂️ Yes, I'd be down to file a PR implementing this feature!",[],3627,"feat: Polymorphic tRPC routes in react client","2023-02-22T18:01:56Z","https://github.com/trpc/trpc/issues/3627",0.69015914,{"description":2959,"labels":2960,"number":2961,"owner":2868,"repository":2868,"state":2878,"title":2962,"updated_at":2910,"url":2963,"score":2964},"### Describe the feature you'd like to request\n\n`createCaller` lets us get a \"client\" that we can use to invoke a router implementation directly (in memory). `createTRPCProxyClient` lets us get a \"true\" client that we can use to invoke a router using actual remote calls. Currently, the types of objects returned by these functions are different, meaning that it's not possible to use a common interface to abstract over whether or not a call is in-memory or over the wire. Specifically, proxy methods must be called with `.query()` or `.mutate()` chains, while caller methods can be executed directly.\r\n\r\nHaving a common interface would be useful when e.g. building a monolith that will later be decomposed, or decomposing an existing monolith in which tRPC is being used to systematically wrap existing components. As an example, suppose an order service depends on a payment service:\r\n\r\n```typescript\r\nfunction createPaymentsRouter() {\r\n return t.router({\r\n takePayment: t.procedure.mutation(() => ...),\r\n })\r\n}\r\n\r\nfunction createOrdersRouter(paymentsService) {\r\n return t.router({\r\n createOrder: t.procedure.mutation(() => ... paymentsService.takePayment.mutate(...) ...)\r\n })\r\n}\r\n```\r\n\r\nIt'd be nice if we could pass either `paymentsRouter.createCaller({})` or `createTRPCProxyClient\u003Ctypeof paymentsRouter>({ links: ... })` to `createOrdersRouter`, depending on whether we are composing into a monolith or a set of discrete services. Currently this isn't possible since if we pass a caller, `.mutate()` doesn't exist, and if we pass a proxy, `takePayment` is not itself callable. Hopefully this makes sense, and thanks for the amazing library!\n\n### Describe the solution you'd like to see\n\nI can think of a few possible solutions, but each has its drawbacks and all may be unsuitable given my ignorance of tRPC's internals:\r\n\r\n1. Have `createCaller` return an object whose methods must be chained with `.query` and `.mutate`. `createCaller`'s return type now aligns with that of `createTRPCProxyClient`. This would be a breaking change as it would change the interface of `createCaller` in a non-backwards-compatible manner.\r\n2. Have `createTRPCProxyClient` return an object whose methods are directly callable. I'm sure there's a good reason that proxies have `.query` and `.mutate` chain finalisers, so this is probably untenable, but if it's e.g. just cosmetic then we could look at making the properties directly callable, rather than having `.query` or `.mutate` child properties. Moreover, we could offer both interfaces (so that e.g. `.takePayment` is a `Function` with an additional `.mutate` property that calls the same code), which would be backwards compatible (I think).\r\n3. Create a new version of `createCaller` or `createProxyTRPCClient` (or both) with compatible types.\r\n4. Create a new type of `link` that makes an in-memory call, so that `createTRPCProxyClient` subsumes `createCaller`'s functionality.\n\n### Describe alternate solutions\n\n(See above)\n\n### Additional information\n\n_No response_\n\n### 👨👧👦 Contributing\n\n- [X] 🙋♂️ Yes, I'd be down to file a PR implementing this feature!",[],3335,"feat: Align createCaller with createTRPCProxyClient","https://github.com/trpc/trpc/issues/3335",0.69149846,["Reactive",2966],{},["Set"],["ShallowReactive",2969],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$fkpgb6Qh2Kxxbk3IoGCr7ZsyfgeFrHQajzowR-JqdcWM":-1},"/trpc/trpc/2806"]