From e84c0dcd995555044eb1c08fd9373620022b669c Mon Sep 17 00:00:00 2001 From: FaberVitale Date: Mon, 21 Jun 2021 15:34:18 +0200 Subject: [PATCH] refactor(rtk-query): move Inspector & Monitor to containers clean up typings Other changes: * chore: improved type coverage * chore: do not lint packages/redux-devtools-rtk-query-monitor/demo folder * refactor: put sort order buttons inside a component * chore: hopefully resolve mockServiceWorker formatting issues --- .prettierignore | 2 +- .../.eslintignore | 5 +- .../demo/.eslintrc.js | 4 +- .../demo/public/mockServiceWorker.js | 182 +++++++++--------- .../demo/src/features/posts/PostDetail.tsx | 6 +- .../demo/src/features/posts/PostsManager.tsx | 4 +- .../src/components/NoRtkQueryApi.tsx | 7 +- .../src/components/QueryForm.tsx | 55 +----- .../src/components/SortOrderButtons.tsx | 67 +++++++ .../{ => containers}/RtkQueryInspector.tsx | 42 ++-- .../src/{ => containers}/RtkQueryMonitor.tsx | 25 ++- .../src/index.ts | 2 +- .../src/reducers.ts | 4 +- .../src/selectors.ts | 2 +- .../src/styles/createStylingFromTheme.ts | 51 ++--- .../src/styles/tree.tsx | 8 +- .../src/types.ts | 14 +- .../src/utils/isIterable.ts | 4 +- .../src/utils/rtk-query.ts | 7 +- 19 files changed, 261 insertions(+), 230 deletions(-) create mode 100644 packages/redux-devtools-rtk-query-monitor/src/components/SortOrderButtons.tsx rename packages/redux-devtools-rtk-query-monitor/src/{ => containers}/RtkQueryInspector.tsx (80%) rename packages/redux-devtools-rtk-query-monitor/src/{ => containers}/RtkQueryMonitor.tsx (77%) diff --git a/.prettierignore b/.prettierignore index 9702c386..0f20aa9c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,4 +10,4 @@ __snapshots__ dev .yarn/* **/.yarn/* -demo/public/** \ No newline at end of file +**/demo/public/** \ No newline at end of file diff --git a/packages/redux-devtools-rtk-query-monitor/.eslintignore b/packages/redux-devtools-rtk-query-monitor/.eslintignore index a2e587ac..9c072ed1 100644 --- a/packages/redux-devtools-rtk-query-monitor/.eslintignore +++ b/packages/redux-devtools-rtk-query-monitor/.eslintignore @@ -1,5 +1,2 @@ lib -demo/public/** -demo/src/mocks/** -demo/src/build/** -demo/build/** \ No newline at end of file +demo/ \ No newline at end of file diff --git a/packages/redux-devtools-rtk-query-monitor/demo/.eslintrc.js b/packages/redux-devtools-rtk-query-monitor/demo/.eslintrc.js index a9ac64f4..e98ddf18 100644 --- a/packages/redux-devtools-rtk-query-monitor/demo/.eslintrc.js +++ b/packages/redux-devtools-rtk-query-monitor/demo/.eslintrc.js @@ -1,9 +1,9 @@ module.exports = { - extends: '../../../.eslintrc', + extends: '../../.eslintrc', overrides: [ { files: ['*.ts', '*.tsx'], - extends: '../../../eslintrc.ts.react.base.json', + extends: '../../eslintrc.ts.react.base.json', parserOptions: { tsconfigRootDir: __dirname, project: ['./tsconfig.json'], diff --git a/packages/redux-devtools-rtk-query-monitor/demo/public/mockServiceWorker.js b/packages/redux-devtools-rtk-query-monitor/demo/public/mockServiceWorker.js index a2a4def7..51e26799 100644 --- a/packages/redux-devtools-rtk-query-monitor/demo/public/mockServiceWorker.js +++ b/packages/redux-devtools-rtk-query-monitor/demo/public/mockServiceWorker.js @@ -7,116 +7,116 @@ /* eslint-disable */ /* tslint:disable */ -const INTEGRITY_CHECKSUM = '82ef9b96d8393b6da34527d1d6e19187'; -const bypassHeaderName = 'x-msw-bypass'; -const activeClientIds = new Set(); +const INTEGRITY_CHECKSUM = '82ef9b96d8393b6da34527d1d6e19187' +const bypassHeaderName = 'x-msw-bypass' +const activeClientIds = new Set() self.addEventListener('install', function () { - return self.skipWaiting(); -}); + return self.skipWaiting() +}) self.addEventListener('activate', async function (event) { - return self.clients.claim(); -}); + return self.clients.claim() +}) self.addEventListener('message', async function (event) { - const clientId = event.source.id; + const clientId = event.source.id if (!clientId || !self.clients) { - return; + return } - const client = await self.clients.get(clientId); + const client = await self.clients.get(clientId) if (!client) { - return; + return } - const allClients = await self.clients.matchAll(); + const allClients = await self.clients.matchAll() switch (event.data) { case 'KEEPALIVE_REQUEST': { sendToClient(client, { type: 'KEEPALIVE_RESPONSE', - }); - break; + }) + break } case 'INTEGRITY_CHECK_REQUEST': { sendToClient(client, { type: 'INTEGRITY_CHECK_RESPONSE', payload: INTEGRITY_CHECKSUM, - }); - break; + }) + break } case 'MOCK_ACTIVATE': { - activeClientIds.add(clientId); + activeClientIds.add(clientId) sendToClient(client, { type: 'MOCKING_ENABLED', payload: true, - }); - break; + }) + break } case 'MOCK_DEACTIVATE': { - activeClientIds.delete(clientId); - break; + activeClientIds.delete(clientId) + break } case 'CLIENT_CLOSED': { - activeClientIds.delete(clientId); + activeClientIds.delete(clientId) const remainingClients = allClients.filter((client) => { - return client.id !== clientId; - }); + return client.id !== clientId + }) // Unregister itself when there are no more clients if (remainingClients.length === 0) { - self.registration.unregister(); + self.registration.unregister() } - break; + break } } -}); +}) // Resolve the "master" client for the given event. // Client that issues a request doesn't necessarily equal the client // that registered the worker. It's with the latter the worker should // communicate with during the response resolving phase. async function resolveMasterClient(event) { - const client = await self.clients.get(event.clientId); + const client = await self.clients.get(event.clientId) if (client.frameType === 'top-level') { - return client; + return client } - const allClients = await self.clients.matchAll(); + const allClients = await self.clients.matchAll() return allClients .filter((client) => { // Get only those clients that are currently visible. - return client.visibilityState === 'visible'; + return client.visibilityState === 'visible' }) .find((client) => { // Find the client ID that's recorded in the // set of clients that have registered the worker. - return activeClientIds.has(client.id); - }); + return activeClientIds.has(client.id) + }) } async function handleRequest(event, requestId) { - const client = await resolveMasterClient(event); - const response = await getResponse(event, client, requestId); + const client = await resolveMasterClient(event) + const response = await getResponse(event, client, requestId) // Send back the response clone for the "response:*" life-cycle events. // Ensure MSW is active and ready to handle the message, otherwise // this message will pend indefinitely. if (client && activeClientIds.has(client.id)) { - (async function () { - const clonedResponse = response.clone(); + ;(async function () { + const clonedResponse = response.clone() sendToClient(client, { type: 'RESPONSE', payload: { @@ -130,21 +130,21 @@ async function handleRequest(event, requestId) { headers: serializeHeaders(clonedResponse.headers), redirected: clonedResponse.redirected, }, - }); - })(); + }) + })() } - return response; + return response } async function getResponse(event, client, requestId) { - const { request } = event; - const requestClone = request.clone(); - const getOriginalResponse = () => fetch(requestClone); + const { request } = event + const requestClone = request.clone() + const getOriginalResponse = () => fetch(requestClone) // Bypass mocking when the request client is not active. if (!client) { - return getOriginalResponse(); + return getOriginalResponse() } // Bypass initial page load requests (i.e. static assets). @@ -152,26 +152,26 @@ async function getResponse(event, client, requestId) { // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet // and is not ready to handle requests. if (!activeClientIds.has(client.id)) { - return await getOriginalResponse(); + return await getOriginalResponse() } // Bypass requests with the explicit bypass header if (requestClone.headers.get(bypassHeaderName) === 'true') { - const cleanRequestHeaders = serializeHeaders(requestClone.headers); + const cleanRequestHeaders = serializeHeaders(requestClone.headers) // Remove the bypass header to comply with the CORS preflight check. - delete cleanRequestHeaders[bypassHeaderName]; + delete cleanRequestHeaders[bypassHeaderName] const originalRequest = new Request(requestClone, { headers: new Headers(cleanRequestHeaders), - }); + }) - return fetch(originalRequest); + return fetch(originalRequest) } // Send the request to the client-side MSW. - const reqHeaders = serializeHeaders(request.headers); - const body = await request.text(); + const reqHeaders = serializeHeaders(request.headers) + const body = await request.text() const clientMessage = await sendToClient(client, { type: 'REQUEST', @@ -192,31 +192,31 @@ async function getResponse(event, client, requestId) { bodyUsed: request.bodyUsed, keepalive: request.keepalive, }, - }); + }) switch (clientMessage.type) { case 'MOCK_SUCCESS': { return delayPromise( () => respondWithMock(clientMessage), - clientMessage.payload.delay - ); + clientMessage.payload.delay, + ) } case 'MOCK_NOT_FOUND': { - return getOriginalResponse(); + return getOriginalResponse() } case 'NETWORK_ERROR': { - const { name, message } = clientMessage.payload; - const networkError = new Error(message); - networkError.name = name; + const { name, message } = clientMessage.payload + const networkError = new Error(message) + networkError.name = name // Rejecting a request Promise emulates a network error. - throw networkError; + throw networkError } case 'INTERNAL_ERROR': { - const parsedBody = JSON.parse(clientMessage.payload.body); + const parsedBody = JSON.parse(clientMessage.payload.body) console.error( `\ @@ -229,38 +229,38 @@ This exception has been gracefully handled as a 500 response, however, it's stro If you wish to mock an error response, please refer to this guide: https://mswjs.io/docs/recipes/mocking-error-responses\ `, request.method, - request.url - ); + request.url, + ) - return respondWithMock(clientMessage); + return respondWithMock(clientMessage) } } - return getOriginalResponse(); + return getOriginalResponse() } self.addEventListener('fetch', function (event) { - const { request } = event; + const { request } = event // Bypass navigation requests. if (request.mode === 'navigate') { - return; + return } // Opening the DevTools triggers the "only-if-cached" request // that cannot be handled by the worker. Bypass such requests. if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { - return; + return } // Bypass all requests when there are no active clients. // Prevents the self-unregistered worked from handling requests // after it's been deleted (still remains active until the next reload). if (activeClientIds.size === 0) { - return; + return } - const requestId = uuidv4(); + const requestId = uuidv4() return event.respondWith( handleRequest(event, requestId).catch((error) => { @@ -268,55 +268,55 @@ self.addEventListener('fetch', function (event) { '[MSW] Failed to mock a "%s" request to "%s": %s', request.method, request.url, - error - ); - }) - ); -}); + error, + ) + }), + ) +}) function serializeHeaders(headers) { - const reqHeaders = {}; + const reqHeaders = {} headers.forEach((value, name) => { reqHeaders[name] = reqHeaders[name] ? [].concat(reqHeaders[name]).concat(value) - : value; - }); - return reqHeaders; + : value + }) + return reqHeaders } function sendToClient(client, message) { return new Promise((resolve, reject) => { - const channel = new MessageChannel(); + const channel = new MessageChannel() channel.port1.onmessage = (event) => { if (event.data && event.data.error) { - return reject(event.data.error); + return reject(event.data.error) } - resolve(event.data); - }; + resolve(event.data) + } - client.postMessage(JSON.stringify(message), [channel.port2]); - }); + client.postMessage(JSON.stringify(message), [channel.port2]) + }) } function delayPromise(cb, duration) { return new Promise((resolve) => { - setTimeout(() => resolve(cb()), duration); - }); + setTimeout(() => resolve(cb()), duration) + }) } function respondWithMock(clientMessage) { return new Response(clientMessage.payload.body, { ...clientMessage.payload, headers: clientMessage.payload.headers, - }); + }) } function uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - const r = (Math.random() * 16) | 0; - const v = c == 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }); + const r = (Math.random() * 16) | 0 + const v = c == 'x' ? r : (r & 0x3) | 0x8 + return v.toString(16) + }) } diff --git a/packages/redux-devtools-rtk-query-monitor/demo/src/features/posts/PostDetail.tsx b/packages/redux-devtools-rtk-query-monitor/demo/src/features/posts/PostDetail.tsx index 98b0edd1..aef3726a 100644 --- a/packages/redux-devtools-rtk-query-monitor/demo/src/features/posts/PostDetail.tsx +++ b/packages/redux-devtools-rtk-query-monitor/demo/src/features/posts/PostDetail.tsx @@ -73,7 +73,7 @@ const PostJsonDetail = ({ id }: { id: string }) => { export const PostDetail = () => { const { id } = useParams<{ id: any }>(); - const { push } = useHistory(); + const history = useHistory(); const toast = useToast(); @@ -137,7 +137,9 @@ export const PostDetail = () => { {isUpdating ? 'Updating...' : 'Edit'} - - + ); diff --git a/packages/redux-devtools-rtk-query-monitor/src/components/SortOrderButtons.tsx b/packages/redux-devtools-rtk-query-monitor/src/components/SortOrderButtons.tsx new file mode 100644 index 00000000..62724e84 --- /dev/null +++ b/packages/redux-devtools-rtk-query-monitor/src/components/SortOrderButtons.tsx @@ -0,0 +1,67 @@ +import React, { MouseEvent } from 'react'; +import { StyleUtilsContext } from '../styles/createStylingFromTheme'; + +export const ascId = 'rtk-query-rb-asc'; +export const descId = 'rtk-query-rb-desc'; + +export interface SortOrderButtonsProps { + readonly isAsc?: boolean; + readonly onChange: (isAsc: boolean) => void; +} + +export function SortOrderButtons({ + isAsc, + onChange, +}: SortOrderButtonsProps): JSX.Element { + const handleButtonGroupClick = ({ + target, + }: MouseEvent): void => { + const targetId = (target as HTMLElement)?.id ?? null; + + if (targetId === ascId && !isAsc) { + onChange(true); + } else if (targetId === descId && isAsc) { + onChange(false); + } + }; + + const isDesc = !isAsc; + + return ( + + {({ styling }) => ( +
+ + +
+ )} +
+ ); +} diff --git a/packages/redux-devtools-rtk-query-monitor/src/RtkQueryInspector.tsx b/packages/redux-devtools-rtk-query-monitor/src/containers/RtkQueryInspector.tsx similarity index 80% rename from packages/redux-devtools-rtk-query-monitor/src/RtkQueryInspector.tsx rename to packages/redux-devtools-rtk-query-monitor/src/containers/RtkQueryInspector.tsx index 4eecc9b2..caa4d069 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/RtkQueryInspector.tsx +++ b/packages/redux-devtools-rtk-query-monitor/src/containers/RtkQueryInspector.tsx @@ -1,37 +1,33 @@ -import React, { Component, createRef, ReactNode } from 'react'; -import { AnyAction, Dispatch, Action } from 'redux'; -import { LiftedAction, LiftedState } from '@redux-devtools/core'; -import * as themes from 'redux-devtools-themes'; -import { Base16Theme } from 'react-base16-styling'; +import React, { PureComponent, createRef, ReactNode } from 'react'; +import type { AnyAction, Dispatch, Action } from '@reduxjs/toolkit'; +import type { LiftedAction, LiftedState } from '@redux-devtools/core'; import { QueryFormValues, QueryInfo, QueryPreviewTabs, RtkQueryMonitorState, StyleUtils, -} from './types'; -import { createInspectorSelectors, computeSelectorSource } from './selectors'; + SelectorsSource, +} from '../types'; +import { createInspectorSelectors, computeSelectorSource } from '../selectors'; import { changeQueryFormValues, selectedPreviewTab, selectQueryKey, -} from './reducers'; -import { QueryList } from './components/QueryList'; -import { QueryForm } from './components/QueryForm'; -import { QueryPreview } from './components/QueryPreview'; -import { getApiStateOf, getQuerySubscriptionsOf } from './utils/rtk-query'; +} from '../reducers'; +import { QueryList } from '../components/QueryList'; +import { QueryForm } from '../components/QueryForm'; +import { QueryPreview } from '../components/QueryPreview'; +import { getApiStateOf, getQuerySubscriptionsOf } from '../utils/rtk-query'; -type SelectorsSource = { - userState: S | null; - monitorState: RtkQueryMonitorState; -}; +type ForwardedMonitorProps> = Pick< + LiftedState, + 'monitorState' | 'currentStateIndex' | 'computedStates' +>; export interface RtkQueryInspectorProps> - extends LiftedState { + extends ForwardedMonitorProps { dispatch: Dispatch>; - theme: keyof typeof themes | Base16Theme; - invertTheme: boolean; - state: S | null; styleUtils: StyleUtils; } @@ -40,13 +36,13 @@ type RtkQueryInspectorState = { isWideLayout: boolean; }; -class RtkQueryInspector> extends Component< +class RtkQueryInspector> extends PureComponent< RtkQueryInspectorProps, RtkQueryInspectorState > { inspectorRef = createRef(); - isWideIntervalRef: number | NodeJS.Timeout | null = null; + isWideIntervalRef: ReturnType | null = null; constructor(props: RtkQueryInspectorProps) { super(props); @@ -98,7 +94,7 @@ class RtkQueryInspector> extends Component< componentWillUnmount(): void { if (this.isWideIntervalRef) { - clearTimeout(this.isWideIntervalRef as any); + clearTimeout(this.isWideIntervalRef); } } diff --git a/packages/redux-devtools-rtk-query-monitor/src/RtkQueryMonitor.tsx b/packages/redux-devtools-rtk-query-monitor/src/containers/RtkQueryMonitor.tsx similarity index 77% rename from packages/redux-devtools-rtk-query-monitor/src/RtkQueryMonitor.tsx rename to packages/redux-devtools-rtk-query-monitor/src/containers/RtkQueryMonitor.tsx index 686351d1..ac8d1817 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/RtkQueryMonitor.tsx +++ b/packages/redux-devtools-rtk-query-monitor/src/containers/RtkQueryMonitor.tsx @@ -1,18 +1,18 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { Action } from 'redux'; +import { Action, AnyAction } from 'redux'; import RtkQueryInspector from './RtkQueryInspector'; -import { reducer } from './reducers'; +import { reducer } from '../reducers'; import { ExternalProps, RtkQueryMonitorProps, RtkQueryMonitorState, StyleUtils, -} from './types'; +} from '../types'; import { createThemeState, StyleUtilsContext, -} from './styles/createStylingFromTheme'; +} from '../styles/createStylingFromTheme'; interface DefaultProps { theme: string; @@ -41,7 +41,7 @@ class RtkQueryMonitor> extends Component< invertTheme: PropTypes.bool, }; - static defaultProps = { + static defaultProps: DefaultProps = { theme: 'nicinabox', invertTheme: false, }; @@ -55,17 +55,16 @@ class RtkQueryMonitor> extends Component< } render() { - const { - styleUtils: { base16Theme }, - } = this.state; - - const RtkQueryInspectorAsAny = RtkQueryInspector as any; + const { currentStateIndex, computedStates, monitorState, dispatch } = + this.props; return ( - + computedStates={computedStates} + currentStateIndex={currentStateIndex} + monitorState={monitorState} + dispatch={dispatch} styleUtils={this.state.styleUtils} /> diff --git a/packages/redux-devtools-rtk-query-monitor/src/index.ts b/packages/redux-devtools-rtk-query-monitor/src/index.ts index fb04bb45..f5ad68f6 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/index.ts +++ b/packages/redux-devtools-rtk-query-monitor/src/index.ts @@ -1,2 +1,2 @@ -export { default } from './RtkQueryMonitor'; +export { default } from './containers/RtkQueryMonitor'; export { ExternalProps } from './types'; diff --git a/packages/redux-devtools-rtk-query-monitor/src/reducers.ts b/packages/redux-devtools-rtk-query-monitor/src/reducers.ts index d4409509..921942c2 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/reducers.ts +++ b/packages/redux-devtools-rtk-query-monitor/src/reducers.ts @@ -1,10 +1,10 @@ import { Action, AnyAction } from 'redux'; import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { RtkQueryInspectorProps } from './RtkQueryInspector'; import { QueryInfo, RtkQueryMonitorState, QueryFormValues, + RtkQueryMonitorProps, QueryPreviewTabs, } from './types'; import { QueryComparators } from './utils/comparators'; @@ -53,7 +53,7 @@ const monitorSlice = createSlice({ }); export function reducer>( - props: RtkQueryInspectorProps, + props: RtkQueryMonitorProps, state: RtkQueryMonitorState | undefined, action: AnyAction ): RtkQueryMonitorState { diff --git a/packages/redux-devtools-rtk-query-monitor/src/selectors.ts b/packages/redux-devtools-rtk-query-monitor/src/selectors.ts index fbd73b06..a9791917 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/selectors.ts +++ b/packages/redux-devtools-rtk-query-monitor/src/selectors.ts @@ -1,5 +1,5 @@ import { Action, createSelector, Selector } from '@reduxjs/toolkit'; -import { RtkQueryInspectorProps } from './RtkQueryInspector'; +import { RtkQueryInspectorProps } from './containers/RtkQueryInspector'; import { ApiStats, QueryInfo, RtkQueryTag, SelectorsSource } from './types'; import { Comparator, queryComparators } from './utils/comparators'; import { FilterList, queryListFilters } from './utils/filters'; diff --git a/packages/redux-devtools-rtk-query-monitor/src/styles/createStylingFromTheme.ts b/packages/redux-devtools-rtk-query-monitor/src/styles/createStylingFromTheme.ts index 140c8d91..168a03fc 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/styles/createStylingFromTheme.ts +++ b/packages/redux-devtools-rtk-query-monitor/src/styles/createStylingFromTheme.ts @@ -14,31 +14,32 @@ import { createContext } from 'react'; jss.setup(preset()); -export const colorMap = (theme: reduxThemes.Base16Theme) => ({ - TEXT_COLOR: theme.base06, - TEXT_PLACEHOLDER_COLOR: rgba(theme.base06, 60), - BACKGROUND_COLOR: theme.base00, - SELECTED_BACKGROUND_COLOR: rgba(theme.base03, 20), - SKIPPED_BACKGROUND_COLOR: rgba(theme.base03, 10), - HEADER_BACKGROUND_COLOR: rgba(theme.base03, 30), - HEADER_BORDER_COLOR: rgba(theme.base03, 20), - BORDER_COLOR: rgba(theme.base03, 50), - LIST_BORDER_COLOR: rgba(theme.base03, 50), - ACTION_TIME_BACK_COLOR: rgba(theme.base03, 20), - ACTION_TIME_COLOR: theme.base04, - PIN_COLOR: theme.base04, - ITEM_HINT_COLOR: rgba(theme.base0F, 90), - TAB_BACK_SELECTED_COLOR: rgba(theme.base03, 20), - TAB_BACK_COLOR: rgba(theme.base00, 70), - TAB_BACK_HOVER_COLOR: rgba(theme.base03, 40), - TAB_BORDER_COLOR: rgba(theme.base03, 50), - DIFF_ADD_COLOR: rgba(theme.base0B, 40), - DIFF_REMOVE_COLOR: rgba(theme.base08, 40), - DIFF_ARROW_COLOR: theme.base0E, - LINK_COLOR: rgba(theme.base0E, 90), - LINK_HOVER_COLOR: theme.base0E, - ERROR_COLOR: theme.base08, -}); +export const colorMap = (theme: reduxThemes.Base16Theme) => + ({ + TEXT_COLOR: theme.base06, + TEXT_PLACEHOLDER_COLOR: rgba(theme.base06, 60), + BACKGROUND_COLOR: theme.base00, + SELECTED_BACKGROUND_COLOR: rgba(theme.base03, 20), + SKIPPED_BACKGROUND_COLOR: rgba(theme.base03, 10), + HEADER_BACKGROUND_COLOR: rgba(theme.base03, 30), + HEADER_BORDER_COLOR: rgba(theme.base03, 20), + BORDER_COLOR: rgba(theme.base03, 50), + LIST_BORDER_COLOR: rgba(theme.base03, 50), + ACTION_TIME_BACK_COLOR: rgba(theme.base03, 20), + ACTION_TIME_COLOR: theme.base04, + PIN_COLOR: theme.base04, + ITEM_HINT_COLOR: rgba(theme.base0F, 90), + TAB_BACK_SELECTED_COLOR: rgba(theme.base03, 20), + TAB_BACK_COLOR: rgba(theme.base00, 70), + TAB_BACK_HOVER_COLOR: rgba(theme.base03, 40), + TAB_BORDER_COLOR: rgba(theme.base03, 50), + DIFF_ADD_COLOR: rgba(theme.base0B, 40), + DIFF_REMOVE_COLOR: rgba(theme.base08, 40), + DIFF_ARROW_COLOR: theme.base0E, + LINK_COLOR: rgba(theme.base0E, 90), + LINK_HOVER_COLOR: theme.base0E, + ERROR_COLOR: theme.base08, + } as const); type Color = keyof ReturnType; type ColorMap = { diff --git a/packages/redux-devtools-rtk-query-monitor/src/styles/tree.tsx b/packages/redux-devtools-rtk-query-monitor/src/styles/tree.tsx index 08fafb41..5840ed5d 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/styles/tree.tsx +++ b/packages/redux-devtools-rtk-query-monitor/src/styles/tree.tsx @@ -5,11 +5,11 @@ import isIterable from '../utils/isIterable'; const IS_IMMUTABLE_KEY = '@@__IS_IMMUTABLE__@@'; -function isImmutable(value: any) { +function isImmutable(value: unknown) { return isKeyed(value) || isIndexed(value) || isCollection(value); } -function getShortTypeString(val: any, diff: boolean | undefined) { +function getShortTypeString(val: unknown, diff: boolean | undefined) { if (diff && Array.isArray(val)) { val = val[val.length === 2 ? 1 : 0]; } @@ -23,7 +23,9 @@ function getShortTypeString(val: any, diff: boolean | undefined) { } else if (val === undefined) { return 'undef'; } else if (typeof val === 'object') { - return Object.keys(val).length > 0 ? '{…}' : '{}'; + return Object.keys(val as Record).length > 0 + ? '{…}' + : '{}'; } else if (typeof val === 'function') { return 'fn'; } else if (typeof val === 'string') { diff --git a/packages/redux-devtools-rtk-query-monitor/src/types.ts b/packages/redux-devtools-rtk-query-monitor/src/types.ts index ac2f7c33..a7dfb0f4 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/types.ts +++ b/packages/redux-devtools-rtk-query-monitor/src/types.ts @@ -1,11 +1,11 @@ -import { LiftedAction, LiftedState } from '@redux-devtools/instrument'; +import type { LiftedAction, LiftedState } from '@redux-devtools/instrument'; import type { createApi, QueryStatus } from '@reduxjs/toolkit/query'; -import { ComponentType, Dispatch } from 'react'; -import { Base16Theme, StylingFunction } from 'react-base16-styling'; -import { Action } from 'redux'; -import * as themes from 'redux-devtools-themes'; -import { QueryComparators } from './utils/comparators'; -import { QueryFilters } from './utils/filters'; +import type { Action, Dispatch } from '@reduxjs/toolkit'; +import type { ComponentType } from 'react'; +import type { Base16Theme, StylingFunction } from 'react-base16-styling'; +import type * as themes from 'redux-devtools-themes'; +import type { QueryComparators } from './utils/comparators'; +import type { QueryFilters } from './utils/filters'; export enum QueryPreviewTabs { queryinfo, diff --git a/packages/redux-devtools-rtk-query-monitor/src/utils/isIterable.ts b/packages/redux-devtools-rtk-query-monitor/src/utils/isIterable.ts index feffafb8..3f5f2d03 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/utils/isIterable.ts +++ b/packages/redux-devtools-rtk-query-monitor/src/utils/isIterable.ts @@ -3,6 +3,8 @@ export default function isIterable(obj: unknown): boolean { obj !== null && typeof obj === 'object' && !Array.isArray(obj) && - typeof (obj as any)[window.Symbol.iterator] === 'function' + typeof (obj as Record)[ + window.Symbol.iterator + ] === 'function' ); } diff --git a/packages/redux-devtools-rtk-query-monitor/src/utils/rtk-query.ts b/packages/redux-devtools-rtk-query-monitor/src/utils/rtk-query.ts index 0e66ab31..04758cbe 100644 --- a/packages/redux-devtools-rtk-query-monitor/src/utils/rtk-query.ts +++ b/packages/redux-devtools-rtk-query-monitor/src/utils/rtk-query.ts @@ -25,6 +25,11 @@ const rtkqueryApiStateKeys: ReadonlyArray = [ 'subscriptions', ]; +/** + * Type guard used to select apis from the user store state. + * @param val + * @returns {boolean} + */ export function isApiSlice(val: unknown): val is RtkQueryApiState { if (!isPlainObject(val)) { return false; @@ -282,7 +287,7 @@ export function getQueryTagsOf( for (const [type, tagIds] of Object.entries(provided)) { if (tagIds) { for (const [id, queryKeys] of Object.entries(tagIds)) { - if (queryKeys.includes(queryInfo.queryKey as any)) { + if ((queryKeys as unknown[]).includes(queryInfo.queryKey)) { const tag: RtkQueryTag = { type }; if (id !== missingTagId) {