This commit is contained in:
Nathan Bierema 2021-08-22 18:29:08 -04:00
parent ca68117921
commit 3415f57757
15 changed files with 128 additions and 67 deletions

View File

@ -67,11 +67,11 @@ export function isFiltered<A extends Action<unknown>>(
function filterActions<A extends Action<unknown>>(
actionsById: { [p: number]: PerformAction<A> },
actionSanitizer: ((action: A, id: number) => A) | undefined
) {
): { [p: number]: PerformAction<A> } {
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<S, A extends Action<unknown>>(
stateSanitizer: ((state: S, index: number) => S) | undefined,
actionSanitizer: ((action: A, id: number) => A) | undefined,
predicate: ((state: S, action: A) => boolean) | undefined
) {
): LiftedState<S, A, unknown> {
if (predicate || !noFiltersApplied(localFilter)) {
const filteredStagedActionIds: number[] = [];
const filteredComputedStates: { state: S; error?: string | undefined }[] =

View File

@ -174,7 +174,7 @@ interface SerializedActionMessage {
readonly instanceId: number;
readonly action: string;
readonly maxAge: number;
readonly nextActionId: number;
readonly nextActionId?: number;
}
interface SerializedStateMessage<S, A extends Action<unknown>> {
@ -320,7 +320,7 @@ interface ExportMessage<S, A extends Action<unknown>> {
readonly instanceId: number;
}
interface StructuralPerformAction<A extends Action<unknown>> {
export interface StructuralPerformAction<A extends Action<unknown>> {
readonly action: A;
readonly timestamp?: number;
readonly stack?: string;
@ -341,7 +341,8 @@ interface ActionMessage<S, A extends Action<unknown>> {
readonly instanceId: number;
readonly action: UserAction<A>;
readonly maxAge: number;
readonly nextActionId: number;
readonly nextActionId?: number;
readonly name?: string;
}
interface StateMessage<S, A extends Action<unknown>> {
@ -350,6 +351,9 @@ interface StateMessage<S, A extends Action<unknown>> {
readonly source: typeof source;
readonly instanceId: number;
readonly libConfig?: LibConfig;
readonly action?: UserAction<A>;
readonly maxAge?: number;
readonly name?: string;
}
export interface ErrorMessage {
@ -439,7 +443,7 @@ export function toContentScript<S, A extends Action<unknown>>(
export function sendMessage<S, A extends Action<unknown>>(
action: StructuralPerformAction<A> | StructuralPerformAction<A>[],
state: S,
state: LiftedState<S, A, unknown>,
config: Config,
instanceId?: number,
name?: string
@ -456,16 +460,16 @@ export function sendMessage<S, A extends Action<unknown>>(
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<S, A>(
{
type: 'STATE',
action: amendedAction,
@ -475,8 +479,8 @@ export function sendMessage<S, A extends Action<unknown>>(
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: <S, A extends Action<unknown>>(
state: S,
liftedData: LiftedState<S, A, unknown>
) => void;
subscribe: <S, A extends Action<unknown>>(
listener: (message: ListenerMessage<S, A>) => void
) => (() => void) | undefined;
unsubscribe: () => void;
send: <S, A extends Action<unknown>>(
action: A,
state: LiftedState<S, A, unknown>
) => 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<Action<unknown>>[] = [];
let delayedStates: unknown[] = [];
let delayedStates: LiftedState<unknown, Action<unknown>, 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 = <S, A extends Action<unknown>>(action: A, state: S) => {
const send = <S, A extends Action<unknown>>(
action: A,
state: LiftedState<S, A, unknown>
) => {
if (
isPaused ||
isFiltered(action, localFilter) ||
@ -684,13 +707,10 @@ export function connect(preConfig: Config) {
export function updateStore<S, A extends Action<unknown>>(
stores: {
[K in string | number]: EnhancedStore<S, Action<A>, unknown>;
[K in string | number]: EnhancedStore<S, A, unknown>;
}
) {
return function (
newStore: EnhancedStore<S, Action<A>, unknown>,
instanceId: number
) {
return function (newStore: EnhancedStore<S, A, unknown>, instanceId: number) {
/* eslint-disable no-console */
console.warn(
'`__REDUX_DEVTOOLS_EXTENSION__.updateStore` is deprecated, remove it and just use ' +

View File

@ -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<S, A extends Action<unknown>> {
@ -99,10 +99,10 @@ interface InitMessage<S, A extends Action<unknown>> {
}
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<S, A extends Action<unknown>> =
| SerializedActionMessage
| SerializedStateMessage<S, A>;
interface EmptyUpdateStateAction {
export interface EmptyUpdateStateAction {
readonly type: typeof UPDATE_STATE;
}

View File

@ -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);
};

View File

@ -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;

View File

@ -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<BackgroundState, BackgroundAction>,
@ -68,7 +71,7 @@ export default function configureStore(
hostname: options['s:hostname'],
port: options['s:port'],
secure: options['s:secure'],
},
} as any,
});
});

View File

@ -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);
}
);
}

View File

@ -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<StoreState, StoreAction> | undefined;
let store: Store<StoreState, StoreActionWithTogglePersist> | undefined;
let bgConnection: chrome.runtime.Port;
let naTimeout: NodeJS.Timeout;
let preloadedState: PreloadedState<StoreState>;

View File

@ -213,7 +213,7 @@ function tryCatch<S, A extends Action<unknown>>(
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<S, A extends Action<unknown>>(
}
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({

View File

@ -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<unknown>,
MonitorState
> = EnhancedStore<S, A, MonitorState> & { initialDispatch: Dispatch<A> };
const source = '@devtools-page';
let stores: {
[K in string | number]: EnhancedStore<unknown, Action<unknown>, unknown>;
[K in string | number]: EnhancedStoreWithInitialDispatch<
unknown,
Action<unknown>,
unknown
>;
} = {};
let reportId: string | null | undefined;
@ -137,7 +150,23 @@ interface ReduxDevtoolsExtension {
): Store<S, A>;
(config?: Config): StoreEnhancer;
open: (position?: Position) => void;
updateStore: (
newStore: EnhancedStore<unknown, Action<unknown>, unknown>,
instanceId: number
) => void;
notifyErrors: (onError?: () => boolean) => void;
send: <S, A extends Action<unknown>>(
action: StructuralPerformAction<A> | StructuralPerformAction<A>[],
state: LiftedState<S, A, unknown>,
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__<S, A extends Action<unknown>>(
reducer?: Reducer<S, A> | Config | undefined,
preloadedState?: PreloadedState<S>,
config?: Config
) {
): Store<S, A> | 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<S, A, unknown>;
let store: EnhancedStoreWithInitialDispatch<S, A, unknown>;
let errorOccurred = false;
let maxAge: number | undefined;
let actionCreators: readonly ActionCreatorObject[];
@ -404,7 +433,7 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<unknown>>(
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__<S, A extends Action<unknown>>(
if (
!liftedAction ||
noFiltersApplied(localFilter) ||
!liftedAction.action
!(liftedAction as PerformAction<A>).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<A>).action, localFilter)) {
// TODO: check also predicate && !predicate(state, action) with current state
maxAge++;
} else {
@ -554,10 +583,10 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<unknown>>(
}
const enhance =
() =>
(): StoreEnhancer =>
<NextExt, NextStateExt>(
next: StoreEnhancerStoreCreator<NextExt, NextStateExt>
) => {
): any => {
return <S2 extends S, A2 extends A>(
reducer_: Reducer<S2, A2>,
initialState_?: PreloadedState<S2>
@ -568,7 +597,7 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<unknown>>(
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__();
}

View File

@ -14,8 +14,9 @@ chrome.storage.local.get(
's:secure': null,
},
(options) => {
const AppAsAny = App as any;
render(
<App
<AppAsAny
selectMonitor={options['select-monitor']}
testTemplates={options['test-templates']}
selectedTemplate={options['test-templates-sel']}

View File

@ -382,7 +382,7 @@ export interface LibConfig {
export interface RequestBase {
id?: string;
instanceId?: string;
instanceId?: string | number;
action?: string;
name?: string | undefined;
libConfig?: LibConfig;
@ -441,7 +441,7 @@ export interface SetStateAction {
export interface RemoveInstanceAction {
type: typeof REMOVE_INSTANCE;
id: string;
id: string | number;
}
export interface ConnectRequestAction {
@ -557,7 +557,6 @@ export type StoreActionWithoutUpdateStateOrLiftedAction =
| ChangeSectionAction
| ChangeThemeAction
| MonitorActionAction
| LiftedActionAction
| SelectInstanceAction
| SelectMonitorAction
| UpdateMonitorStateAction

View File

@ -231,7 +231,7 @@ export function dispatchAction(
return state;
}
function removeState(state: InstancesState, connectionId: string) {
function removeState(state: InstancesState, connectionId: string | number) {
const instanceIds = state.connections[connectionId];
if (!instanceIds) return state;

View File

@ -18,7 +18,7 @@ export interface MonitorStateMonitorState {
}
export interface MonitorState {
selected: string;
monitorState: MonitorStateMonitorState | undefined;
monitorState?: MonitorStateMonitorState | undefined;
sliderIsOpen: boolean;
dispatcherIsOpen: boolean;
}

View File

@ -4,7 +4,7 @@ import stringifyJSON from './stringifyJSON';
import { SET_STATE } from '../constants/actionTypes';
import { InstancesState, State } from '../reducers/instances';
import { Dispatch, MiddlewareAPI } from 'redux';
import { DispatchAction, StoreAction } from '../actions';
import { DispatchAction, StoreActionWithoutLiftedAction } from '../actions';
export function sweep(state: State): State {
return {
@ -21,7 +21,7 @@ export function sweep(state: State): State {
export function nonReduxDispatch(
store: MiddlewareAPI<
Dispatch<StoreAction>,
Dispatch<StoreActionWithoutLiftedAction>,
{ readonly instances: InstancesState }
>,
message: string,