diff --git a/src/api/services/ShlinkApiClientBuilder.ts b/src/api/services/ShlinkApiClientBuilder.ts index 8e64c3ee..b6216a16 100644 --- a/src/api/services/ShlinkApiClientBuilder.ts +++ b/src/api/services/ShlinkApiClientBuilder.ts @@ -1,8 +1,8 @@ import type { HttpClient } from '@shlinkio/shlink-js-sdk'; import { ShlinkApiClient } from '@shlinkio/shlink-js-sdk'; -import type { GetState } from '../../container/types'; import type { ServerWithId } from '../../servers/data'; import { hasServerData } from '../../servers/data'; +import type { GetState } from '../../store'; const apiClients: Map = new Map(); diff --git a/src/container/types.ts b/src/container/types.ts index 46a42482..71b20fbd 100644 --- a/src/container/types.ts +++ b/src/container/types.ts @@ -1,15 +1 @@ -import type { Settings } from '@shlinkio/shlink-web-component/settings'; -import type { SelectedServer, ServersMap } from '../servers/data'; - -/** Deprecated Use RootState */ -export type ShlinkState = { - servers: ServersMap; - selectedServer: SelectedServer; - settings: Settings; - appUpdated: boolean; -}; - export type ConnectDecorator = (props: string[] | null, actions?: string[]) => any; - -/** @deprecated */ -export type GetState = () => ShlinkState; diff --git a/src/servers/reducers/remoteServers.ts b/src/servers/reducers/remoteServers.ts index 37c437d0..d7619e4b 100644 --- a/src/servers/reducers/remoteServers.ts +++ b/src/servers/reducers/remoteServers.ts @@ -1,6 +1,6 @@ import type { HttpClient } from '@shlinkio/shlink-js-sdk'; import pack from '../../../package.json'; -import { createAsyncThunk } from '../../utils/helpers/redux'; +import { createAsyncThunk } from '../../store/helpers'; import { hasServerData } from '../data'; import { ensureUniqueIds } from '../helpers'; import { createServers } from './servers'; diff --git a/src/servers/reducers/selectedServer.ts b/src/servers/reducers/selectedServer.ts index 5a93b8df..5c3a9b33 100644 --- a/src/servers/reducers/selectedServer.ts +++ b/src/servers/reducers/selectedServer.ts @@ -4,7 +4,7 @@ import type { ShlinkHealth } from '@shlinkio/shlink-web-component/api-contract'; import { useCallback } from 'react'; import type { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; import { useAppDispatch, useAppSelector } from '../../store'; -import { createAsyncThunk } from '../../utils/helpers/redux'; +import { createAsyncThunk } from '../../store/helpers'; import { versionToPrintable, versionToSemVer as toSemVer } from '../../utils/helpers/version'; import type { SelectedServer, ServerWithId } from '../data'; diff --git a/src/settings/helpers/index.ts b/src/settings/helpers/index.ts index 509df6cd..53044ad0 100644 --- a/src/settings/helpers/index.ts +++ b/src/settings/helpers/index.ts @@ -1,12 +1,6 @@ -import type { ShlinkState } from '../../container/types'; - -export const migrateDeprecatedSettings = (state: Partial): Partial => { - if (!state.settings) { - return state; - } - +export const migrateDeprecatedSettings = (state: any): any => { // The "last180Days" interval had a typo, with a lowercase d - if (state.settings.visits && (state.settings.visits.defaultInterval as any) === 'last180days') { + if (state.settings?.visits?.defaultInterval === 'last180days') { state.settings.visits.defaultInterval = 'last180Days'; } diff --git a/src/settings/reducers/settings.ts b/src/settings/reducers/settings.ts index f71a1dd2..f05240ec 100644 --- a/src/settings/reducers/settings.ts +++ b/src/settings/reducers/settings.ts @@ -4,8 +4,7 @@ import { mergeDeepRight } from '@shlinkio/data-manipulation'; import { getSystemPreferredTheme } from '@shlinkio/shlink-frontend-kit'; import type { Settings, ShortUrlsListSettings } from '@shlinkio/shlink-web-component/settings'; import { useCallback } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import type { ShlinkState } from '../../container/types'; +import { useAppDispatch, useAppSelector } from '../../store'; import type { Defined } from '../../utils/types'; type ShortUrlsOrder = Defined; @@ -46,9 +45,9 @@ export const { setSettings } = actions; export const settingsReducer = reducer; export const useSettings = () => { - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); const setSettings = useCallback((settings: Settings) => dispatch(actions.setSettings(settings)), [dispatch]); - const settings = useSelector((state: ShlinkState) => state.settings); + const settings = useAppSelector((state) => state.settings); return { settings, setSettings }; }; diff --git a/src/utils/helpers/redux.ts b/src/store/helpers.ts similarity index 77% rename from src/utils/helpers/redux.ts rename to src/store/helpers.ts index d2766cf3..4304ec76 100644 --- a/src/utils/helpers/redux.ts +++ b/src/store/helpers.ts @@ -1,10 +1,10 @@ import type { AsyncThunkPayloadCreator } from '@reduxjs/toolkit'; import { createAsyncThunk as baseCreateAsyncThunk } from '@reduxjs/toolkit'; -import type { ShlinkState } from '../../container/types'; +import type { RootState } from '.'; export const createAsyncThunk = ( typePrefix: string, - payloadCreator: AsyncThunkPayloadCreator, + payloadCreator: AsyncThunkPayloadCreator, ) => baseCreateAsyncThunk( typePrefix, payloadCreator, diff --git a/src/store/index.ts b/src/store/index.ts index f5d425e6..9a122aeb 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -24,7 +24,8 @@ export const setUpStore = (preloadedState = getStateFromLocalStorage()) => confi export type StoreType = ReturnType; export type AppDispatch = StoreType['dispatch']; -export type RootState = ReturnType; +export type GetState = StoreType['getState']; +export type RootState = ReturnType; // Typed versions of useDispatch() and useSelector() export const useAppDispatch = useDispatch.withTypes(); diff --git a/test/__helpers__/setUpTest.tsx b/test/__helpers__/setUpTest.tsx index 7e5b9136..00f4625d 100644 --- a/test/__helpers__/setUpTest.tsx +++ b/test/__helpers__/setUpTest.tsx @@ -3,7 +3,7 @@ import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import type { PropsWithChildren, ReactElement } from 'react'; import { Provider } from 'react-redux'; -import type { ShlinkState } from '../../src/container/types'; +import type { RootState } from '../../src/store'; import { setUpStore } from '../../src/store'; export const renderWithEvents = (element: ReactElement, options?: RenderOptions) => ({ @@ -12,7 +12,7 @@ export const renderWithEvents = (element: ReactElement, options?: RenderOptions) }); export type RenderOptionsWithState = Omit & { - initialState?: Partial; + initialState?: Partial; }; export const renderWithStore = ( diff --git a/test/servers/reducers/selectedServer.test.ts b/test/servers/reducers/selectedServer.test.ts index 87ffc8e9..a7358f2a 100644 --- a/test/servers/reducers/selectedServer.test.ts +++ b/test/servers/reducers/selectedServer.test.ts @@ -1,6 +1,5 @@ import type { ShlinkApiClient } from '@shlinkio/shlink-js-sdk'; import { fromPartial } from '@total-typescript/shoehorn'; -import type { ShlinkState } from '../../../src/container/types'; import type { NonReachableServer, NotFoundServer, RegularServer } from '../../../src/servers/data'; import { MAX_FALLBACK_VERSION, @@ -9,6 +8,7 @@ import { selectedServerReducer as reducer, selectServer, } from '../../../src/servers/reducers/selectedServer'; +import type { RootState } from '../../../src/store'; describe('selectedServerReducer', () => { const dispatch = vi.fn(); @@ -71,7 +71,7 @@ describe('selectedServerReducer', () => { it('dispatches error when server is not found', async () => { const id = crypto.randomUUID(); - const getState = vi.fn(() => fromPartial({ servers: {} })); + const getState = vi.fn(() => fromPartial({ servers: {} })); const expectedSelectedServer: NotFoundServer = { serverNotFound: true }; await selectServer({ serverId: id, buildShlinkApiClient })(dispatch, getState, {}); diff --git a/test/settings/helpers/index.test.ts b/test/settings/helpers/index.test.ts index e69fb899..5fcc9ffc 100644 --- a/test/settings/helpers/index.test.ts +++ b/test/settings/helpers/index.test.ts @@ -1,6 +1,6 @@ import { fromPartial } from '@total-typescript/shoehorn'; -import type { ShlinkState } from '../../../src/container/types'; import { migrateDeprecatedSettings } from '../../../src/settings/helpers'; +import type { RootState } from '../../../src/store'; describe('settings-helpers', () => { describe('migrateDeprecatedSettings', () => { @@ -9,7 +9,7 @@ describe('settings-helpers', () => { }); it('updates settings as expected', () => { - const state = fromPartial({ + const state = fromPartial({ settings: { visits: { defaultInterval: 'last180days' as any,