import {configureStore as configureReduxStore} from '@reduxjs/toolkit'; import type {Action, Dispatch, Middleware, Reducer, UnknownAction} from '@reduxjs/toolkit'; import type {History} from 'history'; import {createBrowserHistory} from 'history'; import {isNil} from 'lodash'; import {listenForHistoryChange} from 'redux-location-state'; import {YdbEmbeddedAPI} from '../services/api'; import {parseJson} from '../utils/utils'; import {getUrlData} from './getUrlData'; import rootReducer from './reducers'; import {api as storeApi} from './reducers/api'; import {preloadUserSettingsFromLS, syncUserSettingsFromLS} from './reducers/settings/settings'; import getLocationMiddleware from './state-url-mapping'; export let backend: string | undefined, basename: string, clusterName: string | undefined, environment: string | undefined; function getUrlDataAndSetParams({ singleClusterMode, customBackend, allowedEnvironments, }: { singleClusterMode: boolean; customBackend?: string; allowedEnvironments?: string[]; }) { const params = getUrlData({ singleClusterMode, customBackend, allowedEnvironments, }); ({basename, clusterName, environment, backend} = params); } function _configureStore< S = unknown, A extends Action = UnknownAction, P = S, M extends Middleware<{}, S, Dispatch> = Middleware<{}, S, Dispatch>, >(aRootReducer: Reducer, history: History, preloadedState: P, middleware: M[]) { const {locationMiddleware, reducersWithLocation} = getLocationMiddleware(history, aRootReducer); const checksDisabled = Boolean(parseJson(window.react_app_disable_checks)); const store = configureReduxStore({ reducer: reducersWithLocation, preloadedState, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ immutableCheck: checksDisabled ? false : undefined, serializableCheck: checksDisabled ? false : { ignoredPaths: ['api'], ignoredActions: ['api/sendQuery/rejected'], }, }).concat(locationMiddleware, ...middleware), }); return store; } // Environment variables are injected into the HTML template (index.html) as string literals. // For example: window.web_version = "<%= !process.env.REACT_APP_BACKEND %>" becomes the string "true" or "false". // We need to parse these string values back to their proper types (booleans, strings, undefined). export const webVersion = Boolean(parseJson(window.web_version)); export const customBackend = parseJson(window.custom_backend); export const metaBackend = parseJson(window.meta_backend); export const multiClusterMode = parseJson(window.multi_cluster_mode); export const codeAssistBackend = parseJson(window.code_assist_backend); const isSingleClusterMode = isNil(multiClusterMode) ? !metaBackend : !multiClusterMode; export function configureStore({ aRootReducer = rootReducer, singleClusterMode = isSingleClusterMode, environments = [] as string[], api = new YdbEmbeddedAPI({ webVersion, singleClusterMode: isSingleClusterMode, withCredentials: !customBackend, proxyMeta: false, csrfTokenGetter: undefined, useRelativePath: false, useMetaSettings: false, defaults: undefined, }), } = {}) { getUrlDataAndSetParams({ singleClusterMode, customBackend, allowedEnvironments: environments, }); const history = createBrowserHistory({basename}); history.listen(() => { getUrlDataAndSetParams({ singleClusterMode, customBackend, allowedEnvironments: environments, }); }); const store = _configureStore(aRootReducer, history, {singleClusterMode}, [ storeApi.middleware, ]); listenForHistoryChange(store, history); syncUserSettingsFromLS(store); if (!api.metaSettings) { preloadUserSettingsFromLS(store); } window.api = api; return {history, store}; }