diff --git a/extension/src/browser/extension/options/index.js b/extension/src/browser/extension/options/index.tsx
similarity index 52%
rename from extension/src/browser/extension/options/index.js
rename to extension/src/browser/extension/options/index.tsx
index 0dbc8719..55805985 100644
--- a/extension/src/browser/extension/options/index.js
+++ b/extension/src/browser/extension/options/index.tsx
@@ -1,19 +1,20 @@
import React from 'react';
import { render } from 'react-dom';
-import Options from './Options';
+import OptionsComponent from './Options';
+import { Options } from './syncOptions';
import '../../views/options.pug';
chrome.runtime.getBackgroundPage((background) => {
- const syncOptions = background.syncOptions;
+ const syncOptions = background!.syncOptions;
- const saveOption = (name, value) => {
+ const saveOption =
(name: K, value: Options[K]) => {
syncOptions.save(name, value);
};
- const renderOptions = (options) => {
+ const renderOptions = (options: Options) => {
render(
- ,
+ ,
document.getElementById('root')
);
};
diff --git a/extension/src/browser/extension/options/syncOptions.js b/extension/src/browser/extension/options/syncOptions.js
deleted file mode 100644
index 04827b5c..00000000
--- a/extension/src/browser/extension/options/syncOptions.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import { FilterState } from '../../../app/api/filters';
-
-let options;
-let subscribers = [];
-
-const save = (toAllTabs) => (key, value) => {
- let obj = {};
- obj[key] = value;
- chrome.storage.sync.set(obj);
- options[key] = value;
- toAllTabs({ options: options });
- subscribers.forEach((s) => s(options));
-};
-
-const migrateOldOptions = (oldOptions) => {
- let newOptions = Object.assign({}, oldOptions);
-
- // Migrate the old `filter` option from 2.2.1
- if (typeof oldOptions.filter === 'boolean') {
- if (oldOptions.filter && oldOptions.whitelist.length > 0) {
- newOptions.filter = FilterState.WHITELIST_SPECIFIC;
- } else if (oldOptions.filter) {
- newOptions.filter = FilterState.BLACKLIST_SPECIFIC;
- } else {
- newOptions.filter = FilterState.DO_NOT_FILTER;
- }
- }
-
- return newOptions;
-};
-
-const get = (callback) => {
- if (options) callback(options);
- else {
- chrome.storage.sync.get(
- {
- useEditor: 0,
- editor: '',
- projectPath: '',
- maxAge: 50,
- filter: FilterState.DO_NOT_FILTER,
- whitelist: '',
- blacklist: '',
- shouldCatchErrors: false,
- inject: true,
- urls: '^https?://localhost|0\\.0\\.0\\.0:\\d+\n^https?://.+\\.github\\.io',
- showContextMenus: true,
- },
- function (items) {
- options = migrateOldOptions(items);
- callback(options);
- }
- );
- }
-};
-
-const subscribe = (callback) => {
- subscribers = subscribers.concat(callback);
-};
-
-const toReg = (str) =>
- str !== '' ? str.split('\n').filter(Boolean).join('|') : null;
-
-export const injectOptions = (newOptions) => {
- if (!newOptions) return;
- if (newOptions.filter !== FilterState.DO_NOT_FILTER) {
- newOptions.whitelist = toReg(newOptions.whitelist);
- newOptions.blacklist = toReg(newOptions.blacklist);
- }
-
- options = newOptions;
- let s = document.createElement('script');
- s.type = 'text/javascript';
- s.appendChild(
- document.createTextNode(
- 'window.devToolsOptions = Object.assign(window.devToolsOptions||{},' +
- JSON.stringify(options) +
- ');'
- )
- );
- (document.head || document.documentElement).appendChild(s);
- s.parentNode.removeChild(s);
-};
-
-export const getOptionsFromBg = () => {
- /* chrome.runtime.sendMessage({ type: 'GET_OPTIONS' }, response => {
- if (response && response.options) injectOptions(response.options);
- });
-*/
- get((newOptions) => {
- injectOptions(newOptions);
- }); // Legacy
-};
-
-export const isAllowed = (localOptions = options) =>
- !localOptions ||
- localOptions.inject ||
- !localOptions.urls ||
- location.href.match(toReg(localOptions.urls));
-
-export default function syncOptions(toAllTabs) {
- if (toAllTabs && !options) get(() => {}); // Initialize
- return {
- save: save(toAllTabs),
- get: get,
- subscribe: subscribe,
- };
-}
diff --git a/extension/src/browser/extension/options/syncOptions.ts b/extension/src/browser/extension/options/syncOptions.ts
new file mode 100644
index 00000000..2164fee1
--- /dev/null
+++ b/extension/src/browser/extension/options/syncOptions.ts
@@ -0,0 +1,152 @@
+import { FilterState, FilterStateValue } from '../../../app/api/filters';
+
+export interface Options {
+ readonly useEditor: number;
+ readonly editor: string;
+ readonly projectPath: string;
+ readonly maxAge: number;
+ readonly filter: FilterStateValue;
+ readonly whitelist: string;
+ readonly blacklist: string;
+ readonly shouldCatchErrors: boolean;
+ readonly inject: boolean;
+ readonly urls: string;
+ readonly showContextMenus: boolean;
+}
+
+interface OldOrNewOptions {
+ readonly useEditor: number;
+ readonly editor: string;
+ readonly projectPath: string;
+ readonly maxAge: number;
+ readonly filter: FilterStateValue | boolean;
+ readonly whitelist: string;
+ readonly blacklist: string;
+ readonly shouldCatchErrors: boolean;
+ readonly inject: boolean;
+ readonly urls: string;
+ readonly showContextMenus: boolean;
+}
+
+let options: Options | undefined;
+let subscribers: ((options: Options) => void)[] = [];
+
+export interface OptionsMessage {
+ readonly options: Options;
+}
+
+type ToAllTabs = (msg: OptionsMessage) => void;
+
+const save =
+ (toAllTabs: ToAllTabs | undefined) =>
+ (key: K, value: Options[K]) => {
+ let obj: { [K1 in keyof Options]?: Options[K1] } = {};
+ obj[key] = value;
+ chrome.storage.sync.set(obj);
+ options![key] = value;
+ toAllTabs!({ options: options! });
+ subscribers.forEach((s) => s(options!));
+ };
+
+const migrateOldOptions = (oldOptions: OldOrNewOptions): Options => ({
+ ...oldOptions,
+ filter:
+ // Migrate the old `filter` option from 2.2.1
+ typeof oldOptions.filter === 'boolean'
+ ? oldOptions.filter && oldOptions.whitelist.length > 0
+ ? FilterState.WHITELIST_SPECIFIC
+ : oldOptions.filter
+ ? FilterState.BLACKLIST_SPECIFIC
+ : FilterState.DO_NOT_FILTER
+ : oldOptions.filter,
+});
+
+const get = (callback: (options: Options) => void) => {
+ if (options) callback(options);
+ else {
+ chrome.storage.sync.get(
+ {
+ useEditor: 0,
+ editor: '',
+ projectPath: '',
+ maxAge: 50,
+ filter: FilterState.DO_NOT_FILTER,
+ whitelist: '',
+ blacklist: '',
+ shouldCatchErrors: false,
+ inject: true,
+ urls: '^https?://localhost|0\\.0\\.0\\.0:\\d+\n^https?://.+\\.github\\.io',
+ showContextMenus: true,
+ },
+ function (items) {
+ options = migrateOldOptions(items as OldOrNewOptions);
+ callback(options);
+ }
+ );
+ }
+};
+
+const subscribe = (callback: (options: Options) => void) => {
+ subscribers = subscribers.concat(callback);
+};
+
+const toReg = (str: string) =>
+ str !== '' ? str.split('\n').filter(Boolean).join('|') : null;
+
+export const injectOptions = (newOptions: Options) => {
+ if (!newOptions) return;
+
+ options = {
+ ...newOptions,
+ whitelist:
+ newOptions.filter !== FilterState.DO_NOT_FILTER
+ ? toReg(newOptions.whitelist)!
+ : newOptions.whitelist,
+ blacklist:
+ newOptions.filter !== FilterState.DO_NOT_FILTER
+ ? toReg(newOptions.blacklist)!
+ : newOptions.blacklist,
+ };
+ let s = document.createElement('script');
+ s.type = 'text/javascript';
+ s.appendChild(
+ document.createTextNode(
+ 'window.devToolsOptions = Object.assign(window.devToolsOptions||{},' +
+ JSON.stringify(options) +
+ ');'
+ )
+ );
+ (document.head || document.documentElement).appendChild(s);
+ s.parentNode!.removeChild(s);
+};
+
+export const getOptionsFromBg = () => {
+ /* chrome.runtime.sendMessage({ type: 'GET_OPTIONS' }, response => {
+ if (response && response.options) injectOptions(response.options);
+ });
+*/
+ get((newOptions) => {
+ injectOptions(newOptions);
+ }); // Legacy
+};
+
+export const isAllowed = (localOptions = options) =>
+ !localOptions ||
+ localOptions.inject ||
+ !localOptions.urls ||
+ location.href.match(toReg(localOptions.urls)!);
+
+export interface SyncOptions {
+ readonly save: (key: K, value: Options[K]) => void;
+ readonly get: (callback: (options: Options) => void) => void;
+ readonly subscribe: (callback: (options: Options) => void) => void;
+}
+
+export default function syncOptions(toAllTabs?: ToAllTabs): SyncOptions {
+ if (toAllTabs && !options) get(() => {}); // Initialize
+ return {
+ save: save(toAllTabs),
+ get: get,
+ subscribe: subscribe,
+ };
+}
diff --git a/extension/src/browser/extension/window/index.js b/extension/src/browser/extension/window/index.tsx
similarity index 76%
rename from extension/src/browser/extension/window/index.js
rename to extension/src/browser/extension/window/index.tsx
index e1f1260f..d583cbbf 100644
--- a/extension/src/browser/extension/window/index.js
+++ b/extension/src/browser/extension/window/index.tsx
@@ -1,27 +1,31 @@
import React from 'react';
import { render } from 'react-dom';
+import { PreloadedState } from 'redux';
import { Provider } from 'react-redux';
import { UPDATE_STATE } from '@redux-devtools/app/lib/constants/actionTypes';
+import { StoreState } from '@redux-devtools/app/lib/reducers';
import App from '../../../app/containers/App';
import configureStore from '../../../app/stores/windowStore';
import getPreloadedState from '../background/getPreloadedState';
import '../../views/window.pug';
+import { MonitorMessage } from '../../../app/middlewares/api';
const position = location.hash;
-let preloadedState;
+let preloadedState: PreloadedState;
getPreloadedState(position, (state) => {
preloadedState = state;
});
-chrome.runtime.getBackgroundPage(({ store }) => {
+chrome.runtime.getBackgroundPage((window) => {
+ const { store } = window!;
const localStore = configureStore(store, position, preloadedState);
let name = 'monitor';
if (chrome && chrome.devtools && chrome.devtools.inspectedWindow) {
name += chrome.devtools.inspectedWindow.tabId;
}
const bg = chrome.runtime.connect({ name });
- const update = (action) => {
+ const update = (action?: MonitorMessage) => {
localStore.dispatch(action || { type: UPDATE_STATE });
};
bg.onMessage.addListener(update);
diff --git a/extension/src/browser/extension/window/remote.js b/extension/src/browser/extension/window/remote.tsx
similarity index 93%
rename from extension/src/browser/extension/window/remote.js
rename to extension/src/browser/extension/window/remote.tsx
index e4e271e6..a2ec9e86 100644
--- a/extension/src/browser/extension/window/remote.js
+++ b/extension/src/browser/extension/window/remote.tsx
@@ -14,12 +14,12 @@ chrome.storage.local.get(
's:secure': null,
},
(options) => {
+ const AppAsAny = App as any;
render(
- ({
// devtool: 'source-map',
@@ -64,7 +64,7 @@ const baseConfig = (params) => ({
app: path.join(__dirname, '../src/app'),
tmp: path.join(__dirname, '../build/tmp'),
},
- extensions: ['.js'],
+ extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
module: {
rules: [
@@ -72,7 +72,7 @@ const baseConfig = (params) => ({
? params.loaders
: [
{
- test: /\.js$/,
+ test: /\.(js|ts)x?$/,
use: 'babel-loader',
exclude: /(node_modules|tmp\/page\.bundle)/,
},
diff --git a/packages/redux-devtools-app/src/actions/index.ts b/packages/redux-devtools-app/src/actions/index.ts
index 3eda8bb8..362834b6 100644
--- a/packages/redux-devtools-app/src/actions/index.ts
+++ b/packages/redux-devtools-app/src/actions/index.ts
@@ -45,6 +45,7 @@ import { Features, State } from '../reducers/instances';
import { MonitorStateMonitorState } from '../reducers/monitor';
import { LiftedAction } from '@redux-devtools/core';
import { Data } from '../reducers/reports';
+import { LiftedState } from '@redux-devtools/instrument';
let monitorReducer: (
monitorProps: unknown,
@@ -53,7 +54,7 @@ let monitorReducer: (
) => unknown;
let monitorProps: unknown = {};
-interface ChangeSectionAction {
+export interface ChangeSectionAction {
readonly type: typeof CHANGE_SECTION;
readonly section: string;
}
@@ -69,7 +70,7 @@ interface ChangeThemeFormData {
interface ChangeThemeData {
readonly formData: ChangeThemeFormData;
}
-interface ChangeThemeAction {
+export interface ChangeThemeAction {
readonly type: typeof CHANGE_THEME;
readonly theme: Theme;
readonly scheme: Scheme;
@@ -119,13 +120,28 @@ export interface LockChangesAction {
}
export interface ToggleActionAction {
type: 'TOGGLE_ACTION';
+ id: number;
}
export interface RollbackAction {
type: 'ROLLBACK';
+ timestamp: number;
}
export interface SweepAction {
type: 'SWEEP';
}
+interface ReorderActionAction {
+ type: 'REORDER_ACTION';
+ actionId: number;
+ beforeActionId: number;
+}
+interface ImportStateAction {
+ type: 'IMPORT_STATE';
+ nextLiftedState:
+ | LiftedState, unknown>
+ | readonly Action[];
+ preloadedState?: unknown;
+ noRecompute?: boolean | undefined;
+}
export type DispatchAction =
| JumpToStateAction
| JumpToActionAction
@@ -133,7 +149,9 @@ export type DispatchAction =
| LockChangesAction
| ToggleActionAction
| RollbackAction
- | SweepAction;
+ | SweepAction
+ | ReorderActionAction
+ | ImportStateAction;
interface LiftedActionActionBase {
action?: DispatchAction | string | CustomAction;
state?: string;
@@ -145,18 +163,18 @@ export interface LiftedActionDispatchAction extends LiftedActionActionBase {
action: DispatchAction;
toAll?: boolean;
}
-interface LiftedActionImportAction extends LiftedActionActionBase {
+export interface LiftedActionImportAction extends LiftedActionActionBase {
type: typeof LIFTED_ACTION;
message: 'IMPORT';
state: string;
preloadedState: unknown | undefined;
}
-interface LiftedActionActionAction extends LiftedActionActionBase {
+export interface LiftedActionActionAction extends LiftedActionActionBase {
type: typeof LIFTED_ACTION;
message: 'ACTION';
action: string | CustomAction;
}
-interface LiftedActionExportAction extends LiftedActionActionBase {
+export interface LiftedActionExportAction extends LiftedActionActionBase {
type: typeof LIFTED_ACTION;
message: 'EXPORT';
toExport: boolean;
@@ -192,15 +210,15 @@ export function liftedDispatch(
} as LiftedActionDispatchAction;
}
-interface SelectInstanceAction {
+export interface SelectInstanceAction {
type: typeof SELECT_INSTANCE;
- selected: string;
+ selected: string | number;
}
export function selectInstance(selected: string): SelectInstanceAction {
return { type: SELECT_INSTANCE, selected };
}
-interface SelectMonitorAction {
+export interface SelectMonitorAction {
type: typeof SELECT_MONITOR;
monitor: string;
monitorState?: MonitorStateMonitorState;
@@ -219,7 +237,7 @@ interface NextState {
subTabName: string;
inspectedStatePath?: string[];
}
-interface UpdateMonitorStateAction {
+export interface UpdateMonitorStateAction {
type: typeof UPDATE_MONITOR_STATE;
nextState: NextState;
}
@@ -240,7 +258,7 @@ export function importState(
return { type: LIFTED_ACTION, message: 'IMPORT', state, preloadedState };
}
-interface ExportAction {
+export interface ExportAction {
type: typeof EXPORT;
}
export function exportState(): ExportAction {
@@ -268,7 +286,7 @@ export function pauseRecording(status: boolean): LiftedActionDispatchAction {
export interface CustomAction {
name: string;
selected: number;
- args: (string | undefined)[];
+ args: string[];
rest: string;
}
export function dispatchRemotely(
@@ -277,28 +295,28 @@ export function dispatchRemotely(
return { type: LIFTED_ACTION, message: 'ACTION', action };
}
-interface TogglePersistAction {
+export interface TogglePersistAction {
type: typeof TOGGLE_PERSIST;
}
export function togglePersist(): TogglePersistAction {
return { type: TOGGLE_PERSIST };
}
-interface ToggleSyncAction {
+export interface ToggleSyncAction {
type: typeof TOGGLE_SYNC;
}
export function toggleSync(): ToggleSyncAction {
return { type: TOGGLE_SYNC };
}
-interface ToggleSliderAction {
+export interface ToggleSliderAction {
type: typeof TOGGLE_SLIDER;
}
export function toggleSlider(): ToggleSliderAction {
return { type: TOGGLE_SLIDER };
}
-interface ToggleDispatcherAction {
+export interface ToggleDispatcherAction {
type: typeof TOGGLE_DISPATCHER;
}
export function toggleDispatcher(): ToggleDispatcherAction {
@@ -312,7 +330,7 @@ export interface ConnectionOptions {
readonly port: number;
readonly secure: boolean;
}
-interface ReconnectAction {
+export interface ReconnectAction {
readonly type: typeof RECONNECT;
readonly options: ConnectionOptions;
}
@@ -326,7 +344,7 @@ interface Notification {
readonly type: 'error';
readonly message: string;
}
-interface ShowNotificationAction {
+export interface ShowNotificationAction {
readonly type: typeof SHOW_NOTIFICATION;
readonly notification: Notification;
}
@@ -334,14 +352,14 @@ export function showNotification(message: string): ShowNotificationAction {
return { type: SHOW_NOTIFICATION, notification: { type: 'error', message } };
}
-interface ClearNotificationAction {
+export interface ClearNotificationAction {
readonly type: typeof CLEAR_NOTIFICATION;
}
export function clearNotification(): ClearNotificationAction {
return { type: CLEAR_NOTIFICATION };
}
-interface GetReportRequest {
+export interface GetReportRequest {
readonly type: typeof GET_REPORT_REQUEST;
readonly report: unknown;
}
@@ -354,7 +372,7 @@ export interface ActionCreator {
name: string;
}
-interface LibConfig {
+export interface LibConfig {
actionCreators?: string;
name?: string;
type?: string;
@@ -363,10 +381,10 @@ interface LibConfig {
}
export interface RequestBase {
- id: string;
- instanceId?: string;
+ id?: string;
+ instanceId?: string | number;
action?: string;
- name?: string;
+ name?: string | undefined;
libConfig?: LibConfig;
actionsById?: string;
computedStates?: string;
@@ -376,14 +394,15 @@ export interface RequestBase {
}
interface InitRequest extends RequestBase {
type: 'INIT';
- action: string;
+ action?: string;
+ payload?: string;
}
interface ActionRequest extends RequestBase {
type: 'ACTION';
- isExcess: boolean;
+ isExcess?: boolean;
nextActionId: number;
maxAge: number;
- batched: boolean;
+ batched?: boolean;
}
interface StateRequest extends RequestBase {
type: 'STATE';
@@ -409,23 +428,23 @@ export type Request =
| LiftedRequest
| ExportRequest;
-interface UpdateStateAction {
+export interface UpdateStateAction {
type: typeof UPDATE_STATE;
request?: Request;
- id?: string;
+ id?: string | number;
}
-interface SetStateAction {
+export interface SetStateAction {
type: typeof SET_STATE;
newState: State;
}
-interface RemoveInstanceAction {
+export interface RemoveInstanceAction {
type: typeof REMOVE_INSTANCE;
- id: string;
+ id: string | number;
}
-interface ConnectRequestAction {
+export interface ConnectRequestAction {
type: typeof CONNECT_REQUEST;
options: ConnectionOptions;
}
@@ -435,58 +454,58 @@ interface ConnectSuccessPayload {
authState: AuthStates;
socketState: States;
}
-interface ConnectSuccessAction {
+export interface ConnectSuccessAction {
type: typeof CONNECT_SUCCESS;
payload: ConnectSuccessPayload;
error: Error | undefined;
}
-interface ConnectErrorAction {
+export interface ConnectErrorAction {
type: typeof CONNECT_ERROR;
error: Error | undefined;
}
-interface AuthRequestAction {
+export interface AuthRequestAction {
type: typeof AUTH_REQUEST;
}
-interface AuthSuccessAction {
+export interface AuthSuccessAction {
type: typeof AUTH_SUCCESS;
baseChannel: string;
}
-interface AuthErrorAction {
+export interface AuthErrorAction {
type: typeof AUTH_ERROR;
error: Error;
}
-interface DisconnectedAction {
+export interface DisconnectedAction {
type: typeof DISCONNECTED;
code: number;
}
-interface DeauthenticateAction {
+export interface DeauthenticateAction {
type: typeof DEAUTHENTICATE;
}
-interface SubscribeRequestAction {
+export interface SubscribeRequestAction {
type: typeof SUBSCRIBE_REQUEST;
channel: string;
subscription: typeof UPDATE_STATE | typeof UPDATE_REPORTS;
}
-interface SubscribeSuccessAction {
+export interface SubscribeSuccessAction {
type: typeof SUBSCRIBE_SUCCESS;
channel: string;
}
-interface SubscribeErrorAction {
+export interface SubscribeErrorAction {
type: typeof SUBSCRIBE_ERROR;
error: Error;
status: string;
}
-interface UnsubscribeAction {
+export interface UnsubscribeAction {
type: typeof UNSUBSCRIBE;
channel: string;
}
@@ -494,8 +513,8 @@ interface UnsubscribeAction {
export interface EmitAction {
type: typeof EMIT;
message: string;
- id?: string | false;
- instanceId?: string;
+ id?: string | number | false;
+ instanceId?: string | number;
action?: unknown;
state?: unknown;
}
@@ -514,31 +533,30 @@ interface RemoveRequest {
id: unknown;
}
export type UpdateReportsRequest = ListRequest | AddRequest | RemoveRequest;
-interface UpdateReportsAction {
+export interface UpdateReportsAction {
type: typeof UPDATE_REPORTS;
request: UpdateReportsRequest;
}
-interface GetReportError {
+export interface GetReportError {
type: typeof GET_REPORT_ERROR;
error: Error;
}
-interface GetReportSuccess {
+export interface GetReportSuccess {
type: typeof GET_REPORT_SUCCESS;
data: { payload: string };
}
-interface ErrorAction {
+export interface ErrorAction {
type: typeof ERROR;
payload: string;
}
-export type StoreAction =
+export type StoreActionWithoutUpdateStateOrLiftedAction =
| ChangeSectionAction
| ChangeThemeAction
| MonitorActionAction
- | LiftedActionAction
| SelectInstanceAction
| SelectMonitorAction
| UpdateMonitorStateAction
@@ -552,7 +570,6 @@ export type StoreAction =
| ClearNotificationAction
| GetReportRequest
| SetStateAction
- | UpdateStateAction
| RemoveInstanceAction
| ConnectRequestAction
| ConnectSuccessAction
@@ -571,3 +588,13 @@ export type StoreAction =
| GetReportError
| GetReportSuccess
| ErrorAction;
+
+export type StoreActionWithoutUpdateState =
+ | StoreActionWithoutUpdateStateOrLiftedAction
+ | LiftedActionAction;
+
+export type StoreActionWithoutLiftedAction =
+ | StoreActionWithoutUpdateStateOrLiftedAction
+ | UpdateStateAction;
+
+export type StoreAction = StoreActionWithoutUpdateState | UpdateStateAction;
diff --git a/packages/redux-devtools-app/src/components/InstanceSelector.tsx b/packages/redux-devtools-app/src/components/InstanceSelector.tsx
index 357351b7..81680a38 100644
--- a/packages/redux-devtools-app/src/components/InstanceSelector.tsx
+++ b/packages/redux-devtools-app/src/components/InstanceSelector.tsx
@@ -9,7 +9,7 @@ type DispatchProps = ResolveThunks;
type Props = StateProps & DispatchProps;
class InstanceSelector extends Component {
- select?: { readonly value: string; readonly label: string }[];
+ select?: { readonly value: string; readonly label: string | number }[];
render() {
this.select = [{ value: '', label: 'Autoselect instances' }];
diff --git a/packages/redux-devtools-app/src/containers/monitors/Dispatcher.tsx b/packages/redux-devtools-app/src/containers/monitors/Dispatcher.tsx
index 63ed71e5..4a6a1746 100644
--- a/packages/redux-devtools-app/src/containers/monitors/Dispatcher.tsx
+++ b/packages/redux-devtools-app/src/containers/monitors/Dispatcher.tsx
@@ -55,7 +55,7 @@ type Props = DispatchProps & OwnProps;
interface State {
selected: 'default' | number;
customAction: string;
- args: (string | undefined)[];
+ args: string[];
rest: string;
changed: boolean;
}
@@ -108,7 +108,7 @@ class Dispatcher extends Component {
handleArg = (argIndex: number) => (value: string) => {
const args = [
...this.state.args.slice(0, argIndex),
- value || undefined,
+ (value || undefined)!,
...this.state.args.slice(argIndex + 1),
];
this.setState({ args, changed: true });
diff --git a/packages/redux-devtools-app/src/middlewares/api.ts b/packages/redux-devtools-app/src/middlewares/api.ts
index 2b135369..f5c29ae1 100644
--- a/packages/redux-devtools-app/src/middlewares/api.ts
+++ b/packages/redux-devtools-app/src/middlewares/api.ts
@@ -30,7 +30,7 @@ let socket: SCClientSocket;
let store: MiddlewareAPI, StoreState>;
function emit({ message: type, id, instanceId, action, state }: EmitAction) {
- socket.emit(id ? 'sc-' + id : 'respond', { type, action, state, instanceId });
+ socket.emit(id ? `sc-${id}` : 'respond', { type, action, state, instanceId });
}
function startMonitoring(channel: string) {
diff --git a/packages/redux-devtools-app/src/middlewares/exportState.ts b/packages/redux-devtools-app/src/middlewares/exportState.ts
index 40e9cd0a..ffefe851 100644
--- a/packages/redux-devtools-app/src/middlewares/exportState.ts
+++ b/packages/redux-devtools-app/src/middlewares/exportState.ts
@@ -5,7 +5,7 @@ import { Dispatch, MiddlewareAPI } from 'redux';
import { ExportRequest, StoreAction } from '../actions';
import { StoreState } from '../reducers';
-let toExport: string | undefined;
+let toExport: string | number | undefined;
function download(state: string) {
const blob = new Blob([state], { type: 'octet/stream' });
diff --git a/packages/redux-devtools-app/src/reducers/instances.ts b/packages/redux-devtools-app/src/reducers/instances.ts
index 9b2aa01e..cbc3fc00 100644
--- a/packages/redux-devtools-app/src/reducers/instances.ts
+++ b/packages/redux-devtools-app/src/reducers/instances.ts
@@ -34,8 +34,8 @@ export interface Features {
}
export interface Options {
- name?: string;
- connectionId?: string;
+ name?: string | number;
+ connectionId?: string | number;
explicitLib?: string;
lib?: string;
actionCreators?: ActionCreator[];
@@ -56,10 +56,10 @@ export interface State {
}
export interface InstancesState {
- selected: string | null;
- current: string;
+ selected: string | number | null;
+ current: string | number;
sync: boolean;
- connections: { [id: string]: string[] };
+ connections: { [id: string]: (string | number)[] };
options: { [id: string]: Options };
states: { [id: string]: State };
persisted?: boolean;
@@ -86,7 +86,7 @@ export const initialState: InstancesState = {
function updateState(
state: { [id: string]: State },
request: Request,
- id: string,
+ id: string | number,
serialize: boolean | undefined
) {
let payload: State = request.payload as State;
@@ -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;
@@ -268,8 +268,8 @@ function removeState(state: InstancesState, connectionId: string) {
function init(
{ type, action, name, libConfig = {} }: Request,
- connectionId: string,
- current: string
+ connectionId: string | number,
+ current: string | number
): Options {
let lib;
let actionCreators;
@@ -310,7 +310,7 @@ export default function instances(
case UPDATE_STATE: {
const { request } = action;
if (!request) return state;
- const connectionId = action.id || request.id;
+ const connectionId = (action.id || request.id)!;
const current = request.instanceId || connectionId;
let connections = state.connections;
let options = state.options;
diff --git a/packages/redux-devtools-app/src/reducers/monitor.ts b/packages/redux-devtools-app/src/reducers/monitor.ts
index 8293d847..be478fb1 100644
--- a/packages/redux-devtools-app/src/reducers/monitor.ts
+++ b/packages/redux-devtools-app/src/reducers/monitor.ts
@@ -18,7 +18,7 @@ export interface MonitorStateMonitorState {
}
export interface MonitorState {
selected: string;
- monitorState: MonitorStateMonitorState | undefined;
+ monitorState?: MonitorStateMonitorState | undefined;
sliderIsOpen: boolean;
dispatcherIsOpen: boolean;
}
diff --git a/packages/redux-devtools-app/src/utils/monitorActions.ts b/packages/redux-devtools-app/src/utils/monitorActions.ts
index 1e5fc604..d2832bd9 100644
--- a/packages/redux-devtools-app/src/utils/monitorActions.ts
+++ b/packages/redux-devtools-app/src/utils/monitorActions.ts
@@ -4,8 +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 { StoreState } from '../reducers';
+import { DispatchAction, StoreActionWithoutLiftedAction } from '../actions';
export function sweep(state: State): State {
return {
@@ -21,12 +20,15 @@ export function sweep(state: State): State {
}
export function nonReduxDispatch(
- store: MiddlewareAPI, StoreState>,
+ store: MiddlewareAPI<
+ Dispatch,
+ { readonly instances: InstancesState }
+ >,
message: string,
- instanceId: string,
+ instanceId: string | number,
action: DispatchAction,
initialState: string | undefined,
- preInstances: InstancesState
+ preInstances?: InstancesState
) {
const instances = preInstances || store.getState().instances;
const state = instances.states[instanceId];
diff --git a/packages/redux-devtools-inspector-monitor-test-tab/package.json b/packages/redux-devtools-inspector-monitor-test-tab/package.json
index 4de697fe..6d529f82 100644
--- a/packages/redux-devtools-inspector-monitor-test-tab/package.json
+++ b/packages/redux-devtools-inspector-monitor-test-tab/package.json
@@ -59,7 +59,7 @@
"@redux-devtools/inspector-monitor": "^1.0.0",
"@types/es6template": "^1.0.0",
"@types/history": "^4.7.8",
- "@types/jsan": "^3.1.0",
+ "@types/jsan": "^3.1.2",
"@types/lodash.shuffle": "^4.2.6",
"@types/object-path": "^0.11.0",
"@types/react": "^16.14.8",
diff --git a/packages/redux-devtools-inspector-monitor-trace-tab/package.json b/packages/redux-devtools-inspector-monitor-trace-tab/package.json
index 9a1efda3..299d2ec2 100644
--- a/packages/redux-devtools-inspector-monitor-trace-tab/package.json
+++ b/packages/redux-devtools-inspector-monitor-trace-tab/package.json
@@ -29,7 +29,7 @@
},
"dependencies": {
"@babel/code-frame": "^7.14.5",
- "@types/chrome": "^0.0.124",
+ "@types/chrome": "^0.0.145",
"anser": "^1.4.10",
"html-entities": "^1.4.0",
"redux-devtools-themes": "^1.0.0",
diff --git a/packages/redux-devtools-inspector-monitor-trace-tab/src/openFile.ts b/packages/redux-devtools-inspector-monitor-trace-tab/src/openFile.ts
index aa8e22f5..a542fa40 100644
--- a/packages/redux-devtools-inspector-monitor-trace-tab/src/openFile.ts
+++ b/packages/redux-devtools-inspector-monitor-trace-tab/src/openFile.ts
@@ -32,11 +32,11 @@ function openAndCloseTab(url: string) {
const removeTab = () => {
chrome.windows.onFocusChanged.removeListener(removeTab);
if (tab && tab.id) {
- chrome.tabs.remove(tab.id, () => {
+ chrome.tabs.remove(tab.id, async () => {
// eslint-disable-next-line no-console
if (chrome.runtime.lastError) console.log(chrome.runtime.lastError);
else if (chrome.devtools && chrome.devtools.inspectedWindow) {
- chrome.tabs.update(chrome.devtools.inspectedWindow.tabId, {
+ await chrome.tabs.update(chrome.devtools.inspectedWindow.tabId, {
active: true,
});
}
diff --git a/packages/redux-devtools-instrument/src/instrument.ts b/packages/redux-devtools-instrument/src/instrument.ts
index 4f6d35aa..91a7772f 100644
--- a/packages/redux-devtools-instrument/src/instrument.ts
+++ b/packages/redux-devtools-instrument/src/instrument.ts
@@ -100,7 +100,7 @@ interface ImportStateAction, MonitorState> {
type: typeof ActionTypes.IMPORT_STATE;
nextLiftedState: LiftedState | readonly A[];
preloadedState?: S;
- noRecompute: boolean | undefined;
+ noRecompute?: boolean | undefined;
}
interface LockChangesAction {
diff --git a/packages/redux-devtools-serialize/package.json b/packages/redux-devtools-serialize/package.json
index ebca64f5..84d9120b 100644
--- a/packages/redux-devtools-serialize/package.json
+++ b/packages/redux-devtools-serialize/package.json
@@ -35,7 +35,7 @@
"jsan": "^3.1.13"
},
"devDependencies": {
- "@types/jsan": "^3.1.0",
+ "@types/jsan": "^3.1.2",
"immutable": "^4.0.0-rc.12"
},
"peerDependencies": {
diff --git a/packages/redux-devtools-utils/src/index.ts b/packages/redux-devtools-utils/src/index.ts
index fd4ab9fc..b4af6b8a 100644
--- a/packages/redux-devtools-utils/src/index.ts
+++ b/packages/redux-devtools-utils/src/index.ts
@@ -3,22 +3,24 @@ import jsan from 'jsan';
import { nanoid } from 'nanoid/non-secure';
import { immutableSerialize } from '@redux-devtools/serialize';
import Immutable from 'immutable';
-import { Action } from 'redux';
+import { Action, ActionCreator } from 'redux';
export function generateId(id: string | undefined) {
return id || nanoid(7);
}
+export interface ActionCreatorObject {
+ readonly name: string;
+ readonly func: ActionCreator>;
+ readonly args: readonly string[];
+}
+
// eslint-disable-next-line @typescript-eslint/ban-types
function flatTree(
- obj: { [key: string]: (...args: any[]) => unknown },
+ obj: { [key: string]: ActionCreator> },
namespace = ''
) {
- let functions: {
- name: string;
- func: (...args: any[]) => unknown;
- args: string[];
- }[] = [];
+ let functions: ActionCreatorObject[] = [];
Object.keys(obj).forEach((key) => {
const prop = obj[key];
if (typeof prop === 'function') {
@@ -63,7 +65,7 @@ export function getMethods(obj: unknown) {
}
export function getActionsArray(actionCreators: {
- [key: string]: (...args: any[]) => unknown;
+ [key: string]: ActionCreator>;
}) {
if (Array.isArray(actionCreators)) return actionCreators;
return flatTree(actionCreators);
@@ -81,10 +83,8 @@ function evalArgs(inArgs: string[], restArgs: string) {
}
export function evalAction(
- action: string | { args: string[]; rest: string; selected: string },
- actionCreators: {
- [selected: string]: { func: (...args: any[]) => Action };
- }
+ action: string | { args: string[]; rest: string; selected: number },
+ actionCreators: readonly ActionCreatorObject[]
) {
if (typeof action === 'string') {
// eslint-disable-next-line @typescript-eslint/no-implied-eval
diff --git a/yarn.lock b/yarn.lock
index 90a9dbce..83bb3385 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3520,7 +3520,7 @@ __metadata:
"@redux-devtools/inspector-monitor": ^1.0.0
"@types/es6template": ^1.0.0
"@types/history": ^4.7.8
- "@types/jsan": ^3.1.0
+ "@types/jsan": ^3.1.2
"@types/lodash.shuffle": ^4.2.6
"@types/object-path": ^0.11.0
"@types/prop-types": ^15.7.3
@@ -3567,7 +3567,7 @@ __metadata:
"@redux-devtools/core": ^3.9.0
"@redux-devtools/inspector-monitor": ^1.0.0
"@types/babel__code-frame": ^7.0.2
- "@types/chrome": ^0.0.124
+ "@types/chrome": ^0.0.145
"@types/enzyme": ^3.10.8
"@types/enzyme-adapter-react-16": ^1.0.6
"@types/html-entities": ^1.3.4
@@ -3682,7 +3682,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@redux-devtools/serialize@workspace:packages/redux-devtools-serialize"
dependencies:
- "@types/jsan": ^3.1.0
+ "@types/jsan": ^3.1.2
immutable: ^4.0.0-rc.12
jsan: ^3.1.13
peerDependencies:
@@ -4825,13 +4825,13 @@ __metadata:
languageName: node
linkType: hard
-"@types/chrome@npm:^0.0.124":
- version: 0.0.124
- resolution: "@types/chrome@npm:0.0.124"
+"@types/chrome@npm:^0.0.145":
+ version: 0.0.145
+ resolution: "@types/chrome@npm:0.0.145"
dependencies:
"@types/filesystem": "*"
"@types/har-format": "*"
- checksum: 6499edca5f608dd48651b20d57d9fb30bbcb02cd695cd94d879a11dba7b9492c618edc6b8b5f718e82b58eceea94fb920c871546c2c3bc867595cb7dd020d527
+ checksum: f826d0a071ac7ea68aa97b2f8e34a944c470fbd036fdd6a413987fea03062d354fb14708cc0b59693b4a78ec88f9c5b1fce0c622a8e29e3e4b0917509eaf2a1a
languageName: node
linkType: hard
@@ -5246,10 +5246,10 @@ __metadata:
languageName: node
linkType: hard
-"@types/jsan@npm:^3.1.0":
- version: 3.1.0
- resolution: "@types/jsan@npm:3.1.0"
- checksum: a0670d90e4bee7110504be73eefff9196b46235faf490062865136b1cbad4d3bac2adb9303e308c523f07716c026bb8e72a12ae7d47a948424d4ca4d7883587d
+"@types/jsan@npm:^3.1.2":
+ version: 3.1.2
+ resolution: "@types/jsan@npm:3.1.2"
+ checksum: 2ff652807d6067bbc650aaefcda4e3c07b54ddfd7d72283d7c1f1892ad1e18e907b1bbdbee7d0a163efa9e8aed9af5fa9f4ed8e2f27243c46383d31e1181fc11
languageName: node
linkType: hard
@@ -23231,6 +23231,7 @@ fsevents@^1.2.7:
"@redux-devtools/serialize": ^0.3.0
"@redux-devtools/slider-monitor": ^2.0.0-8
"@redux-devtools/utils": ^1.0.0-6
+ "@types/jsan": ^3.1.2
bestzip: ^2.2.0
chromedriver: ^91.0.1
electron: ^13.1.2