Skip to content
Snippets Groups Projects
Unverified Commit edd41415 authored by Sloan Sparger's avatar Sloan Sparger Committed by GitHub
Browse files

:man_construction_worker: RTKQuery integration: Setup (#39092)

parent 9c44af47
No related branches found
No related tags found
No related merge requests found
import { createApi } from "@reduxjs/toolkit/query/react";
import { apiQuery } from "./query";
import { tagTypes } from "./tags";
export const Api = createApi({
reducerPath: "metabase-api",
tagTypes,
baseQuery: apiQuery,
endpoints: () => ({}),
});
export * from "./api";
import type { BaseQueryFn } from "@reduxjs/toolkit/query/react";
import api from "metabase/lib/api";
type AllowedHTTPMethods = "GET" | "POST" | "PUT" | "DELETE";
const allowedHTTPMethods = new Set<AllowedHTTPMethods>([
"GET",
"POST",
"PUT",
"DELETE",
]);
const isAllowedHTTPMethod = (method: any): method is AllowedHTTPMethods => {
return allowedHTTPMethods.has(method);
};
// custom fetcher that wraps our Api client
export const apiQuery: BaseQueryFn = async (args, ctx, extraOptions: any) => {
const method = typeof args === "string" ? "GET" : args?.method ?? "GET";
const url = typeof args === "string" ? args : args.url;
if (!isAllowedHTTPMethod(method)) {
return { error: "Invalid HTTP method" };
}
try {
const abortControllerOption = ctx.signal
? { controller: ctx.signal }
: undefined;
const options = Object.assign(
{},
abortControllerOption,
extraOptions?.requestOptions,
);
const response = await api[method](url)(
{ ...args?.body, ...args?.params },
options,
);
return { data: response };
} catch (error) {
return { error };
}
};
export const LIST_ID = "LIST" as const;
export function getListTag<T extends string>(tagType: T) {
return { type: tagType, id: LIST_ID } as const;
}
export function providesList<
Results extends { id: string | number }[],
TagType extends string,
>(resultsWithIds: Results | undefined, tagType: TagType) {
const listTag = getListTag(tagType);
return resultsWithIds
? [listTag, ...resultsWithIds.map(({ id }) => ({ type: tagType, id }))]
: [listTag];
}
export const tagTypes = [];
export type TagTypes = typeof tagTypes[number];
......@@ -235,7 +235,7 @@ export class Api extends EventEmitter {
data,
options,
) {
const controller = new AbortController();
const controller = options.controller || new AbortController();
options.cancelled?.then(() => controller.abort());
const requestUrl = new URL(this.basename + url, location.origin);
......
// Reducers shared between "main" and "public" apps
import { Api } from "metabase/api";
import app from "metabase/redux/app";
import { reducer as auth } from "metabase/redux/auth";
import embed from "metabase/redux/embed";
......@@ -22,4 +23,5 @@ export default {
entities,
upload,
auth,
[Api.reducerPath]: Api.reducer,
};
......@@ -2,12 +2,14 @@ import { configureStore, combineReducers } from "@reduxjs/toolkit";
import { routerReducer as routing, routerMiddleware } from "react-router-redux";
import promise from "redux-promise";
import { Api } from "metabase/api";
import { PLUGIN_REDUX_MIDDLEWARES } from "metabase/plugins";
export function getStore(reducers, history, intialState) {
const reducer = combineReducers({
...reducers,
routing,
[Api.reducerPath]: Api.reducer,
});
return configureStore({
......@@ -19,6 +21,7 @@ export function getStore(reducers, history, intialState) {
serializableCheck: false,
}).concat([
promise,
Api.middleware,
...(history ? [routerMiddleware(history)] : []),
...PLUGIN_REDUX_MIDDLEWARES,
]),
......
......@@ -12,6 +12,7 @@ import { Router, useRouterHistory } from "react-router";
import { routerReducer, routerMiddleware } from "react-router-redux";
import _ from "underscore";
import { Api } from "metabase/api";
import mainReducers from "metabase/reducers-main";
import publicReducers from "metabase/reducers-public";
import { ThemeProvider } from "metabase/ui";
......@@ -77,10 +78,14 @@ export function renderWithProviders(
reducers = { ...reducers, ...customReducers };
}
const storeMiddleware = _.compact([
Api.middleware,
history && routerMiddleware(history),
]);
const store = getStore(
reducers,
initialState,
history ? [routerMiddleware(history)] : [],
storeMiddleware,
) as unknown as Store<State>;
const wrapper = (props: any) => (
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment