This commit is contained in:
Nathan Bierema 2020-08-27 21:51:05 -04:00
parent 5bd39f7a49
commit 72b8ef502e
13 changed files with 144 additions and 34 deletions

View File

@ -13,7 +13,11 @@
}, },
"scripts": { "scripts": {
"start": "webpack-dev-server --open", "start": "webpack-dev-server --open",
"stats": "NODE_ENV=production webpack --json > dist/stats.json" "stats": "NODE_ENV=production webpack --json > dist/stats.json",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix",
"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch"
}, },
"dependencies": { "dependencies": {
"immutable": "^4.0.0-rc.12", "immutable": "^4.0.0-rc.12",

View File

@ -23,6 +23,29 @@ interface KeyObject {
sequence: string; sequence: string;
} }
interface ExternalProps<S, A extends Action<unknown>> {
defaultPosition: 'left' | 'top' | 'right' | 'bottom';
defaultIsVisible: boolean;
defaultSize: number;
toggleVisibilityKey: string;
changePositionKey: string;
changeMonitorKey?: string;
fluid: boolean;
dispatch: Dispatch<DockMonitorAction>;
children:
| Monitor<S, A, LiftedState<S, A, unknown>, unknown, Action<unknown>>
| Monitor<S, A, LiftedState<S, A, unknown>, unknown, Action<unknown>>[];
}
interface DefaultProps {
defaultIsVisible: boolean;
defaultPosition: 'left' | 'top' | 'right' | 'bottom';
defaultSize: number;
fluid: boolean;
}
export interface DockMonitorProps<S, A extends Action<unknown>> export interface DockMonitorProps<S, A extends Action<unknown>>
extends LiftedState<S, A, DockMonitorState> { extends LiftedState<S, A, DockMonitorState> {
defaultPosition: 'left' | 'top' | 'right' | 'bottom'; defaultPosition: 'left' | 'top' | 'right' | 'bottom';
@ -40,10 +63,9 @@ export interface DockMonitorProps<S, A extends Action<unknown>>
| Monitor<S, A, LiftedState<S, A, unknown>, unknown, Action<unknown>>[]; | Monitor<S, A, LiftedState<S, A, unknown>, unknown, Action<unknown>>[];
} }
export default class DockMonitor< class DockMonitor<S, A extends Action<unknown>> extends Component<
S, DockMonitorProps<S, A>
A extends Action<unknown> > {
> extends Component<DockMonitorProps<S, A>> {
static update = reducer; static update = reducer;
static propTypes = { static propTypes = {
@ -64,7 +86,7 @@ export default class DockMonitor<
}), }),
}; };
static defaultProps = { static defaultProps: DefaultProps = {
defaultIsVisible: true, defaultIsVisible: true,
defaultPosition: 'right', defaultPosition: 'right',
defaultSize: 0.3, defaultSize: 0.3,
@ -212,3 +234,14 @@ export default class DockMonitor<
); );
} }
} }
export default (DockMonitor as unknown) as React.ComponentType<
ExternalProps<unknown, Action<unknown>>
> & {
update(
monitorProps: ExternalProps<unknown, Action<unknown>>,
state: DockMonitorState | undefined,
action: DockMonitorAction
): DockMonitorState;
defaultProps: DefaultProps;
};

View File

@ -13,6 +13,8 @@ import reducer, { LogMonitorState } from './reducers';
import LogMonitorButtonBar from './LogMonitorButtonBar'; import LogMonitorButtonBar from './LogMonitorButtonBar';
import LogMonitorEntryList from './LogMonitorEntryList'; import LogMonitorEntryList from './LogMonitorEntryList';
import debounce from 'lodash.debounce'; import debounce from 'lodash.debounce';
import { DockMonitorState } from 'redux-devtools-dock-monitor/lib/reducers';
import { DockMonitorAction } from 'redux-devtools-dock-monitor/lib/actions';
// eslint-disable-next-line @typescript-eslint/unbound-method // eslint-disable-next-line @typescript-eslint/unbound-method
const { toggleAction, setActionsActive } = ActionCreators; const { toggleAction, setActionsActive } = ActionCreators;
@ -41,6 +43,27 @@ const styles: {
}, },
}; };
interface ExternalProps<S, A extends Action<unknown>> {
dispatch: Dispatch<LogMonitorAction | LiftedAction<S, A, LogMonitorState>>;
preserveScrollTop: boolean;
select: (state: S) => unknown;
theme: keyof typeof themes | Base16Theme;
expandActionRoot: boolean;
expandStateRoot: boolean;
markStateDiff: boolean;
hideMainButtons?: boolean;
}
interface DefaultProps<S> {
select: (state: unknown) => unknown;
theme: keyof typeof themes | Base16Theme;
preserveScrollTop: boolean;
expandActionRoot: boolean;
expandStateRoot: boolean;
markStateDiff: boolean;
}
export interface LogMonitorProps<S, A extends Action<unknown>> export interface LogMonitorProps<S, A extends Action<unknown>>
extends LiftedState<S, A, LogMonitorState> { extends LiftedState<S, A, LogMonitorState> {
dispatch: Dispatch<LogMonitorAction | LiftedAction<S, A, LogMonitorState>>; dispatch: Dispatch<LogMonitorAction | LiftedAction<S, A, LogMonitorState>>;
@ -54,10 +77,9 @@ export interface LogMonitorProps<S, A extends Action<unknown>>
hideMainButtons?: boolean; hideMainButtons?: boolean;
} }
export default class LogMonitor< class LogMonitor<S, A extends Action<unknown>> extends PureComponent<
S, LogMonitorProps<S, A>
A extends Action<unknown> > {
> extends PureComponent<LogMonitorProps<S, A>> {
static update = reducer; static update = reducer;
static propTypes = { static propTypes = {
@ -80,7 +102,7 @@ export default class LogMonitor<
hideMainButtons: PropTypes.bool, hideMainButtons: PropTypes.bool,
}; };
static defaultProps = { static defaultProps: DefaultProps<unknown> = {
select: (state: unknown) => state, select: (state: unknown) => state,
theme: 'nicinabox', theme: 'nicinabox',
preserveScrollTop: true, preserveScrollTop: true,
@ -248,3 +270,14 @@ export default class LogMonitor<
); );
} }
} }
export default (LogMonitor as unknown) as React.ComponentType<
ExternalProps<unknown, Action<unknown>>
> & {
update(
monitorProps: ExternalProps<unknown, Action<unknown>>,
state: DockMonitorState | undefined,
action: DockMonitorAction
): DockMonitorState;
defaultProps: DefaultProps<unknown>;
};

View File

@ -12,25 +12,30 @@
"url": "https://github.com/reduxjs/redux-devtools.git" "url": "https://github.com/reduxjs/redux-devtools.git"
}, },
"scripts": { "scripts": {
"start": "webpack-dev-server --open" "start": "webpack-dev-server --open",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix",
"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch"
}, },
"dependencies": { "dependencies": {
"@types/prop-types": "^15.7.3",
"@types/react": "^16.9.46",
"@types/react-dom": "^16.9.8",
"@types/react-redux": "^7.1.9",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react": "^16.13.1", "react": "^16.13.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-hot-loader": "^4.12.21", "react-hot-loader": "^4.12.21",
"react-redux": "^7.2.1", "react-redux": "^7.2.1",
"redux": "^4.0.5", "redux": "^4.0.5",
"redux-devtools": "^3.6.1",
"redux-devtools-dock-monitor": "^1.1.4",
"redux-devtools-log-monitor": "^2.0.1",
"redux-thunk": "^2.3.0" "redux-thunk": "^2.3.0"
}, },
"devDependencies": { "devDependencies": {
"redux-devtools": "^3.6.1", "@types/prop-types": "^15.7.3",
"redux-devtools-dock-monitor": "^1.1.4", "@types/react": "^16.9.46",
"redux-devtools-log-monitor": "^2.0.1" "@types/react-dom": "^16.9.8",
"@types/react-redux": "^7.1.9",
"@types/webpack-env": "^1.15.2"
}, },
"private": true "private": true
} }

View File

@ -1,5 +1,15 @@
if (process.env.NODE_ENV === 'production') { import { Store } from 'redux';
module.exports = require('./Root.prod'); import { CounterState } from '../reducers';
} else { import { CounterAction } from '../actions/CounterActions';
module.exports = require('./Root.dev'); import { ComponentType } from 'react';
interface Props {
store: Store<CounterState, CounterAction>;
} }
const Root: ComponentType<Props> =
process.env.NODE_ENV === 'production'
? // eslint-disable-next-line @typescript-eslint/no-var-requires
require('./Root.prod').default
: // eslint-disable-next-line @typescript-eslint/no-var-requires
require('./Root.dev').default;
export default Root;

View File

@ -15,6 +15,7 @@ render(
if (module.hot) { if (module.hot) {
module.hot.accept('./containers/Root', () => { module.hot.accept('./containers/Root', () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const RootContainer = require('./containers/Root').default; const RootContainer = require('./containers/Root').default;
render( render(
<AppContainer> <AppContainer>

View File

@ -4,10 +4,15 @@ import thunk from 'redux-thunk';
import rootReducer, { CounterState } from '../reducers'; import rootReducer, { CounterState } from '../reducers';
import DevTools from '../containers/DevTools'; import DevTools from '../containers/DevTools';
function getDebugSessionKey() {
const matches = /[?&]debug_session=([^&#]+)\b/.exec(window.location.href);
return matches && matches.length > 0 ? matches[1] : null;
}
const enhancer = compose( const enhancer = compose(
applyMiddleware(thunk), applyMiddleware(thunk),
DevTools.instrument(), DevTools.instrument(),
persistState(window.location.href.match(/[?&]debug_session=([^&#]+)\b/)) persistState(getDebugSessionKey())
); );
export default function configureStore( export default function configureStore(
@ -17,6 +22,7 @@ export default function configureStore(
if (module.hot) { if (module.hot) {
module.hot.accept('../reducers', () => module.hot.accept('../reducers', () =>
// eslint-disable-next-line @typescript-eslint/no-var-requires
store.replaceReducer(require('../reducers').default) store.replaceReducer(require('../reducers').default)
); );
} }

View File

@ -1,5 +1,13 @@
if (process.env.NODE_ENV === 'production') { import { PreloadedState, Store } from 'redux';
module.exports = require('./configureStore.prod'); import { CounterState } from '../reducers';
} else { import { CounterAction } from '../actions/CounterActions';
module.exports = require('./configureStore.dev');
} const configureStore: (
initialState?: PreloadedState<CounterState>
) => Store<CounterState, CounterAction> =
process.env.NODE_ENV === 'production'
? // eslint-disable-next-line @typescript-eslint/no-var-requires
require('./configureStore.prod').default
: // eslint-disable-next-line @typescript-eslint/no-var-requires
require('./configureStore.dev').default;
export default configureStore;

View File

@ -3,7 +3,6 @@ import * as webpack from 'webpack';
module.exports = { module.exports = {
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development', mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
devtool: 'eval-source-map',
entry: [ entry: [
'webpack-dev-server/client?http://localhost:3000', 'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server', 'webpack/hot/only-dev-server',
@ -14,7 +13,6 @@ module.exports = {
filename: 'bundle.js', filename: 'bundle.js',
publicPath: '/static/', publicPath: '/static/',
}, },
plugins: [new webpack.HotModuleReplacementPlugin()],
module: { module: {
rules: [ rules: [
{ {
@ -25,9 +23,14 @@ module.exports = {
}, },
], ],
}, },
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
plugins: [new webpack.HotModuleReplacementPlugin()],
devServer: { devServer: {
historyApiFallback: true, historyApiFallback: true,
hot: true, hot: true,
port: 3000, port: 3000,
}, },
devtool: 'eval-source-map',
}; };

View File

@ -78,7 +78,9 @@ export default function createDevTools<
liftedStore?: LiftedStore<S, A, MonitorState>; liftedStore?: LiftedStore<S, A, MonitorState>;
static instrument = (options: Options<S, A, MonitorState, MonitorAction>) => static instrument = (
options?: Options<S, A, MonitorState, MonitorAction>
) =>
instrument( instrument(
(state, action) => Monitor.update(monitorProps, state, action), (state, action) => Monitor.update(monitorProps, state, action),
options options

View File

@ -8,7 +8,7 @@ export default function persistState<
A extends Action<unknown>, A extends Action<unknown>,
MonitorState MonitorState
>( >(
sessionId?: string, sessionId: string | null | undefined,
deserializeState: (state: S) => S = identity, deserializeState: (state: S) => S = identity,
deserializeAction: (action: A) => A = identity deserializeAction: (action: A) => A = identity
): StoreEnhancer { ): StoreEnhancer {

View File

@ -8,6 +8,6 @@
"esModuleInterop": true, "esModuleInterop": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
// See https://github.com/DefinitelyTyped/DefinitelyTyped/issues/33311 // See https://github.com/DefinitelyTyped/DefinitelyTyped/issues/33311
"types": ["node", "jest"] "types": ["node", "jest", "webpack-env"]
} }
} }

View File

@ -3408,6 +3408,11 @@
"@types/serve-static" "*" "@types/serve-static" "*"
"@types/webpack" "*" "@types/webpack" "*"
"@types/webpack-env@^1.15.2":
version "1.15.2"
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.2.tgz#927997342bb9f4a5185a86e6579a0a18afc33b0a"
integrity sha512-67ZgZpAlhIICIdfQrB5fnDvaKFcDxpKibxznfYRVAT4mQE41Dido/3Ty+E3xGBmTogc5+0Qb8tWhna+5B8z1iQ==
"@types/webpack-sources@*": "@types/webpack-sources@*":
version "1.4.2" version "1.4.2"
resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-1.4.2.tgz#5d3d4dea04008a779a90135ff96fb5c0c9e6292c" resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-1.4.2.tgz#5d3d4dea04008a779a90135ff96fb5c0c9e6292c"