mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-21 17:16:42 +03:00
Move the logic from @redux-devtools/app into @redux-devtools/app-core (#1655)
This change splits out the main logic from the Redux Devtools App into a new core package but keeps the socket connection management in @redux-devtools/app. The aim is to allow for easier reuse of the rest of the app in other envioronments with their own transport methods, such as React Native or Electron.
This commit is contained in:
parent
a4382ecb9c
commit
96ac1f291a
6
.changeset/hip-apricots-laugh.md
Normal file
6
.changeset/hip-apricots-laugh.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'@redux-devtools/app-core': major
|
||||
'@redux-devtools/app': minor
|
||||
---
|
||||
|
||||
Move the logic from @redux-devtools/app into @redux-devtools/app-core
|
2
packages/redux-devtools-app-core/.eslintignore
Normal file
2
packages/redux-devtools-app-core/.eslintignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
build
|
||||
lib
|
21
packages/redux-devtools-app-core/.eslintrc.js
Normal file
21
packages/redux-devtools-app-core/.eslintrc.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
module.exports = {
|
||||
extends: '../../eslintrc.js.base.json',
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
extends: '../../eslintrc.ts.react.base.json',
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['test/**/*.ts', 'test/**/*.tsx'],
|
||||
extends: '../../eslintrc.ts.react.jest.base.json',
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./tsconfig.test.json'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
21
packages/redux-devtools-app-core/LICENSE.md
Normal file
21
packages/redux-devtools-app-core/LICENSE.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Mihail Diordiev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
27
packages/redux-devtools-app-core/README.md
Normal file
27
packages/redux-devtools-app-core/README.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Redux DevTools monitor app core
|
||||
|
||||
The core React component and Redux store for the Redux DevTools monitor app. It is split out to allow you to use it directly for transports other than the standard WebSocket one.
|
||||
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import { Provider } from 'react-redux';
|
||||
import { Persistor } from 'redux-persist';
|
||||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
import { App } from '@redux-devtools/app-core';
|
||||
import { store, persistor } from "./yourStore";
|
||||
|
||||
export function Root() {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<PersistGate loading={null} persistor={persistor!}>
|
||||
<App />
|
||||
</PersistGate>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### License
|
||||
|
||||
MIT
|
8
packages/redux-devtools-app-core/babel.config.esm.json
Normal file
8
packages/redux-devtools-app-core/babel.config.esm.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"presets": [
|
||||
["@babel/preset-env", { "targets": "defaults", "modules": false }],
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": ["@babel/plugin-transform-runtime"]
|
||||
}
|
8
packages/redux-devtools-app-core/babel.config.json
Normal file
8
packages/redux-devtools-app-core/babel.config.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"presets": [
|
||||
["@babel/preset-env", { "targets": "defaults" }],
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": ["@babel/plugin-transform-runtime"]
|
||||
}
|
108
packages/redux-devtools-app-core/package.json
Normal file
108
packages/redux-devtools-app-core/package.json
Normal file
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
"name": "@redux-devtools/app-core",
|
||||
"version": "1.0.0",
|
||||
"description": "Redux DevTools app core",
|
||||
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-app-core",
|
||||
"bugs": {
|
||||
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": "Mihail Diordiev <zalmoxisus@gmail.com> (https://github.com/zalmoxisus)",
|
||||
"files": [
|
||||
"build",
|
||||
"lib",
|
||||
"src",
|
||||
"umd"
|
||||
],
|
||||
"main": "lib/cjs/index.js",
|
||||
"module": "lib/esm/index.js",
|
||||
"types": "lib/types/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types",
|
||||
"build:cjs": "babel src --extensions \".ts,.tsx\" --out-dir lib/cjs",
|
||||
"build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts,.tsx\" --out-dir lib/esm",
|
||||
"build:types": "tsc --emitDeclarationOnly",
|
||||
"clean": "rimraf lib",
|
||||
"test": "jest",
|
||||
"lint": "eslint . --ext .ts,.tsx",
|
||||
"type-check": "tsc --noEmit",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.24.7",
|
||||
"@redux-devtools/chart-monitor": "^5.0.1",
|
||||
"@redux-devtools/core": "^4.0.0",
|
||||
"@redux-devtools/inspector-monitor": "^6.0.0",
|
||||
"@redux-devtools/inspector-monitor-test-tab": "^4.0.0",
|
||||
"@redux-devtools/inspector-monitor-trace-tab": "^4.0.0",
|
||||
"@redux-devtools/log-monitor": "^5.0.0",
|
||||
"@redux-devtools/rtk-query-monitor": "^5.0.0",
|
||||
"@redux-devtools/slider-monitor": "^5.0.0",
|
||||
"@redux-devtools/ui": "^1.3.1",
|
||||
"d3-state-visualizer": "^3.0.0",
|
||||
"javascript-stringify": "^2.1.0",
|
||||
"jsan": "^3.1.14",
|
||||
"jsondiffpatch": "^0.6.0",
|
||||
"react-icons": "^5.2.1",
|
||||
"react-is": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.24.1",
|
||||
"@babel/core": "^7.24.3",
|
||||
"@babel/eslint-parser": "^7.24.1",
|
||||
"@babel/plugin-transform-runtime": "^7.24.3",
|
||||
"@babel/preset-env": "^7.24.3",
|
||||
"@babel/preset-react": "^7.24.1",
|
||||
"@babel/preset-typescript": "^7.24.1",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@rjsf/core": "^4.2.3",
|
||||
"@testing-library/dom": "^10.1.0",
|
||||
"@testing-library/jest-dom": "^6.4.5",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/jsan": "^3.1.5",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@types/node": "^20.11.30",
|
||||
"@types/react": "^18.2.72",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@types/styled-components": "^5.1.34",
|
||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
||||
"@typescript-eslint/parser": "^7.4.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild": "^0.20.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-jest": "^28.6.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-redux": "^8.1.3",
|
||||
"redux": "^4.2.1",
|
||||
"redux-persist": "^6.0.0",
|
||||
"rimraf": "^5.0.7",
|
||||
"styled-components": "^5.3.11",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "~5.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"@types/styled-components": "^5.1.34",
|
||||
"react": "^16.8.4 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0",
|
||||
"react-redux": "^8.0.0 || ^9.0.0",
|
||||
"redux": "^4.0.0 || ^5.0.0",
|
||||
"redux-persist": "^6.0.0",
|
||||
"styled-components": "^5.3.11"
|
||||
}
|
||||
}
|
523
packages/redux-devtools-app-core/src/actions/index.ts
Normal file
523
packages/redux-devtools-app-core/src/actions/index.ts
Normal file
|
@ -0,0 +1,523 @@
|
|||
import { SchemeName, ThemeName } from '@redux-devtools/ui';
|
||||
import { REHYDRATE } from 'redux-persist';
|
||||
import {
|
||||
CHANGE_SECTION,
|
||||
CHANGE_THEME,
|
||||
SELECT_INSTANCE,
|
||||
SELECT_MONITOR,
|
||||
UPDATE_MONITOR_STATE,
|
||||
LIFTED_ACTION,
|
||||
MONITOR_ACTION,
|
||||
EXPORT,
|
||||
TOGGLE_SYNC,
|
||||
TOGGLE_SLIDER,
|
||||
TOGGLE_DISPATCHER,
|
||||
TOGGLE_PERSIST,
|
||||
GET_REPORT_REQUEST,
|
||||
SHOW_NOTIFICATION,
|
||||
CLEAR_NOTIFICATION,
|
||||
UPDATE_STATE,
|
||||
UPDATE_REPORTS,
|
||||
REMOVE_INSTANCE,
|
||||
SET_STATE,
|
||||
GET_REPORT_ERROR,
|
||||
GET_REPORT_SUCCESS,
|
||||
ERROR,
|
||||
SET_PERSIST,
|
||||
CHANGE_STATE_TREE_SETTINGS,
|
||||
CLEAR_INSTANCES,
|
||||
} from '../constants/actionTypes';
|
||||
import { Action } from 'redux';
|
||||
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/core';
|
||||
|
||||
let monitorReducer: (
|
||||
monitorProps: unknown,
|
||||
state: unknown | undefined,
|
||||
action: Action<string>,
|
||||
) => unknown;
|
||||
let monitorProps: unknown = {};
|
||||
|
||||
export interface ChangeSectionAction {
|
||||
readonly type: typeof CHANGE_SECTION;
|
||||
readonly section: string;
|
||||
}
|
||||
export function changeSection(section: string): ChangeSectionAction {
|
||||
return { type: CHANGE_SECTION, section };
|
||||
}
|
||||
|
||||
interface ChangeThemeFormData {
|
||||
readonly theme: ThemeName;
|
||||
readonly scheme: SchemeName;
|
||||
readonly colorPreference: 'auto' | 'light' | 'dark';
|
||||
}
|
||||
interface ChangeThemeData {
|
||||
readonly formData: ChangeThemeFormData;
|
||||
}
|
||||
export interface ChangeThemeAction {
|
||||
readonly type: typeof CHANGE_THEME;
|
||||
readonly theme: ThemeName;
|
||||
readonly scheme: SchemeName;
|
||||
readonly colorPreference: 'auto' | 'light' | 'dark';
|
||||
}
|
||||
export function changeTheme(data: ChangeThemeData): ChangeThemeAction {
|
||||
return { type: CHANGE_THEME, ...data.formData };
|
||||
}
|
||||
|
||||
interface ChangeStateTreeSettingsFormData {
|
||||
readonly sortAlphabetically: boolean;
|
||||
readonly disableCollection: boolean;
|
||||
}
|
||||
|
||||
interface ChangeStateTreeSettingsData {
|
||||
readonly formData: ChangeStateTreeSettingsFormData;
|
||||
}
|
||||
|
||||
export interface ChangeStateTreeSettingsAction {
|
||||
readonly type: typeof CHANGE_STATE_TREE_SETTINGS;
|
||||
readonly sortAlphabetically: boolean;
|
||||
readonly disableCollection: boolean;
|
||||
}
|
||||
|
||||
export function changeStateTreeSettings(
|
||||
data: ChangeStateTreeSettingsData,
|
||||
): ChangeStateTreeSettingsAction {
|
||||
return { type: CHANGE_STATE_TREE_SETTINGS, ...data.formData };
|
||||
}
|
||||
|
||||
export interface InitMonitorAction {
|
||||
type: '@@INIT_MONITOR';
|
||||
newMonitorState: unknown;
|
||||
update: (
|
||||
monitorProps: unknown,
|
||||
state: unknown | undefined,
|
||||
action: Action<string>,
|
||||
) => unknown;
|
||||
monitorProps: unknown;
|
||||
}
|
||||
export interface MonitorActionAction {
|
||||
type: typeof MONITOR_ACTION;
|
||||
action: InitMonitorAction;
|
||||
monitorReducer: (
|
||||
monitorProps: unknown,
|
||||
state: unknown | undefined,
|
||||
action: Action<string>,
|
||||
) => unknown;
|
||||
monitorProps: unknown;
|
||||
}
|
||||
export interface JumpToStateAction {
|
||||
type: 'JUMP_TO_STATE';
|
||||
index: number;
|
||||
}
|
||||
export interface JumpToActionAction {
|
||||
type: 'JUMP_TO_ACTION';
|
||||
actionId: number;
|
||||
}
|
||||
export interface PauseRecordingAction {
|
||||
type: 'PAUSE_RECORDING';
|
||||
status: boolean;
|
||||
}
|
||||
export interface LockChangesAction {
|
||||
type: 'LOCK_CHANGES';
|
||||
status: boolean;
|
||||
}
|
||||
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, Action<string>, unknown>
|
||||
| readonly Action<string>[];
|
||||
preloadedState?: unknown;
|
||||
noRecompute?: boolean | undefined;
|
||||
}
|
||||
export type DispatchAction =
|
||||
| JumpToStateAction
|
||||
| JumpToActionAction
|
||||
| PauseRecordingAction
|
||||
| LockChangesAction
|
||||
| ToggleActionAction
|
||||
| RollbackAction
|
||||
| SweepAction
|
||||
| ReorderActionAction
|
||||
| ImportStateAction;
|
||||
interface LiftedActionActionBase {
|
||||
action?: DispatchAction | string | CustomAction;
|
||||
state?: string;
|
||||
toAll?: boolean;
|
||||
}
|
||||
export interface LiftedActionDispatchAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'DISPATCH';
|
||||
action: DispatchAction;
|
||||
toAll?: boolean;
|
||||
}
|
||||
export interface LiftedActionImportAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'IMPORT';
|
||||
state: string;
|
||||
preloadedState: unknown | undefined;
|
||||
}
|
||||
export interface LiftedActionActionAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'ACTION';
|
||||
action: string | CustomAction;
|
||||
}
|
||||
export interface LiftedActionExportAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'EXPORT';
|
||||
toExport: boolean;
|
||||
}
|
||||
export type LiftedActionAction =
|
||||
| LiftedActionDispatchAction
|
||||
| LiftedActionImportAction
|
||||
| LiftedActionActionAction
|
||||
| LiftedActionExportAction;
|
||||
export function liftedDispatch(
|
||||
action:
|
||||
| InitMonitorAction
|
||||
| JumpToStateAction
|
||||
| JumpToActionAction
|
||||
| LiftedAction<unknown, Action<string>, unknown>,
|
||||
): MonitorActionAction | LiftedActionDispatchAction {
|
||||
if (action.type[0] === '@') {
|
||||
if (action.type === '@@INIT_MONITOR') {
|
||||
monitorReducer = action.update;
|
||||
monitorProps = action.monitorProps;
|
||||
}
|
||||
return {
|
||||
type: MONITOR_ACTION,
|
||||
action,
|
||||
monitorReducer,
|
||||
monitorProps,
|
||||
} as MonitorActionAction;
|
||||
}
|
||||
return {
|
||||
type: LIFTED_ACTION,
|
||||
message: 'DISPATCH',
|
||||
action,
|
||||
} as LiftedActionDispatchAction;
|
||||
}
|
||||
|
||||
export interface SelectInstanceAction {
|
||||
type: typeof SELECT_INSTANCE;
|
||||
selected: string | number;
|
||||
}
|
||||
export function selectInstance(selected: string): SelectInstanceAction {
|
||||
return { type: SELECT_INSTANCE, selected };
|
||||
}
|
||||
|
||||
export interface SelectMonitorAction {
|
||||
type: typeof SELECT_MONITOR;
|
||||
monitor: string;
|
||||
monitorState?: MonitorStateMonitorState;
|
||||
}
|
||||
export function selectMonitor(monitor: string): SelectMonitorAction {
|
||||
return { type: SELECT_MONITOR, monitor };
|
||||
}
|
||||
export function selectMonitorWithState(
|
||||
value: string,
|
||||
monitorState: MonitorStateMonitorState,
|
||||
): SelectMonitorAction {
|
||||
return { type: SELECT_MONITOR, monitor: value, monitorState };
|
||||
}
|
||||
|
||||
interface NextState {
|
||||
subTabName: string;
|
||||
inspectedStatePath?: string[];
|
||||
}
|
||||
export interface UpdateMonitorStateAction {
|
||||
type: typeof UPDATE_MONITOR_STATE;
|
||||
nextState: NextState;
|
||||
}
|
||||
export function selectMonitorTab(subTabName: string): UpdateMonitorStateAction {
|
||||
return { type: UPDATE_MONITOR_STATE, nextState: { subTabName } };
|
||||
}
|
||||
|
||||
export function updateMonitorState(
|
||||
nextState: NextState,
|
||||
): UpdateMonitorStateAction {
|
||||
return { type: UPDATE_MONITOR_STATE, nextState };
|
||||
}
|
||||
|
||||
export function importState(
|
||||
state: string,
|
||||
preloadedState?: unknown,
|
||||
): LiftedActionImportAction {
|
||||
return { type: LIFTED_ACTION, message: 'IMPORT', state, preloadedState };
|
||||
}
|
||||
|
||||
export interface ExportAction {
|
||||
type: typeof EXPORT;
|
||||
}
|
||||
export function exportState(): ExportAction {
|
||||
return { type: EXPORT };
|
||||
}
|
||||
|
||||
export function lockChanges(status: boolean): LiftedActionDispatchAction {
|
||||
return {
|
||||
type: LIFTED_ACTION,
|
||||
message: 'DISPATCH',
|
||||
action: { type: 'LOCK_CHANGES', status },
|
||||
toAll: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function pauseRecording(status: boolean): LiftedActionDispatchAction {
|
||||
return {
|
||||
type: LIFTED_ACTION,
|
||||
message: 'DISPATCH',
|
||||
action: { type: 'PAUSE_RECORDING', status },
|
||||
toAll: true,
|
||||
};
|
||||
}
|
||||
|
||||
export interface CustomAction {
|
||||
name: string;
|
||||
selected: number;
|
||||
args: string[];
|
||||
rest: string;
|
||||
}
|
||||
export function dispatchRemotely(
|
||||
action: string | CustomAction,
|
||||
): LiftedActionActionAction {
|
||||
return { type: LIFTED_ACTION, message: 'ACTION', action };
|
||||
}
|
||||
|
||||
export interface TogglePersistAction {
|
||||
type: typeof TOGGLE_PERSIST;
|
||||
}
|
||||
export function togglePersist(): TogglePersistAction {
|
||||
return { type: TOGGLE_PERSIST };
|
||||
}
|
||||
|
||||
export interface SetPersistAction {
|
||||
type: typeof SET_PERSIST;
|
||||
payload: boolean;
|
||||
}
|
||||
export function setPersist(persist: boolean): SetPersistAction {
|
||||
return { type: SET_PERSIST, payload: persist };
|
||||
}
|
||||
|
||||
export interface ToggleSyncAction {
|
||||
type: typeof TOGGLE_SYNC;
|
||||
}
|
||||
export function toggleSync(): ToggleSyncAction {
|
||||
return { type: TOGGLE_SYNC };
|
||||
}
|
||||
|
||||
export interface ToggleSliderAction {
|
||||
type: typeof TOGGLE_SLIDER;
|
||||
}
|
||||
export function toggleSlider(): ToggleSliderAction {
|
||||
return { type: TOGGLE_SLIDER };
|
||||
}
|
||||
|
||||
export interface ToggleDispatcherAction {
|
||||
type: typeof TOGGLE_DISPATCHER;
|
||||
}
|
||||
export function toggleDispatcher(): ToggleDispatcherAction {
|
||||
return { type: TOGGLE_DISPATCHER };
|
||||
}
|
||||
|
||||
interface Notification {
|
||||
readonly type: 'error';
|
||||
readonly message: string;
|
||||
}
|
||||
export interface ShowNotificationAction {
|
||||
readonly type: typeof SHOW_NOTIFICATION;
|
||||
readonly notification: Notification;
|
||||
}
|
||||
export function showNotification(message: string): ShowNotificationAction {
|
||||
return { type: SHOW_NOTIFICATION, notification: { type: 'error', message } };
|
||||
}
|
||||
|
||||
export interface ClearNotificationAction {
|
||||
readonly type: typeof CLEAR_NOTIFICATION;
|
||||
}
|
||||
export function clearNotification(): ClearNotificationAction {
|
||||
return { type: CLEAR_NOTIFICATION };
|
||||
}
|
||||
|
||||
export interface GetReportRequest {
|
||||
readonly type: typeof GET_REPORT_REQUEST;
|
||||
readonly report: unknown;
|
||||
}
|
||||
export function getReport(report: unknown): GetReportRequest {
|
||||
return { type: GET_REPORT_REQUEST, report };
|
||||
}
|
||||
|
||||
export interface ActionCreator {
|
||||
args: string[];
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface LibConfig {
|
||||
actionCreators?: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
features?: Features;
|
||||
serialize?: boolean;
|
||||
}
|
||||
|
||||
export interface RequestBase {
|
||||
id?: string;
|
||||
instanceId?: string | number;
|
||||
action?: string;
|
||||
name?: string | undefined;
|
||||
libConfig?: LibConfig;
|
||||
actionsById?: string;
|
||||
computedStates?: string;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
payload?: {} | string;
|
||||
liftedState?: Partial<State>;
|
||||
}
|
||||
interface InitRequest extends RequestBase {
|
||||
type: 'INIT';
|
||||
action?: string;
|
||||
payload?: string;
|
||||
}
|
||||
interface ActionRequest extends RequestBase {
|
||||
type: 'ACTION';
|
||||
isExcess?: boolean;
|
||||
nextActionId: number;
|
||||
maxAge: number;
|
||||
batched?: boolean;
|
||||
}
|
||||
interface StateRequest extends RequestBase {
|
||||
type: 'STATE';
|
||||
committedState: unknown;
|
||||
}
|
||||
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
|
||||
| ExportRequest;
|
||||
|
||||
export interface UpdateStateAction {
|
||||
type: typeof UPDATE_STATE;
|
||||
request?: Request;
|
||||
id?: string | number;
|
||||
}
|
||||
|
||||
export interface SetStateAction {
|
||||
type: typeof SET_STATE;
|
||||
newState: State;
|
||||
}
|
||||
|
||||
export interface RemoveInstanceAction {
|
||||
type: typeof REMOVE_INSTANCE;
|
||||
id: string | number;
|
||||
}
|
||||
|
||||
export interface ClearInstancesAction {
|
||||
type: typeof CLEAR_INSTANCES;
|
||||
}
|
||||
|
||||
interface ListRequest {
|
||||
type: 'list';
|
||||
data: Data[];
|
||||
}
|
||||
interface AddRequest {
|
||||
type: 'add';
|
||||
data: Data;
|
||||
}
|
||||
interface RemoveRequest {
|
||||
type: 'remove';
|
||||
data: Data;
|
||||
id: unknown;
|
||||
}
|
||||
export type UpdateReportsRequest = ListRequest | AddRequest | RemoveRequest;
|
||||
export interface UpdateReportsAction {
|
||||
type: typeof UPDATE_REPORTS;
|
||||
request: UpdateReportsRequest;
|
||||
}
|
||||
|
||||
export interface GetReportError {
|
||||
type: typeof GET_REPORT_ERROR;
|
||||
error: Error;
|
||||
}
|
||||
|
||||
export interface GetReportSuccess {
|
||||
type: typeof GET_REPORT_SUCCESS;
|
||||
data: { payload: string };
|
||||
}
|
||||
|
||||
export interface ErrorAction {
|
||||
type: typeof ERROR;
|
||||
payload: string;
|
||||
}
|
||||
|
||||
export interface ReduxPersistRehydrateAction {
|
||||
type: typeof REHYDRATE;
|
||||
payload: unknown;
|
||||
}
|
||||
|
||||
export type CoreStoreActionWithoutUpdateStateOrLiftedAction =
|
||||
| ChangeSectionAction
|
||||
| ChangeThemeAction
|
||||
| ChangeStateTreeSettingsAction
|
||||
| MonitorActionAction
|
||||
| SelectInstanceAction
|
||||
| SelectMonitorAction
|
||||
| UpdateMonitorStateAction
|
||||
| ExportAction
|
||||
| TogglePersistAction
|
||||
| SetPersistAction
|
||||
| ToggleSyncAction
|
||||
| ToggleSliderAction
|
||||
| ToggleDispatcherAction
|
||||
| ShowNotificationAction
|
||||
| ClearNotificationAction
|
||||
| GetReportRequest
|
||||
| SetStateAction
|
||||
| RemoveInstanceAction
|
||||
| ClearInstancesAction
|
||||
| UpdateReportsAction
|
||||
| GetReportError
|
||||
| GetReportSuccess
|
||||
| ErrorAction
|
||||
| ReduxPersistRehydrateAction;
|
||||
|
||||
export type CoreStoreActionWithoutUpdateState =
|
||||
| CoreStoreActionWithoutUpdateStateOrLiftedAction
|
||||
| LiftedActionAction;
|
||||
|
||||
export type CoreStoreActionWithoutLiftedAction =
|
||||
| CoreStoreActionWithoutUpdateStateOrLiftedAction
|
||||
| UpdateStateAction;
|
||||
|
||||
export type CoreStoreAction =
|
||||
| CoreStoreActionWithoutUpdateState
|
||||
| UpdateStateAction;
|
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||
import { connect, ResolveThunks } from 'react-redux';
|
||||
import { Select } from '@redux-devtools/ui';
|
||||
import { selectInstance } from '../actions';
|
||||
import { StoreState } from '../reducers';
|
||||
import { CoreStoreState } from '../reducers';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -32,7 +32,7 @@ class InstanceSelector extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
const mapStateToProps = (state: CoreStoreState) => ({
|
||||
selected: state.instances.selected,
|
||||
instances: state.instances.options,
|
||||
});
|
|
@ -3,7 +3,7 @@ import { connect, ResolveThunks } from 'react-redux';
|
|||
import { Tabs } from '@redux-devtools/ui';
|
||||
import { monitors } from '../utils/getMonitor';
|
||||
import { selectMonitor } from '../actions';
|
||||
import { StoreState } from '../reducers';
|
||||
import { CoreStoreState } from '../reducers';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -28,7 +28,7 @@ class MonitorSelector extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
const mapStateToProps = (state: CoreStoreState) => ({
|
||||
selected: state.monitor.selected,
|
||||
});
|
||||
|
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||
import { connect, ResolveThunks } from 'react-redux';
|
||||
import { Container, Form } from '@redux-devtools/ui';
|
||||
import { changeStateTreeSettings } from '../../actions';
|
||||
import { StoreState } from '../../reducers';
|
||||
import { CoreStoreState } from '../../reducers';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -41,7 +41,7 @@ export class StateTree extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
const mapStateToProps = (state: CoreStoreState) => ({
|
||||
theme: state.stateTreeSettings,
|
||||
});
|
||||
|
|
@ -3,7 +3,7 @@ import { connect, ResolveThunks } from 'react-redux';
|
|||
import { Container, Form } from '@redux-devtools/ui';
|
||||
import { listSchemes, listThemes } from '@redux-devtools/ui';
|
||||
import { changeTheme } from '../../actions';
|
||||
import { StoreState } from '../../reducers';
|
||||
import { CoreStoreState } from '../../reducers';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -49,7 +49,7 @@ export class Themes extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
const mapStateToProps = (state: CoreStoreState) => ({
|
||||
theme: state.theme,
|
||||
});
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Tabs } from '@redux-devtools/ui';
|
||||
import Themes from './Themes';
|
||||
import StateTree from './StateTree';
|
||||
|
||||
interface Props {
|
||||
extraTabs?: { name: string; component: React.ComponentType }[];
|
||||
}
|
||||
|
||||
interface State {
|
||||
selected: string | undefined;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export default class Settings extends Component<Props, State> {
|
||||
state: State = { selected: undefined };
|
||||
|
||||
handleSelect = (selected: string) => {
|
||||
this.setState({ selected });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { extraTabs = [] } = this.props;
|
||||
const tabs = [
|
||||
...extraTabs,
|
||||
{ name: 'Themes', component: Themes },
|
||||
{ name: 'State Tree', component: StateTree },
|
||||
];
|
||||
return (
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
<Tabs<{}>
|
||||
tabs={tabs as any}
|
||||
selected={this.state.selected || tabs[0].name}
|
||||
onClick={this.handleSelect}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { Button } from '@redux-devtools/ui';
|
||||
import { IoIosLock } from 'react-icons/io';
|
||||
import { lockChanges, StoreAction } from '../../actions';
|
||||
import { lockChanges, CoreStoreAction } from '../../actions';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
type DispatchProps = ReturnType<typeof mapDispatchToProps>;
|
||||
|
@ -33,7 +33,7 @@ class LockButton extends Component<Props> {
|
|||
}
|
||||
|
||||
function mapDispatchToProps(
|
||||
dispatch: Dispatch<StoreAction>,
|
||||
dispatch: Dispatch<CoreStoreAction>,
|
||||
ownProps: OwnProps,
|
||||
) {
|
||||
return {
|
|
@ -3,7 +3,7 @@ import { connect, ResolveThunks } from 'react-redux';
|
|||
import { Button } from '@redux-devtools/ui';
|
||||
import { FaThumbtack } from 'react-icons/fa';
|
||||
import { togglePersist } from '../../actions';
|
||||
import { StoreState } from '../../reducers';
|
||||
import { CoreStoreState } from '../../reducers';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -36,7 +36,7 @@ class LockButton extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
const mapStateToProps = (state: CoreStoreState) => ({
|
||||
persisted: state.instances.persisted,
|
||||
});
|
||||
|
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { Button } from '@redux-devtools/ui';
|
||||
import { MdFiberManualRecord } from 'react-icons/md';
|
||||
import { pauseRecording, StoreAction } from '../../actions';
|
||||
import { pauseRecording, CoreStoreAction } from '../../actions';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
type DispatchProps = ReturnType<typeof mapDispatchToProps>;
|
||||
|
@ -31,7 +31,7 @@ class RecordButton extends Component<Props> {
|
|||
}
|
||||
|
||||
function mapDispatchToProps(
|
||||
dispatch: Dispatch<StoreAction>,
|
||||
dispatch: Dispatch<CoreStoreAction>,
|
||||
ownProps: OwnProps,
|
||||
) {
|
||||
return {
|
|
@ -3,7 +3,7 @@ import { connect, ResolveThunks } from 'react-redux';
|
|||
import { Button } from '@redux-devtools/ui';
|
||||
import { TiArrowSync } from 'react-icons/ti';
|
||||
import { toggleSync } from '../../actions';
|
||||
import { StoreState } from '../../reducers';
|
||||
import { CoreStoreState } from '../../reducers';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -28,7 +28,7 @@ class SyncButton extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
const mapStateToProps = (state: CoreStoreState) => ({
|
||||
sync: state.instances.sync,
|
||||
});
|
||||
|
|
@ -6,6 +6,7 @@ export const UPDATE_STATE = 'devTools/UPDATE_STATE';
|
|||
export const SET_STATE = 'devTools/SET_STATE';
|
||||
export const SELECT_INSTANCE = 'devTools/SELECT_INSTANCE';
|
||||
export const REMOVE_INSTANCE = 'devTools/REMOVE_INSTANCE';
|
||||
export const CLEAR_INSTANCES = 'devTools/CLEAR_INSTANCES';
|
||||
export const LIFTED_ACTION = 'devTools/LIFTED_ACTION';
|
||||
export const MONITOR_ACTION = 'devTools/MONITOR_ACTION';
|
||||
export const TOGGLE_SYNC = 'devTools/TOGGLE_SYNC';
|
|
@ -4,11 +4,11 @@ import { Container } from '@redux-devtools/ui';
|
|||
import SliderMonitor from './monitors/Slider';
|
||||
import { liftedDispatch, getReport } from '../actions';
|
||||
import { getActiveInstance } from '../reducers/instances';
|
||||
import DevTools from '../containers/DevTools';
|
||||
import DevTools from './DevTools';
|
||||
import Dispatcher from './monitors/Dispatcher';
|
||||
import TopButtons from '../components/TopButtons';
|
||||
import BottomButtons from '../components/BottomButtons';
|
||||
import { StoreState } from '../reducers';
|
||||
import { CoreStoreState } from '../reducers';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -56,7 +56,7 @@ class Actions extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => {
|
||||
const mapStateToProps = (state: CoreStoreState) => {
|
||||
const instances = state.instances;
|
||||
const id = getActiveInstance(instances);
|
||||
return {
|
|
@ -3,21 +3,24 @@ import { connect, ResolveThunks } from 'react-redux';
|
|||
import { Container, Notification } from '@redux-devtools/ui';
|
||||
import { clearNotification } from '../actions';
|
||||
import Header from '../components/Header';
|
||||
import Actions from '../containers/Actions';
|
||||
import Actions from './Actions';
|
||||
import Settings from '../components/Settings';
|
||||
import { StoreState } from '../reducers';
|
||||
import { CoreStoreState } from '../reducers';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
type Props = StateProps & DispatchProps;
|
||||
type OwnProps = {
|
||||
extraSettingsTabs?: { name: string; component: React.ComponentType }[];
|
||||
};
|
||||
type Props = StateProps & DispatchProps & OwnProps;
|
||||
|
||||
class App extends Component<Props> {
|
||||
render() {
|
||||
const { section, theme, notification } = this.props;
|
||||
const { extraSettingsTabs, section, theme, notification } = this.props;
|
||||
let body;
|
||||
switch (section) {
|
||||
case 'Settings':
|
||||
body = <Settings />;
|
||||
body = <Settings extraTabs={extraSettingsTabs} />;
|
||||
break;
|
||||
default:
|
||||
body = <Actions />;
|
||||
|
@ -40,7 +43,7 @@ class App extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
const mapStateToProps = (state: CoreStoreState) => ({
|
||||
section: state.section,
|
||||
theme: state.theme,
|
||||
notification: state.notification,
|
|
@ -12,7 +12,7 @@ import { selectMonitorTab } from '../../../actions';
|
|||
import RawTab from './RawTab';
|
||||
import ChartTab from './ChartTab';
|
||||
import VisualDiffTab from './VisualDiffTab';
|
||||
import { StoreState } from '../../../reducers';
|
||||
import { CoreStoreState } from '../../../reducers';
|
||||
import type { Delta } from 'jsondiffpatch';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
|
@ -99,7 +99,7 @@ class SubTabs extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
const mapStateToProps = (state: CoreStoreState) => ({
|
||||
parentTab: state.monitor.monitorState!.tabName,
|
||||
selected: state.monitor.monitorState!.subTabName,
|
||||
});
|
26
packages/redux-devtools-app-core/src/index.tsx
Normal file
26
packages/redux-devtools-app-core/src/index.tsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
export * from './actions';
|
||||
export { default as DispatcherButton } from './components/buttons/DispatcherButton';
|
||||
export { default as ExportButton } from './components/buttons/ExportButton';
|
||||
export { default as ImportButton } from './components/buttons/ImportButton';
|
||||
export { default as PrintButton } from './components/buttons/PrintButton';
|
||||
export { default as SliderButton } from './components/buttons/SliderButton';
|
||||
export { default as Header } from './components/Header';
|
||||
export { default as MonitorSelector } from './components/MonitorSelector';
|
||||
export { default as Settings } from './components/Settings';
|
||||
export { default as TopButtons } from './components/TopButtons';
|
||||
export { default as App } from './containers/App';
|
||||
export { default as DevTools } from './containers/DevTools';
|
||||
export { default as Dispatcher } from './containers/monitors/Dispatcher';
|
||||
export { default as SliderMonitor } from './containers/monitors/Slider';
|
||||
export * from './constants/actionTypes';
|
||||
export { default as middlewares } from './middlewares';
|
||||
export * from './middlewares/exportState';
|
||||
export * from './reducers';
|
||||
export * from './reducers/instances';
|
||||
export * from './reducers/monitor';
|
||||
export * from './reducers/notification';
|
||||
export * from './reducers/reports';
|
||||
export * from './reducers/section';
|
||||
export * from './reducers/theme';
|
||||
export * from './reducers/stateTreeSettings';
|
||||
export * from './utils/stringifyJSON';
|
|
@ -2,8 +2,8 @@ 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';
|
||||
import { CoreStoreAction } from '../actions';
|
||||
import { CoreStoreState } from '../reducers';
|
||||
|
||||
let toExport: string | number | undefined;
|
||||
|
||||
|
@ -23,9 +23,9 @@ function download(state: string) {
|
|||
}
|
||||
|
||||
export const exportStateMiddleware =
|
||||
(store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>) =>
|
||||
(next: Dispatch<StoreAction>) =>
|
||||
(action: StoreAction) => {
|
||||
(store: MiddlewareAPI<Dispatch<CoreStoreAction>, CoreStoreState>) =>
|
||||
(next: Dispatch<CoreStoreAction>) =>
|
||||
(action: CoreStoreAction) => {
|
||||
const result = next(action);
|
||||
|
||||
if (
|
|
@ -0,0 +1,5 @@
|
|||
import { exportStateMiddleware } from './exportState';
|
||||
|
||||
const middlewares = [exportStateMiddleware];
|
||||
|
||||
export default middlewares;
|
27
packages/redux-devtools-app-core/src/reducers/index.ts
Normal file
27
packages/redux-devtools-app-core/src/reducers/index.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { section, SectionState } from './section';
|
||||
import { monitor, MonitorState } from './monitor';
|
||||
import { notification, NotificationState } from './notification';
|
||||
import { instances, InstancesState } from './instances';
|
||||
import { reports, ReportsState } from './reports';
|
||||
import { theme, ThemeState } from './theme';
|
||||
import { stateTreeSettings, StateTreeSettings } from './stateTreeSettings';
|
||||
|
||||
export interface CoreStoreState {
|
||||
readonly section: SectionState;
|
||||
readonly theme: ThemeState;
|
||||
readonly stateTreeSettings: StateTreeSettings;
|
||||
readonly monitor: MonitorState;
|
||||
readonly instances: InstancesState;
|
||||
readonly reports: ReportsState;
|
||||
readonly notification: NotificationState;
|
||||
}
|
||||
|
||||
export const coreReducers = {
|
||||
section,
|
||||
theme,
|
||||
stateTreeSettings,
|
||||
monitor,
|
||||
instances,
|
||||
reports,
|
||||
notification,
|
||||
};
|
|
@ -9,15 +9,15 @@ import {
|
|||
TOGGLE_PERSIST,
|
||||
TOGGLE_SYNC,
|
||||
SET_PERSIST,
|
||||
CLEAR_INSTANCES,
|
||||
} from '../constants/actionTypes';
|
||||
import { DISCONNECTED } from '../constants/socketActionTypes';
|
||||
import parseJSON from '../utils/parseJSON';
|
||||
import { recompute } from '../utils/updateState';
|
||||
import {
|
||||
ActionCreator,
|
||||
LiftedActionDispatchAction,
|
||||
Request,
|
||||
StoreAction,
|
||||
CoreStoreAction,
|
||||
} from '../actions';
|
||||
|
||||
export interface Features {
|
||||
|
@ -305,7 +305,7 @@ function init(
|
|||
|
||||
export function instances(
|
||||
state = instancesInitialState,
|
||||
action: StoreAction,
|
||||
action: CoreStoreAction,
|
||||
): InstancesState {
|
||||
switch (action.type) {
|
||||
case UPDATE_STATE: {
|
||||
|
@ -374,7 +374,7 @@ export function instances(
|
|||
}
|
||||
return state;
|
||||
}
|
||||
case DISCONNECTED:
|
||||
case CLEAR_INSTANCES:
|
||||
return instancesInitialState;
|
||||
default:
|
||||
return state;
|
|
@ -6,7 +6,7 @@ import {
|
|||
TOGGLE_SLIDER,
|
||||
TOGGLE_DISPATCHER,
|
||||
} from '../constants/actionTypes';
|
||||
import { MonitorActionAction, StoreAction } from '../actions';
|
||||
import { MonitorActionAction, CoreStoreAction } from '../actions';
|
||||
|
||||
export interface MonitorStateMonitorState {
|
||||
inspectedStatePath?: string[];
|
||||
|
@ -48,7 +48,7 @@ export function dispatchMonitorAction(
|
|||
|
||||
export function monitor(
|
||||
state = initialState,
|
||||
action: StoreAction,
|
||||
action: CoreStoreAction,
|
||||
): MonitorState {
|
||||
switch (action.type) {
|
||||
case MONITOR_ACTION:
|
|
@ -4,7 +4,7 @@ import {
|
|||
LIFTED_ACTION,
|
||||
ERROR,
|
||||
} from '../constants/actionTypes';
|
||||
import { StoreAction } from '../actions';
|
||||
import { CoreStoreAction } from '../actions';
|
||||
|
||||
interface Notification {
|
||||
readonly type: 'error';
|
||||
|
@ -14,7 +14,7 @@ export type NotificationState = Notification | null;
|
|||
|
||||
export function notification(
|
||||
state: NotificationState = null,
|
||||
action: StoreAction,
|
||||
action: CoreStoreAction,
|
||||
): NotificationState {
|
||||
switch (action.type) {
|
||||
case SHOW_NOTIFICATION:
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
UPDATE_REPORTS /* , GET_REPORT_SUCCESS */,
|
||||
} from '../constants/actionTypes';
|
||||
import { StoreAction } from '../actions';
|
||||
import { CoreStoreAction } from '../actions';
|
||||
|
||||
export interface Data {
|
||||
id: unknown;
|
||||
|
@ -17,7 +17,7 @@ const initialState: ReportsState = {
|
|||
|
||||
export function reports(
|
||||
state = initialState,
|
||||
action: StoreAction,
|
||||
action: CoreStoreAction,
|
||||
): ReportsState {
|
||||
/* if (action.type === GET_REPORT_SUCCESS) {
|
||||
const id = action.data.id;
|
|
@ -1,9 +1,9 @@
|
|||
import { CHANGE_SECTION } from '../constants/actionTypes';
|
||||
import { StoreAction } from '../actions';
|
||||
import { CoreStoreAction } from '../actions';
|
||||
|
||||
export type SectionState = string;
|
||||
|
||||
export function section(state = 'Actions', action: StoreAction) {
|
||||
export function section(state = 'Actions', action: CoreStoreAction) {
|
||||
if (action.type === CHANGE_SECTION) {
|
||||
return action.section;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { CHANGE_STATE_TREE_SETTINGS } from '../constants/actionTypes';
|
||||
import { StoreAction } from '../actions';
|
||||
import { CoreStoreAction } from '../actions';
|
||||
|
||||
export interface StateTreeSettings {
|
||||
readonly sortAlphabetically: boolean;
|
||||
|
@ -11,7 +11,7 @@ export function stateTreeSettings(
|
|||
sortAlphabetically: false,
|
||||
disableCollection: false,
|
||||
},
|
||||
action: StoreAction,
|
||||
action: CoreStoreAction,
|
||||
) {
|
||||
if (action.type === CHANGE_STATE_TREE_SETTINGS) {
|
||||
return {
|
|
@ -1,6 +1,6 @@
|
|||
import { SchemeName, ThemeName } from '@redux-devtools/ui';
|
||||
import { CHANGE_THEME } from '../constants/actionTypes';
|
||||
import { StoreAction } from '../actions';
|
||||
import { CoreStoreAction } from '../actions';
|
||||
|
||||
export interface ThemeState {
|
||||
readonly theme: ThemeName;
|
||||
|
@ -14,7 +14,7 @@ export function theme(
|
|||
scheme: 'default',
|
||||
colorPreference: 'auto',
|
||||
},
|
||||
action: StoreAction,
|
||||
action: CoreStoreAction,
|
||||
) {
|
||||
if (action.type === CHANGE_THEME) {
|
||||
return {
|
|
@ -3,11 +3,11 @@ import { Provider } from 'react-redux';
|
|||
import { createStore, applyMiddleware } from 'redux';
|
||||
import { render, screen, within } from '@testing-library/react';
|
||||
import App from '../src/containers/App';
|
||||
import { api } from '../src/middlewares/api';
|
||||
import { exportStateMiddleware } from '../src/middlewares/exportState';
|
||||
import { rootReducer } from '../src/reducers';
|
||||
import { coreReducers } from '../src/reducers';
|
||||
import { DATA_TYPE_KEY } from '../src/constants/dataTypes';
|
||||
import { stringifyJSON } from '../src/utils/stringifyJSON';
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
writable: true,
|
||||
|
@ -24,8 +24,8 @@ Object.defineProperty(window, 'matchMedia', {
|
|||
});
|
||||
|
||||
const store = createStore(
|
||||
rootReducer,
|
||||
applyMiddleware(exportStateMiddleware, api),
|
||||
combineReducers(coreReducers),
|
||||
applyMiddleware(exportStateMiddleware),
|
||||
);
|
||||
|
||||
describe('App container', () => {
|
8
packages/redux-devtools-app-core/tsconfig.json
Normal file
8
packages/redux-devtools-app-core/tsconfig.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../tsconfig.react.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib/types",
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"extends": "../../tsconfig.react.base.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest"]
|
||||
"types": ["node", "jest"]
|
||||
},
|
||||
"include": ["src", "test"]
|
||||
}
|
|
@ -33,32 +33,17 @@
|
|||
"build:umd": "node buildUmd.mjs --dev",
|
||||
"build:umd:min": "node buildUmd.mjs",
|
||||
"clean": "rimraf build lib umd",
|
||||
"test": "jest",
|
||||
"lint": "eslint . --ext .ts,.tsx",
|
||||
"type-check": "tsc --noEmit",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.24.7",
|
||||
"@redux-devtools/chart-monitor": "^5.0.1",
|
||||
"@redux-devtools/core": "^4.0.0",
|
||||
"@redux-devtools/inspector-monitor": "^6.0.0",
|
||||
"@redux-devtools/inspector-monitor-test-tab": "^4.0.0",
|
||||
"@redux-devtools/inspector-monitor-trace-tab": "^4.0.0",
|
||||
"@redux-devtools/log-monitor": "^5.0.0",
|
||||
"@redux-devtools/rtk-query-monitor": "^5.0.0",
|
||||
"@redux-devtools/slider-monitor": "^5.0.0",
|
||||
"@redux-devtools/ui": "^1.3.1",
|
||||
"@reduxjs/toolkit": "^1.9.7",
|
||||
"d3-state-visualizer": "^3.0.0",
|
||||
"javascript-stringify": "^2.1.0",
|
||||
"jsan": "^3.1.14",
|
||||
"jsondiffpatch": "^0.6.0",
|
||||
"@redux-devtools/app-core": "^1.0.0",
|
||||
"@redux-devtools/ui": "^1.3.2",
|
||||
"localforage": "^1.10.0",
|
||||
"jsan": "^3.1.14",
|
||||
"lodash": "^4.17.21",
|
||||
"react-icons": "^5.2.1",
|
||||
"react-is": "^18.3.1",
|
||||
"react-redux": "^8.1.3",
|
||||
"redux": "^4.2.1",
|
||||
"redux-persist": "^6.0.0",
|
||||
|
@ -74,10 +59,6 @@
|
|||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@rjsf/core": "^4.2.3",
|
||||
"@testing-library/dom": "^10.1.0",
|
||||
"@testing-library/jest-dom": "^6.4.5",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/jsan": "^3.1.5",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@types/lodash": "^4.17.4",
|
||||
|
@ -95,14 +76,11 @@
|
|||
"esbuild": "^0.21.4",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-jest": "^28.6.0",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"fork-ts-checker-webpack-plugin": "^9.0.2",
|
||||
"html-loader": "^5.0.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"rimraf": "^5.0.7",
|
||||
|
|
|
@ -1,32 +1,11 @@
|
|||
import { SchemeName, ThemeName } from '@redux-devtools/ui';
|
||||
import { AuthStates, States } from 'socketcluster-client/lib/clientsocket';
|
||||
import { REHYDRATE } from 'redux-persist';
|
||||
import {
|
||||
CHANGE_SECTION,
|
||||
CHANGE_THEME,
|
||||
SELECT_INSTANCE,
|
||||
SELECT_MONITOR,
|
||||
UPDATE_MONITOR_STATE,
|
||||
LIFTED_ACTION,
|
||||
MONITOR_ACTION,
|
||||
EXPORT,
|
||||
TOGGLE_SYNC,
|
||||
TOGGLE_SLIDER,
|
||||
TOGGLE_DISPATCHER,
|
||||
TOGGLE_PERSIST,
|
||||
GET_REPORT_REQUEST,
|
||||
SHOW_NOTIFICATION,
|
||||
CLEAR_NOTIFICATION,
|
||||
UPDATE_STATE,
|
||||
CoreStoreActionWithoutUpdateStateOrLiftedAction,
|
||||
LiftedActionAction,
|
||||
UPDATE_REPORTS,
|
||||
REMOVE_INSTANCE,
|
||||
SET_STATE,
|
||||
GET_REPORT_ERROR,
|
||||
GET_REPORT_SUCCESS,
|
||||
ERROR,
|
||||
SET_PERSIST,
|
||||
CHANGE_STATE_TREE_SETTINGS,
|
||||
} from '../constants/actionTypes';
|
||||
UPDATE_STATE,
|
||||
UpdateStateAction,
|
||||
} from '@redux-devtools/app-core';
|
||||
import {
|
||||
AUTH_ERROR,
|
||||
AUTH_REQUEST,
|
||||
|
@ -43,315 +22,6 @@ import {
|
|||
SUBSCRIBE_SUCCESS,
|
||||
UNSUBSCRIBE,
|
||||
} from '../constants/socketActionTypes';
|
||||
import { Action } from 'redux';
|
||||
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/core';
|
||||
|
||||
let monitorReducer: (
|
||||
monitorProps: unknown,
|
||||
state: unknown | undefined,
|
||||
action: Action<string>,
|
||||
) => unknown;
|
||||
let monitorProps: unknown = {};
|
||||
|
||||
export interface ChangeSectionAction {
|
||||
readonly type: typeof CHANGE_SECTION;
|
||||
readonly section: string;
|
||||
}
|
||||
export function changeSection(section: string): ChangeSectionAction {
|
||||
return { type: CHANGE_SECTION, section };
|
||||
}
|
||||
|
||||
interface ChangeThemeFormData {
|
||||
readonly theme: ThemeName;
|
||||
readonly scheme: SchemeName;
|
||||
readonly colorPreference: 'auto' | 'light' | 'dark';
|
||||
}
|
||||
interface ChangeThemeData {
|
||||
readonly formData: ChangeThemeFormData;
|
||||
}
|
||||
export interface ChangeThemeAction {
|
||||
readonly type: typeof CHANGE_THEME;
|
||||
readonly theme: ThemeName;
|
||||
readonly scheme: SchemeName;
|
||||
readonly colorPreference: 'auto' | 'light' | 'dark';
|
||||
}
|
||||
export function changeTheme(data: ChangeThemeData): ChangeThemeAction {
|
||||
return { type: CHANGE_THEME, ...data.formData };
|
||||
}
|
||||
|
||||
interface ChangeStateTreeSettingsFormData {
|
||||
readonly sortAlphabetically: boolean;
|
||||
readonly disableCollection: boolean;
|
||||
}
|
||||
|
||||
interface ChangeStateTreeSettingsData {
|
||||
readonly formData: ChangeStateTreeSettingsFormData;
|
||||
}
|
||||
|
||||
export interface ChangeStateTreeSettingsAction {
|
||||
readonly type: typeof CHANGE_STATE_TREE_SETTINGS;
|
||||
readonly sortAlphabetically: boolean;
|
||||
readonly disableCollection: boolean;
|
||||
}
|
||||
|
||||
export function changeStateTreeSettings(
|
||||
data: ChangeStateTreeSettingsData,
|
||||
): ChangeStateTreeSettingsAction {
|
||||
return { type: CHANGE_STATE_TREE_SETTINGS, ...data.formData };
|
||||
}
|
||||
|
||||
export interface InitMonitorAction {
|
||||
type: '@@INIT_MONITOR';
|
||||
newMonitorState: unknown;
|
||||
update: (
|
||||
monitorProps: unknown,
|
||||
state: unknown | undefined,
|
||||
action: Action<string>,
|
||||
) => unknown;
|
||||
monitorProps: unknown;
|
||||
}
|
||||
export interface MonitorActionAction {
|
||||
type: typeof MONITOR_ACTION;
|
||||
action: InitMonitorAction;
|
||||
monitorReducer: (
|
||||
monitorProps: unknown,
|
||||
state: unknown | undefined,
|
||||
action: Action<string>,
|
||||
) => unknown;
|
||||
monitorProps: unknown;
|
||||
}
|
||||
export interface JumpToStateAction {
|
||||
type: 'JUMP_TO_STATE';
|
||||
index: number;
|
||||
}
|
||||
export interface JumpToActionAction {
|
||||
type: 'JUMP_TO_ACTION';
|
||||
actionId: number;
|
||||
}
|
||||
export interface PauseRecordingAction {
|
||||
type: 'PAUSE_RECORDING';
|
||||
status: boolean;
|
||||
}
|
||||
export interface LockChangesAction {
|
||||
type: 'LOCK_CHANGES';
|
||||
status: boolean;
|
||||
}
|
||||
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, Action<string>, unknown>
|
||||
| readonly Action<string>[];
|
||||
preloadedState?: unknown;
|
||||
noRecompute?: boolean | undefined;
|
||||
}
|
||||
export type DispatchAction =
|
||||
| JumpToStateAction
|
||||
| JumpToActionAction
|
||||
| PauseRecordingAction
|
||||
| LockChangesAction
|
||||
| ToggleActionAction
|
||||
| RollbackAction
|
||||
| SweepAction
|
||||
| ReorderActionAction
|
||||
| ImportStateAction;
|
||||
interface LiftedActionActionBase {
|
||||
action?: DispatchAction | string | CustomAction;
|
||||
state?: string;
|
||||
toAll?: boolean;
|
||||
}
|
||||
export interface LiftedActionDispatchAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'DISPATCH';
|
||||
action: DispatchAction;
|
||||
toAll?: boolean;
|
||||
}
|
||||
export interface LiftedActionImportAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'IMPORT';
|
||||
state: string;
|
||||
preloadedState: unknown | undefined;
|
||||
}
|
||||
export interface LiftedActionActionAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'ACTION';
|
||||
action: string | CustomAction;
|
||||
}
|
||||
export interface LiftedActionExportAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
message: 'EXPORT';
|
||||
toExport: boolean;
|
||||
}
|
||||
export type LiftedActionAction =
|
||||
| LiftedActionDispatchAction
|
||||
| LiftedActionImportAction
|
||||
| LiftedActionActionAction
|
||||
| LiftedActionExportAction;
|
||||
export function liftedDispatch(
|
||||
action:
|
||||
| InitMonitorAction
|
||||
| JumpToStateAction
|
||||
| JumpToActionAction
|
||||
| LiftedAction<unknown, Action<string>, unknown>,
|
||||
): MonitorActionAction | LiftedActionDispatchAction {
|
||||
if (action.type[0] === '@') {
|
||||
if (action.type === '@@INIT_MONITOR') {
|
||||
monitorReducer = action.update;
|
||||
monitorProps = action.monitorProps;
|
||||
}
|
||||
return {
|
||||
type: MONITOR_ACTION,
|
||||
action,
|
||||
monitorReducer,
|
||||
monitorProps,
|
||||
} as MonitorActionAction;
|
||||
}
|
||||
return {
|
||||
type: LIFTED_ACTION,
|
||||
message: 'DISPATCH',
|
||||
action,
|
||||
} as LiftedActionDispatchAction;
|
||||
}
|
||||
|
||||
export interface SelectInstanceAction {
|
||||
type: typeof SELECT_INSTANCE;
|
||||
selected: string | number;
|
||||
}
|
||||
export function selectInstance(selected: string): SelectInstanceAction {
|
||||
return { type: SELECT_INSTANCE, selected };
|
||||
}
|
||||
|
||||
export interface SelectMonitorAction {
|
||||
type: typeof SELECT_MONITOR;
|
||||
monitor: string;
|
||||
monitorState?: MonitorStateMonitorState;
|
||||
}
|
||||
export function selectMonitor(monitor: string): SelectMonitorAction {
|
||||
return { type: SELECT_MONITOR, monitor };
|
||||
}
|
||||
export function selectMonitorWithState(
|
||||
value: string,
|
||||
monitorState: MonitorStateMonitorState,
|
||||
): SelectMonitorAction {
|
||||
return { type: SELECT_MONITOR, monitor: value, monitorState };
|
||||
}
|
||||
|
||||
interface NextState {
|
||||
subTabName: string;
|
||||
inspectedStatePath?: string[];
|
||||
}
|
||||
export interface UpdateMonitorStateAction {
|
||||
type: typeof UPDATE_MONITOR_STATE;
|
||||
nextState: NextState;
|
||||
}
|
||||
export function selectMonitorTab(subTabName: string): UpdateMonitorStateAction {
|
||||
return { type: UPDATE_MONITOR_STATE, nextState: { subTabName } };
|
||||
}
|
||||
|
||||
export function updateMonitorState(
|
||||
nextState: NextState,
|
||||
): UpdateMonitorStateAction {
|
||||
return { type: UPDATE_MONITOR_STATE, nextState };
|
||||
}
|
||||
|
||||
export function importState(
|
||||
state: string,
|
||||
preloadedState?: unknown,
|
||||
): LiftedActionImportAction {
|
||||
return { type: LIFTED_ACTION, message: 'IMPORT', state, preloadedState };
|
||||
}
|
||||
|
||||
export interface ExportAction {
|
||||
type: typeof EXPORT;
|
||||
}
|
||||
export function exportState(): ExportAction {
|
||||
return { type: EXPORT };
|
||||
}
|
||||
|
||||
export function lockChanges(status: boolean): LiftedActionDispatchAction {
|
||||
return {
|
||||
type: LIFTED_ACTION,
|
||||
message: 'DISPATCH',
|
||||
action: { type: 'LOCK_CHANGES', status },
|
||||
toAll: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function pauseRecording(status: boolean): LiftedActionDispatchAction {
|
||||
return {
|
||||
type: LIFTED_ACTION,
|
||||
message: 'DISPATCH',
|
||||
action: { type: 'PAUSE_RECORDING', status },
|
||||
toAll: true,
|
||||
};
|
||||
}
|
||||
|
||||
export interface CustomAction {
|
||||
name: string;
|
||||
selected: number;
|
||||
args: string[];
|
||||
rest: string;
|
||||
}
|
||||
export function dispatchRemotely(
|
||||
action: string | CustomAction,
|
||||
): LiftedActionActionAction {
|
||||
return { type: LIFTED_ACTION, message: 'ACTION', action };
|
||||
}
|
||||
|
||||
export interface TogglePersistAction {
|
||||
type: typeof TOGGLE_PERSIST;
|
||||
}
|
||||
export function togglePersist(): TogglePersistAction {
|
||||
return { type: TOGGLE_PERSIST };
|
||||
}
|
||||
|
||||
export interface SetPersistAction {
|
||||
type: typeof SET_PERSIST;
|
||||
payload: boolean;
|
||||
}
|
||||
export function setPersist(persist: boolean): SetPersistAction {
|
||||
return { type: SET_PERSIST, payload: persist };
|
||||
}
|
||||
|
||||
export interface ToggleSyncAction {
|
||||
type: typeof TOGGLE_SYNC;
|
||||
}
|
||||
export function toggleSync(): ToggleSyncAction {
|
||||
return { type: TOGGLE_SYNC };
|
||||
}
|
||||
|
||||
export interface ToggleSliderAction {
|
||||
type: typeof TOGGLE_SLIDER;
|
||||
}
|
||||
export function toggleSlider(): ToggleSliderAction {
|
||||
return { type: TOGGLE_SLIDER };
|
||||
}
|
||||
|
||||
export interface ToggleDispatcherAction {
|
||||
type: typeof TOGGLE_DISPATCHER;
|
||||
}
|
||||
export function toggleDispatcher(): ToggleDispatcherAction {
|
||||
return { type: TOGGLE_DISPATCHER };
|
||||
}
|
||||
|
||||
export type ConnectionType = 'disabled' | 'custom';
|
||||
export interface ConnectionOptions {
|
||||
|
@ -370,110 +40,6 @@ export function saveSocketSettings(
|
|||
return { type: RECONNECT, options };
|
||||
}
|
||||
|
||||
interface Notification {
|
||||
readonly type: 'error';
|
||||
readonly message: string;
|
||||
}
|
||||
export interface ShowNotificationAction {
|
||||
readonly type: typeof SHOW_NOTIFICATION;
|
||||
readonly notification: Notification;
|
||||
}
|
||||
export function showNotification(message: string): ShowNotificationAction {
|
||||
return { type: SHOW_NOTIFICATION, notification: { type: 'error', message } };
|
||||
}
|
||||
|
||||
export interface ClearNotificationAction {
|
||||
readonly type: typeof CLEAR_NOTIFICATION;
|
||||
}
|
||||
export function clearNotification(): ClearNotificationAction {
|
||||
return { type: CLEAR_NOTIFICATION };
|
||||
}
|
||||
|
||||
export interface GetReportRequest {
|
||||
readonly type: typeof GET_REPORT_REQUEST;
|
||||
readonly report: unknown;
|
||||
}
|
||||
export function getReport(report: unknown): GetReportRequest {
|
||||
return { type: GET_REPORT_REQUEST, report };
|
||||
}
|
||||
|
||||
export interface ActionCreator {
|
||||
args: string[];
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface LibConfig {
|
||||
actionCreators?: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
features?: Features;
|
||||
serialize?: boolean;
|
||||
}
|
||||
|
||||
export interface RequestBase {
|
||||
id?: string;
|
||||
instanceId?: string | number;
|
||||
action?: string;
|
||||
name?: string | undefined;
|
||||
libConfig?: LibConfig;
|
||||
actionsById?: string;
|
||||
computedStates?: string;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
payload?: {} | string;
|
||||
liftedState?: Partial<State>;
|
||||
}
|
||||
interface InitRequest extends RequestBase {
|
||||
type: 'INIT';
|
||||
action?: string;
|
||||
payload?: string;
|
||||
}
|
||||
interface ActionRequest extends RequestBase {
|
||||
type: 'ACTION';
|
||||
isExcess?: boolean;
|
||||
nextActionId: number;
|
||||
maxAge: number;
|
||||
batched?: boolean;
|
||||
}
|
||||
interface StateRequest extends RequestBase {
|
||||
type: 'STATE';
|
||||
committedState: unknown;
|
||||
}
|
||||
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
|
||||
| ExportRequest;
|
||||
|
||||
export interface UpdateStateAction {
|
||||
type: typeof UPDATE_STATE;
|
||||
request?: Request;
|
||||
id?: string | number;
|
||||
}
|
||||
|
||||
export interface SetStateAction {
|
||||
type: typeof SET_STATE;
|
||||
newState: State;
|
||||
}
|
||||
|
||||
export interface RemoveInstanceAction {
|
||||
type: typeof REMOVE_INSTANCE;
|
||||
id: string | number;
|
||||
}
|
||||
|
||||
export interface ConnectRequestAction {
|
||||
type: typeof CONNECT_REQUEST;
|
||||
}
|
||||
|
@ -548,65 +114,9 @@ export interface EmitAction {
|
|||
state?: unknown;
|
||||
}
|
||||
|
||||
interface ListRequest {
|
||||
type: 'list';
|
||||
data: Data[];
|
||||
}
|
||||
interface AddRequest {
|
||||
type: 'add';
|
||||
data: Data;
|
||||
}
|
||||
interface RemoveRequest {
|
||||
type: 'remove';
|
||||
data: Data;
|
||||
id: unknown;
|
||||
}
|
||||
export type UpdateReportsRequest = ListRequest | AddRequest | RemoveRequest;
|
||||
export interface UpdateReportsAction {
|
||||
type: typeof UPDATE_REPORTS;
|
||||
request: UpdateReportsRequest;
|
||||
}
|
||||
|
||||
export interface GetReportError {
|
||||
type: typeof GET_REPORT_ERROR;
|
||||
error: Error;
|
||||
}
|
||||
|
||||
export interface GetReportSuccess {
|
||||
type: typeof GET_REPORT_SUCCESS;
|
||||
data: { payload: string };
|
||||
}
|
||||
|
||||
export interface ErrorAction {
|
||||
type: typeof ERROR;
|
||||
payload: string;
|
||||
}
|
||||
|
||||
interface ReduxPersistRehydrateAction {
|
||||
type: typeof REHYDRATE;
|
||||
payload: unknown;
|
||||
}
|
||||
|
||||
export type StoreActionWithoutUpdateStateOrLiftedAction =
|
||||
| ChangeSectionAction
|
||||
| ChangeThemeAction
|
||||
| ChangeStateTreeSettingsAction
|
||||
| MonitorActionAction
|
||||
| SelectInstanceAction
|
||||
| SelectMonitorAction
|
||||
| UpdateMonitorStateAction
|
||||
| ExportAction
|
||||
| TogglePersistAction
|
||||
| SetPersistAction
|
||||
| ToggleSyncAction
|
||||
| ToggleSliderAction
|
||||
| ToggleDispatcherAction
|
||||
| CoreStoreActionWithoutUpdateStateOrLiftedAction
|
||||
| ReconnectAction
|
||||
| ShowNotificationAction
|
||||
| ClearNotificationAction
|
||||
| GetReportRequest
|
||||
| SetStateAction
|
||||
| RemoveInstanceAction
|
||||
| ConnectRequestAction
|
||||
| ConnectSuccessAction
|
||||
| ConnectErrorAction
|
||||
|
@ -619,12 +129,7 @@ export type StoreActionWithoutUpdateStateOrLiftedAction =
|
|||
| SubscribeSuccessAction
|
||||
| SubscribeErrorAction
|
||||
| UnsubscribeAction
|
||||
| EmitAction
|
||||
| UpdateReportsAction
|
||||
| GetReportError
|
||||
| GetReportSuccess
|
||||
| ErrorAction
|
||||
| ReduxPersistRehydrateAction;
|
||||
| EmitAction;
|
||||
|
||||
export type StoreActionWithoutUpdateState =
|
||||
| StoreActionWithoutUpdateStateOrLiftedAction
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Tabs } from '@redux-devtools/ui';
|
||||
import Connection from './Connection';
|
||||
import Themes from './Themes';
|
||||
import StateTree from './StateTree';
|
||||
|
||||
interface State {
|
||||
selected: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export default class Settings extends Component<{}, State> {
|
||||
tabs = [
|
||||
{ name: 'Connection', component: Connection },
|
||||
{ name: 'Themes', component: Themes },
|
||||
{ name: 'State Tree', component: StateTree },
|
||||
];
|
||||
state: State = { selected: 'Connection' };
|
||||
|
||||
handleSelect = (selected: string) => {
|
||||
this.setState({ selected });
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
<Tabs<{}>
|
||||
tabs={this.tabs as any}
|
||||
selected={this.state.selected}
|
||||
onClick={this.handleSelect}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,11 +3,12 @@ import { Provider } from 'react-redux';
|
|||
import { Store } from 'redux';
|
||||
import { Persistor } from 'redux-persist';
|
||||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
import configureStore from './store/configureStore';
|
||||
import { CONNECT_REQUEST } from './constants/socketActionTypes';
|
||||
import App from './containers/App';
|
||||
import { App } from '@redux-devtools/app-core';
|
||||
import { StoreState } from './reducers';
|
||||
import { StoreAction } from './actions';
|
||||
import { CONNECT_REQUEST } from './constants/socketActionTypes';
|
||||
import Connection from './components/Settings/Connection';
|
||||
import configureStore from './store/configureStore';
|
||||
|
||||
export class Root extends Component {
|
||||
store?: Store<StoreState, StoreAction>;
|
||||
|
@ -32,39 +33,20 @@ export class Root extends Component {
|
|||
return (
|
||||
<Provider store={this.store}>
|
||||
<PersistGate loading={null} persistor={this.persistor!}>
|
||||
<App />
|
||||
<App
|
||||
extraSettingsTabs={[{ name: 'Connection', component: Connection }]}
|
||||
/>
|
||||
</PersistGate>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export * from '@redux-devtools/app-core';
|
||||
export * from './actions';
|
||||
export { default as DispatcherButton } from './components/buttons/DispatcherButton';
|
||||
export { default as ExportButton } from './components/buttons/ExportButton';
|
||||
export { default as ImportButton } from './components/buttons/ImportButton';
|
||||
export { default as PrintButton } from './components/buttons/PrintButton';
|
||||
export { default as SliderButton } from './components/buttons/SliderButton';
|
||||
export { default as Header } from './components/Header';
|
||||
export { default as MonitorSelector } from './components/MonitorSelector';
|
||||
export { default as Settings } from './components/Settings';
|
||||
export { default as TopButtons } from './components/TopButtons';
|
||||
export { default as DevTools } from './containers/DevTools';
|
||||
export { default as Dispatcher } from './containers/monitors/Dispatcher';
|
||||
export { default as SliderMonitor } from './containers/monitors/Slider';
|
||||
export * from './constants/actionTypes';
|
||||
export * from './constants/socketActionTypes';
|
||||
export * from './middlewares/api';
|
||||
export * from './middlewares/exportState';
|
||||
export * from './reducers';
|
||||
export * from './reducers/connection';
|
||||
export * from './reducers/instances';
|
||||
export * from './reducers/monitor';
|
||||
export * from './reducers/notification';
|
||||
export * from './reducers/reports';
|
||||
export * from './reducers/section';
|
||||
export * from './reducers/socket';
|
||||
export * from './reducers/theme';
|
||||
export * from './reducers/stateTreeSettings';
|
||||
export * from './utils/monitorActions';
|
||||
export * from './utils/stringifyJSON';
|
||||
|
|
|
@ -1,28 +1,26 @@
|
|||
import {
|
||||
DispatchAction,
|
||||
GET_REPORT_ERROR,
|
||||
GET_REPORT_REQUEST,
|
||||
GET_REPORT_SUCCESS,
|
||||
CLEAR_INSTANCES,
|
||||
getActiveInstance,
|
||||
importState,
|
||||
LIFTED_ACTION,
|
||||
LiftedActionAction,
|
||||
REMOVE_INSTANCE,
|
||||
Request,
|
||||
showNotification,
|
||||
UPDATE_REPORTS,
|
||||
UPDATE_STATE,
|
||||
UpdateReportsRequest,
|
||||
} from '@redux-devtools/app-core';
|
||||
import socketClusterClient, { AGClientSocket } from 'socketcluster-client';
|
||||
import { stringify } from 'jsan';
|
||||
import { Dispatch, MiddlewareAPI } from 'redux';
|
||||
import * as actions from '../constants/socketActionTypes';
|
||||
import { getActiveInstance } from '../reducers/instances';
|
||||
import {
|
||||
UPDATE_STATE,
|
||||
REMOVE_INSTANCE,
|
||||
LIFTED_ACTION,
|
||||
UPDATE_REPORTS,
|
||||
GET_REPORT_REQUEST,
|
||||
GET_REPORT_ERROR,
|
||||
GET_REPORT_SUCCESS,
|
||||
} from '../constants/actionTypes';
|
||||
import {
|
||||
showNotification,
|
||||
importState,
|
||||
StoreAction,
|
||||
EmitAction,
|
||||
LiftedActionAction,
|
||||
Request,
|
||||
DispatchAction,
|
||||
UpdateReportsRequest,
|
||||
} from '../actions';
|
||||
import { nonReduxDispatch } from '../utils/monitorActions';
|
||||
import { EmitAction, StoreAction } from '../actions';
|
||||
import { StoreState } from '../reducers';
|
||||
|
||||
let socket: AGClientSocket;
|
||||
|
@ -178,6 +176,7 @@ function handleConnection() {
|
|||
void (async () => {
|
||||
for await (const data of socket.listener('disconnect')) {
|
||||
store.dispatch({ type: actions.DISCONNECTED, code: data.code });
|
||||
store.dispatch({ type: CLEAR_INSTANCES });
|
||||
}
|
||||
})();
|
||||
|
||||
|
|
|
@ -1,35 +1,17 @@
|
|||
import { CoreStoreState, coreReducers } from '@redux-devtools/app-core';
|
||||
import { combineReducers } from 'redux';
|
||||
import { section, SectionState } from './section';
|
||||
import { connection, ConnectionState } from './connection';
|
||||
import { socket, SocketState } from './socket';
|
||||
import { monitor, MonitorState } from './monitor';
|
||||
import { notification, NotificationState } from './notification';
|
||||
import { instances, InstancesState } from './instances';
|
||||
import { reports, ReportsState } from './reports';
|
||||
import { theme, ThemeState } from './theme';
|
||||
import { StoreAction } from '../actions';
|
||||
import { stateTreeSettings, StateTreeSettings } from './stateTreeSettings';
|
||||
|
||||
export interface StoreState {
|
||||
readonly section: SectionState;
|
||||
readonly theme: ThemeState;
|
||||
readonly stateTreeSettings: StateTreeSettings;
|
||||
export interface StoreState extends CoreStoreState {
|
||||
readonly connection: ConnectionState;
|
||||
readonly socket: SocketState;
|
||||
readonly monitor: MonitorState;
|
||||
readonly instances: InstancesState;
|
||||
readonly reports: ReportsState;
|
||||
readonly notification: NotificationState;
|
||||
}
|
||||
|
||||
/// @ts-expect-error An error happens due to TypeScript not being able to reconcile a clash between CoreStoreAction and StoreAction in the core reducers, but this is correct as they're a superset
|
||||
export const rootReducer = combineReducers<StoreState, StoreAction>({
|
||||
section,
|
||||
theme,
|
||||
stateTreeSettings,
|
||||
...coreReducers,
|
||||
connection,
|
||||
socket,
|
||||
monitor,
|
||||
instances,
|
||||
reports,
|
||||
notification,
|
||||
});
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { middlewares } from '@redux-devtools/app-core';
|
||||
import { createStore, compose, applyMiddleware, Reducer, Store } from 'redux';
|
||||
import localForage from 'localforage';
|
||||
import { persistReducer, persistStore } from 'redux-persist';
|
||||
import { api } from '../middlewares/api';
|
||||
import { exportStateMiddleware } from '../middlewares/exportState';
|
||||
import { rootReducer, StoreState } from '../reducers';
|
||||
import { StoreState, rootReducer } from '../reducers';
|
||||
import { StoreAction } from '../actions';
|
||||
|
||||
const persistConfig = {
|
||||
|
@ -39,7 +39,7 @@ export default function configureStore(
|
|||
|
||||
const store = createStore(
|
||||
persistedReducer,
|
||||
composeEnhancers(applyMiddleware(exportStateMiddleware, api)),
|
||||
composeEnhancers(applyMiddleware(...middlewares, api)),
|
||||
);
|
||||
const persistor = persistStore(store, null, () => {
|
||||
callback(store);
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import difference from 'lodash/difference';
|
||||
import omit from 'lodash/omit';
|
||||
import { stringifyJSON } from './stringifyJSON';
|
||||
import { SET_STATE } from '../constants/actionTypes';
|
||||
import { InstancesState, State } from '../reducers/instances';
|
||||
import {
|
||||
DispatchAction,
|
||||
InstancesState,
|
||||
SET_STATE,
|
||||
State,
|
||||
stringifyJSON,
|
||||
} from '@redux-devtools/app-core';
|
||||
import { Dispatch, MiddlewareAPI } from 'redux';
|
||||
import { DispatchAction, StoreActionWithoutLiftedAction } from '../actions';
|
||||
import { StoreActionWithoutLiftedAction } from '../actions';
|
||||
|
||||
export function sweep(state: State): State {
|
||||
return {
|
||||
|
|
22557
pnpm-lock.yaml
22557
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user