\r\n}\r\n\r\n```",[2904],{"name":2905,"color":2906},"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.45457393,{"description":2914,"labels":2915,"number":2916,"owner":2871,"repository":2871,"state":2908,"title":2917,"updated_at":2918,"url":2919,"score":2920},"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.6008955,{"description":2922,"labels":2923,"number":2924,"owner":2871,"repository":2871,"state":2908,"title":2925,"updated_at":2926,"url":2927,"score":2928},"### 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.6180738,{"description":2930,"labels":2931,"number":2936,"owner":2871,"repository":2871,"state":2908,"title":2937,"updated_at":2938,"url":2939,"score":2940},"### Describe the feature you'd like to request\n\n`react-query` matches query invalidation in a fuzzy way, and allows to invalidate queries without having the whole input used to call it.\r\n\r\nFrom this comment on the react query forums: https://github.com/TanStack/query/discussions/4762#discussioncomment-4649876\r\n> from a pure react-query perspective, if your `queryKey` is:\r\n> \r\n> ```\r\n> ['my-path', { a: 'b', foo: 'bar' }]\r\n> ['my-path', { a: 'b', something: 'else' }]\r\n> ```\r\n> \r\n> it should be possible to target them both for query invalidation by doing:\r\n> \r\n> ```\r\n> queryClient.invalidateQueries({\r\n> queryKey: ['my-path', { a: 'b' }]\r\n> })\r\n> ```\r\n> \r\n> because that does fuzzily match them both. It might be that trpc doesn't have a concept for that though ...\r\n\r\nTrpc does not currently allow to match queries this way.\n\n### Describe the solution you'd like to see\n\nHaving a query with the input type type:\r\n\r\n``` typescript\r\ntype TInput = { id: string, name: string, lastName: string | undefined } \r\n```\r\nEven though we call the query with the full TInput, the invalidation should allow to do this:\r\n``` typescript\r\nquery.invalidate({id: 'id'})\r\n```\r\nThis should be easy to do, as `react-query` does already behave like that, it's just a type issue. It should be a deep partialization of it.\n\n### Describe alternate solutions\n\nMaking it `Partial\u003CTInput>` would solve some problems, but I believe `react-query` will match everything fuzzily so the deep partialization is better.\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!",[2932,2935],{"name":2933,"color":2934},"@trpc/react-query","375E6E",{"name":2881,"color":2882},3648,"feat: query invalidation should take `Partial\u003CType>` instead of `Type` as the input","2023-02-15T00:05:31Z","https://github.com/trpc/trpc/issues/3648",0.6291835,{"description":2942,"labels":2943,"number":2944,"owner":2871,"repository":2871,"state":2908,"title":2945,"updated_at":2946,"url":2947,"score":2948},"Welcome back @KATT, I hope you enjoyed your holidays ๐\r\n\r\nThe [`invalidateQueries`](https://trpc.io/docs/invalidateQueries) docs say:\r\n\r\n> [See react-query docs](https://react-query.tanstack.com/guides/query-invalidation) if you want more fine-grained control.\r\n\r\nIn turn, the react query docs say:\r\n\r\n- `invalidateQueries()` will invalidate every query (I found this on some other page)\r\n- `invalidateQueries('todos')` will invalidate every query with a key that starts with `'todos'`\r\n- `invalidateQueries({ predicate: query => boolean })` allows fine-grain control\r\n\r\nHowever, if you now try the following with trpc:\r\n\r\n```ts\r\nimport { trpc } from '../utils/trpc'\r\n\r\nconst context = trpc.useContext()\r\n\r\n// Invalid\r\ncontext.invalidateQueries()\r\n\r\n// Works differently than expected:\r\n// Will invalidate the exact query 'todos'\r\n// Will not clear queries that start with 'todos'!\r\ncontext.invalidateQueries('todos') \r\n\r\n// Invalid\r\ncontext.invalidateQueries({ predicate: () => true })\r\n\r\nconst { queryClient } = context\r\n\r\n// Doesn't seem to work for me. Does nothing.\r\nqueryClient.invalidateQueries('todos')\r\n\r\n// Will invalidate the exact query 'todos', if it has no params\r\nqueryClient.invalidateQueries(['todos'])\r\n```\r\n\r\nIf we want to invalidate all queries it must be done as so:\r\n\r\n```ts\r\nqueryClient.invalidateQueries()\r\n```\r\n\r\nIf we want to invalidate queries that start with `'todos'` it must be done like so:\r\n\r\n```ts\r\nqueryClient.invalidateQueries({\r\n predicate({ queryKey }) {\r\n const name = queryKey[0]\r\n return typeof name === 'string' && name.startsWith('todos')\r\n },\r\n})\r\n```\r\n\r\nFor example, when a user logs off in my application, I clear all private queries like so:\r\n\r\n```ts\r\nqueryClient.removeQueries({\r\n predicate({ queryKey }) {\r\n const name = queryKey[0]\r\n return typeof name !== 'string' || !name.includes('public')\r\n },\r\n})\r\n```\r\n\r\nSolutions I propose:\r\n\r\n1. The distinction should be made in the docs that trpc uses arrays as keys, not strings, and thus `invalidateQueries` can't be used in certain ways.\r\n\r\n2. The typing of `invalidateQueries` needs to be fixed (at least) to allow empty args and `{ predicate: (query) => boolean }`.\r\n\r\n3. Maybe there should be a separate `invalidateQueries` / `removeQueries` methods returned directly from `createReactQueryHooks` that allow others to implement query invalidation in a way that makes better sense with trpc. If the typings of `invalidateQueries` are completely fixed, this change would not be necessary. Looking for feedback on whether anyone else thinks this is a good idea.\r\n\r\n ```ts\r\n // Maybe something like this\r\n import { trpc } from '../utils/trpc'\r\n \r\n // Will correctly invalidate every query with a key that starts with `'todos'`\r\n trpc.invalidateQueries(['todos'])\r\n\r\n // Clear all non-public queries\r\n trpc.removeQueries({\r\n predicate([key, params]) {\r\n return !key.includes('public')\r\n },\r\n })\r\n ```",[],1383,"`invalidateQueries` does not work as expected","2022-10-04T18:07:34Z","https://github.com/trpc/trpc/issues/1383",0.6355131,{"description":2950,"labels":2951,"number":2952,"owner":2871,"repository":2871,"state":2908,"title":2953,"updated_at":2954,"url":2955,"score":2956},"### 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.6409734,{"description":2958,"labels":2959,"number":2963,"owner":2871,"repository":2871,"state":2908,"title":2964,"updated_at":2965,"url":2966,"score":2967},"The `invalidateQueries` function is currently missing the ability to set QueryFilters\r\n\r\n\r\nFrom react-query: https://react-query.tanstack.com/reference/QueryClient#queryclientinvalidatequeries\r\n\r\n```ts\r\n await queryClient.invalidateQueries('posts', {\r\n exact,\r\n refetchActive: true,\r\n refetchInactive: false\r\n }, { throwOnError, cancelRefetch })\r\n```",[2960],{"name":2961,"color":2962},"๐ good first issue","7057ff",1201,"invalidateQueries missing filters","2022-10-04T18:07:53Z","https://github.com/trpc/trpc/issues/1201",0.6557797,["Reactive",2969],{},["Set"],["ShallowReactive",2972],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$frzhgGbRRKctQ984Ve8Ckk9j-DqNehqWfZpIy9vZfyq0":-1},"/trpc/next-13/3"]