rtk-query-codegen icon indicating copy to clipboard operation
rtk-query-codegen copied to clipboard

Is there a way to pass dynamic arguments to the baseQuery?

Open lindapaiste opened this issue 4 years ago • 3 comments

I can define a custom baseQuery function or I can use the defaults which creates an instance of a fetchBaseQuery with the baseUrl from the OpenAPI spec.

I'm wondering if it's possible to define a plug-in replacement for fetchBaseQuery. That is, a factory function which is called with FetchBaseQueryArgs or { baseUrl: string } and returns a base query function.

export const createBaseQuery = ({baseUrl, ...rest}: FetchBaseQueryArgs) => {
    return fetchBaseQuery({
        baseUrl: getRootUrl() + baseUrl,
        prepareHeaders: (headers, { getState }) => {
            headers.set('Content-Type', 'application/json');
            // access token stored in redux
            const userToken = (getState() as {auth: AuthState}).auth?.token;
            if (userToken) {
                headers.set('Authorization', `Bearer ${userToken}`);
            }
            return headers;
        },
        ...rest,
    })
}

I'm dealing with an API setup that is unusual and kind of maddening. Each section of the API is defined independently and has a separate OpenAPI spec, so I am having to run the codegen multiple times. Each API should have the same prepareHeaders function but a different baseUrl. Additionally, the root URL for all APIs varies based on the environment where the code is executed (via the getRootUrl()) function above.

I am trying something like this, but I can't figure out how to create the correct baseQuery or how to override it without touching the generated file.

package.json

  "scripts": {
    "generate": "node generate.js"
  },

generate.js

const {execSync} = require('child_process');

const DIR = "./src/schemas";
const QUERY = "./src/utils/API.ts:baseQuery";

const generateAPI = (slug, version = "v1") => {
    const generated = `${DIR}/${slug}.generated.ts`;
    const remote = `https://api.mydomain.com/${slug}/${version}/openapi.json`;
    console.log(`downloading ${remote}`);
    console.log(`creating API ${generated}`);
    execSync(`npx @rtk-incubator/rtk-query-codegen-openapi --reducerPath ${slug} --baseQuery ${QUERY} --hooks --file ${generated} ${remote}`);
}

generateAPI("first-endpoint");
generateAPI("second-endpoint");
// etc...

lindapaiste avatar Jul 31 '21 19:07 lindapaiste

I ended up approaching this differently. I used openapi-merge-cli to merge all of the API configs into one file and then ran the RTK script only once.

lindapaiste avatar Jul 31 '21 22:07 lindapaiste

Actually, the baseQuery part will probably be removed from the codegen in the medium future, so I would not concentrate too much on that. The idea is to solve it more like the graphql codegen plugin:

You define your api empty in one file and the codegen is going to create one or multiple files that just import your emptyApi and call injectEndpoints on it.

That way you will have much more control over your api and especially the baseQuery without us having to add 1000 more options to deal with that case.

You might even get away with using a single baseQuery that way - you could use per-endpoint extraOptions in combination with enhanceEndpoints to pass additional data in your custom baseQuery, e.g. a different baseUrl or something.

phryneas avatar Jul 31 '21 22:07 phryneas

I'm currently working on the next version of the codegen (with the injectEndpoints approach) over in #81 and could need some feedback. Could you take a look?

phryneas avatar Nov 01 '21 12:11 phryneas