Update Redux packages (#1583)

* Update Redux packages

* Fix instrument build

* Fix some test type errors

* Fix redux-devtools build

* Fix rtk-query-monitor build

* Fix redux-devtools-app build

* Fix redux-devtools-extension build

* Fix redux-devtools-remote build

* Fix extension build

* slider-monitor-example

* test-tab-demo

* inspector-monitor-demo

* rtk-query-monitor-demo

* counter-example

* todomvc-example

* Fix lint

* Fix instrument test types

* Fix core tests

* Fix rtk-query-monitor tests

* Updates
This commit is contained in:
Nathan Bierema 2024-08-05 23:11:13 -04:00 committed by GitHub
parent bd463b19ec
commit 8682d05b0b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
71 changed files with 591 additions and 548 deletions

View File

@ -31,7 +31,7 @@
"@redux-devtools/slider-monitor": "^5.0.1", "@redux-devtools/slider-monitor": "^5.0.1",
"@redux-devtools/ui": "^1.3.2", "@redux-devtools/ui": "^1.3.2",
"@redux-devtools/utils": "^3.0.0", "@redux-devtools/utils": "^3.0.0",
"@reduxjs/toolkit": "^1.9.7", "@reduxjs/toolkit": "^2.2.7",
"@types/jsan": "^3.1.5", "@types/jsan": "^3.1.5",
"jsan": "^3.1.14", "jsan": "^3.1.14",
"localforage": "^1.10.0", "localforage": "^1.10.0",
@ -41,8 +41,8 @@
"react-icons": "^5.2.1", "react-icons": "^5.2.1",
"react-is": "^18.3.1", "react-is": "^18.3.1",
"react-json-tree": "^0.19.0", "react-json-tree": "^0.19.0",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"redux": "^4.2.1", "redux": "^5.0.1",
"redux-persist": "^6.0.0", "redux-persist": "^6.0.0",
"styled-components": "^5.3.11" "styled-components": "^5.3.11"
}, },

View File

@ -18,7 +18,7 @@ import syncOptions, {
} from '../../options/syncOptions'; } from '../../options/syncOptions';
import openDevToolsWindow, { DevToolsPosition } from '../openWindow'; import openDevToolsWindow, { DevToolsPosition } from '../openWindow';
import { getReport } from '../logging'; import { getReport } from '../logging';
import { Action, Dispatch, MiddlewareAPI } from 'redux'; import { Action, Dispatch, Middleware } from 'redux';
import type { import type {
ContentScriptToBackgroundMessage, ContentScriptToBackgroundMessage,
SplitMessage, SplitMessage,
@ -670,10 +670,10 @@ declare global {
window.syncOptions = syncOptions(toAllTabs); // Expose to the options page window.syncOptions = syncOptions(toAllTabs); // Expose to the options page
export default function api( const api: Middleware<{}, BackgroundState, Dispatch<BackgroundAction>> =
store: MiddlewareAPI<Dispatch<BackgroundAction>, BackgroundState>, (store) => (next) => (untypedAction) => {
) { const action = untypedAction as BackgroundAction;
return (next: Dispatch<BackgroundAction>) => (action: BackgroundAction) => {
if (action.type === LIFTED_ACTION) toContentScript(action); if (action.type === LIFTED_ACTION) toContentScript(action);
else if (action.type === TOGGLE_PERSIST) { else if (action.type === TOGGLE_PERSIST) {
togglePersist(); togglePersist();
@ -684,4 +684,5 @@ export default function api(
} }
return next(action); return next(action);
}; };
}
export default api;

View File

@ -1,14 +1,17 @@
import { combineReducers, Reducer } from 'redux'; import { combineReducers, Reducer } from 'redux';
import { instances, InstancesState } from '@redux-devtools/app'; import { instances, InstancesState } from '@redux-devtools/app';
import type { BackgroundAction } from './backgroundStore'; import { BackgroundAction } from './backgroundStore';
export interface BackgroundState { export interface BackgroundState {
readonly instances: InstancesState; readonly instances: InstancesState;
} }
const rootReducer: Reducer<BackgroundState, BackgroundAction> = const rootReducer: Reducer<
combineReducers<BackgroundState>({ BackgroundState,
BackgroundAction,
Partial<BackgroundState>
> = combineReducers({
instances, instances,
}); }) as any;
export default rootReducer; export default rootReducer;

View File

@ -1,4 +1,4 @@
import { createStore, applyMiddleware, PreloadedState } from 'redux'; import { createStore, applyMiddleware } from 'redux';
import { import {
CustomAction, CustomAction,
DispatchAction, DispatchAction,
@ -60,7 +60,7 @@ export type BackgroundAction =
| DisconnectedAction; | DisconnectedAction;
export default function configureStore( export default function configureStore(
preloadedState?: PreloadedState<BackgroundState>, preloadedState?: Partial<BackgroundState>,
) { ) {
return createStore(rootReducer, preloadedState, applyMiddleware(api)); return createStore(rootReducer, preloadedState, applyMiddleware(api));
/* /*

View File

@ -30,8 +30,11 @@ export interface StoreStateWithoutSocket {
readonly stateTreeSettings: StateTreeSettings; readonly stateTreeSettings: StateTreeSettings;
} }
const rootReducer: Reducer<StoreStateWithoutSocket, StoreAction> = const rootReducer: Reducer<
combineReducers<StoreStateWithoutSocket>({ StoreStateWithoutSocket,
StoreAction,
Partial<StoreStateWithoutSocket>
> = combineReducers({
instances, instances,
monitor, monitor,
reports, reports,
@ -40,6 +43,6 @@ const rootReducer: Reducer<StoreStateWithoutSocket, StoreAction> =
theme, theme,
connection, connection,
stateTreeSettings, stateTreeSettings,
}); }) as any;
export default rootReducer; export default rootReducer;

View File

@ -1,4 +1,4 @@
import { createStore, applyMiddleware, Reducer } from 'redux'; import { createStore, applyMiddleware, Reducer, Store } from 'redux';
import localForage from 'localforage'; import localForage from 'localforage';
import { persistReducer, persistStore } from 'redux-persist'; import { persistReducer, persistStore } from 'redux-persist';
import { exportStateMiddleware, StoreAction } from '@redux-devtools/app'; import { exportStateMiddleware, StoreAction } from '@redux-devtools/app';
@ -23,6 +23,6 @@ export default function configureStore(
panelDispatcher(bgConnection), panelDispatcher(bgConnection),
); );
const store = createStore(persistedReducer, enhancer); const store = createStore(persistedReducer, enhancer);
const persistor = persistStore(store); const persistor = persistStore(store as Store);
return { store, persistor }; return { store, persistor };
} }

View File

@ -7,15 +7,17 @@ import {
TOGGLE_PERSIST, TOGGLE_PERSIST,
UPDATE_STATE, UPDATE_STATE,
} from '@redux-devtools/app'; } from '@redux-devtools/app';
import { Dispatch, MiddlewareAPI } from 'redux'; import { Dispatch, Middleware } from 'redux';
function panelDispatcher(bgConnection: chrome.runtime.Port) { function panelDispatcher(
bgConnection: chrome.runtime.Port,
): Middleware<{}, StoreState, Dispatch<StoreAction>> {
let autoselected = false; let autoselected = false;
const tabId = chrome.devtools.inspectedWindow.tabId; const tabId = chrome.devtools.inspectedWindow.tabId;
return (store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>) => return (store) => (next) => (untypedAction) => {
(next: Dispatch<StoreAction>) => const action = untypedAction as StoreAction;
(action: StoreAction) => {
const result = next(action); const result = next(action);
if (!autoselected && action.type === UPDATE_STATE && tabId) { if (!autoselected && action.type === UPDATE_STATE && tabId) {
autoselected = true; autoselected = true;

View File

@ -9,7 +9,6 @@ import {
Action, Action,
ActionCreator, ActionCreator,
Dispatch, Dispatch,
PreloadedState,
Reducer, Reducer,
StoreEnhancer, StoreEnhancer,
StoreEnhancerStoreCreator, StoreEnhancerStoreCreator,
@ -526,32 +525,26 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<string>>(
relayState(liftedState); relayState(liftedState);
} }
const enhance = const enhance = (): StoreEnhancer => (next) => {
(): StoreEnhancer => return <S2, A2 extends Action<string>, PreloadedState>(
<NextExt, NextStateExt>( reducer_: Reducer<S2, A2, PreloadedState>,
next: StoreEnhancerStoreCreator<NextExt, NextStateExt>, initialState_?: PreloadedState | undefined,
): any => {
return <S2 extends S, A2 extends A>(
reducer_: Reducer<S2, A2>,
initialState_?: PreloadedState<S2>,
) => { ) => {
if (!isAllowed(window.devToolsOptions)) { if (!isAllowed(window.devToolsOptions)) {
return next(reducer_, initialState_); return next(reducer_, initialState_);
} }
store = stores[instanceId] = configureStore( store = stores[instanceId] = (
next as StoreEnhancerStoreCreator, configureStore(next, monitor.reducer, {
monitor.reducer,
{
...config, ...config,
maxAge: getMaxAge as any, maxAge: getMaxAge as any,
}, }) as any
)(reducer_, initialState_) as any; )(reducer_, initialState_) as any;
if (isInIframe()) setTimeout(init, 3000); if (isInIframe()) setTimeout(init, 3000);
else init(); else init();
return store; return store as any;
}; };
}; };
@ -598,11 +591,11 @@ export type InferComposedStoreExt<StoreEnhancers> = StoreEnhancers extends [
? HeadStoreEnhancer extends StoreEnhancer<infer StoreExt> ? HeadStoreEnhancer extends StoreEnhancer<infer StoreExt>
? StoreExt & InferComposedStoreExt<RestStoreEnhancers> ? StoreExt & InferComposedStoreExt<RestStoreEnhancers>
: never : never
: unknown; : {};
const extensionCompose = const extensionCompose =
(config: Config) => (config: Config) =>
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>> => { ): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>> => {
// @ts-ignore FIXME // @ts-ignore FIXME
@ -619,10 +612,10 @@ const extensionCompose =
interface ReduxDevtoolsExtensionCompose { interface ReduxDevtoolsExtensionCompose {
( (
config: Config, config: Config,
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( ): <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
} }
@ -635,24 +628,22 @@ declare global {
function reduxDevtoolsExtensionCompose( function reduxDevtoolsExtensionCompose(
config: Config, config: Config,
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( ): <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function reduxDevtoolsExtensionCompose< function reduxDevtoolsExtensionCompose<
StoreEnhancers extends readonly StoreEnhancer<unknown>[], StoreEnhancers extends readonly StoreEnhancer[],
>( >(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function reduxDevtoolsExtensionCompose( function reduxDevtoolsExtensionCompose(...funcs: [Config] | StoreEnhancer[]) {
...funcs: [Config] | StoreEnhancer<unknown>[]
) {
if (funcs.length === 0) { if (funcs.length === 0) {
return __REDUX_DEVTOOLS_EXTENSION__(); return __REDUX_DEVTOOLS_EXTENSION__();
} }
if (funcs.length === 1 && typeof funcs[0] === 'object') { if (funcs.length === 1 && typeof funcs[0] === 'object') {
return extensionCompose(funcs[0]); return extensionCompose(funcs[0]);
} }
return extensionCompose({})(...(funcs as StoreEnhancer<unknown>[])); return extensionCompose({})(...(funcs as StoreEnhancer[]));
} }
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = reduxDevtoolsExtensionCompose; window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = reduxDevtoolsExtensionCompose;

View File

@ -1,4 +1,4 @@
import { Dispatch, MiddlewareAPI } from 'redux'; import { Dispatch, Middleware, MiddlewareAPI } from 'redux';
import { import {
SELECT_INSTANCE, SELECT_INSTANCE,
StoreAction, StoreAction,
@ -9,7 +9,7 @@ import {
function selectInstance( function selectInstance(
tabId: number, tabId: number,
store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>, store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>,
next: Dispatch<StoreAction>, next: (action: unknown) => unknown,
) { ) {
const instances = store.getState().instances; const instances = store.getState().instances;
if (instances.current === 'default') return; if (instances.current === 'default') return;
@ -33,10 +33,10 @@ function getCurrentTabId(next: (tabId: number) => void) {
); );
} }
export default function popupSelector( const popupSelector: Middleware<{}, StoreState, Dispatch<StoreAction>> =
store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>, (store) => (next) => (untypedAction) => {
) { const action = untypedAction as StoreAction;
return (next: Dispatch<StoreAction>) => (action: StoreAction) => {
const result = next(action); const result = next(action);
if (action.type === UPDATE_STATE) { if (action.type === UPDATE_STATE) {
if (chrome.devtools && chrome.devtools.inspectedWindow) { if (chrome.devtools && chrome.devtools.inspectedWindow) {
@ -47,4 +47,5 @@ export default function popupSelector(
} }
return result; return result;
}; };
}
export default popupSelector;

View File

@ -13,8 +13,11 @@ import {
import instances from './instancesReducer'; import instances from './instancesReducer';
import type { WindowStoreAction } from './windowStore'; import type { WindowStoreAction } from './windowStore';
const rootReducer: Reducer<StoreState, WindowStoreAction> = const rootReducer: Reducer<
combineReducers<StoreState>({ StoreState,
WindowStoreAction,
Partial<StoreState>
> = combineReducers({
instances, instances,
monitor, monitor,
socket, socket,
@ -24,6 +27,6 @@ const rootReducer: Reducer<StoreState, WindowStoreAction> =
theme, theme,
connection, connection,
stateTreeSettings, stateTreeSettings,
}); }) as any;
export default rootReducer; export default rootReducer;

View File

@ -69,7 +69,7 @@ export default function configureStore(
); );
} }
const store = createStore(persistedReducer, enhancer); const store = createStore(persistedReducer, enhancer);
const persistor = persistStore(store, null, () => { const persistor = persistStore(store as Store, null, () => {
if (store.getState().connection.type !== 'disabled') { if (store.getState().connection.type !== 'disabled') {
store.dispatch({ store.dispatch({
type: CONNECT_REQUEST, type: CONNECT_REQUEST,

View File

@ -6,16 +6,19 @@ import {
TOGGLE_PERSIST, TOGGLE_PERSIST,
UPDATE_STATE, UPDATE_STATE,
} from '@redux-devtools/app'; } from '@redux-devtools/app';
import { Dispatch, MiddlewareAPI, Store } from 'redux'; import { Dispatch, Middleware, Store } from 'redux';
import type { BackgroundState } from '../../background/store/backgroundReducer'; import type { BackgroundState } from '../../background/store/backgroundReducer';
import type { WindowStoreAction } from './windowStore';
import type { BackgroundAction } from '../../background/store/backgroundStore'; import type { BackgroundAction } from '../../background/store/backgroundStore';
const syncStores = const syncStores =
(baseStore: Store<BackgroundState, BackgroundAction>) => (
(store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>) => baseStore: Store<BackgroundState, BackgroundAction>,
(next: Dispatch<WindowStoreAction>) => ): Middleware<{}, StoreState, Dispatch<StoreAction>> =>
(action: StoreAction) => { (store) =>
(next) =>
(untypedAction) => {
const action = untypedAction as StoreAction;
if (action.type === UPDATE_STATE) { if (action.type === UPDATE_STATE) {
return next({ return next({
...action, ...action,

View File

@ -61,6 +61,7 @@
"@babel/preset-react": "^7.24.7", "@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7", "@babel/preset-typescript": "^7.24.7",
"@emotion/react": "^11.13.0", "@emotion/react": "^11.13.0",
"@reduxjs/toolkit": "^2.2.7",
"@rjsf/core": "^4.2.3", "@rjsf/core": "^4.2.3",
"@testing-library/dom": "^10.3.2", "@testing-library/dom": "^10.3.2",
"@testing-library/jest-dom": "^6.4.6", "@testing-library/jest-dom": "^6.4.6",
@ -85,8 +86,8 @@
"jest-environment-jsdom": "^29.7.0", "jest-environment-jsdom": "^29.7.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"redux": "^4.2.1", "redux": "^5.0.1",
"redux-persist": "^6.0.0", "redux-persist": "^6.0.0",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"styled-components": "^5.3.11", "styled-components": "^5.3.11",

View File

@ -1,7 +1,7 @@
import { stringifyJSON } from '../utils/stringifyJSON'; import { stringifyJSON } from '../utils/stringifyJSON';
import { UPDATE_STATE, LIFTED_ACTION, EXPORT } from '../constants/actionTypes'; import { UPDATE_STATE, LIFTED_ACTION, EXPORT } from '../constants/actionTypes';
import { getActiveInstance } from '../reducers/instances'; import { getActiveInstance } from '../reducers/instances';
import { Dispatch, MiddlewareAPI } from 'redux'; import { Dispatch, Middleware } from 'redux';
import { CoreStoreAction } from '../actions'; import { CoreStoreAction } from '../actions';
import { CoreStoreState } from '../reducers'; import { CoreStoreState } from '../reducers';
@ -22,12 +22,15 @@ function download(state: string) {
}, 0); }, 0);
} }
export const exportStateMiddleware = export const exportStateMiddleware: Middleware<
(store: MiddlewareAPI<Dispatch<CoreStoreAction>, CoreStoreState>) => // eslint-disable-next-line @typescript-eslint/no-empty-object-type
(next: Dispatch<CoreStoreAction>) => {},
(action: CoreStoreAction) => { CoreStoreState,
const result = next(action); Dispatch<CoreStoreAction>
> = (store) => (next) => (untypedAction) => {
const result = next(untypedAction);
const action = untypedAction as CoreStoreAction;
if ( if (
toExport && toExport &&
action.type === UPDATE_STATE && action.type === UPDATE_STATE &&
@ -53,13 +56,11 @@ export const exportStateMiddleware =
const instanceId = getActiveInstance(instances); const instanceId = getActiveInstance(instances);
const options = instances.options[instanceId]; const options = instances.options[instanceId];
if (options.features.export === true) { if (options.features.export === true) {
download( download(stringifyJSON(instances.states[instanceId], options.serialize));
stringifyJSON(instances.states[instanceId], options.serialize),
);
} else { } else {
toExport = instanceId; toExport = instanceId;
next({ type: LIFTED_ACTION, message: 'EXPORT', toExport: true }); next({ type: LIFTED_ACTION, message: 'EXPORT', toExport: true });
} }
} }
return result; return result;
}; };

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux'; import { createStore, applyMiddleware, Reducer } from 'redux';
import { render, screen, within } from '@testing-library/react'; import { render, screen, within } from '@testing-library/react';
import App from '../src/containers/App'; import App from '../src/containers/App';
import { exportStateMiddleware } from '../src/middlewares/exportState'; import { exportStateMiddleware } from '../src/middlewares/exportState';
@ -8,6 +8,7 @@ import { coreReducers } from '../src/reducers';
import { DATA_TYPE_KEY } from '../src/constants/dataTypes'; import { DATA_TYPE_KEY } from '../src/constants/dataTypes';
import { stringifyJSON } from '../src/utils/stringifyJSON'; import { stringifyJSON } from '../src/utils/stringifyJSON';
import { combineReducers } from 'redux'; import { combineReducers } from 'redux';
import { CoreStoreAction, CoreStoreState } from '../lib/types';
Object.defineProperty(window, 'matchMedia', { Object.defineProperty(window, 'matchMedia', {
writable: true, writable: true,
@ -24,7 +25,11 @@ Object.defineProperty(window, 'matchMedia', {
}); });
const store = createStore( const store = createStore(
combineReducers(coreReducers), combineReducers(coreReducers) as Reducer<
CoreStoreState,
CoreStoreAction,
Partial<CoreStoreState>
>,
applyMiddleware(exportStateMiddleware), applyMiddleware(exportStateMiddleware),
); );

View File

@ -44,8 +44,8 @@
"localforage": "^1.10.0", "localforage": "^1.10.0",
"jsan": "^3.1.14", "jsan": "^3.1.14",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"redux": "^4.2.1", "redux": "^5.0.1",
"redux-persist": "^6.0.0", "redux-persist": "^6.0.0",
"socketcluster-client": "^19.2.1" "socketcluster-client": "^19.2.1"
}, },
@ -58,6 +58,7 @@
"@babel/preset-react": "^7.24.7", "@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7", "@babel/preset-typescript": "^7.24.7",
"@emotion/react": "^11.13.0", "@emotion/react": "^11.13.0",
"@reduxjs/toolkit": "^2.2.7",
"@rjsf/core": "^4.2.3", "@rjsf/core": "^4.2.3",
"@types/jsan": "^3.1.5", "@types/jsan": "^3.1.5",
"@types/json-schema": "^7.0.15", "@types/json-schema": "^7.0.15",

View File

@ -17,7 +17,7 @@ import {
} from '@redux-devtools/app-core'; } from '@redux-devtools/app-core';
import socketClusterClient, { AGClientSocket } from 'socketcluster-client'; import socketClusterClient, { AGClientSocket } from 'socketcluster-client';
import { stringify } from 'jsan'; import { stringify } from 'jsan';
import { Dispatch, MiddlewareAPI } from 'redux'; import { Dispatch, Middleware, MiddlewareAPI } from 'redux';
import * as actions from '../constants/socketActionTypes'; import * as actions from '../constants/socketActionTypes';
import { nonReduxDispatch } from '../utils/monitorActions'; import { nonReduxDispatch } from '../utils/monitorActions';
import { EmitAction, StoreAction } from '../actions'; import { EmitAction, StoreAction } from '../actions';
@ -266,10 +266,15 @@ function getReport(reportId: unknown) {
})(); })();
} }
export function api(inStore: MiddlewareAPI<Dispatch<StoreAction>, StoreState>) { // eslint-disable-next-line @typescript-eslint/no-empty-object-type
export const api: Middleware<{}, StoreState, Dispatch<StoreAction>> = (
inStore,
) => {
store = inStore; store = inStore;
return (next: Dispatch<StoreAction>) => (action: StoreAction) => { return (next) => (untypedAction) => {
const result = next(action); const result = next(untypedAction);
const action = untypedAction as StoreAction;
switch (action.type) { switch (action.type) {
case actions.CONNECT_REQUEST: case actions.CONNECT_REQUEST:
connect(); connect();
@ -299,4 +304,4 @@ export function api(inStore: MiddlewareAPI<Dispatch<StoreAction>, StoreState>) {
} }
return result; return result;
}; };
} };

View File

@ -2,15 +2,13 @@ import { CoreStoreState, coreReducers } from '@redux-devtools/app-core';
import { combineReducers } from 'redux'; import { combineReducers } from 'redux';
import { connection, ConnectionState } from './connection'; import { connection, ConnectionState } from './connection';
import { socket, SocketState } from './socket'; import { socket, SocketState } from './socket';
import { StoreAction } from '../actions';
export interface StoreState extends CoreStoreState { export interface StoreState extends CoreStoreState {
readonly connection: ConnectionState; readonly connection: ConnectionState;
readonly socket: SocketState; readonly socket: SocketState;
} }
/// @ts-expect-error An error happens due to TypeScript not being able to reconcile a clash between CoreStoreAction and StoreAction in the core reducers, but this is correct as they're a superset export const rootReducer = combineReducers({
export const rootReducer = combineReducers<StoreState, StoreAction>({
...coreReducers, ...coreReducers,
connection, connection,
socket, socket,

View File

@ -14,7 +14,7 @@ const persistConfig = {
const persistedReducer: Reducer<StoreState, StoreAction> = persistReducer( const persistedReducer: Reducer<StoreState, StoreAction> = persistReducer(
persistConfig, persistConfig,
rootReducer, rootReducer as unknown as Reducer<StoreState, StoreAction>,
) as any; ) as any;
export default function configureStore( export default function configureStore(
@ -41,7 +41,7 @@ export default function configureStore(
persistedReducer, persistedReducer,
composeEnhancers(applyMiddleware(...middlewares, api)), composeEnhancers(applyMiddleware(...middlewares, api)),
); );
const persistor = persistStore(store, null, () => { const persistor = persistStore(store as Store, null, () => {
callback(store); callback(store);
}); });
return { store, persistor }; return { store, persistor };

View File

@ -61,7 +61,7 @@
"eslint-plugin-react": "^7.35.0", "eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"react": "^18.3.1", "react": "^18.3.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"typescript": "~5.5.3" "typescript": "~5.5.3"
}, },

View File

@ -44,7 +44,7 @@
"@apollo/server": "^4.10.4", "@apollo/server": "^4.10.4",
"@emotion/react": "^11.13.0", "@emotion/react": "^11.13.0",
"@redux-devtools/app": "^6.0.0", "@redux-devtools/app": "^6.0.0",
"@reduxjs/toolkit": "^1.9.7", "@reduxjs/toolkit": "^2.2.7",
"@types/react": "^18.3.3", "@types/react": "^18.3.3",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
"chalk": "^5.3.0", "chalk": "^5.3.0",

View File

@ -63,7 +63,7 @@
"eslint-plugin-react": "^7.35.0", "eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"react": "^18.3.1", "react": "^18.3.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"typescript": "~5.5.3" "typescript": "~5.5.3"
}, },

View File

@ -43,7 +43,7 @@
"@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/parser": "^8.0.0",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"typescript": "~5.5.3" "typescript": "~5.5.3"
}, },

View File

@ -15,18 +15,16 @@ declare const process: {
function extensionComposeStub( function extensionComposeStub(
config: Config, config: Config,
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( ): <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function extensionComposeStub< function extensionComposeStub<StoreEnhancers extends readonly StoreEnhancer[]>(
StoreEnhancers extends readonly StoreEnhancer<unknown>[],
>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function extensionComposeStub(...funcs: [Config] | StoreEnhancer<unknown>[]) { function extensionComposeStub(...funcs: [Config] | StoreEnhancer[]) {
if (funcs.length === 0) return undefined; if (funcs.length === 0) return undefined;
if (typeof funcs[0] === 'object') return compose; if (typeof funcs[0] === 'object') return compose;
return compose(...(funcs as StoreEnhancer<unknown>[])); return compose(...(funcs as StoreEnhancer[]));
} }
export const composeWithDevTools: ReduxDevtoolsExtensionCompose = export const composeWithDevTools: ReduxDevtoolsExtensionCompose =

View File

@ -235,15 +235,16 @@ export type InferComposedStoreExt<StoreEnhancers> = StoreEnhancers extends [
? HeadStoreEnhancer extends StoreEnhancer<infer StoreExt> ? HeadStoreEnhancer extends StoreEnhancer<infer StoreExt>
? StoreExt & InferComposedStoreExt<RestStoreEnhancers> ? StoreExt & InferComposedStoreExt<RestStoreEnhancers>
: never : never
: unknown; : // eslint-disable-next-line @typescript-eslint/no-empty-object-type
{};
export interface ReduxDevtoolsExtensionCompose { export interface ReduxDevtoolsExtensionCompose {
( (
config: Config, config: Config,
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( ): <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
<StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
} }
@ -257,18 +258,16 @@ declare global {
function extensionComposeStub( function extensionComposeStub(
config: Config, config: Config,
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( ): <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function extensionComposeStub< function extensionComposeStub<StoreEnhancers extends readonly StoreEnhancer[]>(
StoreEnhancers extends readonly StoreEnhancer<unknown>[],
>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function extensionComposeStub(...funcs: [Config] | StoreEnhancer<unknown>[]) { function extensionComposeStub(...funcs: [Config] | StoreEnhancer[]) {
if (funcs.length === 0) return undefined; if (funcs.length === 0) return undefined;
if (typeof funcs[0] === 'object') return compose; if (typeof funcs[0] === 'object') return compose;
return compose(...(funcs as StoreEnhancer<unknown>[])); return compose(...(funcs as StoreEnhancer[]));
} }
export const composeWithDevTools: ReduxDevtoolsExtensionCompose = export const composeWithDevTools: ReduxDevtoolsExtensionCompose =

View File

@ -1,12 +1,5 @@
import assign from './utils/assign';
import { compose } from 'redux'; import { compose } from 'redux';
import type { import type { Action, Dispatch, Reducer, StoreEnhancer } from 'redux';
Action,
Dispatch,
PreloadedState,
Reducer,
StoreEnhancer,
} from 'redux';
import type { Config, EnhancerOptions, InferComposedStoreExt } from './index'; import type { Config, EnhancerOptions, InferComposedStoreExt } from './index';
function enhancer(options?: EnhancerOptions): StoreEnhancer { function enhancer(options?: EnhancerOptions): StoreEnhancer {
@ -17,9 +10,9 @@ function enhancer(options?: EnhancerOptions): StoreEnhancer {
if (config.latency === undefined) config.latency = 500; if (config.latency === undefined) config.latency = 500;
return function (createStore) { return function (createStore) {
return function <S, A extends Action<string>>( return function <S, A extends Action<string>, PreloadedState>(
reducer: Reducer<S, A>, reducer: Reducer<S, A, PreloadedState>,
preloadedState: PreloadedState<S> | undefined, preloadedState?: PreloadedState | undefined,
) { ) {
const store = createStore(reducer, preloadedState); const store = createStore(reducer, preloadedState);
const origDispatch = store.dispatch; const origDispatch = store.dispatch;
@ -33,35 +26,32 @@ function enhancer(options?: EnhancerOptions): StoreEnhancer {
return r; return r;
}; };
if (Object.assign) return Object.assign(store, { dispatch: dispatch }); return Object.assign(store, { dispatch: dispatch });
return assign(store, 'dispatch', dispatch);
}; };
}; };
} }
function composeWithEnhancer(config?: EnhancerOptions) { function composeWithEnhancer(config?: EnhancerOptions) {
return function (...funcs: StoreEnhancer<unknown>[]) { return function (...funcs: StoreEnhancer[]) {
return compose(compose(...funcs), enhancer(config)); return compose(compose(...funcs), enhancer(config));
}; };
} }
export function composeWithDevTools( export function composeWithDevTools(
config: Config, config: Config,
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( ): <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
export function composeWithDevTools< export function composeWithDevTools<
StoreEnhancers extends readonly StoreEnhancer<unknown>[], StoreEnhancers extends readonly StoreEnhancer[],
>( >(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
export function composeWithDevTools( export function composeWithDevTools(...funcs: [Config] | StoreEnhancer[]) {
...funcs: [Config] | StoreEnhancer<unknown>[]
) {
if (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__) { if (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__) {
if (funcs.length === 0) return enhancer(); if (funcs.length === 0) return enhancer();
if (typeof funcs[0] === 'object') return composeWithEnhancer(funcs[0]); if (typeof funcs[0] === 'object') return composeWithEnhancer(funcs[0]);
return composeWithEnhancer()(...(funcs as StoreEnhancer<unknown>[])); return composeWithEnhancer()(...(funcs as StoreEnhancer[]));
} }
if (funcs.length === 0) return undefined; if (funcs.length === 0) return undefined;

View File

@ -16,18 +16,16 @@ declare const process: {
function extensionComposeStub( function extensionComposeStub(
config: Config, config: Config,
): <StoreEnhancers extends readonly StoreEnhancer<unknown>[]>( ): <StoreEnhancers extends readonly StoreEnhancer[]>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ) => StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function extensionComposeStub< function extensionComposeStub<StoreEnhancers extends readonly StoreEnhancer[]>(
StoreEnhancers extends readonly StoreEnhancer<unknown>[],
>(
...funcs: StoreEnhancers ...funcs: StoreEnhancers
): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>; ): StoreEnhancer<InferComposedStoreExt<StoreEnhancers>>;
function extensionComposeStub(...funcs: [Config] | StoreEnhancer<unknown>[]) { function extensionComposeStub(...funcs: [Config] | StoreEnhancer[]) {
if (funcs.length === 0) return undefined; if (funcs.length === 0) return undefined;
if (typeof funcs[0] === 'object') return compose; if (typeof funcs[0] === 'object') return compose;
return compose(...(funcs as StoreEnhancer<unknown>[])); return compose(...(funcs as StoreEnhancer[]));
} }
export const composeWithDevTools: ReduxDevtoolsExtensionCompose = export const composeWithDevTools: ReduxDevtoolsExtensionCompose =

View File

@ -1,26 +0,0 @@
const objectKeys =
Object.keys ||
function (obj) {
const keys = [];
for (const key in obj) {
if ({}.hasOwnProperty.call(obj, key)) keys.push(key);
}
return keys;
};
export default function assign<T extends object, K extends keyof T>(
obj: T,
newKey: K,
newValue: T[K],
): T {
const keys = objectKeys(obj);
const copy: T = {} as T;
for (let i = 0, l = keys.length; i < l; i++) {
const key = keys[i];
copy[key as keyof T] = obj[key as keyof T];
}
copy[newKey] = newValue;
return copy;
}

View File

@ -21,9 +21,9 @@
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-is": "^18.3.1", "react-is": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"react-router-dom": "^6.25.1", "react-router-dom": "^6.25.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"redux-logger": "^3.0.6", "redux-logger": "^3.0.6",
"styled-components": "^5.3.11" "styled-components": "^5.3.11"
}, },
@ -36,7 +36,7 @@
"@types/node": "^20.14.11", "@types/node": "^20.14.11",
"@types/react": "^18.3.3", "@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@types/redux-logger": "3.0.12", "@types/redux-logger": "^3.0.13",
"@types/styled-components": "^5.1.34", "@types/styled-components": "^5.1.34",
"@types/webpack-env": "^1.18.5", "@types/webpack-env": "^1.18.5",
"@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0",

View File

@ -33,9 +33,9 @@ const useDevtoolsExtension =
!!(window as unknown as { __REDUX_DEVTOOLS_EXTENSION__: unknown }) && !!(window as unknown as { __REDUX_DEVTOOLS_EXTENSION__: unknown }) &&
getOptions(window.location).useExtension; getOptions(window.location).useExtension;
const enhancer = compose( const enhancer: StoreEnhancer = compose(
applyMiddleware(logger), applyMiddleware(logger),
(next: StoreEnhancerStoreCreator) => { ((next) => {
const instrument = useDevtoolsExtension const instrument = useDevtoolsExtension
? ( ? (
window as unknown as { window as unknown as {
@ -44,9 +44,9 @@ const enhancer = compose(
).__REDUX_DEVTOOLS_EXTENSION__() ).__REDUX_DEVTOOLS_EXTENSION__()
: DevTools.instrument(); : DevTools.instrument();
return instrument(next); return instrument(next);
}, }) as StoreEnhancer,
persistState(getDebugSessionKey()), persistState(getDebugSessionKey()),
); ) as any;
const store = createStore(rootReducer, enhancer); const store = createStore(rootReducer, enhancer);

View File

@ -155,12 +155,12 @@ export interface DemoAppState {
} }
export const rootReducer: Reducer<DemoAppState, DemoAppAction> = export const rootReducer: Reducer<DemoAppState, DemoAppAction> =
combineReducers<DemoAppState, DemoAppAction>({ combineReducers({
timeoutUpdateEnabled: (state = false, action) => timeoutUpdateEnabled: (state = false, action: DemoAppAction) =>
action.type === 'TOGGLE_TIMEOUT_UPDATE' action.type === 'TOGGLE_TIMEOUT_UPDATE'
? action.timeoutUpdateEnabled ? action.timeoutUpdateEnabled
: state, : state,
store: (state = 0, action) => store: (state = 0, action: DemoAppAction) =>
action.type === 'INCREMENT' ? state + 1 : state, action.type === 'INCREMENT' ? state + 1 : state,
undefined: (state = { val: undefined }) => state, undefined: (state = { val: undefined }) => state,
null: (state = null) => state, null: (state = null) => state,
@ -169,7 +169,7 @@ export const rootReducer: Reducer<DemoAppState, DemoAppAction> =
// noop // noop
}, },
) => state, ) => state,
array: (state = [], action) => array: (state = [], action: DemoAppAction) =>
action.type === 'PUSH' action.type === 'PUSH'
? [...state, Math.random()] ? [...state, Math.random()]
: action.type === 'POP' : action.type === 'POP'
@ -177,13 +177,13 @@ export const rootReducer: Reducer<DemoAppState, DemoAppAction> =
: action.type === 'REPLACE' : action.type === 'REPLACE'
? [Math.random(), ...state.slice(1)] ? [Math.random(), ...state.slice(1)]
: state, : state,
hugeArrays: (state = [], action) => hugeArrays: (state = [], action: DemoAppAction) =>
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state, action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
hugeObjects: (state = [], action) => hugeObjects: (state = [], action: DemoAppAction) =>
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state, action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
iterators: (state = [], action) => iterators: (state = [], action: DemoAppAction) =>
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state, action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
nested: (state = NESTED, action) => nested: (state = NESTED, action: DemoAppAction) =>
action.type === 'CHANGE_NESTED' action.type === 'CHANGE_NESTED'
? { ? {
...state, ...state,
@ -200,23 +200,23 @@ export const rootReducer: Reducer<DemoAppState, DemoAppAction> =
}, },
} }
: state, : state,
recursive: (state = [], action) => recursive: (state = [], action: DemoAppAction) =>
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state, action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
immutables: (state = [], action) => immutables: (state = [], action: DemoAppAction) =>
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state, action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
immutableNested: (state = IMMUTABLE_NESTED, action) => immutableNested: (state = IMMUTABLE_NESTED, action: DemoAppAction) =>
action.type === 'CHANGE_IMMUTABLE_NESTED' action.type === 'CHANGE_IMMUTABLE_NESTED'
? state.updateIn( ? state.updateIn(
['long', 'nested', 0, 'path', 'to', 'a'], ['long', 'nested', 0, 'path', 'to', 'a'],
(str: unknown) => (str as string) + '!', (str: unknown) => (str as string) + '!',
) )
: state, : state,
addFunction: (state = null, action) => addFunction: (state = null, action: DemoAppAction) =>
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state, action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
addSymbol: (state = null, action) => addSymbol: (state = null, action: DemoAppAction) =>
action.type === 'ADD_SYMBOL' action.type === 'ADD_SYMBOL'
? { s: window.Symbol('symbol'), error: new Error('TEST') } ? { s: window.Symbol('symbol'), error: new Error('TEST') }
: state, : state,
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) => shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action: DemoAppAction) =>
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state, action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
}); }) as any;

View File

@ -81,7 +81,7 @@
"jest-environment-jsdom": "^29.7.0", "jest-environment-jsdom": "^29.7.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"ts-jest": "^29.2.3", "ts-jest": "^29.2.3",
"typescript": "~5.5.3" "typescript": "~5.5.3"

View File

@ -70,7 +70,7 @@
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-test-renderer": "^18.3.1", "react-test-renderer": "^18.3.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"ts-jest": "^29.2.3", "ts-jest": "^29.2.3",
"typescript": "~5.5.3" "typescript": "~5.5.3"

View File

@ -20,9 +20,9 @@
"react-base16-styling": "^0.10.0", "react-base16-styling": "^0.10.0",
"react-bootstrap": "^2.10.4", "react-bootstrap": "^2.10.4",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"react-router-dom": "^6.25.1", "react-router-dom": "^6.25.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"redux-logger": "^3.0.6" "redux-logger": "^3.0.6"
}, },
"devDependencies": { "devDependencies": {
@ -34,7 +34,7 @@
"@types/node": "^20.14.11", "@types/node": "^20.14.11",
"@types/react": "^18.3.3", "@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@types/redux-logger": "3.0.12", "@types/redux-logger": "^3.0.13",
"@types/webpack-env": "^1.18.5", "@types/webpack-env": "^1.18.5",
"@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/parser": "^8.0.0",

View File

@ -32,7 +32,7 @@ const useDevtoolsExtension =
!!(window as unknown as { __REDUX_DEVTOOLS_EXTENSION__: unknown }) !!(window as unknown as { __REDUX_DEVTOOLS_EXTENSION__: unknown })
.__REDUX_DEVTOOLS_EXTENSION__ && getOptions(window.location).useExtension; .__REDUX_DEVTOOLS_EXTENSION__ && getOptions(window.location).useExtension;
const enhancer = compose( const enhancer: StoreEnhancer = compose(
applyMiddleware(logger), applyMiddleware(logger),
(next: StoreEnhancerStoreCreator) => { (next: StoreEnhancerStoreCreator) => {
const instrument = useDevtoolsExtension const instrument = useDevtoolsExtension
@ -45,7 +45,7 @@ const enhancer = compose(
return instrument(next); return instrument(next);
}, },
persistState(getDebugSessionKey()), persistState(getDebugSessionKey()),
); ) as any;
const store = createStore(rootReducer, enhancer); const store = createStore(rootReducer, enhancer);

View File

@ -185,12 +185,12 @@ export interface DemoAppState {
} }
export const rootReducer: Reducer<DemoAppState, DemoAppAction> = export const rootReducer: Reducer<DemoAppState, DemoAppAction> =
combineReducers<DemoAppState, DemoAppAction>({ combineReducers({
timeoutUpdateEnabled: (state = false, action) => timeoutUpdateEnabled: (state = false, action: DemoAppAction) =>
action.type === 'TOGGLE_TIMEOUT_UPDATE' action.type === 'TOGGLE_TIMEOUT_UPDATE'
? action.timeoutUpdateEnabled ? action.timeoutUpdateEnabled
: state, : state,
store: (state = 0, action) => store: (state = 0, action: DemoAppAction) =>
action.type === 'INCREMENT' ? state + 1 : state, action.type === 'INCREMENT' ? state + 1 : state,
undefined: (state = { val: undefined }) => state, undefined: (state = { val: undefined }) => state,
null: (state = null) => state, null: (state = null) => state,
@ -199,7 +199,7 @@ export const rootReducer: Reducer<DemoAppState, DemoAppAction> =
// noop // noop
}, },
) => state, ) => state,
array: (state = [], action) => array: (state = [], action: DemoAppAction) =>
action.type === 'PUSH' action.type === 'PUSH'
? [...state, Math.random()] ? [...state, Math.random()]
: action.type === 'POP' : action.type === 'POP'
@ -207,13 +207,13 @@ export const rootReducer: Reducer<DemoAppState, DemoAppAction> =
: action.type === 'REPLACE' : action.type === 'REPLACE'
? [Math.random(), ...state.slice(1)] ? [Math.random(), ...state.slice(1)]
: state, : state,
hugeArrays: (state = [], action) => hugeArrays: (state = [], action: DemoAppAction) =>
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state, action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
hugeObjects: (state = [], action) => hugeObjects: (state = [], action: DemoAppAction) =>
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state, action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
iterators: (state = [], action) => iterators: (state = [], action: DemoAppAction) =>
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state, action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
nested: (state = NESTED, action) => nested: (state = NESTED, action: DemoAppAction) =>
action.type === 'CHANGE_NESTED' action.type === 'CHANGE_NESTED'
? { ? {
...state, ...state,
@ -230,25 +230,28 @@ export const rootReducer: Reducer<DemoAppState, DemoAppAction> =
}, },
} }
: state, : state,
recursive: (state: { obj?: unknown }[] = [], action) => recursive: (state: { obj?: unknown }[] = [], action: DemoAppAction) =>
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state, action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
immutables: (state: Immutable.Map<string, unknown>[] = [], action) => immutables: (
state: Immutable.Map<string, unknown>[] = [],
action: DemoAppAction,
) =>
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state, action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
maps: (state: Map<string, MapValue>[] = [], action) => maps: (state: Map<string, MapValue>[] = [], action: DemoAppAction) =>
action.type === 'ADD_NATIVE_MAP' ? [...state, NATIVE_MAP] : state, action.type === 'ADD_NATIVE_MAP' ? [...state, NATIVE_MAP] : state,
immutableNested: (state = IMMUTABLE_NESTED, action) => immutableNested: (state = IMMUTABLE_NESTED, action: DemoAppAction) =>
action.type === 'CHANGE_IMMUTABLE_NESTED' action.type === 'CHANGE_IMMUTABLE_NESTED'
? state.updateIn( ? state.updateIn(
['long', 'nested', 0, 'path', 'to', 'a'], ['long', 'nested', 0, 'path', 'to', 'a'],
(str: unknown) => (str as string) + '!', (str: unknown) => (str as string) + '!',
) )
: state, : state,
addFunction: (state = null, action) => addFunction: (state = null, action: DemoAppAction) =>
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state, action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
addSymbol: (state = null, action) => addSymbol: (state = null, action: DemoAppAction) =>
action.type === 'ADD_SYMBOL' action.type === 'ADD_SYMBOL'
? { s: window.Symbol('symbol'), error: new Error('TEST') } ? { s: window.Symbol('symbol'), error: new Error('TEST') }
: state, : state,
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) => shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action: DemoAppAction) =>
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state, action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
}); }) as any;

View File

@ -72,7 +72,7 @@
"eslint-plugin-react": "^7.35.0", "eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"react": "^18.3.1", "react": "^18.3.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"typescript": "~5.5.3" "typescript": "~5.5.3"
}, },

View File

@ -60,7 +60,7 @@
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-jest": "^28.6.0", "eslint-plugin-jest": "^28.6.0",
"jest": "^29.7.0", "jest": "^29.7.0",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"ts-jest": "^29.2.3", "ts-jest": "^29.2.3",

View File

@ -4,7 +4,6 @@ import isPlainObject from 'lodash/isPlainObject';
import { import {
Action, Action,
Observer, Observer,
PreloadedState,
Reducer, Reducer,
Store, Store,
StoreEnhancer, StoreEnhancer,
@ -271,8 +270,8 @@ export const INIT_ACTION = { type: '@@INIT' };
/** /**
* Computes the next entry with exceptions catching. * Computes the next entry with exceptions catching.
*/ */
function computeWithTryCatch<S, A extends Action<string>>( function computeWithTryCatch<S, A extends Action<string>, PreloadedState>(
reducer: Reducer<S, A>, reducer: Reducer<S, A, PreloadedState>,
action: A, action: A,
state: S, state: S,
) { ) {
@ -301,8 +300,8 @@ function computeWithTryCatch<S, A extends Action<string>>(
/** /**
* Computes the next entry in the log by applying an action. * Computes the next entry in the log by applying an action.
*/ */
function computeNextEntry<S, A extends Action<string>>( function computeNextEntry<S, A extends Action<string>, PreloadedState>(
reducer: Reducer<S, A>, reducer: Reducer<S, A, PreloadedState>,
action: A, action: A,
state: S, state: S,
shouldCatchErrors: boolean | undefined, shouldCatchErrors: boolean | undefined,
@ -316,10 +315,10 @@ function computeNextEntry<S, A extends Action<string>>(
/** /**
* Runs the reducer on invalidated actions to get a fresh computation log. * Runs the reducer on invalidated actions to get a fresh computation log.
*/ */
function recomputeStates<S, A extends Action<string>>( function recomputeStates<S, A extends Action<string>, PreloadedState>(
computedStates: { state: S; error?: string }[], computedStates: { state: S; error?: string }[],
minInvalidatedStateIndex: number, minInvalidatedStateIndex: number,
reducer: Reducer<S, A>, reducer: Reducer<S, A, PreloadedState>,
committedState: S, committedState: S,
actionsById: { [actionId: number]: PerformAction<A> }, actionsById: { [actionId: number]: PerformAction<A> },
stagedActionIds: number[], stagedActionIds: number[],
@ -413,11 +412,12 @@ export interface LiftedState<S, A extends Action<string>, MonitorState> {
function liftReducerWith< function liftReducerWith<
S, S,
A extends Action<string>, A extends Action<string>,
PreloadedState,
MonitorState, MonitorState,
MonitorAction extends Action<string>, MonitorAction extends Action<string>,
>( >(
reducer: Reducer<S, A>, reducer: Reducer<S, A, PreloadedState>,
initialCommittedState: PreloadedState<S> | undefined, initialCommittedState: S | PreloadedState | undefined,
monitorReducer: Reducer<MonitorState, MonitorAction>, monitorReducer: Reducer<MonitorState, MonitorAction>,
options: Options<S, A, MonitorState, MonitorAction>, options: Options<S, A, MonitorState, MonitorAction>,
): Reducer<LiftedState<S, A, MonitorState>, LiftedAction<S, A, MonitorState>> { ): Reducer<LiftedState<S, A, MonitorState>, LiftedAction<S, A, MonitorState>> {
@ -575,7 +575,7 @@ function liftReducerWith<
if (maxAge && stagedActionIds.length > maxAge) { if (maxAge && stagedActionIds.length > maxAge) {
// States must be recomputed before committing excess. // States must be recomputed before committing excess.
computedStates = recomputeStates<S, A>( computedStates = recomputeStates<S, A, PreloadedState>(
computedStates, computedStates,
minInvalidatedStateIndex, minInvalidatedStateIndex,
reducer, reducer,
@ -872,6 +872,7 @@ export type EnhancedStore<S, A extends Action<string>, MonitorState> = Store<
function unliftStore< function unliftStore<
S, S,
A extends Action<string>, A extends Action<string>,
PreloadedState,
MonitorState, MonitorState,
MonitorAction extends Action<string>, MonitorAction extends Action<string>,
NextExt, NextExt,
@ -882,7 +883,9 @@ function unliftStore<
LiftedAction<S, A, MonitorState> LiftedAction<S, A, MonitorState>
> & > &
NextExt, NextExt,
liftReducer: (r: Reducer<S, A>) => LiftedReducer<S, A, MonitorState>, liftReducer: (
r: Reducer<S, A, PreloadedState>,
) => LiftedReducer<S, A, MonitorState>,
options: Options<S, A, MonitorState, MonitorAction>, options: Options<S, A, MonitorState, MonitorAction>,
) { ) {
let lastDefinedState: S & NextStateExt; let lastDefinedState: S & NextStateExt;
@ -924,7 +927,7 @@ function unliftStore<
replaceReducer(nextReducer: Reducer<S & NextStateExt, A>) { replaceReducer(nextReducer: Reducer<S & NextStateExt, A>) {
liftedStore.replaceReducer( liftedStore.replaceReducer(
liftReducer( liftReducer(
nextReducer as unknown as Reducer<S, A>, nextReducer as unknown as Reducer<S, A, PreloadedState>,
) as unknown as Reducer< ) as unknown as Reducer<
LiftedState<S, A, MonitorState> & NextStateExt, LiftedState<S, A, MonitorState> & NextStateExt,
LiftedAction<S, A, MonitorState> LiftedAction<S, A, MonitorState>
@ -1006,14 +1009,17 @@ export function instrument<
); );
} }
return <NextExt, NextStateExt>( return <
NextExt extends NonNullable<unknown>,
NextStateExt extends NonNullable<unknown>,
>(
createStore: StoreEnhancerStoreCreator<NextExt, NextStateExt>, createStore: StoreEnhancerStoreCreator<NextExt, NextStateExt>,
) => ) =>
<S, A extends Action<string>>( <S, A extends Action<string>, PreloadedState>(
reducer: Reducer<S, A>, reducer: Reducer<S, A, PreloadedState>,
initialState?: PreloadedState<S>, initialState?: PreloadedState | undefined,
) => { ) => {
function liftReducer(r: Reducer<S, A>) { function liftReducer(r: Reducer<S, A, PreloadedState>) {
if (typeof r !== 'function') { if (typeof r !== 'function') {
if (r && typeof (r as { default: unknown }).default === 'function') { if (r && typeof (r as { default: unknown }).default === 'function') {
throw new Error( throw new Error(
@ -1025,7 +1031,13 @@ export function instrument<
} }
throw new Error('Expected the reducer to be a function.'); throw new Error('Expected the reducer to be a function.');
} }
return liftReducerWith<S, A, MonitorState, MonitorAction>( return liftReducerWith<
S,
A,
PreloadedState,
MonitorState,
MonitorAction
>(
r, r,
initialState, initialState,
monitorReducer, monitorReducer,
@ -1057,12 +1069,17 @@ export function instrument<
return unliftStore< return unliftStore<
S, S,
A, A,
PreloadedState,
MonitorState, MonitorState,
MonitorAction, MonitorAction,
NextExt, NextExt,
NextStateExt NextStateExt
>( >(
liftedStore, liftedStore as Store<
LiftedState<S, A, MonitorState> & NextStateExt,
LiftedAction<S, A, MonitorState>
> &
NextExt,
liftReducer, liftReducer,
options as unknown as Options<S, A, MonitorState, MonitorAction>, options as unknown as Options<S, A, MonitorState, MonitorAction>,
); );

View File

@ -1,8 +1,16 @@
import { createStore, compose, Reducer, Store, Action } from 'redux'; import {
createStore,
compose,
Reducer,
Store,
Action,
StoreEnhancer,
} from 'redux';
import { import {
ActionCreators, ActionCreators,
EnhancedStore, EnhancedStore,
instrument, instrument,
LiftedAction,
LiftedStore, LiftedStore,
LiftedState, LiftedState,
} from '../src/instrument'; } from '../src/instrument';
@ -487,10 +495,18 @@ describe('instrument', () => {
const savedComputedStates = monitoredLiftedStore.getState().computedStates; const savedComputedStates = monitoredLiftedStore.getState().computedStates;
monitoredLiftedStore.dispatch({ type: 'lol' } as Action); monitoredLiftedStore.dispatch({ type: 'lol' } as unknown as LiftedAction<
number,
Action,
null
>);
expect(reducerCalls).toBe(4); expect(reducerCalls).toBe(4);
monitoredLiftedStore.dispatch({ type: 'wat' } as Action); monitoredLiftedStore.dispatch({ type: 'wat' } as unknown as LiftedAction<
number,
Action,
null
>);
expect(reducerCalls).toBe(4); expect(reducerCalls).toBe(4);
expect(monitoredLiftedStore.getState().computedStates).toBe( expect(monitoredLiftedStore.getState().computedStates).toBe(
@ -1366,7 +1382,9 @@ describe('instrument', () => {
it('throws if reducer is not a function', () => { it('throws if reducer is not a function', () => {
expect(() => expect(() =>
createStore(undefined as unknown as Reducer, instrument()), createStore(undefined as unknown as Reducer, instrument()),
).toThrow('Expected the reducer to be a function.'); ).toThrow(
"Expected the root reducer to be a function. Instead, received: 'undefined'",
);
}); });
it('warns if the reducer is not a function but has a default field that is', () => { it('warns if the reducer is not a function but has a default field that is', () => {
@ -1380,16 +1398,16 @@ describe('instrument', () => {
instrument(), instrument(),
), ),
).toThrow( ).toThrow(
'Expected the reducer to be a function. ' + "Expected the root reducer to be a function. Instead, received: 'object'",
'Instead got an object with a "default" field. ' +
'Did you pass a module instead of the default export? ' +
'Try passing require(...).default instead.',
); );
}); });
it('throws if there are more than one instrument enhancer included', () => { it('throws if there are more than one instrument enhancer included', () => {
expect(() => { expect(() => {
createStore(counter, compose(instrument(), instrument())); createStore(
counter,
compose(instrument(), instrument()) as StoreEnhancer,
);
}).toThrow( }).toThrow(
'DevTools instrumentation should not be applied more than once. ' + 'DevTools instrumentation should not be applied more than once. ' +
'Check your store configuration.', 'Check your store configuration.',

View File

@ -64,7 +64,7 @@
"eslint-plugin-react": "^7.35.0", "eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"react": "^18.3.1", "react": "^18.3.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"typescript": "~5.5.3" "typescript": "~5.5.3"
}, },

View File

@ -63,7 +63,7 @@
"@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/parser": "^8.0.0",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"typescript": "~5.5.3" "typescript": "~5.5.3"
}, },

View File

@ -7,8 +7,7 @@ export default function configureStore<
MonitorState, MonitorState,
MonitorAction extends Action<string>, MonitorAction extends Action<string>,
>( >(
// eslint-disable-next-line @typescript-eslint/no-empty-object-type next: StoreEnhancerStoreCreator,
next: StoreEnhancerStoreCreator<{}, unknown>,
subscriber: Reducer<MonitorState, MonitorAction>, subscriber: Reducer<MonitorState, MonitorAction>,
options: Options<S, A, MonitorState, MonitorAction>, options: Options<S, A, MonitorState, MonitorAction>,
) { ) {

View File

@ -6,7 +6,6 @@ import getHostForRN from 'rn-host-detect';
import { import {
Action, Action,
ActionCreator, ActionCreator,
PreloadedState,
Reducer, Reducer,
StoreEnhancer, StoreEnhancer,
StoreEnhancerStoreCreator, StoreEnhancerStoreCreator,
@ -174,7 +173,7 @@ type Message<S, A extends Action<string>> =
| ActionMessage | ActionMessage
| DispatchMessage<S, A>; | DispatchMessage<S, A>;
class DevToolsEnhancer<S, A extends Action<string>> { class DevToolsEnhancer<S, A extends Action<string>, PreloadedState> {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type // eslint-disable-next-line @typescript-eslint/no-empty-object-type
store!: EnhancedStore<S, A, {}>; store!: EnhancedStore<S, A, {}>;
filters: LocalFilter | undefined; filters: LocalFilter | undefined;
@ -547,11 +546,14 @@ class DevToolsEnhancer<S, A extends Action<string>> {
? process.env.NODE_ENV === 'development' ? process.env.NODE_ENV === 'development'
: options.realtime; : options.realtime;
if (!realtime && !(this.startOn || this.sendOn || this.sendOnError)) if (!realtime && !(this.startOn || this.sendOn || this.sendOnError))
return (f: StoreEnhancerStoreCreator) => f; return (f) => f;
const maxAge = options.maxAge || 30; const maxAge = options.maxAge || 30;
return ((next: StoreEnhancerStoreCreator) => { return ((next: StoreEnhancerStoreCreator) => {
return (reducer: Reducer<S, A>, initialState: PreloadedState<S>) => { return (
reducer: Reducer<S, A, PreloadedState>,
initialState?: PreloadedState | undefined,
) => {
this.store = configureStore(next, this.monitorReducer, { this.store = configureStore(next, this.monitorReducer, {
maxAge, maxAge,
trace: options.trace, trace: options.trace,
@ -578,8 +580,9 @@ class DevToolsEnhancer<S, A extends Action<string>> {
}; };
} }
export default <S, A extends Action<string>>(options?: Options<S, A>) => export default <S, A extends Action<string>, PreloadedState>(
new DevToolsEnhancer<S, A>().enhance(options); options?: Options<S, A>,
) => new DevToolsEnhancer<S, A, PreloadedState>().enhance(options);
const compose = const compose =
(options: Options<unknown, Action<string>>) => (options: Options<unknown, Action<string>>) =>
@ -588,9 +591,9 @@ const compose =
const devToolsEnhancer = new DevToolsEnhancer(); const devToolsEnhancer = new DevToolsEnhancer();
function preEnhancer(createStore: StoreEnhancerStoreCreator) { function preEnhancer(createStore: StoreEnhancerStoreCreator) {
return <S, A extends Action<string>>( return <S, A extends Action<string>, PreloadedState>(
reducer: Reducer<S, A>, reducer: Reducer<S, A, PreloadedState>,
preloadedState: PreloadedState<S>, preloadedState?: PreloadedState | undefined,
) => { ) => {
devToolsEnhancer.store = createStore(reducer, preloadedState) as any; devToolsEnhancer.store = createStore(reducer, preloadedState) as any;
return { return {

View File

@ -18,14 +18,14 @@
"@redux-devtools/core": "^4.0.0", "@redux-devtools/core": "^4.0.0",
"@redux-devtools/dock-monitor": "^4.0.0", "@redux-devtools/dock-monitor": "^4.0.0",
"@redux-devtools/rtk-query-monitor": "^5.0.0", "@redux-devtools/rtk-query-monitor": "^5.0.0",
"@reduxjs/toolkit": "^1.9.7", "@reduxjs/toolkit": "^2.2.7",
"framer-motion": "^11.3.8", "framer-motion": "^11.3.8",
"msw": "^2.3.5", "msw": "^2.3.5",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-icons": "^5.2.1", "react-icons": "^5.2.1",
"react-is": "^18.3.1", "react-is": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"react-router-dom": "^6.25.1", "react-router-dom": "^6.25.1",
"styled-components": "^5.3.11" "styled-components": "^5.3.11"
}, },

View File

@ -1,6 +1,5 @@
import { import {
configureStore, configureStore,
Middleware,
combineReducers, combineReducers,
EnhancedStore, EnhancedStore,
} from '@reduxjs/toolkit'; } from '@reduxjs/toolkit';
@ -21,9 +20,6 @@ export const store: EnhancedStore<ReturnType<typeof reducer>> = configureStore({
devTools, devTools,
// adding the api middleware enables caching, invalidation, polling and other features of `rtk-query` // adding the api middleware enables caching, invalidation, polling and other features of `rtk-query`
middleware: (getDefaultMiddleware) => middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat([ getDefaultMiddleware().concat([pokemonApi.middleware, postsApi.middleware]),
pokemonApi.middleware,
postsApi.middleware,
]) as Middleware[],
enhancers: (devTools ? [] : [DevTools.instrument()]) as any, enhancers: (devTools ? [] : [DevTools.instrument()]) as any,
}); });

View File

@ -64,7 +64,7 @@
"@emotion/babel-preset-css-prop": "^11.12.0", "@emotion/babel-preset-css-prop": "^11.12.0",
"@emotion/react": "^11.13.0", "@emotion/react": "^11.13.0",
"@redux-devtools/core": "^4.0.0", "@redux-devtools/core": "^4.0.0",
"@reduxjs/toolkit": "^1.9.7", "@reduxjs/toolkit": "^2.2.7",
"@testing-library/dom": "^10.3.2", "@testing-library/dom": "^10.3.2",
"@testing-library/jest-dom": "^6.4.6", "@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "^16.0.0", "@testing-library/react": "^16.0.0",
@ -83,8 +83,8 @@
"jest-environment-jsdom": "^29.7.0", "jest-environment-jsdom": "^29.7.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"ts-jest": "^29.2.3", "ts-jest": "^29.2.3",
"typescript": "~5.5.3" "typescript": "~5.5.3"

View File

@ -1,5 +1,5 @@
import { createSelector, Selector } from '@reduxjs/toolkit'; import { createSelector, Selector } from '@reduxjs/toolkit';
import { QueryStatus } from '@reduxjs/toolkit/dist/query'; import { QueryStatus } from '@reduxjs/toolkit/query';
import React, { ReactNode, PureComponent } from 'react'; import React, { ReactNode, PureComponent } from 'react';
import type { ShouldExpandNodeInitially } from 'react-json-tree'; import type { ShouldExpandNodeInitially } from 'react-json-tree';
import { QueryPreviewTabs, RtkResourceInfo, RTKStatusFlags } from '../types'; import { QueryPreviewTabs, RtkResourceInfo, RTKStatusFlags } from '../types';

View File

@ -1,5 +1,5 @@
import React, { PureComponent, createRef, ReactNode } from 'react'; import React, { PureComponent, createRef, ReactNode } from 'react';
import type { AnyAction, Dispatch, Action } from '@reduxjs/toolkit'; import type { Dispatch, Action } from '@reduxjs/toolkit';
import type { LiftedAction, LiftedState } from '@redux-devtools/core'; import type { LiftedAction, LiftedState } from '@redux-devtools/core';
import { import {
QueryFormValues, QueryFormValues,
@ -96,15 +96,33 @@ class RtkQueryInspector<S, A extends Action<string>> extends PureComponent<
} }
handleQueryFormValuesChange = (values: Partial<QueryFormValues>): void => { handleQueryFormValuesChange = (values: Partial<QueryFormValues>): void => {
this.props.dispatch(changeQueryFormValues(values) as AnyAction); this.props.dispatch(
changeQueryFormValues(values) as unknown as LiftedAction<
S,
A,
RtkQueryMonitorState
>,
);
}; };
handleSelectQuery = (queryInfo: RtkResourceInfo): void => { handleSelectQuery = (queryInfo: RtkResourceInfo): void => {
this.props.dispatch(selectQueryKey(queryInfo) as AnyAction); this.props.dispatch(
selectQueryKey(queryInfo) as unknown as LiftedAction<
S,
A,
RtkQueryMonitorState
>,
);
}; };
handleTabChange = (tab: QueryPreviewTabs): void => { handleTabChange = (tab: QueryPreviewTabs): void => {
this.props.dispatch(selectedPreviewTab(tab) as AnyAction); this.props.dispatch(
selectedPreviewTab(tab) as unknown as LiftedAction<
S,
A,
RtkQueryMonitorState
>,
);
}; };
render(): ReactNode { render(): ReactNode {

View File

@ -3,6 +3,7 @@ import {
configureStore, configureStore,
EnhancedStore, EnhancedStore,
Middleware, Middleware,
Tuple,
} from '@reduxjs/toolkit'; } from '@reduxjs/toolkit';
import { createApi } from '@reduxjs/toolkit/query/react'; import { createApi } from '@reduxjs/toolkit/query/react';
import type { BaseQueryFn, FetchArgs } from '@reduxjs/toolkit/query'; import type { BaseQueryFn, FetchArgs } from '@reduxjs/toolkit/query';
@ -70,8 +71,9 @@ export function setupStore(
devTools: false, devTools: false,
// adding the api middleware enables caching, invalidation, polling and other features of `rtk-query` // adding the api middleware enables caching, invalidation, polling and other features of `rtk-query`
middleware: (getDefaultMiddleware) => middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat([pokemonApi.middleware]) as Middleware[], getDefaultMiddleware().concat(pokemonApi.middleware),
enhancers: [devTools.instrument()], enhancers: (getDefaultEnhancers) =>
getDefaultEnhancers().concat(devTools.instrument()),
}); });
return { return {

View File

@ -23,8 +23,8 @@
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-is": "^18.3.1", "react-is": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"redux": "^4.2.1", "redux": "^5.0.1",
"styled-components": "^5.3.11", "styled-components": "^5.3.11",
"todomvc-app-css": "^2.4.3" "todomvc-app-css": "^2.4.3"
}, },

View File

@ -1,12 +1,17 @@
import { combineReducers } from 'redux'; import { combineReducers, Reducer } from 'redux';
import todos, { Todo } from './todos'; import todos, { Todo } from './todos';
import { TodoAction } from '../actions/TodoActions';
export interface TodoState { export interface TodoState {
todos: Todo[]; todos: Todo[];
} }
const rootReducer = combineReducers({ const rootReducer: Reducer<
TodoState,
TodoAction,
Partial<TodoState>
> = combineReducers({
todos, todos,
}); }) as any;
export default rootReducer; export default rootReducer;

View File

@ -1,4 +1,4 @@
import { createStore, compose, PreloadedState } from 'redux'; import { createStore, compose, StoreEnhancer } from 'redux';
import { persistState } from '@redux-devtools/core'; import { persistState } from '@redux-devtools/core';
import rootReducer, { TodoState } from '../reducers'; import rootReducer, { TodoState } from '../reducers';
import DevTools from '../containers/DevTools'; import DevTools from '../containers/DevTools';
@ -8,13 +8,11 @@ function getDebugSessionKey() {
return matches && matches.length > 0 ? matches[1] : null; return matches && matches.length > 0 ? matches[1] : null;
} }
const enhancer = compose( const enhancer: StoreEnhancer = compose(
DevTools.instrument(), DevTools.instrument(),
persistState(getDebugSessionKey()), persistState(getDebugSessionKey()),
); );
export default function configureStore( export default function configureStore(initialState?: Partial<TodoState>) {
initialState?: PreloadedState<TodoState>,
) {
return createStore(rootReducer, initialState, enhancer); return createStore(rootReducer, initialState, enhancer);
} }

View File

@ -1,8 +1,6 @@
import { createStore, PreloadedState } from 'redux'; import { createStore } from 'redux';
import rootReducer, { TodoState } from '../reducers'; import rootReducer, { TodoState } from '../reducers';
export default function configureStore( export default function configureStore(initialState?: Partial<TodoState>) {
initialState?: PreloadedState<TodoState>,
) {
return createStore(rootReducer, initialState); return createStore(rootReducer, initialState);
} }

View File

@ -1,9 +1,9 @@
import { PreloadedState, Store } from 'redux'; import { Store } from 'redux';
import { TodoState } from '../reducers'; import { TodoState } from '../reducers';
import { TodoAction } from '../actions/TodoActions'; import { TodoAction } from '../actions/TodoActions';
const configureStore: ( const configureStore: (
initialState?: PreloadedState<TodoState>, initialState?: Partial<TodoState>,
) => Store<TodoState, TodoAction> = ) => Store<TodoState, TodoAction> =
process.env.NODE_ENV === 'production' process.env.NODE_ENV === 'production'
? // eslint-disable-next-line @typescript-eslint/no-require-imports ? // eslint-disable-next-line @typescript-eslint/no-require-imports

View File

@ -53,7 +53,7 @@
"eslint-plugin-react": "^7.35.0", "eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.2",
"react": "^18.3.1", "react": "^18.3.1",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"typescript": "~5.5.3" "typescript": "~5.5.3"
}, },

View File

@ -41,7 +41,7 @@
"jsan": "^3.1.14", "jsan": "^3.1.14",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
"redux": "^4.2.1" "redux": "^5.0.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.24.8", "@babel/cli": "^7.24.8",

View File

@ -24,9 +24,9 @@
"@redux-devtools/log-monitor": "^5.0.0", "@redux-devtools/log-monitor": "^5.0.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"redux": "^4.2.1", "redux": "^5.0.1",
"redux-thunk": "^2.4.2" "redux-thunk": "^3.1.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.24.9", "@babel/core": "^7.24.9",

View File

@ -1,9 +1,14 @@
import { combineReducers } from 'redux'; import { combineReducers, Reducer } from 'redux';
import counter from './counter'; import counter from './counter';
import { CounterAction } from '../actions/CounterActions';
const rootReducer = combineReducers({ const rootReducer: Reducer<
CounterState,
CounterAction,
Partial<CounterState>
> = combineReducers({
counter, counter,
}); }) as any;
export interface CounterState { export interface CounterState {
counter: number; counter: number;

View File

@ -2,34 +2,40 @@ import {
createStore, createStore,
applyMiddleware, applyMiddleware,
compose, compose,
PreloadedState,
Reducer, Reducer,
StoreEnhancer,
Middleware,
} from 'redux'; } from 'redux';
import { persistState } from '@redux-devtools/core'; import { persistState } from '@redux-devtools/core';
import thunk from 'redux-thunk'; import thunk from 'redux-thunk';
import rootReducer, { CounterState } from '../reducers'; import rootReducer, { CounterState } from '../reducers';
import DevTools from '../containers/DevTools'; import DevTools from '../containers/DevTools';
import { CounterAction } from '../actions/CounterActions';
function getDebugSessionKey() { function getDebugSessionKey() {
const matches = /[?&]debug_session=([^&#]+)\b/.exec(window.location.href); const matches = /[?&]debug_session=([^&#]+)\b/.exec(window.location.href);
return matches && matches.length > 0 ? matches[1] : null; return matches && matches.length > 0 ? matches[1] : null;
} }
const enhancer = compose( const enhancer: StoreEnhancer = compose(
applyMiddleware(thunk), applyMiddleware(thunk as unknown as Middleware),
DevTools.instrument(), DevTools.instrument(),
persistState(getDebugSessionKey()), persistState(getDebugSessionKey()),
); );
export default function configureStore( export default function configureStore(initialState?: Partial<CounterState>) {
initialState?: PreloadedState<CounterState>,
) {
const store = createStore(rootReducer, initialState, enhancer); const store = createStore(rootReducer, initialState, enhancer);
if (module.hot) { if (module.hot) {
module.hot.accept('../reducers', () => module.hot.accept('../reducers', () =>
store.replaceReducer(
// eslint-disable-next-line @typescript-eslint/no-require-imports // eslint-disable-next-line @typescript-eslint/no-require-imports
store.replaceReducer(require('../reducers').default as Reducer), require('../reducers').default as Reducer<
CounterState,
CounterAction,
Partial<CounterState>
>,
),
); );
} }

View File

@ -1,11 +1,9 @@
import { createStore, applyMiddleware, PreloadedState } from 'redux'; import { createStore, applyMiddleware, Middleware } from 'redux';
import thunk from 'redux-thunk'; import thunk from 'redux-thunk';
import rootReducer, { CounterState } from '../reducers'; import rootReducer, { CounterState } from '../reducers';
const enhancer = applyMiddleware(thunk); const enhancer = applyMiddleware(thunk as unknown as Middleware);
export default function configureStore( export default function configureStore(initialState?: Partial<CounterState>) {
initialState?: PreloadedState<CounterState>,
) {
return createStore(rootReducer, initialState, enhancer); return createStore(rootReducer, initialState, enhancer);
} }

View File

@ -1,9 +1,9 @@
import { PreloadedState, Store } from 'redux'; import { Store } from 'redux';
import { CounterState } from '../reducers'; import { CounterState } from '../reducers';
import { CounterAction } from '../actions/CounterActions'; import { CounterAction } from '../actions/CounterActions';
const configureStore: ( const configureStore: (
initialState?: PreloadedState<CounterState>, initialState?: Partial<CounterState>,
) => Store<CounterState, CounterAction> = ) => Store<CounterState, CounterAction> =
process.env.NODE_ENV === 'production' process.env.NODE_ENV === 'production'
? // eslint-disable-next-line @typescript-eslint/no-require-imports ? // eslint-disable-next-line @typescript-eslint/no-require-imports

View File

@ -37,8 +37,8 @@
"classnames": "^2.5.1", "classnames": "^2.5.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"redux": "^4.2.1", "redux": "^5.0.1",
"todomvc-app-css": "^2.4.3" "todomvc-app-css": "^2.4.3"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,12 +1,17 @@
import { combineReducers } from 'redux'; import { combineReducers, Reducer } from 'redux';
import todos, { Todo } from './todos'; import todos, { Todo } from './todos';
import { TodoAction } from '../actions/TodoActions';
export interface TodoState { export interface TodoState {
todos: Todo[]; todos: Todo[];
} }
const rootReducer = combineReducers({ const rootReducer: Reducer<
TodoState,
TodoAction,
Partial<TodoState>
> = combineReducers({
todos, todos,
}); }) as any;
export default rootReducer; export default rootReducer;

View File

@ -1,4 +1,4 @@
import { createStore, compose, PreloadedState } from 'redux'; import { createStore, compose, StoreEnhancer } from 'redux';
import { persistState } from '@redux-devtools/core'; import { persistState } from '@redux-devtools/core';
import rootReducer, { TodoState } from '../reducers'; import rootReducer, { TodoState } from '../reducers';
import DevTools from '../containers/DevTools'; import DevTools from '../containers/DevTools';
@ -8,13 +8,11 @@ function getDebugSessionKey() {
return matches && matches.length > 0 ? matches[1] : null; return matches && matches.length > 0 ? matches[1] : null;
} }
const enhancer = compose( const enhancer: StoreEnhancer = compose(
DevTools.instrument(), DevTools.instrument(),
persistState(getDebugSessionKey()), persistState(getDebugSessionKey()),
); );
export default function configureStore( export default function configureStore(initialState?: Partial<TodoState>) {
initialState?: PreloadedState<TodoState>,
) {
return createStore(rootReducer, initialState, enhancer); return createStore(rootReducer, initialState, enhancer);
} }

View File

@ -1,8 +1,6 @@
import { createStore, PreloadedState } from 'redux'; import { createStore } from 'redux';
import rootReducer, { TodoState } from '../reducers'; import rootReducer, { TodoState } from '../reducers';
export default function configureStore( export default function configureStore(initialState?: Partial<TodoState>) {
initialState?: PreloadedState<TodoState>,
) {
return createStore(rootReducer, initialState); return createStore(rootReducer, initialState);
} }

View File

@ -1,9 +1,9 @@
import { PreloadedState, Store } from 'redux'; import { Store } from 'redux';
import { TodoState } from '../reducers'; import { TodoState } from '../reducers';
import { TodoAction } from '../actions/TodoActions'; import { TodoAction } from '../actions/TodoActions';
const configureStore: ( const configureStore: (
initialState?: PreloadedState<TodoState>, initialState?: Partial<TodoState>,
) => Store<TodoState, TodoAction> = ) => Store<TodoState, TodoAction> =
process.env.NODE_ENV === 'production' process.env.NODE_ENV === 'production'
? // eslint-disable-next-line @typescript-eslint/no-require-imports ? // eslint-disable-next-line @typescript-eslint/no-require-imports

View File

@ -67,8 +67,8 @@
"jest": "^29.7.0", "jest": "^29.7.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-redux": "^8.1.3", "react-redux": "^9.1.2",
"redux": "^4.2.1", "redux": "^5.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"ts-jest": "^29.2.3", "ts-jest": "^29.2.3",
"typescript": "~5.5.3" "typescript": "~5.5.3"

View File

@ -1,6 +1,6 @@
import mapValues from 'lodash/mapValues'; import mapValues from 'lodash/mapValues';
import identity from 'lodash/identity'; import identity from 'lodash/identity';
import { Action, PreloadedState, Reducer, StoreEnhancer } from 'redux'; import { Action, Reducer, StoreEnhancer } from 'redux';
import { LiftedState } from '@redux-devtools/instrument'; import { LiftedState } from '@redux-devtools/instrument';
export default function persistState<S, A extends Action<string>, MonitorState>( export default function persistState<S, A extends Action<string>, MonitorState>(
@ -32,9 +32,9 @@ export default function persistState<S, A extends Action<string>, MonitorState>(
} }
return (next) => return (next) =>
<S2, A2 extends Action<string>>( <S2, A2 extends Action<string>, PreloadedState>(
reducer: Reducer<S2, A2>, reducer: Reducer<S2, A2, PreloadedState>,
initialState?: PreloadedState<S2>, initialState?: PreloadedState | undefined,
) => { ) => {
const key = `redux-dev-session-${sessionId}`; const key = `redux-dev-session-${sessionId}`;
@ -58,7 +58,7 @@ export default function persistState<S, A extends Action<string>, MonitorState>(
const store = next( const store = next(
reducer, reducer,
finalInitialState as PreloadedState<S2> | undefined, finalInitialState as PreloadedState | undefined,
); );
return { return {

View File

@ -1,5 +1,5 @@
import { instrument, persistState } from '../src'; import { instrument, persistState } from '../src';
import { compose, createStore } from 'redux'; import { compose, createStore, StoreEnhancer } from 'redux';
describe('persistState', () => { describe('persistState', () => {
const savedLocalStorage = global.localStorage; const savedLocalStorage = global.localStorage;
@ -50,7 +50,7 @@ describe('persistState', () => {
it('should persist state', () => { it('should persist state', () => {
const store = createStore( const store = createStore(
reducer, reducer,
compose(instrument(), persistState('id')), compose(instrument(), persistState('id')) as StoreEnhancer,
); );
expect(store.getState()).toBe(0); expect(store.getState()).toBe(0);
@ -60,20 +60,26 @@ describe('persistState', () => {
const store2 = createStore( const store2 = createStore(
reducer, reducer,
compose(instrument(), persistState('id')), compose(instrument(), persistState('id')) as StoreEnhancer,
); );
expect(store2.getState()).toBe(2); expect(store2.getState()).toBe(2);
}); });
it('should not persist state if no session id', () => { it('should not persist state if no session id', () => {
const store = createStore(reducer, compose(instrument(), persistState())); const store = createStore(
reducer,
compose(instrument(), persistState()) as StoreEnhancer,
);
expect(store.getState()).toBe(0); expect(store.getState()).toBe(0);
store.dispatch({ type: 'INCREMENT' }); store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'INCREMENT' }); store.dispatch({ type: 'INCREMENT' });
expect(store.getState()).toBe(2); expect(store.getState()).toBe(2);
const store2 = createStore(reducer, compose(instrument(), persistState())); const store2 = createStore(
reducer,
compose(instrument(), persistState()) as StoreEnhancer,
);
expect(store2.getState()).toBe(0); expect(store2.getState()).toBe(0);
}); });
@ -82,7 +88,7 @@ describe('persistState', () => {
state === undefined ? -1 : state - 1; state === undefined ? -1 : state - 1;
const store = createStore( const store = createStore(
reducer, reducer,
compose(instrument(), persistState('id', oneLess)), compose(instrument(), persistState('id', oneLess)) as StoreEnhancer,
); );
expect(store.getState()).toBe(0); expect(store.getState()).toBe(0);
@ -92,7 +98,7 @@ describe('persistState', () => {
const store2 = createStore( const store2 = createStore(
reducer, reducer,
compose(instrument(), persistState('id', oneLess)), compose(instrument(), persistState('id', oneLess)) as StoreEnhancer,
); );
expect(store2.getState()).toBe(1); expect(store2.getState()).toBe(1);
}); });
@ -102,7 +108,10 @@ describe('persistState', () => {
action.type === 'INCREMENT' ? ({ type: 'DECREMENT' } as const) : action; action.type === 'INCREMENT' ? ({ type: 'DECREMENT' } as const) : action;
const store = createStore( const store = createStore(
reducer, reducer,
compose(instrument(), persistState('id', undefined, incToDec)), compose(
instrument(),
persistState('id', undefined, incToDec),
) as StoreEnhancer,
); );
expect(store.getState()).toBe(0); expect(store.getState()).toBe(0);
@ -112,7 +121,10 @@ describe('persistState', () => {
const store2 = createStore( const store2 = createStore(
reducer, reducer,
compose(instrument(), persistState('id', undefined, incToDec)), compose(
instrument(),
persistState('id', undefined, incToDec),
) as StoreEnhancer,
); );
expect(store2.getState()).toBe(-2); expect(store2.getState()).toBe(-2);
}); });
@ -124,7 +136,10 @@ describe('persistState', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
delete global.localStorage.getItem; delete global.localStorage.getItem;
createStore(reducer, compose(instrument(), persistState('id'))); createStore(
reducer,
compose(instrument(), persistState('id')) as StoreEnhancer,
);
expect(spy.mock.calls[0]).toContain( expect(spy.mock.calls[0]).toContain(
'Could not read debug session from localStorage:', 'Could not read debug session from localStorage:',
@ -142,7 +157,7 @@ describe('persistState', () => {
delete global.localStorage.setItem; delete global.localStorage.setItem;
const store = createStore( const store = createStore(
reducer, reducer,
compose(instrument(), persistState('id')), compose(instrument(), persistState('id')) as StoreEnhancer,
); );
store.dispatch({ type: 'INCREMENT' }); store.dispatch({ type: 'INCREMENT' });

View File

@ -81,8 +81,8 @@ importers:
specifier: ^3.0.0 specifier: ^3.0.0
version: link:../packages/redux-devtools-utils version: link:../packages/redux-devtools-utils
'@reduxjs/toolkit': '@reduxjs/toolkit':
specifier: ^1.9.7 specifier: ^2.2.7
version: 1.9.7(react-redux@8.1.3)(react@18.3.1) version: 2.2.7(react-redux@9.1.2)(react@18.3.1)
'@types/jsan': '@types/jsan':
specifier: ^3.1.5 specifier: ^3.1.5
version: 3.1.5 version: 3.1.5
@ -111,14 +111,14 @@ importers:
specifier: ^0.19.0 specifier: ^0.19.0
version: link:../packages/react-json-tree version: link:../packages/react-json-tree
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
redux-persist: redux-persist:
specifier: ^6.0.0 specifier: ^6.0.0
version: 6.0.0(react@18.3.1)(redux@4.2.1) version: 6.0.0(react@18.3.1)(redux@5.0.1)
styled-components: styled-components:
specifier: ^5.3.11 specifier: ^5.3.11
version: 5.3.11(@babel/core@7.24.9)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1) version: 5.3.11(@babel/core@7.24.9)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1)
@ -829,11 +829,11 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -852,9 +852,6 @@ importers:
'@redux-devtools/ui': '@redux-devtools/ui':
specifier: ^1.3.2 specifier: ^1.3.2
version: link:../redux-devtools-ui version: link:../redux-devtools-ui
'@reduxjs/toolkit':
specifier: ^1.0.0 || ^2.0.0
version: 1.9.7(react-redux@8.1.3)(react@18.3.1)
jsan: jsan:
specifier: ^3.1.14 specifier: ^3.1.14
version: 3.1.14 version: 3.1.14
@ -865,14 +862,14 @@ importers:
specifier: ^4.17.21 specifier: ^4.17.21
version: 4.17.21 version: 4.17.21
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
redux-persist: redux-persist:
specifier: ^6.0.0 specifier: ^6.0.0
version: 6.0.0(react@18.3.1)(redux@4.2.1) version: 6.0.0(react@18.3.1)(redux@5.0.1)
socketcluster-client: socketcluster-client:
specifier: ^19.2.1 specifier: ^19.2.1
version: 19.2.1 version: 19.2.1
@ -901,6 +898,9 @@ importers:
'@emotion/react': '@emotion/react':
specifier: ^11.13.0 specifier: ^11.13.0
version: 11.13.0(@types/react@18.3.3)(react@18.3.1) version: 11.13.0(@types/react@18.3.3)(react@18.3.1)
'@reduxjs/toolkit':
specifier: ^2.2.7
version: 2.2.7(react-redux@9.1.2)(react@18.3.1)
'@rjsf/core': '@rjsf/core':
specifier: ^4.2.3 specifier: ^4.2.3
version: 4.2.3(react@18.3.1) version: 4.2.3(react@18.3.1)
@ -1036,9 +1036,6 @@ importers:
'@redux-devtools/ui': '@redux-devtools/ui':
specifier: ^1.3.1 specifier: ^1.3.1
version: link:../redux-devtools-ui version: link:../redux-devtools-ui
'@reduxjs/toolkit':
specifier: ^1.0.0 || ^2.0.0
version: 1.9.7(react-redux@8.1.3)(react@18.3.1)
d3-state-visualizer: d3-state-visualizer:
specifier: ^3.0.0 specifier: ^3.0.0
version: link:../d3-state-visualizer version: link:../d3-state-visualizer
@ -1082,6 +1079,9 @@ importers:
'@emotion/react': '@emotion/react':
specifier: ^11.13.0 specifier: ^11.13.0
version: 11.13.0(@types/react@18.3.3)(react@18.3.1) version: 11.13.0(@types/react@18.3.3)(react@18.3.1)
'@reduxjs/toolkit':
specifier: ^2.2.7
version: 2.2.7(react-redux@9.1.2)(react@18.3.1)
'@rjsf/core': '@rjsf/core':
specifier: ^4.2.3 specifier: ^4.2.3
version: 4.2.3(react@18.3.1) version: 4.2.3(react@18.3.1)
@ -1155,14 +1155,14 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
redux-persist: redux-persist:
specifier: ^6.0.0 specifier: ^6.0.0
version: 6.0.0(react@18.3.1)(redux@4.2.1) version: 6.0.0(react@18.3.1)(redux@5.0.1)
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -1243,8 +1243,8 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1 version: 18.3.1
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -1264,8 +1264,8 @@ importers:
specifier: ^6.0.0 specifier: ^6.0.0
version: link:../redux-devtools-app version: link:../redux-devtools-app
'@reduxjs/toolkit': '@reduxjs/toolkit':
specifier: ^1.9.7 specifier: ^2.2.7
version: 1.9.7(react-redux@8.1.3)(react@18.3.1) version: 2.2.7(react-redux@9.1.2)(react@18.3.1)
'@types/react': '@types/react':
specifier: ^18.3.3 specifier: ^18.3.3
version: 18.3.3 version: 18.3.3
@ -1479,8 +1479,8 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1 version: 18.3.1
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -1528,8 +1528,8 @@ importers:
specifier: ^9.1.0 specifier: ^9.1.0
version: 9.1.0(eslint@8.57.0) version: 9.1.0(eslint@8.57.0)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -1649,8 +1649,8 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1 version: 18.3.1
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -1776,8 +1776,8 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -1824,14 +1824,14 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1 version: 18.3.1
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
react-router-dom: react-router-dom:
specifier: ^6.25.1 specifier: ^6.25.1
version: 6.25.1(react-dom@18.3.1)(react@18.3.1) version: 6.25.1(react-dom@18.3.1)(react@18.3.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
redux-logger: redux-logger:
specifier: ^3.0.6 specifier: ^3.0.6
version: 3.0.6 version: 3.0.6
@ -1864,8 +1864,8 @@ importers:
specifier: ^18.3.0 specifier: ^18.3.0
version: 18.3.0 version: 18.3.0
'@types/redux-logger': '@types/redux-logger':
specifier: 3.0.12 specifier: ^3.0.13
version: 3.0.12 version: 3.0.13
'@types/styled-components': '@types/styled-components':
specifier: ^5.1.34 specifier: ^5.1.34
version: 5.1.34 version: 5.1.34
@ -2042,8 +2042,8 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -2087,14 +2087,14 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
react-router-dom: react-router-dom:
specifier: ^6.25.1 specifier: ^6.25.1
version: 6.25.1(react-dom@18.3.1)(react@18.3.1) version: 6.25.1(react-dom@18.3.1)(react@18.3.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
redux-logger: redux-logger:
specifier: ^3.0.6 specifier: ^3.0.6
version: 3.0.6 version: 3.0.6
@ -2124,8 +2124,8 @@ importers:
specifier: ^18.3.0 specifier: ^18.3.0
version: 18.3.0 version: 18.3.0
'@types/redux-logger': '@types/redux-logger':
specifier: 3.0.12 specifier: ^3.0.13
version: 3.0.12 version: 3.0.13
'@types/webpack-env': '@types/webpack-env':
specifier: ^1.18.5 specifier: ^1.18.5
version: 1.18.5 version: 1.18.5
@ -2230,8 +2230,8 @@ importers:
specifier: ^29.7.0 specifier: ^29.7.0
version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2) version: 29.7.0(@types/node@20.14.11)(ts-node@10.9.2)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -2312,8 +2312,8 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1 version: 18.3.1
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -2385,8 +2385,8 @@ importers:
specifier: ^9.1.0 specifier: ^9.1.0
version: 9.1.0(eslint@8.57.0) version: 9.1.0(eslint@8.57.0)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -2458,8 +2458,8 @@ importers:
specifier: ^4.0.0 specifier: ^4.0.0
version: link:../redux-devtools version: link:../redux-devtools
'@reduxjs/toolkit': '@reduxjs/toolkit':
specifier: ^1.9.7 specifier: ^2.2.7
version: 1.9.7(react-redux@8.1.3)(react@18.3.1) version: 2.2.7(react-redux@9.1.2)(react@18.3.1)
'@testing-library/dom': '@testing-library/dom':
specifier: ^10.3.2 specifier: ^10.3.2
version: 10.3.2 version: 10.3.2
@ -2515,11 +2515,11 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -2557,8 +2557,8 @@ importers:
specifier: ^5.0.0 specifier: ^5.0.0
version: link:.. version: link:..
'@reduxjs/toolkit': '@reduxjs/toolkit':
specifier: ^1.9.7 specifier: ^2.2.7
version: 1.9.7(react-redux@8.1.3)(react@18.3.1) version: 2.2.7(react-redux@9.1.2)(react@18.3.1)
framer-motion: framer-motion:
specifier: ^11.3.8 specifier: ^11.3.8
version: 11.3.8(react-dom@18.3.1)(react@18.3.1) version: 11.3.8(react-dom@18.3.1)(react@18.3.1)
@ -2578,8 +2578,8 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1 version: 18.3.1
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
react-router-dom: react-router-dom:
specifier: ^6.25.1 specifier: ^6.25.1
version: 6.25.1(react-dom@18.3.1)(react@18.3.1) version: 6.25.1(react-dom@18.3.1)(react@18.3.1)
@ -2800,8 +2800,8 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1 version: 18.3.1
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
rimraf: rimraf:
specifier: ^6.0.1 specifier: ^6.0.1
version: 6.0.1 version: 6.0.1
@ -2836,11 +2836,11 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1 version: 18.3.1
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
styled-components: styled-components:
specifier: ^5.3.11 specifier: ^5.3.11
version: 5.3.11(@babel/core@7.24.9)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1) version: 5.3.11(@babel/core@7.24.9)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1)
@ -3144,8 +3144,8 @@ importers:
specifier: ^5.0.7 specifier: ^5.0.7
version: 5.0.7 version: 5.0.7
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
devDependencies: devDependencies:
'@babel/cli': '@babel/cli':
specifier: ^7.24.8 specifier: ^7.24.8
@ -3211,14 +3211,14 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
redux-thunk: redux-thunk:
specifier: ^2.4.2 specifier: ^3.1.0
version: 2.4.2(redux@4.2.1) version: 3.1.0(redux@5.0.1)
devDependencies: devDependencies:
'@babel/core': '@babel/core':
specifier: ^7.24.9 specifier: ^7.24.9
@ -3311,11 +3311,11 @@ importers:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^9.1.2
version: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) version: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: redux:
specifier: ^4.2.1 specifier: ^5.0.1
version: 4.2.1 version: 5.0.1
todomvc-app-css: todomvc-app-css:
specifier: ^2.4.3 specifier: ^2.4.3
version: 2.4.3 version: 2.4.3
@ -7870,23 +7870,23 @@ packages:
react: 18.3.1 react: 18.3.1
dev: false dev: false
/@reduxjs/toolkit@1.9.7(react-redux@8.1.3)(react@18.3.1): /@reduxjs/toolkit@2.2.7(react-redux@9.1.2)(react@18.3.1):
resolution: {integrity: sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==} resolution: {integrity: sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==}
peerDependencies: peerDependencies:
react: ^16.9.0 || ^17.0.0 || ^18 react: ^16.9.0 || ^17.0.0 || ^18
react-redux: ^7.2.1 || ^8.0.2 react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0
peerDependenciesMeta: peerDependenciesMeta:
react: react:
optional: true optional: true
react-redux: react-redux:
optional: true optional: true
dependencies: dependencies:
immer: 9.0.21 immer: 10.1.1
react: 18.3.1 react: 18.3.1
react-redux: 8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1) react-redux: 9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1)
redux: 4.2.1 redux: 5.0.1
redux-thunk: 2.4.2(redux@4.2.1) redux-thunk: 3.1.0(redux@5.0.1)
reselect: 4.1.8 reselect: 5.1.1
/@remix-run/router@1.18.0: /@remix-run/router@1.18.0:
resolution: {integrity: sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==} resolution: {integrity: sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==}
@ -9452,6 +9452,7 @@ packages:
resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
dependencies: dependencies:
'@types/react': 18.3.3 '@types/react': 18.3.3
dev: true
/@types/react-test-renderer@18.3.0: /@types/react-test-renderer@18.3.0:
resolution: {integrity: sha512-HW4MuEYxfDbOHQsVlY/XtOvNHftCVEPhJF2pQXXwcUiUF+Oyb0usgp48HSgpK5rt8m9KZb22yqOeZm+rrVG8gw==} resolution: {integrity: sha512-HW4MuEYxfDbOHQsVlY/XtOvNHftCVEPhJF2pQXXwcUiUF+Oyb0usgp48HSgpK5rt8m9KZb22yqOeZm+rrVG8gw==}
@ -9471,10 +9472,10 @@ packages:
'@types/prop-types': 15.7.12 '@types/prop-types': 15.7.12
csstype: 3.1.3 csstype: 3.1.3
/@types/redux-logger@3.0.12: /@types/redux-logger@3.0.13:
resolution: {integrity: sha512-5vAlwokZi/Unb1eGoZfVVzIBTPNDflwXiDzPLT1SynP6hdJfsOEf+w6ZOySOyboLWciCRYeE5DGYUnwVCq+Uyg==} resolution: {integrity: sha512-jylqZXQfMxahkuPcO8J12AKSSCQngdEWQrw7UiLUJzMBcv1r4Qg77P6mjGLjM27e5gFQDPD8vwUMJ9AyVxFSsg==}
dependencies: dependencies:
redux: 4.2.1 redux: 5.0.1
dev: true dev: true
/@types/resolve@1.20.6: /@types/resolve@1.20.6:
@ -14355,8 +14356,8 @@ packages:
/immediate@3.0.6: /immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
/immer@9.0.21: /immer@10.1.1:
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==}
/immutable@4.3.6: /immutable@4.3.6:
resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==} resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==}
@ -17693,37 +17694,22 @@ packages:
resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
dev: false dev: false
/react-redux@8.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(redux@4.2.1): /react-redux@9.1.2(@types/react@18.3.3)(react@18.3.1)(redux@5.0.1):
resolution: {integrity: sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==} resolution: {integrity: sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==}
peerDependencies: peerDependencies:
'@types/react': ^16.8 || ^17.0 || ^18.0 '@types/react': ^18.2.25
'@types/react-dom': ^16.8 || ^17.0 || ^18.0 react: ^18.0
react: ^16.8 || ^17.0 || ^18.0 redux: ^5.0.0
react-dom: ^16.8 || ^17.0 || ^18.0
react-native: '>=0.59'
redux: ^4 || ^5.0.0-beta.0
peerDependenciesMeta: peerDependenciesMeta:
'@types/react': '@types/react':
optional: true optional: true
'@types/react-dom':
optional: true
react-dom:
optional: true
react-native:
optional: true
redux: redux:
optional: true optional: true
dependencies: dependencies:
'@babel/runtime': 7.24.8
'@types/hoist-non-react-statics': 3.3.5
'@types/react': 18.3.3 '@types/react': 18.3.3
'@types/react-dom': 18.3.0
'@types/use-sync-external-store': 0.0.3 '@types/use-sync-external-store': 0.0.3
hoist-non-react-statics: 3.3.2
react: 18.3.1 react: 18.3.1
react-dom: 18.3.1(react@18.3.1) redux: 5.0.1
react-is: 18.3.1
redux: 4.2.1
use-sync-external-store: 1.2.2(react@18.3.1) use-sync-external-store: 1.2.2(react@18.3.1)
/react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1): /react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1):
@ -17931,7 +17917,7 @@ packages:
deep-diff: 0.3.8 deep-diff: 0.3.8
dev: false dev: false
/redux-persist@6.0.0(react@18.3.1)(redux@4.2.1): /redux-persist@6.0.0(react@18.3.1)(redux@5.0.1):
resolution: {integrity: sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==} resolution: {integrity: sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==}
peerDependencies: peerDependencies:
react: '>=16' react: '>=16'
@ -17941,19 +17927,17 @@ packages:
optional: true optional: true
dependencies: dependencies:
react: 18.3.1 react: 18.3.1
redux: 4.2.1 redux: 5.0.1
/redux-thunk@2.4.2(redux@4.2.1): /redux-thunk@3.1.0(redux@5.0.1):
resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==} resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==}
peerDependencies: peerDependencies:
redux: ^4 redux: ^5.0.0
dependencies: dependencies:
redux: 4.2.1 redux: 5.0.1
/redux@4.2.1: /redux@5.0.1:
resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==}
dependencies:
'@babel/runtime': 7.24.8
/reflect.getprototypeof@1.0.6: /reflect.getprototypeof@1.0.6:
resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==}
@ -18070,8 +18054,8 @@ packages:
/requires-port@1.0.0: /requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
/reselect@4.1.8: /reselect@5.1.1:
resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==} resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
/resolve-alpn@1.2.1: /resolve-alpn@1.2.1:
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}