mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-26 07:59:48 +03:00
Define ContentScriptToPageScriptMessage
This commit is contained in:
parent
eb35441e17
commit
d23bf68b15
|
@ -8,6 +8,7 @@ import generateId from './generateInstanceId';
|
|||
import { Config } from '../../browser/extension/inject/pageScript';
|
||||
import { Action } from 'redux';
|
||||
import { LiftedState, PerformAction } from '@redux-devtools/instrument';
|
||||
import { LibConfig } from '@redux-devtools/app/lib/actions';
|
||||
|
||||
const listeners = {};
|
||||
export const source = '@devtools-page';
|
||||
|
@ -125,7 +126,7 @@ interface InitMessage<S, A extends Action<unknown>> {
|
|||
action?: string;
|
||||
name?: string | undefined;
|
||||
liftedState?: LiftedState<S, A, unknown>;
|
||||
libConfig?: unknown;
|
||||
libConfig?: LibConfig;
|
||||
}
|
||||
|
||||
interface SerializedPartialLiftedState<S, A extends Action<unknown>> {
|
||||
|
@ -171,17 +172,15 @@ interface SerializedStateMessage<S, A extends Action<unknown>> {
|
|||
>;
|
||||
readonly source: typeof source;
|
||||
readonly instanceId: number;
|
||||
readonly libConfig?: unknown;
|
||||
readonly libConfig?: LibConfig;
|
||||
readonly actionsById: string;
|
||||
readonly computedStates: string;
|
||||
readonly committedState: boolean;
|
||||
}
|
||||
|
||||
export type PageScriptToContentScriptMessageWithoutDisconnect<
|
||||
export type PageScriptToContentScriptMessageWithoutDisconnectOrInitInstance<
|
||||
S,
|
||||
A extends Action<unknown>
|
||||
> =
|
||||
| InitInstancePageScriptToContentScriptMessage
|
||||
| InitMessage<S, A>
|
||||
| LiftedMessage
|
||||
| SerializedPartialStateMessage<S, A>
|
||||
|
@ -193,6 +192,13 @@ export type PageScriptToContentScriptMessageWithoutDisconnect<
|
|||
| GetReportMessage
|
||||
| StopMessage;
|
||||
|
||||
export type PageScriptToContentScriptMessageWithoutDisconnect<
|
||||
S,
|
||||
A extends Action<unknown>
|
||||
> =
|
||||
| PageScriptToContentScriptMessageWithoutDisconnectOrInitInstance<S, A>
|
||||
| InitInstancePageScriptToContentScriptMessage;
|
||||
|
||||
export type PageScriptToContentScriptMessage<S, A extends Action<unknown>> =
|
||||
| PageScriptToContentScriptMessageWithoutDisconnect<S, A>
|
||||
| DisconnectMessage;
|
||||
|
@ -258,7 +264,7 @@ function amendActionType(
|
|||
|
||||
export interface LiftedMessage {
|
||||
readonly type: 'LIFTED';
|
||||
readonly liftedState: { readonly isPaused: boolean };
|
||||
readonly liftedState: { readonly isPaused: boolean | undefined };
|
||||
readonly instanceId: number;
|
||||
readonly source: typeof source;
|
||||
}
|
||||
|
@ -294,7 +300,7 @@ interface StateMessage<S, A extends Action<unknown>> {
|
|||
readonly payload: LiftedState<S, A, unknown>;
|
||||
readonly source: typeof source;
|
||||
readonly instanceId: number;
|
||||
readonly libConfig?: unknown;
|
||||
readonly libConfig?: LibConfig;
|
||||
}
|
||||
|
||||
interface ErrorMessage {
|
||||
|
@ -447,7 +453,7 @@ export function disconnect() {
|
|||
post({ type: 'DISCONNECT', source });
|
||||
}
|
||||
|
||||
export function connect(preConfig) {
|
||||
export function connect(preConfig: Config) {
|
||||
const config = preConfig || {};
|
||||
const id = generateId(config.instanceId);
|
||||
if (!config.instanceId) config.instanceId = id;
|
||||
|
|
|
@ -6,20 +6,65 @@ import {
|
|||
} from '@redux-devtools/app/lib/constants/actionTypes';
|
||||
import { nonReduxDispatch } from '@redux-devtools/app/lib/utils/monitorActions';
|
||||
import syncOptions, {
|
||||
Options,
|
||||
OptionsMessage,
|
||||
SyncOptions,
|
||||
} from '../../browser/extension/options/syncOptions';
|
||||
import openDevToolsWindow from '../../browser/extension/background/openWindow';
|
||||
import { getReport } from '../../browser/extension/background/logging';
|
||||
import { StoreAction } from '@redux-devtools/app/lib/actions';
|
||||
import { Dispatch } from 'redux';
|
||||
import {
|
||||
CustomAction,
|
||||
DispatchAction as AppDispatchAction,
|
||||
LiftedActionAction,
|
||||
StoreAction,
|
||||
} from '@redux-devtools/app/lib/actions';
|
||||
import { Action, Dispatch } from 'redux';
|
||||
import { ContentScriptToBackgroundMessage } from '../../browser/extension/inject/contentScript';
|
||||
|
||||
interface StartAction {
|
||||
readonly type: 'START';
|
||||
interface TabMessageBase {
|
||||
readonly type: string;
|
||||
readonly state?: string | undefined;
|
||||
readonly id?: string;
|
||||
}
|
||||
|
||||
interface StopAction {
|
||||
interface StartAction extends TabMessageBase {
|
||||
readonly type: 'START';
|
||||
readonly state: never;
|
||||
readonly id: never;
|
||||
}
|
||||
|
||||
interface StopAction extends TabMessageBase {
|
||||
readonly type: 'STOP';
|
||||
readonly state: never;
|
||||
readonly id: never;
|
||||
}
|
||||
|
||||
interface DispatchAction extends TabMessageBase {
|
||||
readonly type: 'DISPATCH';
|
||||
readonly action: AppDispatchAction;
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
interface ImportAction extends TabMessageBase {
|
||||
readonly type: 'IMPORT';
|
||||
readonly action: undefined;
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
interface ActionAction extends TabMessageBase {
|
||||
readonly type: 'ACTION';
|
||||
readonly action: string | CustomAction;
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
interface ExportAction extends TabMessageBase {
|
||||
readonly type: 'EXPORT';
|
||||
readonly action: undefined;
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
interface NAAction {
|
||||
|
@ -31,7 +76,14 @@ interface UpdateStateAction {
|
|||
readonly type: typeof UPDATE_STATE;
|
||||
}
|
||||
|
||||
export type TabMessage = StartAction | StopAction | OptionsMessage;
|
||||
export type TabMessage =
|
||||
| StartAction
|
||||
| StopAction
|
||||
| OptionsMessage
|
||||
| DispatchAction
|
||||
| ImportAction
|
||||
| ActionAction
|
||||
| ExportAction;
|
||||
type PanelMessage = NAAction;
|
||||
type MonitorMessage = UpdateStateAction;
|
||||
|
||||
|
@ -87,7 +139,7 @@ interface ImportMessage {
|
|||
readonly state: string;
|
||||
}
|
||||
|
||||
type ToContentScriptMessage = ImportMessage;
|
||||
type ToContentScriptMessage = ImportMessage | LiftedActionAction;
|
||||
|
||||
function toContentScript({
|
||||
message,
|
||||
|
@ -144,13 +196,13 @@ function togglePersist() {
|
|||
}
|
||||
|
||||
type BackgroundStoreMessage = unknown;
|
||||
type BackgroundStoreResponse = never;
|
||||
type BackgroundStoreResponse = { readonly options: Options };
|
||||
|
||||
// Receive messages from content scripts
|
||||
function messaging(
|
||||
request: BackgroundStoreMessage,
|
||||
sender: chrome.runtime.MessageSender,
|
||||
sendResponse: (response?: BackgroundStoreResponse) => void
|
||||
sendResponse?: (response?: BackgroundStoreResponse) => void
|
||||
) {
|
||||
let tabId = getId(sender);
|
||||
if (!tabId) return;
|
||||
|
@ -168,7 +220,7 @@ function messaging(
|
|||
}
|
||||
if (request.type === 'GET_OPTIONS') {
|
||||
window.syncOptions.get((options) => {
|
||||
sendResponse({ options });
|
||||
sendResponse!({ options });
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -256,7 +308,7 @@ function disconnect(
|
|||
};
|
||||
}
|
||||
|
||||
function onConnect(port: chrome.runtime.Port) {
|
||||
function onConnect<S, A extends Action<unknown>>(port: chrome.runtime.Port) {
|
||||
let id: number | string;
|
||||
let listener;
|
||||
|
||||
|
@ -266,7 +318,7 @@ function onConnect(port: chrome.runtime.Port) {
|
|||
id = getId(port.sender!);
|
||||
if (port.sender!.frameId) id = `${id}-${port.sender!.frameId}`;
|
||||
connections.tab[id] = port;
|
||||
listener = (msg) => {
|
||||
listener = (msg: ContentScriptToBackgroundMessage<S, A>) => {
|
||||
if (msg.name === 'INIT_INSTANCE') {
|
||||
if (typeof id === 'number') {
|
||||
chrome.pageAction.show(id);
|
||||
|
@ -292,7 +344,7 @@ function onConnect(port: chrome.runtime.Port) {
|
|||
return;
|
||||
}
|
||||
if (msg.name === 'RELAY') {
|
||||
messaging(msg.message, port.sender!, id);
|
||||
messaging(msg.message, port.sender!);
|
||||
}
|
||||
};
|
||||
port.onMessage.addListener(listener);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Action } from 'redux';
|
||||
import { LiftedState } from '@redux-devtools/instrument';
|
||||
import { StoreAction } from '@redux-devtools/app/lib/actions';
|
||||
import { LibConfig, StoreAction } from '@redux-devtools/app/lib/actions';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -11,7 +11,7 @@ declare global {
|
|||
export default class Monitor<S, A extends Action<unknown>> {
|
||||
update: (
|
||||
liftedState?: LiftedState<S, A, unknown> | undefined,
|
||||
libConfig?: unknown
|
||||
libConfig?: LibConfig
|
||||
) => void;
|
||||
active?: boolean;
|
||||
paused?: boolean;
|
||||
|
@ -19,7 +19,7 @@ export default class Monitor<S, A extends Action<unknown>> {
|
|||
constructor(
|
||||
update: (
|
||||
liftedState?: LiftedState<S, A, unknown> | undefined,
|
||||
libConfig?: unknown
|
||||
libConfig?: LibConfig
|
||||
) => void
|
||||
) {
|
||||
this.update = update;
|
||||
|
|
|
@ -7,8 +7,13 @@ import { TabMessage } from '../../../app/middlewares/api';
|
|||
import {
|
||||
PageScriptToContentScriptMessage,
|
||||
PageScriptToContentScriptMessageWithoutDisconnect,
|
||||
PageScriptToContentScriptMessageWithoutDisconnectOrInitInstance,
|
||||
} from '../../../app/api';
|
||||
import { Action } from 'redux';
|
||||
import {
|
||||
CustomAction,
|
||||
DispatchAction as AppDispatchAction,
|
||||
} from '@redux-devtools/app/lib/actions';
|
||||
const source = '@devtools-extension';
|
||||
const pageSource = '@devtools-page';
|
||||
// Chrome message limit is 64 MB, but we're using 32 MB to include other object's parts
|
||||
|
@ -22,6 +27,73 @@ declare global {
|
|||
}
|
||||
}
|
||||
|
||||
interface StartAction {
|
||||
readonly type: 'START';
|
||||
readonly state: undefined;
|
||||
readonly id: undefined;
|
||||
readonly source: typeof source;
|
||||
}
|
||||
|
||||
interface StopAction {
|
||||
readonly type: 'STOP';
|
||||
readonly state: undefined;
|
||||
readonly id: undefined;
|
||||
readonly source: typeof source;
|
||||
readonly failed?: boolean;
|
||||
}
|
||||
|
||||
interface DispatchAction {
|
||||
readonly type: 'DISPATCH';
|
||||
readonly payload: AppDispatchAction;
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
readonly source: typeof source;
|
||||
}
|
||||
|
||||
interface ImportAction {
|
||||
readonly type: 'IMPORT';
|
||||
readonly payload: undefined;
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
readonly source: typeof source;
|
||||
}
|
||||
|
||||
interface ActionAction {
|
||||
readonly type: 'ACTION';
|
||||
readonly payload: string | CustomAction;
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
readonly source: typeof source;
|
||||
}
|
||||
|
||||
interface ExportAction {
|
||||
readonly type: 'EXPORT';
|
||||
readonly payload: undefined;
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
readonly source: typeof source;
|
||||
}
|
||||
|
||||
interface UpdateAction {
|
||||
readonly type: 'UPDATE';
|
||||
readonly state: string | undefined;
|
||||
readonly id: string;
|
||||
readonly source: typeof source;
|
||||
}
|
||||
|
||||
export type ContentScriptToPageScriptMessage =
|
||||
| StartAction
|
||||
| StopAction
|
||||
| DispatchAction
|
||||
| ImportAction
|
||||
| ActionAction
|
||||
| ExportAction
|
||||
| UpdateAction;
|
||||
|
||||
function postToPageScript(message: ContentScriptToPageScriptMessage) {
|
||||
window.postMessage(message, '*');
|
||||
}
|
||||
|
||||
function connect() {
|
||||
// Connect to the background script
|
||||
connected = true;
|
||||
|
@ -35,28 +107,40 @@ function connect() {
|
|||
// Relay background script messages to the page script
|
||||
bg.onMessage.addListener((message: TabMessage) => {
|
||||
if ('action' in message) {
|
||||
window.postMessage(
|
||||
{
|
||||
if (message.type === 'DISPATCH') {
|
||||
postToPageScript({
|
||||
type: message.type,
|
||||
payload: message.action,
|
||||
state: message.state,
|
||||
id: message.id,
|
||||
source,
|
||||
},
|
||||
'*'
|
||||
);
|
||||
} else if ('options' in message) {
|
||||
injectOptions(message.options);
|
||||
} else {
|
||||
window.postMessage(
|
||||
{
|
||||
});
|
||||
} else if (message.type === 'ACTION') {
|
||||
postToPageScript({
|
||||
type: message.type,
|
||||
payload: message.action,
|
||||
state: message.state,
|
||||
id: message.id,
|
||||
source,
|
||||
},
|
||||
'*'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
postToPageScript({
|
||||
type: message.type,
|
||||
payload: message.action,
|
||||
state: message.state,
|
||||
id: message.id,
|
||||
source,
|
||||
});
|
||||
}
|
||||
} else if ('options' in message) {
|
||||
injectOptions(message.options);
|
||||
} else {
|
||||
postToPageScript({
|
||||
type: message.type,
|
||||
state: message.state,
|
||||
id: message.id,
|
||||
source,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -93,7 +177,9 @@ interface SplitMessageEnd extends SplitMessageBase {
|
|||
type SplitMessage = SplitMessageStart | SplitMessageChunk | SplitMessageEnd;
|
||||
|
||||
function tryCatch<S, A extends Action<unknown>>(
|
||||
fn: (args: PageScriptToContentScriptMessage<S, A> | SplitMessage) => void,
|
||||
fn: (
|
||||
args: PageScriptToContentScriptMessageWithoutDisconnect<S, A> | SplitMessage
|
||||
) => void,
|
||||
args: PageScriptToContentScriptMessageWithoutDisconnect<S, A>
|
||||
) {
|
||||
try {
|
||||
|
@ -145,21 +231,27 @@ interface InitInstanceContentScriptToBackgroundMessage {
|
|||
readonly instanceId: number;
|
||||
}
|
||||
|
||||
interface RelayMessage {
|
||||
interface RelayMessage<S, A extends Action<unknown>> {
|
||||
readonly name: 'RELAY';
|
||||
readonly message: unknown;
|
||||
readonly message:
|
||||
| PageScriptToContentScriptMessageWithoutDisconnectOrInitInstance<S, A>
|
||||
| SplitMessage;
|
||||
}
|
||||
|
||||
export type ContentScriptToBackgroundMessage =
|
||||
export type ContentScriptToBackgroundMessage<S, A extends Action<unknown>> =
|
||||
| InitInstanceContentScriptToBackgroundMessage
|
||||
| RelayMessage;
|
||||
| RelayMessage<S, A>;
|
||||
|
||||
function postToBackground(message: ContentScriptToBackgroundMessage) {
|
||||
function postToBackground<S, A extends Action<unknown>>(
|
||||
message: ContentScriptToBackgroundMessage<S, A>
|
||||
) {
|
||||
bg!.postMessage(message);
|
||||
}
|
||||
|
||||
function send<S, A extends Action<unknown>>(
|
||||
message: PageScriptToContentScriptMessage<S, A> | SplitMessage
|
||||
message:
|
||||
| PageScriptToContentScriptMessageWithoutDisconnect<S, A>
|
||||
| SplitMessage
|
||||
) {
|
||||
if (!connected) connect();
|
||||
if (message.type === 'INIT_INSTANCE') {
|
||||
|
|
|
@ -41,6 +41,13 @@ import {
|
|||
LiftedState,
|
||||
PerformAction,
|
||||
} from '@redux-devtools/instrument';
|
||||
import {
|
||||
CustomAction,
|
||||
DispatchAction,
|
||||
LibConfig,
|
||||
} from '@redux-devtools/app/lib/actions';
|
||||
import { ContentScriptToPageScriptMessage } from './contentScript';
|
||||
import { Features } from '@redux-devtools/app/lib/reducers/instances';
|
||||
|
||||
const source = '@devtools-page';
|
||||
let stores: {
|
||||
|
@ -62,10 +69,10 @@ interface SerializeWithImmutable extends Serialize {
|
|||
}
|
||||
|
||||
export interface ConfigWithExpandedMaxAge {
|
||||
readonly instanceId?: number;
|
||||
instanceId?: number;
|
||||
readonly actionsBlacklist?: string | readonly string[];
|
||||
readonly actionsWhitelist?: string | readonly string[];
|
||||
readonly serialize?: boolean | SerializeWithImmutable;
|
||||
serialize?: boolean | SerializeWithImmutable;
|
||||
readonly serializeState?:
|
||||
| boolean
|
||||
| ((key: string, value: unknown) => unknown)
|
||||
|
@ -107,7 +114,9 @@ export interface ConfigWithExpandedMaxAge {
|
|||
readonly pauseActionType?: unknown;
|
||||
readonly deserializeState?: <S>(state: S) => S;
|
||||
readonly deserializeAction?: <A extends Action<unknown>>(action: A) => A;
|
||||
readonly name?: string;
|
||||
name?: string;
|
||||
readonly autoPause?: boolean;
|
||||
readonly features?: Features;
|
||||
}
|
||||
|
||||
export interface Config extends ConfigWithExpandedMaxAge {
|
||||
|
@ -182,7 +191,7 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<unknown>>(
|
|||
const relayState = throttle(
|
||||
(
|
||||
liftedState?: LiftedState<S, A, unknown> | undefined,
|
||||
libConfig?: unknown
|
||||
libConfig?: LibConfig
|
||||
) => {
|
||||
relayAction.cancel();
|
||||
const state = liftedState || store.liftedStore.getState();
|
||||
|
@ -328,8 +337,8 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<unknown>>(
|
|||
);
|
||||
}, latency);
|
||||
|
||||
function dispatchRemotely(action) {
|
||||
if (config.features && !config.features.dispatch) return;
|
||||
function dispatchRemotely(action: string | CustomAction) {
|
||||
if (config!.features && !config!.features.dispatch) return;
|
||||
try {
|
||||
const result = evalAction(action, actionCreators);
|
||||
(store.initialDispatch || store.dispatch)(result);
|
||||
|
@ -367,7 +376,7 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<unknown>>(
|
|||
}
|
||||
}
|
||||
|
||||
function dispatchMonitorAction(action) {
|
||||
function dispatchMonitorAction(action: DispatchAction) {
|
||||
const type = action.type;
|
||||
const features = config.features;
|
||||
if (features) {
|
||||
|
@ -393,7 +402,7 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<unknown>>(
|
|||
store.liftedStore.dispatch(action);
|
||||
}
|
||||
|
||||
function onMessage(message) {
|
||||
function onMessage(message: ContentScriptToPageScriptMessage) {
|
||||
switch (message.type) {
|
||||
case 'DISPATCH':
|
||||
dispatchMonitorAction(message.payload);
|
||||
|
@ -416,10 +425,10 @@ function __REDUX_DEVTOOLS_EXTENSION__<S, A extends Action<unknown>>(
|
|||
actionCreators = getActionsArray(config.actionCreators);
|
||||
}
|
||||
relayState(undefined, {
|
||||
name: config.name || document.title,
|
||||
name: config!.name || document.title,
|
||||
actionCreators: JSON.stringify(actionCreators),
|
||||
features: config.features,
|
||||
serialize: !!config.serialize,
|
||||
features: config!.features,
|
||||
serialize: !!config!.serialize,
|
||||
type: 'redux',
|
||||
});
|
||||
|
||||
|
|
|
@ -268,7 +268,7 @@ export function pauseRecording(status: boolean): LiftedActionDispatchAction {
|
|||
export interface CustomAction {
|
||||
name: string;
|
||||
selected: number;
|
||||
args: (string | undefined)[];
|
||||
args: string[];
|
||||
rest: string;
|
||||
}
|
||||
export function dispatchRemotely(
|
||||
|
@ -354,7 +354,7 @@ export interface ActionCreator {
|
|||
name: string;
|
||||
}
|
||||
|
||||
interface LibConfig {
|
||||
export interface LibConfig {
|
||||
actionCreators?: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
|
|
|
@ -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<Props, State> {
|
|||
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 });
|
||||
|
|
|
@ -26,7 +26,7 @@ export function nonReduxDispatch(
|
|||
instanceId: string,
|
||||
action: DispatchAction,
|
||||
initialState: string | undefined,
|
||||
preInstances: InstancesState
|
||||
preInstances?: InstancesState
|
||||
) {
|
||||
const instances = preInstances || store.getState().instances;
|
||||
const state = instances.states[instanceId];
|
||||
|
|
Loading…
Reference in New Issue
Block a user