From 3415f577574c2e69ddcda6653d7ba439fe689a54 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Sun, 22 Aug 2021 18:29:08 -0400 Subject: [PATCH] Work --- extension/src/app/api/filters.ts | 8 +-- extension/src/app/api/index.ts | 58 ++++++++++------ extension/src/app/middlewares/api.ts | 12 ++-- extension/src/app/middlewares/windowSync.ts | 2 +- .../src/app/reducers/window/instances.ts | 10 ++- extension/src/app/stores/windowStore.ts | 9 ++- .../extension/background/getPreloadedState.ts | 4 +- .../src/browser/extension/devpanel/index.tsx | 4 +- .../browser/extension/inject/contentScript.ts | 4 +- .../browser/extension/inject/pageScript.ts | 68 ++++++++++++++----- .../src/browser/extension/window/remote.tsx | 3 +- .../redux-devtools-app/src/actions/index.ts | 5 +- .../src/reducers/instances.ts | 2 +- .../src/reducers/monitor.ts | 2 +- .../src/utils/monitorActions.ts | 4 +- 15 files changed, 128 insertions(+), 67 deletions(-) diff --git a/extension/src/app/api/filters.ts b/extension/src/app/api/filters.ts index 3bcb356d..37fa4ae9 100644 --- a/extension/src/app/api/filters.ts +++ b/extension/src/app/api/filters.ts @@ -67,11 +67,11 @@ export function isFiltered>( function filterActions>( actionsById: { [p: number]: PerformAction }, actionSanitizer: ((action: A, id: number) => A) | undefined -) { +): { [p: number]: PerformAction } { if (!actionSanitizer) return actionsById; - return mapValues(actionsById, (action, id: number) => ({ + return mapValues(actionsById, (action, id) => ({ ...action, - action: actionSanitizer(action.action, id), + action: actionSanitizer(action.action, id as unknown as number), })); } @@ -92,7 +92,7 @@ export function filterState>( stateSanitizer: ((state: S, index: number) => S) | undefined, actionSanitizer: ((action: A, id: number) => A) | undefined, predicate: ((state: S, action: A) => boolean) | undefined -) { +): LiftedState { if (predicate || !noFiltersApplied(localFilter)) { const filteredStagedActionIds: number[] = []; const filteredComputedStates: { state: S; error?: string | undefined }[] = diff --git a/extension/src/app/api/index.ts b/extension/src/app/api/index.ts index d23120ad..217540ac 100644 --- a/extension/src/app/api/index.ts +++ b/extension/src/app/api/index.ts @@ -174,7 +174,7 @@ interface SerializedActionMessage { readonly instanceId: number; readonly action: string; readonly maxAge: number; - readonly nextActionId: number; + readonly nextActionId?: number; } interface SerializedStateMessage> { @@ -320,7 +320,7 @@ interface ExportMessage> { readonly instanceId: number; } -interface StructuralPerformAction> { +export interface StructuralPerformAction> { readonly action: A; readonly timestamp?: number; readonly stack?: string; @@ -341,7 +341,8 @@ interface ActionMessage> { readonly instanceId: number; readonly action: UserAction; readonly maxAge: number; - readonly nextActionId: number; + readonly nextActionId?: number; + readonly name?: string; } interface StateMessage> { @@ -350,6 +351,9 @@ interface StateMessage> { readonly source: typeof source; readonly instanceId: number; readonly libConfig?: LibConfig; + readonly action?: UserAction; + readonly maxAge?: number; + readonly name?: string; } export interface ErrorMessage { @@ -439,7 +443,7 @@ export function toContentScript>( export function sendMessage>( action: StructuralPerformAction | StructuralPerformAction[], - state: S, + state: LiftedState, config: Config, instanceId?: number, name?: string @@ -456,16 +460,16 @@ export function sendMessage>( type: 'ACTION', action: amendedAction, payload: state, - maxAge: config.maxAge, + maxAge: config.maxAge!, source, name: config.name || name, instanceId: config.instanceId || instanceId || 1, }, - config.serialize, - config.serialize + config.serialize as Serialize | undefined, + config.serialize as Serialize | undefined ); } - toContentScript( + toContentScript( { type: 'STATE', action: amendedAction, @@ -475,8 +479,8 @@ export function sendMessage>( name: config.name || name, instanceId: config.instanceId || instanceId || 1, }, - config.serialize, - config.serialize + config.serialize as Serialize | undefined, + config.serialize as Serialize | undefined ); } @@ -530,7 +534,23 @@ export function disconnect() { post({ type: 'DISCONNECT', source }); } -export function connect(preConfig: Config) { +export interface ConnectResponse { + init: >( + state: S, + liftedData: LiftedState + ) => void; + subscribe: >( + listener: (message: ListenerMessage) => void + ) => (() => void) | undefined; + unsubscribe: () => void; + send: >( + action: A, + state: LiftedState + ) => void; + error: (payload: string) => void; +} + +export function connect(preConfig: Config): ConnectResponse { const config = preConfig || {}; const id = generateId(config.instanceId); if (!config.instanceId) config.instanceId = id; @@ -546,7 +566,7 @@ export function connect(preConfig: Config) { const autoPause = config.autoPause; let isPaused = autoPause; let delayedActions: StructuralPerformAction>[] = []; - let delayedStates: unknown[] = []; + let delayedStates: LiftedState, unknown>[] = []; const rootListener = (action: ContentScriptToPageScriptMessage) => { if (autoPause) { @@ -590,12 +610,15 @@ export function connect(preConfig: Config) { }; const sendDelayed = throttle(() => { - sendMessage(delayedActions, delayedStates, config); + sendMessage(delayedActions, delayedStates as any, config); delayedActions = []; delayedStates = []; }, latency); - const send = >(action: A, state: S) => { + const send = >( + action: A, + state: LiftedState + ) => { if ( isPaused || isFiltered(action, localFilter) || @@ -684,13 +707,10 @@ export function connect(preConfig: Config) { export function updateStore>( stores: { - [K in string | number]: EnhancedStore, unknown>; + [K in string | number]: EnhancedStore; } ) { - return function ( - newStore: EnhancedStore, unknown>, - instanceId: number - ) { + return function (newStore: EnhancedStore, instanceId: number) { /* eslint-disable no-console */ console.warn( '`__REDUX_DEVTOOLS_EXTENSION__.updateStore` is deprecated, remove it and just use ' + diff --git a/extension/src/app/middlewares/api.ts b/extension/src/app/middlewares/api.ts index 4896c0da..b6dd67c0 100644 --- a/extension/src/app/middlewares/api.ts +++ b/extension/src/app/middlewares/api.ts @@ -82,9 +82,9 @@ interface ExportAction extends TabMessageBase { readonly id: string; } -interface NAAction { +export interface NAAction { readonly type: 'NA'; - readonly id: string; + readonly id: string | number; } interface InitMessage> { @@ -99,10 +99,10 @@ interface InitMessage> { } interface LiftedMessage { - readonly type: 'LIFTED'; - readonly liftedState: { readonly isPaused: boolean | undefined }; + type: 'LIFTED'; + liftedState: { isPaused: boolean | undefined }; instanceId: number; - readonly source: '@devtools-page'; + source: '@devtools-page'; } interface SerializedPartialLiftedState { @@ -162,7 +162,7 @@ type UpdateStateRequest> = | SerializedActionMessage | SerializedStateMessage; -interface EmptyUpdateStateAction { +export interface EmptyUpdateStateAction { readonly type: typeof UPDATE_STATE; } diff --git a/extension/src/app/middlewares/windowSync.ts b/extension/src/app/middlewares/windowSync.ts index 8de3be55..f8823ba8 100644 --- a/extension/src/app/middlewares/windowSync.ts +++ b/extension/src/app/middlewares/windowSync.ts @@ -28,7 +28,7 @@ const syncStores = const instances = store.getState().instances; const instanceId = getActiveInstance(instances); const id = instances.options[instanceId].connectionId; - baseStore.dispatch({ ...action, instanceId, id }); + baseStore.dispatch({ ...action, instanceId, id } as any); } return next(action); }; diff --git a/extension/src/app/reducers/window/instances.ts b/extension/src/app/reducers/window/instances.ts index f95f0982..1db1a6ec 100644 --- a/extension/src/app/reducers/window/instances.ts +++ b/extension/src/app/reducers/window/instances.ts @@ -7,7 +7,10 @@ import { SELECT_INSTANCE, LIFTED_ACTION, } from '@redux-devtools/app/lib/constants/actionTypes'; -import { WindowStoreAction } from '../../stores/windowStore'; +import { + ExpandedUpdateStateAction, + WindowStoreAction, +} from '../../stores/windowStore'; export default function instances( state = initialState, @@ -15,7 +18,10 @@ export default function instances( ) { switch (action.type) { case UPDATE_STATE: - return { ...action.instances, selected: state.selected }; + return { + ...(action as ExpandedUpdateStateAction).instances, + selected: state.selected, + }; case LIFTED_ACTION: if (action.message === 'DISPATCH') return dispatchAction(state, action); return state; diff --git a/extension/src/app/stores/windowStore.ts b/extension/src/app/stores/windowStore.ts index 9eb8b351..fa1b406c 100644 --- a/extension/src/app/stores/windowStore.ts +++ b/extension/src/app/stores/windowStore.ts @@ -21,6 +21,7 @@ import instanceSelector from '../middlewares/instanceSelector'; import rootReducer from '../reducers/window'; import { BackgroundState } from '../reducers/background'; import { BackgroundAction } from './backgroundStore'; +import { EmptyUpdateStateAction, NAAction } from '../middlewares/api'; export interface TogglePersistAction { readonly type: 'TOGGLE_PERSIST'; @@ -28,14 +29,16 @@ export interface TogglePersistAction { export type StoreActionWithTogglePersist = StoreAction | TogglePersistAction; -interface ExpandedUpdateStateAction extends UpdateStateAction { +export interface ExpandedUpdateStateAction extends UpdateStateAction { readonly instances: InstancesState; } export type WindowStoreAction = | StoreActionWithoutUpdateState | TogglePersistAction - | ExpandedUpdateStateAction; + | ExpandedUpdateStateAction + | NAAction + | EmptyUpdateStateAction; export default function configureStore( baseStore: Store, @@ -68,7 +71,7 @@ export default function configureStore( hostname: options['s:hostname'], port: options['s:port'], secure: options['s:secure'], - }, + } as any, }); }); diff --git a/extension/src/browser/extension/background/getPreloadedState.ts b/extension/src/browser/extension/background/getPreloadedState.ts index 00ea732e..e4cfa83a 100644 --- a/extension/src/browser/extension/background/getPreloadedState.ts +++ b/extension/src/browser/extension/background/getPreloadedState.ts @@ -1,7 +1,7 @@ import { PreloadedState } from 'redux'; import { StoreState } from '@redux-devtools/app/lib/reducers'; -const getIfExists = (sel, template) => +const getIfExists = (sel: any, template: any) => typeof sel === 'undefined' || typeof template === 'undefined' || typeof template[sel] === 'undefined' @@ -34,7 +34,7 @@ export default function getPreloadedState( ), templates: options['test-templates'], }, - }); + } as any); } ); } diff --git a/extension/src/browser/extension/devpanel/index.tsx b/extension/src/browser/extension/devpanel/index.tsx index dfb24372..484e5e38 100644 --- a/extension/src/browser/extension/devpanel/index.tsx +++ b/extension/src/browser/extension/devpanel/index.tsx @@ -9,8 +9,8 @@ import getPreloadedState from '../background/getPreloadedState'; import '../../views/devpanel.pug'; import { Action, PreloadedState, Store } from 'redux'; import { StoreState } from '@redux-devtools/app/lib/reducers'; -import { StoreAction } from '@redux-devtools/app/lib/actions'; import { PanelMessage } from '../../../app/middlewares/api'; +import { StoreActionWithTogglePersist } from '../../../app/stores/windowStore'; const position = location.hash; const messageStyle: CSSProperties = { @@ -20,7 +20,7 @@ const messageStyle: CSSProperties = { }; let rendered: boolean | undefined; -let store: Store | undefined; +let store: Store | undefined; let bgConnection: chrome.runtime.Port; let naTimeout: NodeJS.Timeout; let preloadedState: PreloadedState; diff --git a/extension/src/browser/extension/inject/contentScript.ts b/extension/src/browser/extension/inject/contentScript.ts index 8675f1d0..c1abac34 100644 --- a/extension/src/browser/extension/inject/contentScript.ts +++ b/extension/src/browser/extension/inject/contentScript.ts @@ -213,7 +213,7 @@ function tryCatch>( return fn(args); } catch (err) { if (err.message === 'Message length exceeded maximum allowed length.') { - const instanceId = args.instanceId; + const instanceId = (args as any).instanceId; const newArgs = { split: 'start', }; @@ -231,7 +231,7 @@ function tryCatch>( } newArgs[key as keyof typeof newArgs] = arg; }); - fn(newArgs); + fn(newArgs as any); for (let i = 0; i < toSplit.length; i++) { for (let j = 0; j < toSplit[i][1].length; j += maxChromeMsgSize) { fn({ diff --git a/extension/src/browser/extension/inject/pageScript.ts b/extension/src/browser/extension/inject/pageScript.ts index 88e6b2f5..24a219b0 100644 --- a/extension/src/browser/extension/inject/pageScript.ts +++ b/extension/src/browser/extension/inject/pageScript.ts @@ -7,6 +7,7 @@ import throttle from 'lodash/throttle'; import { Action, ActionCreator, + Dispatch, PreloadedState, Reducer, Store, @@ -14,7 +15,7 @@ import { StoreEnhancerStoreCreator, } from 'redux'; import Immutable from 'immutable'; -import { EnhancedStore } from '@redux-devtools/instrument'; +import { EnhancedStore, PerformAction } from '@redux-devtools/instrument'; import createStore from '../../../app/stores/createStore'; import configureStore, { getUrlParam } from '../../../app/stores/enhancerStore'; import { isAllowed, Options } from '../options/syncOptions'; @@ -40,6 +41,8 @@ import { isInIframe, getSerializeParameter, Serialize, + StructuralPerformAction, + ConnectResponse, } from '../../../app/api'; import { LiftedAction, LiftedState } from '@redux-devtools/instrument'; import { @@ -50,9 +53,19 @@ import { import { ContentScriptToPageScriptMessage } from './contentScript'; import { Features } from '@redux-devtools/app/lib/reducers/instances'; +type EnhancedStoreWithInitialDispatch< + S, + A extends Action, + MonitorState +> = EnhancedStore & { initialDispatch: Dispatch }; + const source = '@devtools-page'; let stores: { - [K in string | number]: EnhancedStore, unknown>; + [K in string | number]: EnhancedStoreWithInitialDispatch< + unknown, + Action, + unknown + >; } = {}; let reportId: string | null | undefined; @@ -137,7 +150,23 @@ interface ReduxDevtoolsExtension { ): Store; (config?: Config): StoreEnhancer; open: (position?: Position) => void; + updateStore: ( + newStore: EnhancedStore, unknown>, + instanceId: number + ) => void; notifyErrors: (onError?: () => boolean) => void; + send: >( + action: StructuralPerformAction | StructuralPerformAction[], + state: LiftedState, + config: Config, + instanceId?: number, + name?: string + ) => void; + listen: ( + onMessage: (message: ContentScriptToPageScriptMessage) => void, + instanceId: number + ) => void; + connect: (preConfig: Config) => ConnectResponse; disconnect: () => void; } @@ -157,16 +186,16 @@ function __REDUX_DEVTOOLS_EXTENSION__>( reducer?: Reducer | Config | undefined, preloadedState?: PreloadedState, config?: Config -) { +): Store | StoreEnhancer { /* eslint-disable no-param-reassign */ if (typeof reducer === 'object') { config = reducer; reducer = undefined; } else if (typeof config !== 'object') config = {}; /* eslint-enable no-param-reassign */ - if (!window.devToolsOptions) window.devToolsOptions = {}; + if (!window.devToolsOptions) window.devToolsOptions = {} as any; - let store: EnhancedStore; + let store: EnhancedStoreWithInitialDispatch; let errorOccurred = false; let maxAge: number | undefined; let actionCreators: readonly ActionCreatorObject[]; @@ -404,7 +433,7 @@ function __REDUX_DEVTOOLS_EXTENSION__>( store.liftedStore.dispatch({ type: action.type, index }); return; } - store.liftedStore.dispatch(action); + store.liftedStore.dispatch(action as any); } function onMessage(message: ContentScriptToPageScriptMessage) { @@ -479,12 +508,12 @@ function __REDUX_DEVTOOLS_EXTENSION__>( if ( !liftedAction || noFiltersApplied(localFilter) || - !liftedAction.action + !(liftedAction as PerformAction).action ) { return m; } if (!maxAge || maxAge < m) maxAge = m; // it can be modified in process on options page - if (isFiltered(liftedAction.action, localFilter)) { + if (isFiltered((liftedAction as PerformAction).action, localFilter)) { // TODO: check also predicate && !predicate(state, action) with current state maxAge++; } else { @@ -554,10 +583,10 @@ function __REDUX_DEVTOOLS_EXTENSION__>( } const enhance = - () => + (): StoreEnhancer => ( next: StoreEnhancerStoreCreator - ) => { + ): any => { return ( reducer_: Reducer, initialState_?: PreloadedState @@ -568,7 +597,7 @@ function __REDUX_DEVTOOLS_EXTENSION__>( return configureStore(next, monitor.reducer, { ...config, - maxAge: getMaxAge, + maxAge: getMaxAge as any, })(reducer_, initialState_); if (isInIframe()) setTimeout(init, 3000); @@ -610,24 +639,27 @@ const preEnhancer = const store = next(reducer, preloadedState); if (stores[instanceId]) { - stores[instanceId].initialDispatch = store.dispatch; + (stores[instanceId].initialDispatch as any) = store.dispatch; } return { ...store, - dispatch: (...args) => - !window.__REDUX_DEVTOOLS_EXTENSION_LOCKED__ && store.dispatch(...args), - }; + dispatch: (...args: any[]) => + !window.__REDUX_DEVTOOLS_EXTENSION_LOCKED__ && + (store.dispatch as any)(...args), + } as any; }; const extensionCompose = (config: Config) => (...funcs: StoreEnhancer[]) => { - return (...args) => { + return (...args: any[]) => { const instanceId = generateId(config.instanceId); return [preEnhancer(instanceId), ...funcs].reduceRight( (composed, f) => f(composed), - __REDUX_DEVTOOLS_EXTENSION__({ ...config, instanceId })(...args) + (__REDUX_DEVTOOLS_EXTENSION__({ ...config, instanceId }) as any)( + ...args + ) ); }; }; @@ -638,7 +670,7 @@ declare global { } } -window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = (...funcs) => { +window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = (...funcs: any[]) => { if (funcs.length === 0) { return __REDUX_DEVTOOLS_EXTENSION__(); } diff --git a/extension/src/browser/extension/window/remote.tsx b/extension/src/browser/extension/window/remote.tsx index 3c31bb66..a2ec9e86 100644 --- a/extension/src/browser/extension/window/remote.tsx +++ b/extension/src/browser/extension/window/remote.tsx @@ -14,8 +14,9 @@ chrome.storage.local.get( 's:secure': null, }, (options) => { + const AppAsAny = App as any; render( - , + Dispatch, { readonly instances: InstancesState } >, message: string,