mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-26 16:09:50 +03:00
stash
This commit is contained in:
parent
6266d6bd5a
commit
2bfeb49b43
|
@ -20,6 +20,9 @@ import {
|
|||
UPDATE_REPORTS,
|
||||
REMOVE_INSTANCE,
|
||||
SET_STATE,
|
||||
GET_REPORT_ERROR,
|
||||
GET_REPORT_SUCCESS,
|
||||
ERROR,
|
||||
} from '../constants/actionTypes';
|
||||
import {
|
||||
AUTH_ERROR,
|
||||
|
@ -41,6 +44,7 @@ import { Action } from 'redux';
|
|||
import { Features, State } from '../reducers/instances';
|
||||
import { MonitorStateMonitorState } from '../reducers/monitor';
|
||||
import { LiftedAction } from 'redux-devtools-instrument';
|
||||
import { Data } from '../reducers/reports';
|
||||
|
||||
let monitorReducer: (
|
||||
monitorProps: unknown,
|
||||
|
@ -95,49 +99,73 @@ export interface MonitorActionAction {
|
|||
) => unknown;
|
||||
monitorProps: unknown;
|
||||
}
|
||||
interface JumpToStateAction {
|
||||
export interface JumpToStateAction {
|
||||
type: 'JUMP_TO_STATE';
|
||||
index: number;
|
||||
actionId: number;
|
||||
}
|
||||
interface JumpToActionAction {
|
||||
export interface JumpToActionAction {
|
||||
type: 'JUMP_TO_ACTION';
|
||||
index: number;
|
||||
actionId: number;
|
||||
}
|
||||
interface PauseRecordingAction {
|
||||
export interface PauseRecordingAction {
|
||||
type: 'PAUSE_RECORDING';
|
||||
status: boolean;
|
||||
}
|
||||
interface LockChangesAction {
|
||||
export interface LockChangesAction {
|
||||
type: 'LOCK_CHANGES';
|
||||
status: boolean;
|
||||
}
|
||||
export interface LiftedActionDispatchAction {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'DISPATCH';
|
||||
action:
|
||||
| JumpToStateAction
|
||||
| JumpToActionAction
|
||||
| PauseRecordingAction
|
||||
| LockChangesAction;
|
||||
export interface ToggleActionAction {
|
||||
type: 'TOGGLE_ACTION';
|
||||
}
|
||||
export interface RollbackAction {
|
||||
type: 'ROLLBACK';
|
||||
}
|
||||
export interface SweepAction {
|
||||
type: 'SWEEP';
|
||||
}
|
||||
export type DispatchAction =
|
||||
| JumpToStateAction
|
||||
| JumpToActionAction
|
||||
| PauseRecordingAction
|
||||
| LockChangesAction
|
||||
| ToggleActionAction
|
||||
| RollbackAction
|
||||
| SweepAction;
|
||||
interface LiftedActionActionBase {
|
||||
action?: DispatchAction | string | CustomAction;
|
||||
state?: string;
|
||||
toAll?: boolean;
|
||||
}
|
||||
interface LiftedActionImportAction {
|
||||
export interface LiftedActionDispatchAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'DISPATCH';
|
||||
action: DispatchAction;
|
||||
toAll?: boolean;
|
||||
}
|
||||
interface LiftedActionImportAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'IMPORT';
|
||||
state: string;
|
||||
preloadedState: unknown | undefined;
|
||||
}
|
||||
interface LiftedActionActionAction {
|
||||
interface LiftedActionActionAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'ACTION';
|
||||
action: Action<unknown>;
|
||||
action: string | CustomAction;
|
||||
}
|
||||
interface LiftedActionExportAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'EXPORT';
|
||||
toExport: boolean;
|
||||
}
|
||||
export type LiftedActionAction =
|
||||
| LiftedActionDispatchAction
|
||||
| LiftedActionImportAction
|
||||
| LiftedActionActionAction;
|
||||
| LiftedActionActionAction
|
||||
| LiftedActionExportAction;
|
||||
export function liftedDispatch(
|
||||
action:
|
||||
| InitMonitorAction
|
||||
|
@ -237,8 +265,14 @@ export function pauseRecording(status: boolean): LiftedActionDispatchAction {
|
|||
};
|
||||
}
|
||||
|
||||
export interface CustomAction {
|
||||
name: string;
|
||||
selected: number;
|
||||
args: (string | undefined)[];
|
||||
rest: string;
|
||||
}
|
||||
export function dispatchRemotely(
|
||||
action: Action<unknown>
|
||||
action: string | CustomAction
|
||||
): LiftedActionActionAction {
|
||||
return { type: LIFTED_ACTION, message: 'ACTION', action };
|
||||
}
|
||||
|
@ -317,6 +351,7 @@ export function getReport(report: unknown): GetReportRequest {
|
|||
|
||||
export interface ActionCreator {
|
||||
args: string[];
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface LibConfig {
|
||||
|
@ -337,6 +372,7 @@ export interface RequestBase {
|
|||
computedStates?: string;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
payload?: {} | string;
|
||||
liftedState?: Partial<State>;
|
||||
}
|
||||
interface InitRequest extends RequestBase {
|
||||
type: 'INIT';
|
||||
|
@ -344,6 +380,10 @@ interface InitRequest extends RequestBase {
|
|||
}
|
||||
interface ActionRequest extends RequestBase {
|
||||
type: 'ACTION';
|
||||
isExcess: boolean;
|
||||
nextActionId: number;
|
||||
maxAge: number;
|
||||
batched: boolean;
|
||||
}
|
||||
interface StateRequest extends RequestBase {
|
||||
type: 'STATE';
|
||||
|
@ -352,16 +392,22 @@ interface StateRequest extends RequestBase {
|
|||
interface PartialStateRequest extends RequestBase {
|
||||
type: 'PARTIAL_STATE';
|
||||
committedState: unknown;
|
||||
maxAge: number;
|
||||
}
|
||||
interface LiftedRequest extends RequestBase {
|
||||
type: 'LIFTED';
|
||||
}
|
||||
export interface ExportRequest extends RequestBase {
|
||||
type: 'EXPORT';
|
||||
committedState: unknown;
|
||||
}
|
||||
export type Request =
|
||||
| InitRequest
|
||||
| ActionRequest
|
||||
| StateRequest
|
||||
| PartialStateRequest
|
||||
| LiftedRequest;
|
||||
| LiftedRequest
|
||||
| ExportRequest;
|
||||
|
||||
interface UpdateStateAction {
|
||||
type: typeof UPDATE_STATE;
|
||||
|
@ -445,10 +491,47 @@ interface UnsubscribeAction {
|
|||
channel: string;
|
||||
}
|
||||
|
||||
interface EmitAction {
|
||||
export interface EmitAction {
|
||||
type: typeof EMIT;
|
||||
message: string;
|
||||
id: string;
|
||||
id?: string | false;
|
||||
instanceId?: string;
|
||||
action?: unknown;
|
||||
state?: unknown;
|
||||
}
|
||||
|
||||
interface ListRequest {
|
||||
type: 'list';
|
||||
data: Data;
|
||||
}
|
||||
interface AddRequest {
|
||||
type: 'add';
|
||||
data: Data;
|
||||
}
|
||||
interface RemoveRequest {
|
||||
type: 'remove';
|
||||
data: Data;
|
||||
id: unknown;
|
||||
}
|
||||
type UpdateReportsRequest = ListRequest | AddRequest | RemoveRequest;
|
||||
interface UpdateReportsAction {
|
||||
type: typeof UPDATE_REPORTS;
|
||||
request: UpdateReportsRequest;
|
||||
}
|
||||
|
||||
interface GetReportError {
|
||||
type: typeof GET_REPORT_ERROR;
|
||||
error: Error;
|
||||
}
|
||||
|
||||
interface GetReportSuccess {
|
||||
type: typeof GET_REPORT_SUCCESS;
|
||||
data: { payload: string };
|
||||
}
|
||||
|
||||
interface ErrorAction {
|
||||
type: typeof ERROR;
|
||||
payload: string;
|
||||
}
|
||||
|
||||
export type StoreAction =
|
||||
|
@ -483,4 +566,8 @@ export type StoreAction =
|
|||
| SubscribeSuccessAction
|
||||
| SubscribeErrorAction
|
||||
| UnsubscribeAction
|
||||
| EmitAction;
|
||||
| EmitAction
|
||||
| UpdateReportsAction
|
||||
| GetReportError
|
||||
| GetReportSuccess
|
||||
| ErrorAction;
|
||||
|
|
|
@ -21,7 +21,8 @@ class Settings extends Component<{}, State> {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<Tabs
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
<Tabs<{}>
|
||||
toRight
|
||||
tabs={this.tabs}
|
||||
selected={this.state.selected}
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
import socketCluster from 'socketcluster-client';
|
||||
|
||||
interface States {
|
||||
CLOSED: 'closed';
|
||||
CONNECTING: 'connecting';
|
||||
OPEN: 'open';
|
||||
AUTHENTICATED: 'authenticated';
|
||||
PENDING: 'pending';
|
||||
UNAUTHENTICATED: 'unauthenticated';
|
||||
}
|
||||
|
||||
export const {
|
||||
CLOSED,
|
||||
CONNECTING,
|
||||
|
@ -7,7 +16,7 @@ export const {
|
|||
AUTHENTICATED,
|
||||
PENDING,
|
||||
UNAUTHENTICATED,
|
||||
} = socketCluster.SCClientSocket;
|
||||
} = (socketCluster.SCClientSocket as unknown) as States;
|
||||
export const CONNECT_REQUEST = 'socket/CONNECT_REQUEST';
|
||||
export const CONNECT_SUCCESS = 'socket/CONNECT_SUCCESS';
|
||||
export const CONNECT_ERROR = 'socket/CONNECT_ERROR';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect, ResolveThunks } from 'react-redux';
|
||||
import { Container } from 'devui';
|
||||
import SliderMonitor from './monitors/Slider';
|
||||
|
@ -55,16 +54,6 @@ class Actions extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
Actions.propTypes = {
|
||||
liftedDispatch: PropTypes.func.isRequired,
|
||||
liftedState: PropTypes.object.isRequired,
|
||||
monitorState: PropTypes.object,
|
||||
options: PropTypes.object.isRequired,
|
||||
monitor: PropTypes.string,
|
||||
dispatcherIsOpen: PropTypes.bool,
|
||||
sliderIsOpen: PropTypes.bool,
|
||||
};
|
||||
|
||||
const mapStateToProps = (state: StoreState) => {
|
||||
const instances = state.instances;
|
||||
const id = getActiveInstance(instances);
|
||||
|
|
|
@ -2,7 +2,6 @@ import React, { Component } from 'react';
|
|||
import { withTheme } from 'styled-components';
|
||||
import { LiftedAction, LiftedState } from 'redux-devtools-instrument';
|
||||
import { Action } from 'redux';
|
||||
import { Monitor } from 'redux-devtools';
|
||||
import getMonitor from '../utils/getMonitor';
|
||||
import { InitMonitorAction } from '../actions';
|
||||
import { Features, State } from '../reducers/instances';
|
||||
|
@ -22,13 +21,15 @@ interface Props {
|
|||
|
||||
class DevTools extends Component<Props> {
|
||||
monitorProps: unknown;
|
||||
Monitor?: Monitor<
|
||||
unknown,
|
||||
Action<unknown>,
|
||||
LiftedState<unknown, Action<unknown>, unknown>,
|
||||
unknown,
|
||||
Action<unknown>
|
||||
>;
|
||||
Monitor?: React.ComponentType<
|
||||
LiftedState<unknown, Action<unknown>, unknown>
|
||||
> & {
|
||||
update(
|
||||
monitorProps: unknown,
|
||||
state: unknown | undefined,
|
||||
action: Action<unknown>
|
||||
): unknown;
|
||||
};
|
||||
preventRender?: boolean;
|
||||
|
||||
constructor(props: Props) {
|
||||
|
@ -41,6 +42,7 @@ class DevTools extends Component<Props> {
|
|||
this.monitorProps = monitorElement.props;
|
||||
this.Monitor = monitorElement.type;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const update = this.Monitor!.update;
|
||||
if (update) {
|
||||
let newMonitorState;
|
||||
|
@ -51,7 +53,11 @@ class DevTools extends Component<Props> {
|
|||
) {
|
||||
newMonitorState = monitorState;
|
||||
} else {
|
||||
newMonitorState = update(this.monitorProps, undefined, {});
|
||||
newMonitorState = update(
|
||||
this.monitorProps,
|
||||
undefined,
|
||||
{} as Action<unknown>
|
||||
);
|
||||
if (newMonitorState !== monitorState) {
|
||||
this.preventRender = true;
|
||||
}
|
||||
|
@ -95,9 +101,10 @@ class DevTools extends Component<Props> {
|
|||
...this.props.liftedState,
|
||||
monitorState: this.props.monitorState,
|
||||
};
|
||||
const MonitorAsAny = this.Monitor as any;
|
||||
return (
|
||||
<div className={`monitor monitor-${this.props.monitor}`}>
|
||||
<this.Monitor
|
||||
<MonitorAsAny
|
||||
{...liftedState}
|
||||
{...this.monitorProps}
|
||||
features={this.props.features}
|
||||
|
|
|
@ -35,6 +35,8 @@ class ChartMonitorWrapper extends Component<Props> {
|
|||
|
||||
render() {
|
||||
return (
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
<ChartMonitor
|
||||
defaultIsVisible
|
||||
invertTheme
|
||||
|
|
|
@ -53,15 +53,15 @@ interface OwnProps {
|
|||
type Props = DispatchProps & OwnProps;
|
||||
|
||||
interface State {
|
||||
selected: string;
|
||||
selected: 'default' | number;
|
||||
customAction: string;
|
||||
args: unknown[];
|
||||
args: (string | undefined)[];
|
||||
rest: string;
|
||||
changed: boolean;
|
||||
}
|
||||
|
||||
class Dispatcher extends Component<Props, State> {
|
||||
state = {
|
||||
state: State = {
|
||||
selected: 'default',
|
||||
customAction:
|
||||
this.props.options.lib === 'redux' ? "{\n type: ''\n}" : 'this.',
|
||||
|
@ -89,7 +89,7 @@ class Dispatcher extends Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
selectActionCreator = (selected) => {
|
||||
selectActionCreator = (selected: 'default' | 'actions-help' | number) => {
|
||||
if (selected === 'actions-help') {
|
||||
window.open(
|
||||
'https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/' +
|
||||
|
@ -98,14 +98,14 @@ class Dispatcher extends Component<Props, State> {
|
|||
return;
|
||||
}
|
||||
|
||||
const args = [];
|
||||
const args: string[] = [];
|
||||
if (selected !== 'default') {
|
||||
args.length = this.props.options.actionCreators![selected].args.length;
|
||||
}
|
||||
this.setState({ selected, args, rest: '[]', changed: false });
|
||||
};
|
||||
|
||||
handleArg = (argIndex) => (value) => {
|
||||
handleArg = (argIndex: number) => (value: string) => {
|
||||
const args = [
|
||||
...this.state.args.slice(0, argIndex),
|
||||
value || undefined,
|
||||
|
@ -114,26 +114,26 @@ class Dispatcher extends Component<Props, State> {
|
|||
this.setState({ args, changed: true });
|
||||
};
|
||||
|
||||
handleRest = (rest) => {
|
||||
handleRest = (rest: string) => {
|
||||
this.setState({ rest, changed: true });
|
||||
};
|
||||
|
||||
handleCustomAction = (customAction) => {
|
||||
handleCustomAction = (customAction: string) => {
|
||||
this.setState({ customAction, changed: true });
|
||||
};
|
||||
|
||||
dispatchAction = () => {
|
||||
const { selected, customAction, args, rest } = this.state;
|
||||
|
||||
if (this.state.selected !== 'default') {
|
||||
if (selected !== 'default') {
|
||||
// remove trailing `undefined` arguments
|
||||
let i = args.length - 1;
|
||||
while (i >= 0 && typeof args[i] === 'undefined') {
|
||||
args.pop(i);
|
||||
args.pop();
|
||||
i--;
|
||||
}
|
||||
this.props.dispatch({
|
||||
name: this.props.options.actionCreators[selected].name,
|
||||
name: this.props.options.actionCreators![selected].name,
|
||||
selected,
|
||||
args,
|
||||
rest,
|
||||
|
@ -182,7 +182,9 @@ class Dispatcher extends Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
let options = [{ value: 'default', label: 'Custom action' }];
|
||||
let options: { value: string | number; label: string }[] = [
|
||||
{ value: 'default', label: 'Custom action' },
|
||||
];
|
||||
if (actionCreators && actionCreators.length > 0) {
|
||||
options = options.concat(
|
||||
actionCreators.map(({ name, args }, i) => ({
|
||||
|
|
|
@ -72,20 +72,20 @@ class ChartTab extends Component<Props> {
|
|||
style: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
node: {
|
||||
node: ({
|
||||
colors: {
|
||||
default: theme.base0B,
|
||||
collapsed: theme.base0B,
|
||||
parent: theme.base0E,
|
||||
},
|
||||
radius: 7,
|
||||
},
|
||||
text: {
|
||||
} as unknown) as string,
|
||||
text: ({
|
||||
colors: {
|
||||
default: theme.base0D,
|
||||
hover: theme.base06,
|
||||
},
|
||||
},
|
||||
} as unknown) as string,
|
||||
},
|
||||
onClickText: this.onClickText,
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@ import RawTab from './RawTab';
|
|||
import ChartTab from './ChartTab';
|
||||
import VisualDiffTab from './VisualDiffTab';
|
||||
import { StoreState } from '../../../reducers';
|
||||
import { Delta } from 'jsondiffpatch';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -19,7 +20,7 @@ type Props = StateProps &
|
|||
TabComponentProps<unknown, Action<unknown>>;
|
||||
|
||||
class SubTabs extends Component<Props> {
|
||||
tabs?: Tab<unknown>[];
|
||||
tabs?: (Tab<Props> | Tab<{ data: unknown }> | Tab<{ data?: Delta }>)[];
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
@ -56,7 +57,7 @@ class SubTabs extends Component<Props> {
|
|||
{
|
||||
name: 'Raw',
|
||||
component: VisualDiffTab,
|
||||
selector: this.selector,
|
||||
selector: this.selector as () => { data?: Delta },
|
||||
},
|
||||
];
|
||||
return;
|
||||
|
@ -88,7 +89,7 @@ class SubTabs extends Component<Props> {
|
|||
|
||||
return (
|
||||
<Tabs
|
||||
tabs={this.tabs!}
|
||||
tabs={this.tabs! as any}
|
||||
selected={selected || 'Tree'}
|
||||
onClick={this.props.selectMonitorTab}
|
||||
/>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React, { Component } from 'react';
|
||||
import styled, { withTheme } from 'styled-components';
|
||||
import SliderMonitor from 'redux-devtools-slider-monitor';
|
||||
import { LiftedAction, LiftedState } from 'redux-devtools-instrument';
|
||||
import { Action, Dispatch } from 'redux';
|
||||
import { LiftedAction } from 'redux-devtools-instrument';
|
||||
import { Action } from 'redux';
|
||||
import { ThemeFromProvider } from 'devui';
|
||||
import { State } from '../../reducers/instances';
|
||||
|
||||
const SliderWrapper = styled.div`
|
||||
border-color: ${(props) => props.theme.base02};
|
||||
|
@ -12,8 +13,8 @@ const SliderWrapper = styled.div`
|
|||
`;
|
||||
|
||||
interface Props {
|
||||
liftedState: LiftedState<unknown, Action<unknown>, unknown>;
|
||||
dispatch: Dispatch<LiftedAction<unknown, Action<unknown>, unknown>>;
|
||||
liftedState: State;
|
||||
dispatch: (action: LiftedAction<unknown, Action<unknown>, unknown>) => void;
|
||||
theme: ThemeFromProvider;
|
||||
}
|
||||
|
||||
|
@ -29,6 +30,8 @@ class Slider extends Component<Props> {
|
|||
<SliderWrapper>
|
||||
<SliderMonitor
|
||||
{...this.props.liftedState}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
dispatch={this.props.dispatch}
|
||||
theme={this.props.theme}
|
||||
hideResetButton
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'devui/lib/presets';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Provider } from 'react-redux';
|
||||
import { Store } from 'redux';
|
||||
import configureStore from './store/configureStore';
|
||||
|
@ -21,7 +20,8 @@ class Root extends Component<Props> {
|
|||
this.store = store;
|
||||
store.dispatch({
|
||||
type: CONNECT_REQUEST,
|
||||
options: preloadedState!.connection || this.props.socketOptions,
|
||||
options: (preloadedState!.connection ||
|
||||
this.props.socketOptions) as ConnectionOptions,
|
||||
});
|
||||
this.forceUpdate();
|
||||
});
|
||||
|
@ -29,21 +29,13 @@ class Root extends Component<Props> {
|
|||
|
||||
render() {
|
||||
if (!this.store) return null;
|
||||
const AppAsAny = App as any;
|
||||
return (
|
||||
<Provider store={this.store}>
|
||||
<App {...this.props} />
|
||||
<AppAsAny {...this.props} />
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Root.propTypes = {
|
||||
socketOptions: PropTypes.shape({
|
||||
hostname: PropTypes.string,
|
||||
port: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
autoReconnect: PropTypes.bool,
|
||||
secure: PropTypes.bool,
|
||||
}),
|
||||
};
|
||||
|
||||
export default Root;
|
||||
|
|
|
@ -13,23 +13,36 @@ import {
|
|||
GET_REPORT_ERROR,
|
||||
GET_REPORT_SUCCESS,
|
||||
} from '../constants/actionTypes';
|
||||
import { showNotification, importState, StoreAction } from '../actions';
|
||||
import {
|
||||
showNotification,
|
||||
importState,
|
||||
StoreAction,
|
||||
EmitAction,
|
||||
LiftedActionAction,
|
||||
Request,
|
||||
DispatchAction,
|
||||
} from '../actions';
|
||||
import { nonReduxDispatch } from '../utils/monitorActions';
|
||||
import { StoreState } from '../reducers';
|
||||
|
||||
let socket: SCClientSocket;
|
||||
let store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>;
|
||||
|
||||
function emit({ message: type, id, instanceId, action, state }) {
|
||||
function emit({ message: type, id, instanceId, action, state }: EmitAction) {
|
||||
socket.emit(id ? 'sc-' + id : 'respond', { type, action, state, instanceId });
|
||||
}
|
||||
|
||||
function startMonitoring(channel) {
|
||||
function startMonitoring(channel: string) {
|
||||
if (channel !== store.getState().socket.baseChannel) return;
|
||||
store.dispatch({ type: actions.EMIT, message: 'START' });
|
||||
}
|
||||
|
||||
function dispatchRemoteAction({ message, action, state, toAll }) {
|
||||
function dispatchRemoteAction({
|
||||
message,
|
||||
action,
|
||||
state,
|
||||
toAll,
|
||||
}: LiftedActionAction) {
|
||||
const instances = store.getState().instances;
|
||||
const instanceId = getActiveInstance(instances);
|
||||
const id = !toAll && instances.options[instanceId].connectionId;
|
||||
|
@ -41,7 +54,7 @@ function dispatchRemoteAction({ message, action, state, toAll }) {
|
|||
store,
|
||||
message,
|
||||
instanceId,
|
||||
action,
|
||||
action as DispatchAction,
|
||||
state,
|
||||
instances
|
||||
),
|
||||
|
@ -50,21 +63,32 @@ function dispatchRemoteAction({ message, action, state, toAll }) {
|
|||
});
|
||||
}
|
||||
|
||||
interface DisconnectedAction {
|
||||
interface RequestBase {
|
||||
id?: string;
|
||||
instanceId?: string;
|
||||
}
|
||||
interface DisconnectedAction extends RequestBase {
|
||||
type: 'DISCONNECTED';
|
||||
id: string;
|
||||
}
|
||||
interface StartAction {
|
||||
interface StartAction extends RequestBase {
|
||||
type: 'START';
|
||||
id: string;
|
||||
}
|
||||
interface ErrorAction {
|
||||
interface ErrorAction extends RequestBase {
|
||||
type: 'ERROR';
|
||||
payload: string;
|
||||
}
|
||||
type Request = DisconnectedAction | StartAction | ErrorAction;
|
||||
interface RequestWithData extends RequestBase {
|
||||
data: Request;
|
||||
}
|
||||
type MonitoringRequest =
|
||||
| DisconnectedAction
|
||||
| StartAction
|
||||
| ErrorAction
|
||||
| Request;
|
||||
|
||||
function monitoring(request: Request) {
|
||||
function monitoring(request: MonitoringRequest) {
|
||||
if (request.type === 'DISCONNECTED') {
|
||||
store.dispatch({
|
||||
type: REMOVE_INSTANCE,
|
||||
|
@ -84,7 +108,9 @@ function monitoring(request: Request) {
|
|||
|
||||
store.dispatch({
|
||||
type: UPDATE_STATE,
|
||||
request: request.data ? { ...request.data, id: request.id } : request,
|
||||
request: ((request as unknown) as RequestWithData).data
|
||||
? { ...((request as unknown) as RequestWithData).data, id: request.id }
|
||||
: request,
|
||||
});
|
||||
|
||||
const instances = store.getState().instances;
|
||||
|
@ -110,7 +136,7 @@ function subscribe(
|
|||
const channel = socket.subscribe(channelName);
|
||||
if (subscription === UPDATE_STATE) channel.watch(monitoring);
|
||||
else {
|
||||
const watcher = (request) => {
|
||||
const watcher = (request: Request) => {
|
||||
store.dispatch({ type: subscription, request });
|
||||
};
|
||||
channel.watch(watcher);
|
||||
|
@ -201,15 +227,19 @@ function login() {
|
|||
});
|
||||
}
|
||||
|
||||
function getReport(reportId) {
|
||||
socket.emit('getReport', reportId, (error, data) => {
|
||||
if (error) {
|
||||
store.dispatch({ type: GET_REPORT_ERROR, error });
|
||||
return;
|
||||
function getReport(reportId: unknown) {
|
||||
socket.emit(
|
||||
'getReport',
|
||||
reportId,
|
||||
(error: Error, data: { payload: string }) => {
|
||||
if (error) {
|
||||
store.dispatch({ type: GET_REPORT_ERROR, error });
|
||||
return;
|
||||
}
|
||||
store.dispatch({ type: GET_REPORT_SUCCESS, data });
|
||||
store.dispatch(importState(data.payload));
|
||||
}
|
||||
store.dispatch({ type: GET_REPORT_SUCCESS, data });
|
||||
store.dispatch(importState(data.payload));
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
export default function api(
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import stringifyJSON from '../utils/stringifyJSON';
|
||||
import { UPDATE_STATE, LIFTED_ACTION, EXPORT } from '../constants/actionTypes';
|
||||
import { getActiveInstance } from '../reducers/instances';
|
||||
import { Dispatch, MiddlewareAPI } from 'redux';
|
||||
import { ExportRequest, StoreAction } from '../actions';
|
||||
import { StoreState } from '../reducers';
|
||||
|
||||
let toExport;
|
||||
let toExport: string | undefined;
|
||||
|
||||
function download(state) {
|
||||
function download(state: string) {
|
||||
const blob = new Blob([state], { type: 'octet/stream' });
|
||||
const href = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
|
@ -19,15 +22,17 @@ function download(state) {
|
|||
}, 0);
|
||||
}
|
||||
|
||||
const exportState = (store) => (next) => (action) => {
|
||||
const exportState = (
|
||||
store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>
|
||||
) => (next: Dispatch<StoreAction>) => (action: StoreAction) => {
|
||||
const result = next(action);
|
||||
|
||||
if (
|
||||
toExport &&
|
||||
action.type === UPDATE_STATE &&
|
||||
action.request.type === 'EXPORT'
|
||||
action.request!.type === 'EXPORT'
|
||||
) {
|
||||
const request = action.request;
|
||||
const request = action.request!;
|
||||
const id = request.instanceId || request.id;
|
||||
if (id === toExport) {
|
||||
toExport = undefined;
|
||||
|
@ -35,7 +40,7 @@ const exportState = (store) => (next) => (action) => {
|
|||
JSON.stringify(
|
||||
{
|
||||
payload: request.payload,
|
||||
preloadedState: request.committedState,
|
||||
preloadedState: (request as ExportRequest).committedState,
|
||||
},
|
||||
null,
|
||||
'\t'
|
||||
|
|
|
@ -89,19 +89,20 @@ function updateState(
|
|||
id: string,
|
||||
serialize: boolean | undefined
|
||||
) {
|
||||
let payload = request.payload;
|
||||
let payload: State = request.payload as State;
|
||||
const actionsById = request.actionsById;
|
||||
if (actionsById) {
|
||||
payload = {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
...payload,
|
||||
actionsById: parseJSON(actionsById, serialize),
|
||||
computedStates: parseJSON(request.computedStates, serialize),
|
||||
};
|
||||
} as State;
|
||||
if (request.type === 'STATE' && request.committedState) {
|
||||
payload.committedState = payload.computedStates[0].state;
|
||||
}
|
||||
} else {
|
||||
payload = parseJSON(payload, serialize);
|
||||
payload = parseJSON((payload as unknown) as string, serialize) as State;
|
||||
}
|
||||
|
||||
let newState;
|
||||
|
@ -112,11 +113,11 @@ function updateState(
|
|||
case 'INIT':
|
||||
newState = recompute(state.default, payload, {
|
||||
action: { type: '@@INIT' },
|
||||
timestamp: action.timestamp || Date.now(),
|
||||
timestamp: (action as { timestamp?: unknown }).timestamp || Date.now(),
|
||||
});
|
||||
break;
|
||||
case 'ACTION': {
|
||||
let isExcess = request.isExcess;
|
||||
const isExcess = request.isExcess;
|
||||
const nextActionId = request.nextActionId || liftedState.nextActionId + 1;
|
||||
const maxAge = request.maxAge;
|
||||
if (Array.isArray(action)) {
|
||||
|
@ -125,7 +126,7 @@ function updateState(
|
|||
for (let i = 0; i < action.length; i++) {
|
||||
newState = recompute(
|
||||
newState,
|
||||
request.batched ? payload : payload[i],
|
||||
request.batched ? payload : ((payload as unknown) as State[])[i],
|
||||
action[i],
|
||||
newState.nextActionId + 1,
|
||||
maxAge,
|
||||
|
|
|
@ -36,13 +36,12 @@ export function dispatchMonitorAction(
|
|||
): MonitorState {
|
||||
return {
|
||||
...state,
|
||||
monitorState:
|
||||
action.action.newMonitorState ||
|
||||
monitorState: (action.action.newMonitorState ||
|
||||
action.monitorReducer(
|
||||
action.monitorProps,
|
||||
state.monitorState,
|
||||
action.action
|
||||
),
|
||||
)) as MonitorStateMonitorState,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,12 @@ import {
|
|||
} from '../constants/actionTypes';
|
||||
import { StoreAction } from '../actions';
|
||||
|
||||
export interface Data {
|
||||
id: unknown;
|
||||
}
|
||||
|
||||
export interface ReportsState {
|
||||
data: unknown[];
|
||||
data: Data[];
|
||||
}
|
||||
|
||||
const initialState: ReportsState = {
|
||||
|
|
|
@ -6,8 +6,10 @@ export interface SocketState {
|
|||
id: string | null;
|
||||
channels: string[];
|
||||
socketState: States;
|
||||
authState: AuthStates;
|
||||
authState: AuthStates | 'pending';
|
||||
error: Error | undefined;
|
||||
baseChannel?: string;
|
||||
authToken?: null;
|
||||
}
|
||||
|
||||
const initialState: SocketState = {
|
||||
|
@ -18,7 +20,10 @@ const initialState: SocketState = {
|
|||
error: undefined,
|
||||
};
|
||||
|
||||
export default function socket(state = initialState, action: StoreAction) {
|
||||
export default function socket(
|
||||
state = initialState,
|
||||
action: StoreAction
|
||||
): SocketState {
|
||||
switch (action.type) {
|
||||
case actions.CONNECT_REQUEST: {
|
||||
return {
|
||||
|
|
|
@ -25,15 +25,23 @@ export default function configureStore(
|
|||
deserialize: (data: unknown) => data,
|
||||
} as unknown) as PersistorConfig;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
getStoredState<StoreState>(persistConfig, (err, restoredState) => {
|
||||
let composeEnhancers = compose;
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) {
|
||||
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
|
||||
if (
|
||||
((window as unknown) as {
|
||||
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
|
||||
}).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
||||
) {
|
||||
composeEnhancers = ((window as unknown) as {
|
||||
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__: typeof compose;
|
||||
}).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
|
||||
}
|
||||
if (module.hot) {
|
||||
// Enable Webpack hot module replacement for reducers
|
||||
module.hot.accept('../reducers', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const nextReducer = require('../reducers'); // eslint-disable-line global-require
|
||||
store.replaceReducer(nextReducer);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Based on https://github.com/gaearon/redux-devtools/pull/241
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
||||
export default function commitExcessActions(liftedState, n = 1) {
|
||||
import { State } from '../reducers/instances';
|
||||
|
||||
export default function commitExcessActions(liftedState: State, n = 1) {
|
||||
// Auto-commits n-number of excess actions.
|
||||
let excess = n;
|
||||
let idsToDelete = liftedState.stagedActionIds.slice(1, excess + 1);
|
||||
|
|
|
@ -2,7 +2,10 @@ import difference from 'lodash/difference';
|
|||
import omit from 'lodash/omit';
|
||||
import stringifyJSON from './stringifyJSON';
|
||||
import { SET_STATE } from '../constants/actionTypes';
|
||||
import { State } from '../reducers/instances';
|
||||
import { InstancesState, State } from '../reducers/instances';
|
||||
import { Dispatch, MiddlewareAPI } from 'redux';
|
||||
import { DispatchAction, StoreAction } from '../actions';
|
||||
import { StoreState } from '../reducers';
|
||||
|
||||
export function sweep(state: State): State {
|
||||
return {
|
||||
|
@ -18,12 +21,12 @@ export function sweep(state: State): State {
|
|||
}
|
||||
|
||||
export function nonReduxDispatch(
|
||||
store,
|
||||
message,
|
||||
instanceId,
|
||||
action,
|
||||
initialState,
|
||||
preInstances
|
||||
store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>,
|
||||
message: string,
|
||||
instanceId: string,
|
||||
action: DispatchAction,
|
||||
initialState: string | undefined,
|
||||
preInstances: InstancesState
|
||||
) {
|
||||
const instances = preInstances || store.getState().instances;
|
||||
const state = instances.states[instanceId];
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import jsan from 'jsan';
|
||||
import { DATA_TYPE_KEY, DATA_REF_KEY } from '../constants/dataTypes';
|
||||
|
||||
export function reviver(key, value) {
|
||||
export function reviver(key: string, value: unknown) {
|
||||
if (
|
||||
typeof value === 'object' &&
|
||||
value !== null &&
|
||||
'__serializedType__' in value &&
|
||||
typeof value.data === 'object'
|
||||
typeof (value as any).data === 'object'
|
||||
) {
|
||||
const data = value.data;
|
||||
data[DATA_TYPE_KEY] = value.__serializedType__;
|
||||
const data = (value as any).data;
|
||||
data[DATA_TYPE_KEY] = (value as any).__serializedType__;
|
||||
if ('__serializedRef__' in value)
|
||||
data[DATA_REF_KEY] = value.__serializedRef__;
|
||||
data[DATA_REF_KEY] = (value as any).__serializedRef__;
|
||||
/*
|
||||
if (Array.isArray(data)) {
|
||||
data.__serializedType__ = value.__serializedType__;
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
import jsan from 'jsan';
|
||||
import { DATA_TYPE_KEY, DATA_REF_KEY } from '../constants/dataTypes';
|
||||
|
||||
function replacer(key, value) {
|
||||
function replacer(key: string, value: unknown) {
|
||||
if (typeof value === 'object' && value !== null && DATA_TYPE_KEY in value) {
|
||||
const __serializedType__ = value[DATA_TYPE_KEY];
|
||||
const __serializedType__ = (value as any)[DATA_TYPE_KEY];
|
||||
const clone = { ...value };
|
||||
delete clone[DATA_TYPE_KEY]; // eslint-disable-line no-param-reassign
|
||||
delete (clone as any)[DATA_TYPE_KEY]; // eslint-disable-line no-param-reassign
|
||||
const r = { data: clone, __serializedType__ };
|
||||
if (DATA_REF_KEY in value) r.__serializedRef__ = clone[DATA_REF_KEY];
|
||||
if (DATA_REF_KEY in value)
|
||||
(r as any).__serializedRef__ = (clone as any)[DATA_REF_KEY];
|
||||
return r;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export default function stringifyJSON(data, serialize) {
|
||||
export default function stringifyJSON(data: unknown, serialize: boolean) {
|
||||
return serialize
|
||||
? jsan.stringify(data, replacer, null, true)
|
||||
? jsan.stringify(data, replacer, (null as unknown) as undefined, true)
|
||||
: jsan.stringify(data);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import commitExcessActions from './commitExcessActions';
|
||||
import { State } from '../reducers/instances';
|
||||
import { Action } from 'redux';
|
||||
import { PerformAction } from 'redux-devtools-instrument';
|
||||
|
||||
export function recompute(
|
||||
previousLiftedState: State,
|
||||
storeState,
|
||||
action,
|
||||
storeState: State,
|
||||
action: Action<unknown>,
|
||||
nextActionId = 1,
|
||||
maxAge?: number,
|
||||
isExcess?: boolean
|
||||
|
@ -21,12 +23,14 @@ export function recompute(
|
|||
liftedState.stagedActionIds = [...liftedState.stagedActionIds, actionId];
|
||||
liftedState.actionsById = { ...liftedState.actionsById };
|
||||
if (action.type === 'PERFORM_ACTION') {
|
||||
liftedState.actionsById[actionId] = action;
|
||||
liftedState.actionsById[actionId] = action as PerformAction<
|
||||
Action<unknown>
|
||||
>;
|
||||
} else {
|
||||
liftedState.actionsById[actionId] = {
|
||||
action: action.action || action,
|
||||
timestamp: action.timestamp || Date.now(),
|
||||
stack: action.stack,
|
||||
action: (action as any).action || action,
|
||||
timestamp: (action as any).timestamp || Date.now(),
|
||||
stack: (action as any).stack,
|
||||
type: 'PERFORM_ACTION',
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,28 +1,53 @@
|
|||
const ERROR = '@@redux-devtools/ERROR';
|
||||
|
||||
export default function catchErrors(sendError) {
|
||||
interface ErrorAction {
|
||||
type: typeof ERROR;
|
||||
message?: Event | string;
|
||||
url?: string | undefined;
|
||||
lineNo?: number | undefined;
|
||||
columnNo?: number | undefined;
|
||||
stack?: string;
|
||||
error?: Error;
|
||||
isFatal?: boolean;
|
||||
sourceURL?: string;
|
||||
line?: number;
|
||||
column?: number;
|
||||
}
|
||||
|
||||
export default function catchErrors(
|
||||
sendError: (errorAction: ErrorAction) => void
|
||||
) {
|
||||
if (typeof window === 'object' && typeof window.onerror === 'object') {
|
||||
window.onerror = function (message, url, lineNo, columnNo, error) {
|
||||
const errorAction = { type: ERROR, message, url, lineNo, columnNo };
|
||||
const errorAction: ErrorAction = {
|
||||
type: ERROR,
|
||||
message,
|
||||
url,
|
||||
lineNo,
|
||||
columnNo,
|
||||
};
|
||||
if (error && error.stack) errorAction.stack = error.stack;
|
||||
sendError(errorAction);
|
||||
return false;
|
||||
};
|
||||
} else if (typeof global !== 'undefined' && global.ErrorUtils) {
|
||||
global.ErrorUtils.setGlobalHandler((error, isFatal) => {
|
||||
sendError({ type: ERROR, error, isFatal });
|
||||
});
|
||||
} else if (typeof global !== 'undefined' && (global as any).ErrorUtils) {
|
||||
(global as any).ErrorUtils.setGlobalHandler(
|
||||
(error: Error, isFatal: boolean) => {
|
||||
sendError({ type: ERROR, error, isFatal });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* eslint-disable no-console */
|
||||
if (
|
||||
typeof console === 'object' &&
|
||||
typeof console.error === 'function' &&
|
||||
!console.beforeRemotedev
|
||||
!(console as any).beforeRemotedev
|
||||
) {
|
||||
console.beforeRemotedev = console.error.bind(console);
|
||||
(console as any).beforeRemotedev = console.error.bind(console);
|
||||
console.error = function () {
|
||||
let errorAction = { type: ERROR };
|
||||
let errorAction: ErrorAction = { type: ERROR };
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
const error = arguments[0];
|
||||
errorAction.message = error.message ? error.message : error;
|
||||
if (error.sourceURL) {
|
||||
|
@ -35,7 +60,8 @@ export default function catchErrors(sendError) {
|
|||
}
|
||||
if (error.stack) errorAction.stack = error.stack;
|
||||
sendError(errorAction);
|
||||
console.beforeRemotedev.apply(null, arguments);
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
(console as any).beforeRemotedev.apply(null, arguments);
|
||||
};
|
||||
}
|
||||
/* eslint-enable no-console */
|
||||
|
|
Loading…
Reference in New Issue
Block a user