anymaniax / orval

orval is able to generate client with appropriate type-signatures (TypeScript) from any valid OpenAPI v3 or Swagger v2 specification, either in yaml or json formats. 🍺
https://orval.dev
MIT License
2.55k stars 281 forks source link

Customize default query keys #243

Open mpetito-envative opened 2 years ago

mpetito-envative commented 2 years ago

Is it possible to configure the convention used for query key generation?

I see that you can override the query key when using the generated hook, but this requires remembering to do so each time. Instead, I'd like to configure how the query key is constructed project-wide because our APIs already have consistent hierarchical routes.

For ex., instead of this generated query key:

export const getGetResourceByIdQueryKey = (resourceId: number,) => [`/resource/${resourceId}`];

It would make a lot more sense in my project for the query key to be split by path segments, e.g.:

['resource', resourceId]

I don't see any obvious way to configure or override the convention used for query keys.

My motivation is to simplify query invalidation by having predictable query keys and support prefix invalidation.

anymaniax commented 2 years ago

Hello @mpetito-envative, not really the only thing that you can do at the moment is to override the options in the orval config. Could be a new option but how would you do it?

mpetito-envative commented 2 years ago

It seems like this would be a runtime behavior because the queryKey depends on properties passed into the query hook.

It is already possible to do something similar with the mutator override for the purpose of replacing the http request. Perhaps a queryKey override would allow for replacement of the queryKeyFn at runtime?

Alternatively (or in addition), it might make sense to change the default convention used for queryKey generation. I know this would be a breaking change, but I can't think of any disadvantage to splitting the route on / and it would offer an easy path for prefix invalidation if routes already represent a hierarchy.

anymaniax commented 2 years ago

It's also what I thought but if we do a sort of mutator I will need to pass the route and all params to the function. For the other one, could make sense but since it's a breaking change I will add it for the next major release

vezaynk commented 2 years ago

@anymaniax Any updates on this? This issue just bit me and I'm not sure how to move forward without hardcoding the path in some form and matching with a predicate.

missing1984 commented 1 year ago

+1. This is an awesome tool but the queryKey is blocking me from using it. Is there a workaround before it get addressed?

anymaniax commented 1 year ago

@missing1984 it's on my todo list for the next version. Sorry I have a lot of stuff to do lately

OliverDudgeon commented 1 year ago

Another use case for query-key customisation is when there are more than one orval-generated api clients. If both have a /version endpoint for example, then the queries keys clash.

la55u commented 1 year ago

Did you guys manage to find a workaround?

missing1984 commented 1 year ago

I wrote a custom script base on "ts-morph" to process the generated file. It will be great to have native support though

vezaynk commented 1 year ago

@missing1984 Can you share it?

missing1984 commented 1 year ago

@knyzorg sure, https://gist.github.com/missing1984/907c2b6aef0206e8944ccbaea7c4d0a9 the script basically break key into arrays

missing1984 commented 1 year ago

I found a changelog item in 6.11. Is this possible now, I can't find an example in the doc. @anymaniax

anymaniax commented 1 year ago

Hello @missing1984, you can do it with this and you can do the same with the property queryKey only. It’s completely new and the doc is not complete about it but it’s like a mutator.

OliverDudgeon commented 1 year ago

Has anyone got this solution working? My queryOptions function isn't run by orval.

anymaniax commented 1 year ago

What is your config @OliverDudgeon?

OliverDudgeon commented 1 year ago

The queryOptions mutator function is used in the generated file but not imported.

I have this block in my config

{
    query: {
        useQuery: true,
        queryOptions: './src/queryMutator.ts',
    },
}

mutator is the default export of that file:

// src/queryMutator.ts
export const mutator = (args: any) => {
  console.log('Mutator:');
  console.log(args);
};

export default mutator;

In generated hooks,

const customOptions = getAssetQueryOptionsMutator({
  ...queryOptions,
  queryKey,
  queryFn,
});

is generated but ts errors on getAssetQueryOptionsMutator as it isn't imported.

If I use

{
    query: {
        useQuery: true,
        queryOptions: {
            path: './src/queryMutator.ts',
            name: 'mutator',
        },
    },
}
then this is generated in hooks

```ts
const customOptions = mutator({ ...queryOptions, queryKey, queryFn });

but mutator isn't imported.

There isn't anything in the orval logs.

anymaniax commented 1 year ago

@OliverDudgeon you have the last version of orval?

OliverDudgeon commented 1 year ago

Using 6.12.0

anymaniax commented 1 year ago

I am currently trying on the react basic samples with this config and it seems to work properly.

import { defineConfig } from 'orval';

export default defineConfig({
  petstore: {
    output: {
      target: 'src/api/endpoints/petstoreFromFileSpecWithTransformer.ts',
      schemas: 'src/api/model',
      client: 'react-query',
      override: {
        query: {
          useQuery: true,
          queryOptions: {
            path: './src/api/mutator/queryMutator.ts',
            name: 'mutator',
          },
        },
      },
    },
    input: {
      target: './petstore.yaml',
    },
  },
});
anymaniax commented 1 year ago

@OliverDudgeon Do You have extra information that can help me reproduce this?

OliverDudgeon commented 1 year ago

Don't have time tonight to figure out a minimal example but here is what I have.

This is my project, https://github.com/InformaticsMatters/squonk2-openapi-js-client-generator.

  1. Update orval to @latest
  2. Place this OpenApi, https://pastebin.com/EsN5cVUW, in the root as openapi.yaml
  3. Add the mutator file below this
  4. Add a path to it in queryOptions
  5. Run npm i && npm run orval
// // src/queryMutator.ts
export const mutator = (args: any) => {
  console.log('Mutator:');
  console.log(args);

  return args;
};

export default mutator;
anymaniax commented 1 year ago

Hello @OliverDudgeon, I can reproduce a problem only when I use the path directly like the following. Otherwise it seems to work properly

{
 query: {
  queryOptions: './src/queryMutator'
}
}
anymaniax commented 1 year ago

@OliverDudgeon I did a fix will be in the next release

OliverDudgeon commented 1 year ago

Ok this is even more strange. On 6.12.0, the error only happens on some of the generated files. I'm using mode: 'tags-split'. Two of my tags have the import statement missing when the others are fine.

I will try get your recent commit working to test it out.

OliverDudgeon commented 1 year ago

Great, the update on master seems to fix the issue. Cheers!

missing1984 commented 10 months ago

hmm, i did try out the mutator but i found the getXXXQueryKey function remains unchanged. We're rely on this function to do cache invalidation..

Any idea how can i override the key getter function? @anymaniax

soartec-lab commented 4 months ago

Hi, @missing1984

In the version 6.24.0 it is possible to override keys by specifying options in the custom hook that is generated. Could you please check this?