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",[2867],{"name":2868,"color":2869},"💡 ideas","bfdadc",2215,"closed","Documentation Proxy Api and @trcp/client","2022-10-04T06:09:12Z","https://github.com/trpc/trpc/issues/2215",0.6360751,{"description":2877,"labels":2878,"number":2882,"owner":2857,"repository":2857,"state":2871,"title":2883,"updated_at":2884,"url":2885,"score":2886},"Currently, there's an inconsistency between `@trpc/react` and `@trpc/client`\n\n\nI think they should be a wrapper around the client and be i.e:\n\n```ts\n// raw:\nconst client = createTRPCClient\u003CAppRouter>({ /* ... */ })\nconst rawProxy = createClientProxy(client)\n\n// react\nconst trpcReact = createReactHooks\u003CAppRouter>({ /* ... */} )\nconst reactProxy = createReactProxy(trpcReact)\n```\n\n",[2879],{"name":2880,"color":2881},"next-major/definite","5319E7",2111,"Fix abstractions for proxies and align across React + raw","2022-10-04T06:09:18Z","https://github.com/trpc/trpc/issues/2111",0.6423797,{"description":2888,"labels":2889,"number":2893,"owner":2857,"repository":2857,"state":2871,"title":2894,"updated_at":2895,"url":2896,"score":2897},"## 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",[2890],{"name":2891,"color":2892},"RFC","78B062",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.64373255,{"description":2899,"labels":2900,"number":2901,"owner":2857,"repository":2858,"state":2871,"title":2902,"updated_at":2903,"url":2904,"score":2905},"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,"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.65546733,{"description":2907,"labels":2908,"number":2909,"owner":2857,"repository":2857,"state":2871,"title":2910,"updated_at":2911,"url":2912,"score":2913},"When calling tRPC procedures for instance integration tests or in pure backend calls that aren't over the wire.\r\n\r\n\r\n### Given this backend\r\n\r\n```ts\r\ntype Context = {\r\n user?: { id: string },\r\n}\r\ntype Meta = {\r\n openapi: { \r\n enabled: true, \r\n method: 'GET', \r\n path: '/say-hello' ,\r\n }\r\n}\r\nconst t = initTRPC\u003C{ \r\n ctx: Context; \r\n meta?: Meta; // meta is set to be optional\r\n}>();\r\n\r\nconst appRouter = t.router({\r\n postById: procedure\r\n .input(\r\n z.object({\r\n id: z.string(),\r\n }),\r\n )\r\n .query(({ input }) => {\r\n //\r\n })\r\n});\r\n```\r\n\r\n**We want to allow calling it like this:**\r\n\r\n\r\n```ts\r\nconst result = await appRouter.post.byId({ \r\n input: { id: '1' },\r\n ctx: {},\r\n});\r\nconst result = await appRouter.post.byId({ \r\n input: { id: '1' },\r\n ctx: {\r\n user: {\r\n id: 'KATT'\r\n }\r\n }\r\n});\r\n```\r\n\r\n\r\n\u003Cdetails>\u003Csummary>Old example ahead of @sachinraja's suggestion\u003C/summary>\r\n```ts\r\nconst result = await appRouter.post.byId.call({ \r\n input: { id: '1' },\r\n ctx: {},\r\n});\r\nconst result = await appRouter.post.byId.call({ \r\n input: { id: '1' },\r\n ctx: {\r\n user: {\r\n id: 'KATT'\r\n }\r\n }\r\n});\r\n```\r\n\u003C/details>\r\n\r\n**And we want to be able to access metadata like this**:\r\n\r\n```ts\r\nconst postDef = appRouter.post.byId._def;\r\npostDef.input // -> z.ZodType\u003C...>\r\npostDef.output // ->undefined\r\npostDef.meta // -> Meta | undefined\r\n```\r\n\r\n\r\n### Stretch goal\r\n\r\nRelated to this: we should delete the \"internal procedure builder\" and replace it by a procedure exposing an interface like this when `.query` or `mutation` is called:\r\n\r\n```ts\r\ninterface Procedure\u003CTParams> {\r\n _def: ProcedureDef;\r\n // input should be `input?:` if it input is optional\r\n call(opts: { input: TParams['input_in'], ctx: TParams['_config']['ctx']): Promise\u003CTParams['_output_out']>;\r\n}\r\n```\r\n\r\nThis means we need to update the client and react lib as well to remap to their own implementation.",[],2124,"[RFC] Server-side calls & metadata","2022-10-04T06:09:11Z","https://github.com/trpc/trpc/issues/2124",0.65951514,{"description":2915,"labels":2916,"number":2917,"owner":2857,"repository":2857,"state":2871,"title":2918,"updated_at":2919,"url":2920,"score":2921},"### Describe the feature you'd like to request\n\nGeneric types cannot be passed to client methods, they are taken from the router definitions, which means they are always set to the default value.\r\nThis deprives the functions of flexibility and functionality.\r\nExample:\r\n```ts\r\nimport { createTRPCProxyClient } from \"@trpc/client\";\r\nimport { initTRPC } from \"@trpc/server\";\r\n\r\ntype InputType = { optional: boolean; };\r\ntype Res\u003CT> = ({ field: number; }) & (T extends { optional: true; } ? { optional_field: number; } : {});\r\n\r\nfunction fn\u003CInput extends InputType>(input: Input) {\r\n return {\r\n field: 123,\r\n ...(input.optional ? { optional_field: 456 } : {})\r\n } as Res\u003CInput>;\r\n}\r\n\r\nconst t = initTRPC.create({/* ... */ });\r\nconst router = t.router({\r\n qwe: t.procedure\r\n .input((value) => (value as InputType))\r\n .query(({ input }) => fn(input))\r\n});\r\ntype Router = typeof router;\r\nconst client = createTRPCProxyClient\u003CRouter>({/* ... */ } as any); // browser client\r\nconst caller = router.createCaller({}); // server client\r\n```\r\n```ts\r\nconst { optional_field: test1 } = fn({ optional: true }); // no error, right\r\nconst { optional_field: test2 } = fn({ optional: false }); // error, no field, right\r\nconst { optional_field: test3 } = client.qwe.query({ optional: true }); // error, no field, wrong\r\nconst { optional_field: test4 } = client.qwe.query({ optional: false }); // error, no field, right\r\nconst { optional_field: test5 } = caller.qwe({ optional: true }); // error, no field, wrong\r\nconst { optional_field: test6 } = caller.qwe({ optional: false }); // error, no field, right\r\n```\n\n### Describe the solution you'd like to see\n\nI don't know if it will be possible to do this.\n\n### Describe alternate solutions\n\nI don't know.\n\n### Additional information\n\n_No response_\n\n### 👨👧👦 Contributing\n\n- [ ] 🙋♂️ Yes, I'd be down to file a PR implementing this feature!",[],3637,"feat: Add generics to client methods","2023-02-01T18:02:01Z","https://github.com/trpc/trpc/issues/3637",0.65991426,{"description":2923,"labels":2924,"number":2932,"owner":2857,"repository":2857,"state":2871,"title":2933,"updated_at":2934,"url":2935,"score":2936},"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>",[2925,2928,2931],{"name":2926,"color":2927},"🙏 review please","A7356F",{"name":2929,"color":2930},"💸 Get paid!","c2e0c6",{"name":2880,"color":2881},887,"[RFC] Next major overview","2022-12-19T22:11:47Z","https://github.com/trpc/trpc/issues/887",0.66116863,{"description":2938,"labels":2939,"number":2940,"owner":2857,"repository":2857,"state":2871,"title":2941,"updated_at":2942,"url":2943,"score":2944},"(This is a follow-up to [this Discord thread](https://discord.com/channels/867764511159091230/894984069291581511/997850601100677150))\r\n\r\nI was checking out the v10 docs (https://alpha.trpc.io) and noticed a bunch of things I was massively turned off by and I'm pretty confident I'm not alone in this, I figured maybe I should provide this feedback to you guys before v10 gets released so that hopefully things improve.\r\nThe major issue for me is the new client API:\r\n\r\n## Client API:\r\n### The setup:\r\nThe new client API basically has a two-step setup:\r\n```ts\r\nimport { createTRPCClient, createTRPCClientProxy } from '@trpc/client';\r\n\r\nconst client = createTRPCClient\u003CAppRouter>({\r\n url: 'http://localhost:5000/trpc'\r\n});\r\n\r\nconst proxy = createTRPCClientProxy(client);\r\n```\r\nI'm not quite sure about the rationale behind this design but I'm pretty sure it would feel confusing, redundant, and verbose to most users. I especially dislike the fact that the variable (or constant, to be more accurate) that you will have to use over and over again to execute your procedures is called `proxy`, that's pretty vague and the word `client` would've been far better, but sadly it's taken in this context due to the two-step nature of this setup. The current workaround for this would be something like:\r\n```ts\r\nimport { createTRPCClient, createTRPCClientProxy } from '@trpc/client';\r\n\r\nconst client = createTRPCClientProxy(\r\n createTRPCClient\u003CAppRouter>({\r\n url: 'http://localhost:5000/trpc'\r\n })\r\n);\r\n```\r\nWhich is obviously verbose and ugly, so why not just:\r\n```ts\r\nimport { createClient } from '@trpc/client';\r\n\r\nconst client = createClient({\r\n url: 'http://localhost:5000/trpc'\r\n});\r\n```\r\nNotice the `createClient` function name as well. This provides two advantages:\r\n- It's shorter and more easily readable than `createTRPCClient`, I think putting the word `TRPC` in that function name is fundamentally redundant since the function is being imported from `@trpc/client` anyway. If someone has the same function name in the same scope they could simply do `import * as trpc from '@trpc/client` and then `trpc.createClient(...)`, which looks much better in my opinion. Although I understand this point could be somewhat subjective.\r\n- The more objective reason, so to speak, is that this allows you to keep the old `createTRPCClient` function for backward-compatibility, which seems to me to be the reason behind this new `createTRCPClientProxy` thing in the first place. Correct me if I'm wrong.\r\n\r\n### The usage:\r\nApparently the way you're supposed to call the procedures is like this:\r\n```ts\r\nconst bilbo = await proxy.getUser.query('id_bilbo');\r\nconst frodo = await proxy.createUser.mutation({ name: 'Frodo' });\r\n```\r\nThis one was legit painful for me to look at. At first glance, this syntax doesn't make any sense. Why not just:\r\n```ts\r\nconst bilbo = await proxy.getUser('id_bilbo');\r\nconst frodo = await proxy.createUser({ name: 'Frodo' });\r\n```\r\nIt's clear that `getUser` is a query and `createUser` is a mutation, so why the unnecessary verbosity?!\r\nTurns out the purpose of this peculiar syntax is to account for [a very specific type of scenario](https://discord.com/channels/867764511159091230/997850601100677150/997855779187077203) in which a query has an input that's too large to fit inside the character limit of URLs in a GET request, so it's instead sent as a mutation (i.e. as a POST request) so that input gets sent put in the body of that request.\r\n\r\nThis feels to me like a cheap hack to solve a specific problem for which tRPC should instead provide an explicit solution/configuration option, instead of doing something like this which apart from being extremely non-obvious, downright violates the semantics of queries and mutations, and makes the syntax nonsensical and needlessly verbose.\r\n\r\nI think it makes more sense for tRPC to provide an explicit configuration option to address this particular problem (e.g. `usePost: true`), take a look at [this](https://discord.com/channels/867764511159091230/997850601100677150/997858329567182988) and the other comments for some ideas.\r\n\r\nLet me know your thoughts.\r\nThank you.",[],2217,"v10 client API design","2022-07-20T11:19:13Z","https://github.com/trpc/trpc/issues/2217",0.6672868,{"description":2946,"labels":2947,"number":2948,"owner":2857,"repository":2857,"state":2871,"title":2949,"updated_at":2950,"url":2951,"score":2952},"### 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","2023-04-21T18:01:53Z","https://github.com/trpc/trpc/issues/3335",0.67607284,["Reactive",2954],{},["Set"],["ShallowReactive",2957],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$fnU-N8dpKmsvul8uOVOjXZXgFQk0_cqZuUe2RrMww1Us":-1},"/trpc/v10-playground/26"]