\r\n}\r\n\r\n```",[3030],{"name":3031,"color":3032},"question","d876e3","examples-v10-next-prisma-starter-sqlite","closed","[RFC] `invalidateQueries` and other `react-query` `useContext()`-fns","2022-08-25T23:31:17Z","https://github.com/trpc/examples-v10-next-prisma-starter-sqlite/issues/3",0.64844495,{"description":3040,"labels":3041,"number":104,"owner":3021,"repository":3042,"state":3034,"title":3043,"updated_at":3044,"url":3045,"score":3038},"Just dumping some thoughts / half-baked ideas here\r\n\r\n\r\n\r\n\r\n- ~~With RSC - is there a point of tRPC? Is there a \"lighter\" approach that might be nice(r)?~~ Maybe, but not for all\r\n- ~~With RSC - is there a point of react-query?~~ yes, there's still client components\r\n- Will there be a way to sync state and make sync the underlying state of the queries from RSC -> client & make *isomorphic* components?\r\n - Biggest question - unsure how state sync can work from a root `\"use client\"` Provider that renders on the server to the client that uses it.\r\n- Will importing the full router on every RSC-request add any significant overhead?\r\n- ~~Will React Context providers be available on the server? If so, it be possible to do any \"isomorphic\" context providers? Will components be able to be isomorphic?~~ This was a misconception. We'll do a root `\"use client\"` component & likely not sync state from actual RSC-components to client\r\n - If query state could be synced from server to client and context providers + components could be isomorphic, we could do stuff like using optimistic updates of a component that was initially rendered on the server.\r\n- How to deal with caching? \r\n- [..]",[],"next-13","Open questions","2022-11-28T10:46:18Z","https://github.com/trpc/next-13/issues/3",{"description":3047,"labels":3048,"number":3049,"owner":3021,"repository":3021,"state":3034,"title":3050,"updated_at":3051,"url":3052,"score":3053},"### Describe the feature you'd like to request\r\n\r\nIn implementing #2713 I came across a possible issue prompted by @KATT 's thought provoking edge case #2737 .\r\n\r\nThe `invalidate()` function when used on a router must traverse all possible procedures on sub routers that could be effected by the invalidation and infer any possible `input` values that could be passed to filter them. \r\n\r\nCurrently it does this by traversing all procedures of the current, and sub routers and getting all input types in a big Partial Union. \r\n\r\nHowever, as pointed out by @KATT we could have procedures with `.` in them. So consider the router below: \r\n\r\n```ts\r\nexport const appRouter = t.router({\r\n user: t.router({\r\n byId: t.procedure\r\n .input(\r\n z.object({\r\n id: z.string(),\r\n }),\r\n )\r\n .query(({ input }) => ({ user: { id: input.id } })),\r\n }),\r\n // A procedure that would appear to be in the user router. \r\n 'user.getAvatar': t.procedure\r\n .input(z.object({ userId: z.string() }))\r\n .query(({ input }) => ({ userId: input.userId, avatar: 'url' })),\r\n});\r\n```\r\n\r\nif we then did an invalidate like: \r\n```\r\nconst utils = trpc.useContext()\r\nutils.user.invalidate()\r\n```\r\n\r\nIt would be invalidating both of the procedures defined above... This is because [we decided, at least initially](https://github.com/trpc/trpc/pull/2713#issuecomment-1249121655), to store procedures like the `.` defined one above with a key of `[[['user','getAvatar']], {userId: \"10\"}]`. This key puts it within the user router, even though it is defined in a parent router! \r\n\r\nThis is not a huge issue, but it does mean we would miss the possible input filter of `userId: string` as `utils.user.invalidate()` searches the `user` router and any sub routers ... not the parent router where this is defined! 🤦\r\n\r\n### Describe the solution you'd like to see\r\n\r\nIdeally we would make sure that the input types available for `invalidate()` come from all possible queries that will be invalidated... even if defined on a parent (Or grand parent! etc) router.\r\n\r\nWe could possibly do this by traversing from the very top router and searching out all procedures that would match the path of the current router but this could get very expensive Typescript Performance wise 🤑... \r\n\r\n### Desribe alternate solutions\r\n\r\nAlternatives are either:\r\n- To disallow `.`'s in procedure names (Now that we have sub routers do we really need to allow it?!)\r\n - This would give the advantages of \r\n - Avoiding conflicts like we can encounter in [this comment](https://github.com/trpc/trpc/pull/2713#issuecomment-1246956147).\r\n - Avoid funny looking proxy code like `trpc.posts['comments.getById'].useQuery({ id: 1 })`\r\n - Always knowing relevant type information for any procedures operating at a router level will be in the current or sub routers ... not spuriously above! \r\n- To change query keys used to keep the `.` defined procedures as a single element IE: `[[\"user.getAvatar\"],{ userId:10 }]` or the example above `[[\"posts\",\"comments.getById\"], { id:1 }]`\r\n - This would require a big re write of how the `@trpc/react` client passes around query paths as it currently does the same behaviour as the keys and just creates a single `.` joined string of all elements. Making it indistiguishable between one properly generated using sub routers. [This is also true for the back end](https://github.com/trpc/trpc/pull/2713#issuecomment-1246956147) that considers `'user.all':t.procedure....` the same as `user: t.router({all:t.procedure...})` and just takes the definition of the last one defined in the router. \r\n\r\n### Additional information\r\n\r\nJust a heads up - I'd happily help tackle this but some of it may go DEEP. I also may not have time to implement this quickly! 🙁\r\n\r\n### 👨👧👦 Contributing\r\n\r\n- [X] 🙋♂️ Yes, I'd be down to file a PR implementing this feature!",[],2759,"feat: Allow `invalidate()` to infer input types from `.` containing procedure names of parent routers","2022-12-11T18:01:43Z","https://github.com/trpc/trpc/issues/2759",0.65545213,{"description":3055,"labels":3056,"number":3057,"owner":3021,"repository":3021,"state":3034,"title":3058,"updated_at":3059,"url":3060,"score":3061},"Let's say I have an API that lists dogs and an API that gets an individual dog. If I delete a dog, I'd like to be able to just do something like:\r\n```typescript\r\nconst utils = trpc.useContext();\r\nutils.invalidateQueries(\"dogs.*\")\r\n```\r\n\r\nCurrently I have to do:\r\n```typescript\r\nconst utils = trpc.useContext();\r\nutils.invalidateQueries([\"dogs.getDog\", { id:\"dog-id\" }])\r\nutils.invalidateQueries([\"dogs.listDogs\"])\r\n```\r\n\r\nUsing vanilla Express and react-query, I'm able to do something like this:\r\n```typescript\r\nconst { data: allDogs } = useQuery([\"dogs\"], /* query definition*/)\r\nconst { data: aDog } = useQuery([\"dogs\", { id: \"dog-id\" }], /* query definition*/)\r\n\r\nconst utils = trpc.useContext();\r\nutils.invalidateQueries([\"dogs\"])\r\n```\r\n\r\nBut with since tRPC structures the query keys for you, I'm not able to.",[],2098,"Support invalidating multiple router queries in one go","2022-07-06T04:22:16Z","https://github.com/trpc/trpc/issues/2098",0.676218,{"description":3063,"labels":3064,"number":3065,"owner":3021,"repository":3021,"state":3034,"title":3066,"updated_at":3067,"url":3068,"score":3069},"### Describe the feature you'd like to request\r\n\r\n### Context\r\nI'm trying to invalidate a query based on some complex rules, as I don't want to invalidate every single call to that query.\r\nThe way to do this is using `.invalidate(undefined, {predicate: (query) })`, where predicate takes a function that dictates which queries should be invalidated.\r\nThe problem I have, is that the `query` has the default `react-query` type of `Query\u003Cunknown,unknown,unknown, unknown[]>` which is not true for our TRPC queries.\r\n\r\n### Demonstration\r\n``` typescript\r\nconst utils = trpc.useContext()\r\nutils.router.query.invalidate(undefined, {\r\n predicate: (query: Query\u003Cunknown,unknown,unknown, unknown[]>) => {\r\n // We will have to cast `query` here to perform the invalidation based on the input data\r\n return true\r\n }\r\n})\r\n```\r\n\r\n### Describe the solution you'd like to see\r\n\r\nWe know that if `invalidate()` is called on a query defined by the user, the typing will be:\r\n``` typescript\r\ntype RouterInput= inferRouterInputs\u003CAppRouter>\r\ntype RouterOutput = inferRouterOutputs\u003CAppRouter>\r\n\r\n// desired type of example query called with `trpc.router.fn` , in predicate invalidation\r\ntype DesiredType = Query\u003C\r\n RouterInput['router']['fn'],\r\n TRPCClientError\u003CAppRouter>,\r\n RouterOutput['router']['fn'],\r\n [ [['router],['fn']], { input: RouterInput10['router']['fn'] } ]\r\n>\r\n```\r\n\r\nIf `invalidate()` is called at a router level, the type of the query, should be a union amongst the posible `DesiredType`'s of the procedures/routers inside it.\r\n\r\n\r\n\r\n### Describe alternate solutions\r\n\r\nCurrently, I implemented a worse version of this to cast the type of the query, but its bad since it only supports queries and only exactly two levels for the path:\r\n\r\n``` typescript\r\ntype QueryHelper\u003C\r\n RouterOutput,\r\n K extends keyof RouterOutput & keyof RouterInput,\r\n K2 extends keyof RouterOutput[K] & keyof RouterInput[K],\r\n > = Query\u003C\r\n RouterInput[K][K2],\r\n TRPCClientError\u003CAppRouter>,\r\n RouterOutput[K][K2],\r\n [K, { input: RouterInput[K][K2] }]\r\n >\r\n\r\nutils.router.query.invalidate(undefined, {\r\n predicate: (_query) => {\r\n const query = _query as unknown as QueryHelper\u003CRouterOutput10, 'router', 'query'>\r\n return false\r\n }\r\n})\r\n```\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!",[],3545,"feat: Stronger typing for predicate invalidation","2023-03-12T18:02:06Z","https://github.com/trpc/trpc/issues/3545",0.6830639,{"description":3071,"labels":3072,"number":3073,"owner":3021,"repository":3021,"state":3034,"title":3074,"updated_at":3075,"url":3076,"score":3077},"### Provide environment information\n\n```\r\n System:\r\n OS: macOS 12.5.1\r\n CPU: (8) arm64 Apple M1 Pro\r\n Memory: 146.83 MB / 32.00 GB\r\n Shell: 5.8.1 - /bin/zsh\r\n Binaries:\r\n Node: 16.13.0 - ~/.nvm/versions/node/v16.13.0/bin/node\r\n npm: 8.1.0 - ~/.nvm/versions/node/v16.13.0/bin/npm\r\n Browsers:\r\n Brave Browser: 107.1.45.113\r\n Chrome: 107.0.5304.87\r\n Firefox Developer Edition: 106.0\r\n Safari: 15.6.1\r\n npmPackages:\r\n typescript: 4.6.2 => 4.6.2 \r\n @tanstack/react-query: 4.10.3 => 4.10.3 \r\n @trpc/client: 10.0.0-rc.3 => 10.0.0-rc.3 \r\n @trpc/next: 10.0.0-rc.3 => 10.0.0-rc.3 \r\n @trpc/react-query: 10.0.0-rc.3 => 10.0.0-rc.3 \r\n @trpc/server: 10.0.0-rc.3 => 10.0.0-rc.3 \r\n next: 12.3.0 => 12.3.0 \r\n react: 17.0.2 => 17.0.2 \r\n```\n\n### Describe the bug\n\nIf you have nested routers, you can use `useContext()` and call `invalidate` on a router with wrong variables, which doesn't work at runtime and should yield a type error (but it doesn't).\n\n### Link to reproduction\n\nhttps://codesandbox.io/s/festive-star-xjoi30?file=/src/pages/index.tsx\n\n### To reproduce\n\nlook at the code for the button that says `this doesn't do anything ❌`\r\n\r\nit doesn't do anything at runtime, which is fine, but it should yield a type error when trying to invoke:\r\n\r\n```\r\nutils.todos.invalidate({ id: 5 });\r\n```\n\n### Additional information\n\n_No response_\n\n### 👨👧👦 Contributing\n\n- [ ] 🙋♂️ Yes, I'd be down to file a PR fixing this bug!",[],3122,"bug: nested routers allow invalidation with wrong params","2022-11-20T12:02:10Z","https://github.com/trpc/trpc/issues/3122",0.7026242,{"description":3079,"labels":3080,"number":3081,"owner":3021,"repository":3021,"state":3034,"title":3082,"updated_at":3083,"url":3084,"score":3085},"### Describe the feature you'd like to request\n\nchange query key shape so you can invalidate entire routers\n\n### Describe the solution you'd like to see\n\n```ts\r\n[\"todo.detail.get\",1] \r\n--> \r\n[\"todo\", \"detail\", \"get\",1] \r\n\r\n[\"todo.list.get\", { done: true }]\r\n--> \r\n[\"todo\", \"list\", \"get\", { done: true }]\r\n```\r\n\r\nThis way you can invalidate entire routers too:\r\n```ts\r\nutils.todo.invalidate()\r\nutils.todo.list.invalidate()\r\n```\r\n\r\nsuggested by @TkDodo in the Discord: \r\nhttps://discord.com/channels/867764511159091230/1014458860355981332/1014505247902797886\n\n### Desribe alternate solutions\n\nnone\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!",[],2611,"individual array entries for query key path","2022-10-20T18:11:42Z","https://github.com/trpc/trpc/issues/2611",0.71173227,{"description":3087,"labels":3088,"number":1629,"owner":3021,"repository":3092,"state":3034,"title":3093,"updated_at":3094,"url":3095,"score":3096},"# The router API\r\n\r\n## Challenges with the current implementation\r\n\r\n- TypeScript performance. Each procedure added creates a new Router that TypeScript chokes on as the underlying complexity grows non-linearly with each added procedure - each procedure basically has its \"own instance\" within the compiler even if it's flattened and unaffected at runtime.\r\n- I find that those queries are hard/unintuitive to write, I find myself counting parentheses and curly brackets all too often. Arguably, your suggestions with the resolver API could also address this.\r\n- No CMD+click\r\n\r\n## Suggested implementation\r\n\r\n- Flat router\r\n- No automatic prefixing (breaks jump to definition / CMD+click)\r\n\r\n```tsx\r\nimport { z } from 'zod';\r\nimport { initTRPC } from './trpc/server';\r\n\r\nconst trpc = initTRPC\u003CContext>();\r\n\r\nconst postRouter = trpc.router({\r\n queries: {\r\n postById: null as any /* resolver implementation is a separate discussion */\r\n postAll: null as any /* resolver implementation is a separate discussion */\r\n },\r\n mutations: {\r\n postAdd: null as any /* resolver implementation is a separate discussion */\r\n});\r\n\r\nconst userRouter = trpc.router({\r\n queries: {\r\n userAll: null as any /* resolver implementation is a separate discussion */\r\n },\r\n);\r\n\r\nconst appRouter = trpc.mergeRouters(\r\n postRouter, \r\n userRouter, \r\n // ...\r\n)\r\n```",[3089],{"name":3090,"color":3091},"❕ RFC","008672","v10-playground","Chapter 1) The Router API","2022-04-12T12:36:28Z","https://github.com/trpc/v10-playground/issues/24",0.71615344,{"description":3098,"labels":3099,"number":3100,"owner":3021,"repository":3021,"state":3034,"title":3101,"updated_at":3102,"url":3103,"score":3104},"### Describe the feature you'd like to request\n\nInstead of having inference helpers that expose input and output together, I think we should make _two_ distinct inference helpers\r\n\r\nCurrent:\r\n\r\n```tsx\r\ntype RouterTypes = GetInferenceHelpers\u003CAppRouter>;\r\n\r\ntype Post = RouterTypes['public']['post']['list']['output']['items'][number];\r\n// Getting `items[number]` of `public.post.list.output`\r\n// Hard to read\r\n```\r\n\n\n### Describe the solution you'd like to see\n\n\r\nBetter legibility:\r\n\r\n```tsx\r\ntype RouterOutput = GetOutputInferenceHelpers\u003CAppRouter>;\r\ntype RouterInput = GetInputInferenceHelpers\u003CAppRouter>;\r\n\r\n\r\ntype Post = RouterOutput['public']['post']['list']['items'][number];\r\n```\r\n\r\n\r\n\r\nSplit inference helpers in two.\n\n### Desribe alternate solutions\n\nWe could also allow for this, which is even better legibility but will negatively affect TS perf on bigger routers.\r\n\r\n\r\n#### Flattened path\r\n\r\n```tsx\r\ntype RouterOutput = inferRouterOutput\u003CAppRouter>;\r\ntype RouterInput = inferRouterInput\u003CAppRouter>;\r\n\r\n\r\ntype Post = RouterOutput['public.post.list']['items'][number];\r\n```\r\n\r\n#### Fake representation of a router\r\n\r\n@sachinraja brought up this idea as well:\r\n\r\n\r\n```tsx\r\n// could be a proxy for a readable error or we could just straight-up lie about the types\r\n\r\nconst routerOutputs = createRouterOutputTypes\u003CAppRouter>();\r\nconst routerInputs = createRouterOutputTypes\u003CAppRouter>();\r\n\r\ntype Post = typeof routerOutputs.post.byId\r\n```\r\n\r\nIt's arguably a lot nicer for power users, but we do lie about the types.\n\n### Additional information\n\nDiscussion about naming: https://github.com/trpc/trpc/discussions/2825\n\n### 👨👧👦 Contributing\n\n- [X] 🙋♂️ Yes, I'd be down to file a PR implementing this feature!",[],3041,"feat: Split `GetInferenceHelpers` in `Output` and `Input`","2022-11-10T00:06:21Z","https://github.com/trpc/trpc/issues/3041",0.72056675,["Reactive",3106],{},["Set"],["ShallowReactive",3109],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$fGxhGytuYnkJFEV4la_fofW2jRIwK9ya_bFzYFWYDjyE":-1},"/trpc/trpc/5966"]