\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.67093146,{"description":2915,"labels":2916,"number":2931,"owner":2871,"repository":2871,"state":2885,"title":2932,"updated_at":2933,"url":2934,"score":2935},"### Provide environment information\n\n System:\r\n OS: Windows 11 10.0.22631\r\n CPU: (12) x64 AMD Ryzen 5 5600X 6-Core Processor\r\n Memory: 10.76 GB / 31.95 GB\r\n Binaries:\r\n Node: 18.19.1 - C:\\Program Files\\nodejs\\node.EXE\r\n npm: 10.2.4 - C:\\Program Files\\nodejs\\npm.CMD\r\n pnpm: 8.15.4 - ~\\AppData\\Local\\pnpm\\pnpm.EXE\r\n Browsers:\r\n Edge: Chromium (130.0.2849.68)\r\n Internet Explorer: 11.0.22621.3527\r\n npmPackages:\r\n @tanstack/react-query: ^5.60.6 => 5.60.6\r\n @trpc/client: ^11.0.0-rc.638 => 11.0.0-rc.638+09a76869e\r\n @trpc/react-query: ^11.0.0-rc.638 => 11.0.0-rc.638+09a76869e\r\n @trpc/server: ^11.0.0-rc.638 => 11.0.0-rc.638+09a76869e\r\n next: 15.0.3 => 15.0.3\r\n react: 19.0.0-rc-66855b96-20241106 => 19.0.0-rc-66855b96-20241106\r\n typescript: ^5 => 5.6.3\r\n\n\n### Describe the bug\n\nAfter creating an object from the method \"createTRPCReact\" there is no the method \"createClient\" or any procedures in it.\r\n\r\n`const trpc = createTRPCReact\u003CAppRouter>();\r\n\r\ntrpc.\u003C...no createClient or procedures..>`\r\n\n\n### Link to reproduction\n\nhttps://stackblitz.com/edit/github-is5mgb?file=src%2Fserver%2Ftrpc.ts\n\n### To reproduce\n\nIt's easy to reproduce - clean Nextjs project and instructions from quickstart from react query integration\n\n### Additional information\n\nI investigated working code from @jherr [repo](https://github.com/jherr/trpc-on-the-app-router.git) the file createTRPCReact.tsx was much changed - almost 300 rows were added and the main method \"createTRPCReact\" was changed\r\n\r\n/------ working version of the method --------/\r\n`export function createTRPCReact\u003C\r\n TRouter extends AnyRouter,\r\n TSSRContext = unknown,\r\n TFlags = null,\r\n>(\r\n opts?: CreateTRPCReactOptions\u003CTRouter>,\r\n): CreateTRPCReact\u003CTRouter, TSSRContext, TFlags> {\r\n const hooks = createHooksInternal\u003CTRouter, TSSRContext>(opts);\r\n const proxy = createHooksInternalProxy\u003CTRouter, TSSRContext, TFlags>(hooks);\r\n\r\n return proxy as any;\r\n}`\r\n/------------------------------------------------/\r\n\r\n/---------------- not working -----------------/\r\n`export function createTRPCReact\u003C\r\n TRouter extends AnyRouter,\r\n TSSRContext = unknown,\r\n>(\r\n opts?: CreateTRPCReactOptions\u003CTRouter>,\r\n): CreateTRPCReact\u003CTRouter, TSSRContext> {\r\n const hooks = createRootHooks\u003CTRouter, TSSRContext>(opts);\r\n const proxy = createHooksInternal\u003CTRouter, TSSRContext>(hooks);\r\n\r\n return proxy as any;\r\n}\r\n`\r\n\r\n\n\n### 👨👧👦 Contributing\n\n- [ ] 🙋♂️ Yes, I'd be down to file a PR fixing this bug!",[2917,2920,2923,2926,2929],{"name":2918,"color":2919},"👻 invalid","e4e669",{"name":2921,"color":2922},"🔎 needs more investigation/info","d4c5f9",{"name":2924,"color":2925},"⏮ needs reproduction","000055",{"name":2927,"color":2928},"🐛 bug: unconfirmed","e99695",{"name":2930,"color":2922},"⏳ close if no activity",6252,"bug: Can't create \"createClient\" after creating \"createTRPCReact\u003CAppRouter>()\"","2025-03-20T15:42:43Z","https://github.com/trpc/trpc/issues/6252",0.6745847,{"description":2937,"labels":2938,"number":2939,"owner":2871,"repository":2940,"state":2885,"title":2941,"updated_at":2942,"url":2943,"score":2944},"To take the example from the README, if I create a router with the endpoint:\r\n```typescript\r\n...\r\n sayHello: t.procedure\r\n .meta({ openapi: { method: 'GET', path: '/say-hello/{name}' /* 👈 */ } })\r\n .input(z.object({ name: z.string() /* 👈 */, greeting: z.string() }))\r\n .output(z.object({ greeting: z.string() }))\r\n .query(({ input }) => {\r\n return { greeting: `${input.greeting} ${input.name}!` }\r\n }),\r\n```\r\n\r\nAnd then later I create a client from this router like this:\r\n```typescript\r\nconst client = createTRPCProxyClient\u003CAppRouter>({\r\n links: [httpBatchLink({ url: \"...\" }),\r\n ],\r\n})\r\n```\r\nAnd then finally invoke the client on this endpoint like this:\r\n```typescript\r\nawait client.sayHello.query({ greeting: 'hello', name: 'foobar' })\r\n```\r\nthe client his an url at `/sayHello?batch=1&input=%7B%220%22%3A%7B%22greeting%22%3A%22hello%22%2C%22name%22%3A%22foobar%22%7D%7D` rather than `/say-hello?/foobar`.\r\n",[],259,"trpc-openapi","createTRPCProxyClient from @trpc/client does not respect the openapi path field","2023-02-24T19:30:24Z","https://github.com/trpc/trpc-openapi/issues/259",0.67559266,{"description":2946,"labels":2947,"number":2951,"owner":2871,"repository":2871,"state":2885,"title":2952,"updated_at":2953,"url":2954,"score":2955},"The new v10 trpc server looks clean, such as the following code snippet:\r\n\r\n```ts\r\nconst postRouter = trpc.router({\r\n queries: {\r\n getAllPosts: protectedProcedure.resolve(() => postsDb),\r\n postById: protectedProcedure\r\n}})\r\n```\r\nThe object based approach works a lot better than defining query endpoints as string. However, the client side feels left behind and out of sync with the syntax with the server side. Personally, I would like to propose a new api / syntax for the client. \r\n\r\n\r\n```ts\r\n// I don't know how the typescript is structured. I will use this type as an example.\r\ntype AppRouter = {\r\n posts: {\r\n getAll: Function,\r\n postById: Function,\r\n }\r\n}\r\n \r\ntype AppRouterFlat = {\r\ngetAllPosts: Function,\r\n postById: Function,\r\n}\r\n\r\n// just like normal instantiate the client \r\n// const api = createTRPCClient\u003CAppRouter>({\r\n// url: 'http://localhost:5000/trpc',\r\n// });\r\n// For simplicity lets say the relation between api and AppRouter is this after client creation:\r\n\r\nconst api : AppRouter = {}; // currently this gives an error, but don't bother \r\n\r\n// now typescript says this is possible with intellisense.\r\nconst posts = api.posts.getAll(); \r\nconst post = api.posts.postById(2); /// \u003C--- I propose this kind of api \r\n\r\n```\r\nI propose just like the server an object based approach to fetch on client. An experienced developer will spot these code lines will produce errors, like `getAll is not function` and `posts is undefined` and other missing key errors. This will all explained in the technical details. At this moment, I just want to point out the api / syntax. \r\n\r\nnote: It doesn't matter what the type structure is (`AppRouter` or `AppRouterFlat`), it is about the intellisense typescript gives. \r\n\r\n## Technical details\r\nWhen you see this code you will immediately think I am a javascript noob as all of the mentioned above produces errors. So how do you implement this? How do you solve these errors? A year ago I read a medium post (unfortunately lost) about a npm package that was able to transform objects in url fetch endpoints, such as \r\n\r\n```ts\r\napi.orders.id(33) // will be transformed in api/orders/33\r\n```\r\n *If you know this package please commented it below*\r\n\r\nIn the context of trpc the following transformation is needed. \r\n```ts\r\napi.posts.postById(33) // should be transformed to { endpoint: 'api-posts-postById', data: [33] } \r\n```\r\n\r\nMy tinkered late night code below is working example of how to achieve this \r\n\r\n```ts\r\ntype AppRouter = {\r\n orders: {\r\n getAll: Function,\r\n postById: Function,\r\n }\r\n}\r\n\r\nconst handlers = {\r\n apply: function (target, thisArg, argumentsList) {\r\n const path = target._path;\r\n console.log(` Fetch ${path} with these arguments ${argumentsList} `);\r\n },\r\n get(target, prop) {\r\n // this is needed, otherwise _path would become a function/object (this makes also possible to use additional keys on the //beginning object such as setConfig()\r\n if (prop in target) return prop;\r\n console.log(` unknown prop ${prop} was accessed `);\r\n const f = new Function();\r\n\r\n f._path = `${target._path || \"\"}.${prop}`;\r\n const next = new Proxy(f, handlers);\r\n\r\n return next;\r\n },\r\n};\r\n\r\nconst start_object = new Function();\r\nstart_object._path = \"api\";\r\nconst $api = new Proxy(start_object, handlers);\r\n\r\n$api.orders.getAll(\"a\", \"b\", \"c\");\r\n// > Fetch api.orders.getAll with these arguments a,b,c \r\n\r\n```\r\ncomments: \r\n- I left out the comments as I don't know how to document it right, so here are some comments. \r\n- is use proxies to solve the missing key errors. \r\n- Functions are needed making it possible to be `api.orders` and `api.orders()`. \r\n- _path saves the path like `api.orders.getAll`\r\n- When somewhere a function is called, handlers.apply is called. \r\n- this is *an* implementation not *the* implementation, rather a proof of concept. I use the proxy syntax never, but vue's reactivity system uses it.\r\n\r\n## Final notes\r\nI trying my best to make it easy to grasp, Try the code provided in technical details in your own sandbox to understand a little bit better how it works. Personally, I think this is the easiest syntax as it feels like your calling a function on your backend. I also understand this not Graphql like syntax. Potentially you can have multiple client interfaces. To be honest, I only know this library for a couple of days, because Theo appeared in my youtube feed. So I also don't know if this syntax is in line with the vision of trpc. \r\n\r\nAfter all, I still wanted to show this javascript trickery and proposal, especially after the many hours figuring it out. Do not hesitate to ask further questions if something is unclear. \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n",[2948],{"name":2949,"color":2950},"💡 ideas","bfdadc",2215,"Documentation Proxy Api and @trcp/client","2022-10-04T06:09:12Z","https://github.com/trpc/trpc/issues/2215",0.68003535,{"description":2957,"labels":2958,"number":2959,"owner":2871,"repository":2871,"state":2885,"title":2960,"updated_at":2961,"url":2962,"score":2963},"### Describe the feature you'd like to request\r\n\r\nI would like a link for `createTRPCProxyClient` that behaves like `router.createCaller`.\r\n\r\nThis allows a server-side rendered web app to choose whether to use a remote backend or a local backend. See below picture for explanation of the scenario.\r\n\r\n\u003Cimg width=\"1153\" alt=\"image\" src=\"https://user-images.githubusercontent.com/193136/235290100-47a18440-0a17-4acf-8218-69524cdfe6c3.png\">\r\n\r\n### Describe the solution you'd like to see\r\n\r\nBasic usage:\r\n\r\n```ts\r\n// Server-side code\r\nimport { createTRPCProxyClient } from '@trpc/client';\r\nimport { directLink } from '@trpc/client/????';\r\nimport type { AppRouter } from '../server';\r\n\r\nfunction createServerSideClient(authToken?: string) {\r\n return createTRPCProxyClient\u003CAppRouter>({\r\n links: [\r\n directLink({\r\n router: () => import('../server').then(s => s.AppRouter),\r\n context: { authToken },\r\n }),\r\n ],\r\n });\r\n}\r\n```\r\n\r\nUsage in above scenario\r\n\r\n```ts\r\n// Server-side code\r\nimport { createTRPCProxyClient, httpLink } from '@trpc/client';\r\nimport { directLink } from '@trpc/client/????';\r\nimport type { AppRouter } from '../server';\r\n\r\nfunction createServerSideClient(authToken?: string) {\r\n return createTRPCProxyClient\u003CAppRouter>({\r\n links: [\r\n process.env.BACKEND\r\n ? httpLink({\r\n url: process.env.BACKEND,\r\n }),\r\n : directLink({\r\n router: () => import('../server').then(s => s.AppRouter),\r\n context: { authToken },\r\n }),\r\n ],\r\n });\r\n}\r\n```\r\n\r\n\r\n\r\n### Describe alternate solutions\r\n\r\n**Alternative A:** We could make an HTTP request to localhost.\r\n\r\n- Overhead of making an actual HTTP request (albeit to localhost).\r\n- Sometimes it is unclear which port the server is running on, especially in serverless providers like Vercel/Netlify. On such environments, detecting which port the server is running in may require brittle code that peeks into the serverless runtime’s implementation details. Alternatively we can run a secondary web server from the application side, which could mean more complex code and overhead.\r\n\r\n**Alternative B:** Hijack `httpLink`’s `fetch` implementation to send the request directly to the tRPC router instead of making a network call.\r\n\r\n- This is what we are using. It is very hacky but works flawlessly!\r\n\r\n```ts\r\nimport { fetchRequestHandler } from '@trpc/server/adapters/fetch'\r\nimport { createTRPCProxyClient, httpLink } from '@trpc/client';\r\nimport type { AppRouter } from '../server';\r\n\r\nexport function createServerSideClient(authToken?: string) {\r\n const url = process.env.BACKEND || 'http://fake'\r\n\r\n return createTRPCProxyClient\u003CAppRouter>({\r\n links: [\r\n httpBatchLink({\r\n url,\r\n headers: authToken ? {\r\n authorization: `Bearer ${authToken}`\r\n } : {},\r\n fetch: async (input, init) => {\r\n if (\r\n typeof input === 'string' &&\r\n input.startsWith('http://fake')\r\n ) {\r\n const request = new Request(input, init as RequestInit)\r\n const { createContextFromRequest, AppRouter } = await import('../server')\r\n return fetchRequestHandler({\r\n endpoint: prefix,\r\n req: request,\r\n router: AppRouter,\r\n createContext: ({ req }) => {\r\n return createContextFromRequest(req)\r\n },\r\n })\r\n }\r\n return fetch(input, init as RequestInit)\r\n },\r\n }),\r\n ],\r\n })\r\n}\r\n```\r\n\r\n\r\n\r\n### Additional information\r\n\r\nSee actual implementation here\r\n\r\n- https://github.com/creatorsgarten/contentsgarten/blob/258e746519b49e49b93e81e0d19f90553d51f5b4/packages/server-utils/src/index.ts#L9-L34\r\n- https://github.com/creatorsgarten/contentsgarten/blob/258e746519b49e49b93e81e0d19f90553d51f5b4/packages/contentsgarten/src/Contentsgarten.ts#L41-L61\r\n\r\n### 👨👧👦 Contributing\r\n\r\n- [X] 🙋♂️ Yes, I'd be down to file a PR implementing this feature!",[],4275,"feat: @trpc/client: Direct server-side link","2023-05-13T12:01:51Z","https://github.com/trpc/trpc/issues/4275",0.6801076,{"description":2965,"labels":2966,"number":2967,"owner":2871,"repository":2871,"state":2885,"title":2968,"updated_at":2969,"url":2970,"score":2971},"### Describe the feature you'd like to request\r\n\r\nI have many microservice projects using tRPC with Expressjs (like SSO, Order etc). \r\nSometimes they need call each other in backend by RPC.\r\n\r\nI try to init one @trpc/client and call the router in the other tRPC backend. And it works well, even though I can not get advantage of Typescript.\r\nIt is amazing. tPRC is totaly RPC.Not only Client-Server tRPC, but also Server-Server tRPC.\r\n\r\nmy question is:\r\nI need some guidance about the best practice of Server-Server(or microservice) tRPC and get the advantage of Typescript.\r\n\r\n### Describe the solution you'd like to see\r\n\r\n1. tRPC backends support micro service through RPC (or instead of gRPC).\r\n2. @trpc/client could init and call the router in the other tRPC backend (or through ETCD ZooKeeper). \r\n3. then get the advantage of Typescript.\r\n\r\n\r\n### Describe alternate solutions\r\n\r\n1. no createCaller, only router(query/mutate)\r\n2. when deploying a tRPC backend, deploy the appRouter.d.ts by the way\r\n3. appRouter.d.ts could import through HTTP or WS for the purpose of Typescript\r\n\r\n### Additional information\r\n\r\nI just could add some docs about my practice at the position of Backend Usage>Server Side Calls.\r\n\r\n### 👨👧👦 Contributing\r\n\r\n- [ ] 🙋♂️ Yes, I'd be down to file a PR implementing this feature!",[],4170,"feat: micro service support","2023-04-26T12:02:31Z","https://github.com/trpc/trpc/issues/4170",0.68260556,["Reactive",2973],{},["Set"],["ShallowReactive",2976],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$faCjsYpe6yy6JEbgFWXdSNYZvJyjAz3WPBF3SrhhyWU4":-1},"/trpc/trpc/3335"]