1
0
Fork 0
mirror of https://github.com/mastodon/mastodon.git synced 2024-08-20 21:08:15 -07:00

Upgrade Redux packages (#28585)

This commit is contained in:
Renaud Chaput 2024-01-08 11:57:40 +01:00 committed by GitHub
parent fe2667bb0d
commit a0e237a96f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 167 additions and 104 deletions

View file

@ -245,7 +245,7 @@ module.exports = defineConfig({
},
// Immutable / Redux / data store
{
pattern: '{immutable,react-redux,react-immutable-proptypes,react-immutable-pure-component,reselect}',
pattern: '{immutable,@reduxjs/toolkit,react-redux,react-immutable-proptypes,react-immutable-pure-component}',
group: 'external',
position: 'before',
},
@ -353,7 +353,14 @@ module.exports = defineConfig({
'@typescript-eslint/consistent-type-exports': 'error',
'@typescript-eslint/consistent-type-imports': 'error',
"@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }],
"@typescript-eslint/no-restricted-imports": [
"warn",
{
"name": "react-redux",
"importNames": ["useSelector", "useDispatch"],
"message": "Use typed hooks `useAppDispatch` and `useAppSelector` instead."
}
],
'jsdoc/require-jsdoc': 'off',
// Those rules set stricter rules for TS files

View file

@ -1,6 +1,7 @@
import { createSelector } from '@reduxjs/toolkit';
import { Map as ImmutableMap } from 'immutable';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { useEmoji } from '../../../actions/emojis';
import { changeSetting } from '../../../actions/settings';

View file

@ -1,6 +1,7 @@
import { createSelector } from '@reduxjs/toolkit';
import { Map as ImmutableMap } from 'immutable';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { changeComposeLanguage } from 'mastodon/actions/compose';
import { useLanguage } from 'mastodon/actions/languages';

View file

@ -1,6 +1,7 @@
import { createSelector } from '@reduxjs/toolkit';
import { Map as ImmutableMap } from 'immutable';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { addReaction, removeReaction, dismissAnnouncement } from 'mastodon/actions/announcements';

View file

@ -6,9 +6,9 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import { Helmet } from 'react-helmet';
import { createSelector } from '@reduxjs/toolkit';
import { List as ImmutableList } from 'immutable';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { ReactComponent as CampaignIcon } from '@material-symbols/svg-600/outlined/campaign.svg';
import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';

View file

@ -2,10 +2,10 @@ import PropTypes from 'prop-types';
import { injectIntl } from 'react-intl';
import { createSelector } from '@reduxjs/toolkit';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { setupListAdder, resetListAdder } from '../../actions/lists';
import NewListForm from '../lists/components/new_list_form';

View file

@ -4,10 +4,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { Helmet } from 'react-helmet';
import { createSelector } from '@reduxjs/toolkit';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';

View file

@ -5,10 +5,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { Helmet } from 'react-helmet';
import { createSelector } from '@reduxjs/toolkit';
import { List as ImmutableList } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { ReactComponent as DoneAllIcon } from '@material-symbols/svg-600/outlined/done_all.svg';
import { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications-fill.svg';

View file

@ -3,10 +3,10 @@ import { useCallback, useEffect, useRef } from 'react';
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
import { createSelector } from '@reduxjs/toolkit';
import { OrderedSet, List as ImmutableList } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { shallowEqual } from 'react-redux';
import { createSelector } from 'reselect';
import Toggle from 'react-toggle';

View file

@ -6,11 +6,11 @@ import classNames from 'classnames';
import { Helmet } from 'react-helmet';
import { withRouter } from 'react-router-dom';
import { createSelector } from '@reduxjs/toolkit';
import Immutable from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { ReactComponent as VisibilityIcon } from '@material-symbols/svg-600/outlined/visibility.svg';
import { ReactComponent as VisibilityOffIcon } from '@material-symbols/svg-600/outlined/visibility_off.svg';

View file

@ -2,11 +2,11 @@ import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { createSelector } from '@reduxjs/toolkit';
import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';

View file

@ -1,9 +1,9 @@
import PropTypes from 'prop-types';
import { createSelector } from '@reduxjs/toolkit';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';

View file

@ -1,6 +1,6 @@
import { createSelector } from '@reduxjs/toolkit';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { debounce } from 'lodash';

View file

@ -1,7 +1,6 @@
import type { Reducer } from '@reduxjs/toolkit';
import { Map as ImmutableMap } from 'immutable';
import type { Reducer } from 'redux';
import {
followAccountSuccess,
unfollowAccountSuccess,

View file

@ -1,6 +1,5 @@
import { Record as ImmutableRecord, Stack } from 'immutable';
import type { Reducer } from '@reduxjs/toolkit';
import { Record as ImmutableRecord, Stack } from 'immutable';
import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
import type { ModalType } from '../actions/modal';

View file

@ -1,7 +1,6 @@
import { Map as ImmutableMap } from 'immutable';
import { isFulfilled } from '@reduxjs/toolkit';
import type { Reducer } from 'redux';
import type { Reducer } from '@reduxjs/toolkit';
import { Map as ImmutableMap } from 'immutable';
import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
import type { Account } from 'mastodon/models/account';

View file

@ -1,5 +1,5 @@
import { createSelector } from '@reduxjs/toolkit';
import { Record as ImmutableRecord } from 'immutable';
import { createSelector } from 'reselect';
import { accountDefaultValues } from 'mastodon/models/account';
import type { Account, AccountShape } from 'mastodon/models/account';

View file

@ -1,5 +1,5 @@
import { createSelector } from '@reduxjs/toolkit';
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
import { createSelector } from 'reselect';
import { toServerSideType } from 'mastodon/utils/filters';

View file

@ -1,20 +1,34 @@
import type { AnyAction, Middleware } from 'redux';
import { isAction } from '@reduxjs/toolkit';
import type { Action, Middleware } from '@reduxjs/toolkit';
import type { RootState } from '..';
import { showAlertForError } from '../../actions/alerts';
const defaultFailSuffix = 'FAIL';
const isFailedAction = new RegExp(`${defaultFailSuffix}$`, 'g');
export const errorsMiddleware: Middleware<unknown, RootState> =
interface ActionWithMaybeAlertParams extends Action {
skipAlert?: boolean;
skipNotFound?: boolean;
error?: unknown;
}
function isActionWithmaybeAlertParams(
action: unknown,
): action is ActionWithMaybeAlertParams {
return isAction(action);
}
export const errorsMiddleware: Middleware<Record<string, never>, RootState> =
({ dispatch }) =>
(next) =>
(action: AnyAction & { skipAlert?: boolean; skipNotFound?: boolean }) => {
if (action.type && !action.skipAlert) {
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
if (typeof action.type === 'string' && action.type.match(isFail)) {
dispatch(showAlertForError(action.error, action.skipNotFound));
}
(action) => {
if (
isActionWithmaybeAlertParams(action) &&
!action.skipAlert &&
action.type.match(isFailedAction)
) {
dispatch(showAlertForError(action.error, action.skipNotFound));
}
return next(action);

View file

@ -3,9 +3,11 @@ import {
isPending as isThunkActionPending,
isFulfilled as isThunkActionFulfilled,
isRejected as isThunkActionRejected,
isAction,
} from '@reduxjs/toolkit';
import type { Middleware, UnknownAction } from '@reduxjs/toolkit';
import { showLoading, hideLoading } from 'react-redux-loading-bar';
import type { AnyAction, Middleware } from 'redux';
import type { RootState } from '..';
@ -19,14 +21,28 @@ const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = [
'REJECTED',
];
interface ActionWithSkipLoading extends UnknownAction {
skipLoading: boolean;
}
function isActionWithSkipLoading(
action: unknown,
): action is ActionWithSkipLoading {
return (
isAction(action) &&
'skipLoading' in action &&
typeof action.skipLoading === 'boolean'
);
}
export const loadingBarMiddleware = (
config: Config = {},
): Middleware<unknown, RootState> => {
): Middleware<{ skipLoading?: boolean }, RootState> => {
const promiseTypeSuffixes = config.promiseTypeSuffixes ?? defaultTypeSuffixes;
return ({ dispatch }) =>
(next) =>
(action: AnyAction) => {
(action) => {
let isPending = false;
let isFulfilled = false;
let isRejected = false;
@ -39,7 +55,7 @@ export const loadingBarMiddleware = (
else if (isThunkActionFulfilled(action)) isFulfilled = true;
else if (isThunkActionRejected(action)) isRejected = true;
} else if (
action.type &&
isActionWithSkipLoading(action) &&
!action.skipLoading &&
typeof action.type === 'string'
) {

View file

@ -1,4 +1,5 @@
import type { Middleware, AnyAction } from 'redux';
import { isAction } from '@reduxjs/toolkit';
import type { Middleware, UnknownAction } from '@reduxjs/toolkit';
import ready from 'mastodon/ready';
import { assetHost } from 'mastodon/utils/config';
@ -10,6 +11,21 @@ interface AudioSource {
type: string;
}
interface ActionWithMetaSound extends UnknownAction {
meta: { sound: string };
}
function isActionWithMetaSound(action: unknown): action is ActionWithMetaSound {
return (
isAction(action) &&
'meta' in action &&
typeof action.meta === 'object' &&
!!action.meta &&
'sound' in action.meta &&
typeof action.meta.sound === 'string'
);
}
const createAudio = (sources: AudioSource[]) => {
const audio = new Audio();
sources.forEach(({ type, src }) => {
@ -34,7 +50,10 @@ const play = (audio: HTMLAudioElement) => {
void audio.play();
};
export const soundsMiddleware = (): Middleware<unknown, RootState> => {
export const soundsMiddleware = (): Middleware<
Record<string, never>,
RootState
> => {
const soundCache: Record<string, HTMLAudioElement> = {};
void ready(() => {
@ -50,15 +69,15 @@ export const soundsMiddleware = (): Middleware<unknown, RootState> => {
]);
});
return () =>
(next) =>
(action: AnyAction & { meta?: { sound?: string } }) => {
const sound = action.meta?.sound;
return () => (next) => (action) => {
if (isActionWithMetaSound(action)) {
const sound = action.meta.sound;
if (sound && Object.hasOwn(soundCache, sound)) {
play(soundCache[sound]);
}
}
return next(action);
};
return next(action);
};
};

View file

@ -1,7 +1,7 @@
import type { TypedUseSelectorHook } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { createAsyncThunk } from '@reduxjs/toolkit';
import type { TypedUseSelectorHook } from 'react-redux';
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { useDispatch, useSelector } from 'react-redux';
import type { AppDispatch, RootState } from './store';

View file

@ -7,8 +7,14 @@ module.exports = {
include: [
settings.source_path,
...settings.resolved_paths,
'node_modules/@reduxjs'
].map(p => resolve(p)),
exclude: /node_modules/,
exclude: function(modulePath) {
return (
/node_modules/.test(modulePath) &&
!/@reduxjs/.test(modulePath)
);
},
use: [
{
loader: 'babel-loader',

View file

@ -51,7 +51,7 @@
"@github/webauthn-json": "^2.1.1",
"@material-symbols/svg-600": "^0.14.0",
"@rails/ujs": "^7.1.1",
"@reduxjs/toolkit": "^1.9.5",
"@reduxjs/toolkit": "^2.0.1",
"@svgr/webpack": "^5.5.0",
"arrow-key-navigation": "^1.2.0",
"async-mutex": "^0.4.0",
@ -106,8 +106,8 @@
"react-motion": "^0.5.2",
"react-notification": "^6.8.5",
"react-overlays": "^5.2.1",
"react-redux": "^8.0.4",
"react-redux-loading-bar": "^5.0.4",
"react-redux": "^9.0.4",
"react-redux-loading-bar": "^5.0.8",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4",
"react-router-scroll-4": "^1.0.0-beta.1",
@ -116,12 +116,9 @@
"react-swipeable-views": "^0.14.0",
"react-textarea-autosize": "^8.4.1",
"react-toggle": "^4.1.3",
"redux": "^4.2.1",
"redux-immutable": "^4.0.0",
"redux-thunk": "^2.4.2",
"regenerator-runtime": "^0.14.0",
"requestidlecallback": "^0.3.0",
"reselect": "^4.1.8",
"rimraf": "^5.0.1",
"sass": "^1.62.1",
"sass-loader": "^10.2.0",

104
yarn.lock
View file

@ -1483,7 +1483,7 @@ __metadata:
languageName: node
linkType: hard
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
version: 7.23.7
resolution: "@babel/runtime@npm:7.23.7"
dependencies:
@ -2302,7 +2302,7 @@ __metadata:
"@github/webauthn-json": "npm:^2.1.1"
"@material-symbols/svg-600": "npm:^0.14.0"
"@rails/ujs": "npm:^7.1.1"
"@reduxjs/toolkit": "npm:^1.9.5"
"@reduxjs/toolkit": "npm:^2.0.1"
"@svgr/webpack": "npm:^5.5.0"
"@testing-library/jest-dom": "npm:^6.0.0"
"@testing-library/react": "npm:^14.0.0"
@ -2410,8 +2410,8 @@ __metadata:
react-motion: "npm:^0.5.2"
react-notification: "npm:^6.8.5"
react-overlays: "npm:^5.2.1"
react-redux: "npm:^8.0.4"
react-redux-loading-bar: "npm:^5.0.4"
react-redux: "npm:^9.0.4"
react-redux-loading-bar: "npm:^5.0.8"
react-router: "npm:^5.3.4"
react-router-dom: "npm:^5.3.4"
react-router-scroll-4: "npm:^1.0.0-beta.1"
@ -2421,12 +2421,9 @@ __metadata:
react-test-renderer: "npm:^18.2.0"
react-textarea-autosize: "npm:^8.4.1"
react-toggle: "npm:^4.1.3"
redux: "npm:^4.2.1"
redux-immutable: "npm:^4.0.0"
redux-thunk: "npm:^2.4.2"
regenerator-runtime: "npm:^0.14.0"
requestidlecallback: "npm:^0.3.0"
reselect: "npm:^4.1.8"
rimraf: "npm:^5.0.1"
sass: "npm:^1.62.1"
sass-loader: "npm:^10.2.0"
@ -2622,23 +2619,23 @@ __metadata:
languageName: node
linkType: hard
"@reduxjs/toolkit@npm:^1.9.5":
version: 1.9.7
resolution: "@reduxjs/toolkit@npm:1.9.7"
"@reduxjs/toolkit@npm:^2.0.1":
version: 2.0.1
resolution: "@reduxjs/toolkit@npm:2.0.1"
dependencies:
immer: "npm:^9.0.21"
redux: "npm:^4.2.1"
redux-thunk: "npm:^2.4.2"
reselect: "npm:^4.1.8"
immer: "npm:^10.0.3"
redux: "npm:^5.0.0"
redux-thunk: "npm:^3.1.0"
reselect: "npm:^5.0.1"
peerDependencies:
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:
react:
optional: true
react-redux:
optional: true
checksum: fa0aa4b7c6973ac87ce0ac7e45faa02c73b66c4ee0bc950d178494539a42a1bb908d109297102458b7ea14d5e7dae356e7a7ce9a1b9849b0e8451e6dd70fca9c
checksum: 161b9b8e11d9688890ab97b604a4c10c0d41b1369425a5fa821586932db4cd5a391d15799732b3612e6120a6336458ff577ff254219315c05ecd68da5d15fd79
languageName: node
linkType: hard
@ -9128,10 +9125,10 @@ __metadata:
languageName: node
linkType: hard
"immer@npm:^9.0.21":
version: 9.0.21
resolution: "immer@npm:9.0.21"
checksum: 03ea3ed5d4d72e8bd428df4a38ad7e483ea8308e9a113d3b42e0ea2cc0cc38340eb0a6aca69592abbbf047c685dbda04e3d34bf2ff438ab57339ed0a34cc0a05
"immer@npm:^10.0.3":
version: 10.0.3
resolution: "immer@npm:10.0.3"
checksum: 282a4f8479a40f7d12b2b3243c095e3e892bf99058e2ffcdd6b8e9fd143e6a90f2717ab9b6c8b97c927ffb8054465c8f647056f41660dbfd672e240cf1063503
languageName: node
linkType: hard
@ -13104,7 +13101,17 @@ __metadata:
languageName: node
linkType: hard
"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4":
"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4":
version: 6.0.13
resolution: "postcss-selector-parser@npm:6.0.13"
dependencies:
cssesc: "npm:^3.0.0"
util-deprecate: "npm:^1.0.2"
checksum: 51f099b27f7c7198ea1826470ef0adfa58b3bd3f59b390fda123baa0134880a5fa9720137b6009c4c1373357b144f700b0edac73335d0067422063129371444e
languageName: node
linkType: hard
"postcss-selector-parser@npm:^6.0.15":
version: 6.0.15
resolution: "postcss-selector-parser@npm:6.0.15"
dependencies:
@ -13693,7 +13700,7 @@ __metadata:
languageName: node
linkType: hard
"react-redux-loading-bar@npm:^5.0.4":
"react-redux-loading-bar@npm:^5.0.8":
version: 5.0.8
resolution: "react-redux-loading-bar@npm:5.0.8"
dependencies:
@ -13708,35 +13715,25 @@ __metadata:
languageName: node
linkType: hard
"react-redux@npm:^8.0.4":
version: 8.1.3
resolution: "react-redux@npm:8.1.3"
"react-redux@npm:^9.0.4":
version: 9.0.4
resolution: "react-redux@npm:9.0.4"
dependencies:
"@babel/runtime": "npm:^7.12.1"
"@types/hoist-non-react-statics": "npm:^3.3.1"
"@types/use-sync-external-store": "npm:^0.0.3"
hoist-non-react-statics: "npm:^3.3.2"
react-is: "npm:^18.0.0"
use-sync-external-store: "npm:^1.0.0"
peerDependencies:
"@types/react": ^16.8 || ^17.0 || ^18.0
"@types/react-dom": ^16.8 || ^17.0 || ^18.0
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
react-native: ">=0.59"
redux: ^4 || ^5.0.0-beta.0
"@types/react": ^18.2.25
react: ^18.0
react-native: ">=0.69"
redux: ^5.0.0
peerDependenciesMeta:
"@types/react":
optional: true
"@types/react-dom":
optional: true
react-dom:
optional: true
react-native:
optional: true
redux:
optional: true
checksum: 64c8be2765568dc66a3c442a41dd0ed74fe048d5ceb7a4fe72e5bac3d3687996a7115f57b5156af7406521087065a0e60f9194318c8ca99c55e9ce48558980ce
checksum: 23af10014b129aeb051de729bde01de21175170b860deefb7ad83483feab5816253f770a4cea93333fc22a53ac9ac699b27f5c3705c388dab53dbcb2906a571a
languageName: node
linkType: hard
@ -14039,16 +14036,16 @@ __metadata:
languageName: node
linkType: hard
"redux-thunk@npm:^2.4.2":
version: 2.4.2
resolution: "redux-thunk@npm:2.4.2"
"redux-thunk@npm:^3.1.0":
version: 3.1.0
resolution: "redux-thunk@npm:3.1.0"
peerDependencies:
redux: ^4
checksum: e202d6ef7dfa7df08ed24cb221aa89d6c84dbaa7d65fe90dbd8e826d0c10d801f48388f9a7598a4fd970ecbc93d335014570a61ca7bc8bf569eab5de77b31a3c
redux: ^5.0.0
checksum: 21557f6a30e1b2e3e470933247e51749be7f1d5a9620069a3125778675ce4d178d84bdee3e2a0903427a5c429e3aeec6d4df57897faf93eb83455bc1ef7b66fd
languageName: node
linkType: hard
"redux@npm:^4.0.0, redux@npm:^4.2.1":
"redux@npm:^4.0.0":
version: 4.2.1
resolution: "redux@npm:4.2.1"
dependencies:
@ -14057,6 +14054,13 @@ __metadata:
languageName: node
linkType: hard
"redux@npm:^5.0.0":
version: 5.0.1
resolution: "redux@npm:5.0.1"
checksum: b10c28357194f38e7d53b760ed5e64faa317cc63de1fb95bc5d9e127fab956392344368c357b8e7a9bedb0c35b111e7efa522210cfdc3b3c75e5074718e9069c
languageName: node
linkType: hard
"reflect.getprototypeof@npm:^1.0.4":
version: 1.0.4
resolution: "reflect.getprototypeof@npm:1.0.4"
@ -14226,10 +14230,10 @@ __metadata:
languageName: node
linkType: hard
"reselect@npm:^4.1.8":
version: 4.1.8
resolution: "reselect@npm:4.1.8"
checksum: 06a305a504affcbb67dd0561ddc8306b35796199c7e15b38934c80606938a021eadcf68cfd58e7bb5e17786601c37602a3362a4665c7bf0a96c1041ceee9d0b7
"reselect@npm:^5.0.1":
version: 5.0.1
resolution: "reselect@npm:5.0.1"
checksum: 0724b4555cd6411849de334a75177780f127af849eb71c4b709966d07ade8090d125c0c926dc6cf936866d23ebadda6aad1da93cd8340525323b889f25d56d51
languageName: node
linkType: hard