diff --git a/packages/redux-devtools-inspector-monitor/demo/src/js/DevTools.tsx b/packages/redux-devtools-inspector-monitor/demo/src/js/DevTools.tsx index cf48d1d3..bae66bd0 100644 --- a/packages/redux-devtools-inspector-monitor/demo/src/js/DevTools.tsx +++ b/packages/redux-devtools-inspector-monitor/demo/src/js/DevTools.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { connect } from 'react-redux'; import { createDevTools } from 'redux-devtools'; import DockMonitor from 'redux-devtools-dock-monitor'; +import { Location } from 'history'; import DevtoolsInspector from '../../../src/DevtoolsInspector'; import getOptions from './getOptions'; import { base16Themes } from '../../../src/utils/createStylingFromTheme'; -import { Location } from 'history'; import { DemoAppState } from './reducers'; const CustomComponent = () => ( diff --git a/packages/redux-devtools-inspector-monitor/demo/src/js/reducers.ts b/packages/redux-devtools-inspector-monitor/demo/src/js/reducers.ts index 7d2e9941..3fdbe4fc 100644 --- a/packages/redux-devtools-inspector-monitor/demo/src/js/reducers.ts +++ b/packages/redux-devtools-inspector-monitor/demo/src/js/reducers.ts @@ -194,7 +194,7 @@ const createRootReducer = ( ): Reducer => combineReducers({ router: connectRouter(history) as Reducer, - timeoutUpdateEnabled: (state = false, action: DemoAppAction) => + timeoutUpdateEnabled: (state = false, action) => action.type === 'TOGGLE_TIMEOUT_UPDATE' ? action.timeoutUpdateEnabled : state, @@ -207,7 +207,7 @@ const createRootReducer = ( // noop } ) => state, - array: (state = [], action: DemoAppAction) => + array: (state = [], action) => action.type === 'PUSH' ? [...state, Math.random()] : action.type === 'POP' @@ -215,13 +215,13 @@ const createRootReducer = ( : action.type === 'REPLACE' ? [Math.random(), ...state.slice(1)] : state, - hugeArrays: (state = [], action: DemoAppAction) => + hugeArrays: (state = [], action) => action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state, - hugeObjects: (state = [], action: DemoAppAction) => + hugeObjects: (state = [], action) => action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state, - iterators: (state = [], action: DemoAppAction) => + iterators: (state = [], action) => action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state, - nested: (state = NESTED, action: DemoAppAction) => + nested: (state = NESTED, action) => action.type === 'CHANGE_NESTED' ? { ...state, @@ -238,29 +238,26 @@ const createRootReducer = ( }, } : state, - recursive: (state: { obj?: unknown }[] = [], action: DemoAppAction) => + recursive: (state: { obj?: unknown }[] = [], action) => action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state, - immutables: ( - state: Immutable.Map[] = [], - action: DemoAppAction - ) => + immutables: (state: Immutable.Map[] = [], action) => action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state, - maps: (state: Map[] = [], action: DemoAppAction) => + maps: (state: Map[] = [], action) => action.type === 'ADD_NATIVE_MAP' ? [...state, NATIVE_MAP] : state, - immutableNested: (state = IMMUTABLE_NESTED, action: DemoAppAction) => + immutableNested: (state = IMMUTABLE_NESTED, action) => action.type === 'CHANGE_IMMUTABLE_NESTED' ? state.updateIn( ['long', 'nested', 0, 'path', 'to', 'a'], (str: string) => str + '!' ) : state, - addFunction: (state = null, action: DemoAppAction) => + addFunction: (state = null, action) => action.type === 'ADD_FUNCTION' ? { f: FUNC } : state, - addSymbol: (state = null, action: DemoAppAction) => + addSymbol: (state = null, action) => action.type === 'ADD_SYMBOL' ? { s: window.Symbol('symbol'), error: new Error('TEST') } : state, - shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action: DemoAppAction) => + shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) => action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state, }); diff --git a/packages/redux-devtools-inspector-monitor/src/index.ts b/packages/redux-devtools-inspector-monitor/src/index.ts index 01eb309d..fdddf57d 100644 --- a/packages/redux-devtools-inspector-monitor/src/index.ts +++ b/packages/redux-devtools-inspector-monitor/src/index.ts @@ -1,4 +1,5 @@ import DevtoolsInspector from './DevtoolsInspector'; export default DevtoolsInspector; -export { TabComponentProps } from './ActionPreview'; +export { Tab, TabComponentProps } from './ActionPreview'; export { DevtoolsInspectorState } from './redux'; +export { base16Themes } from './utils/createStylingFromTheme'; diff --git a/packages/redux-devtools-test-generator/demo/config/tsconfig.json b/packages/redux-devtools-test-generator/demo/config/tsconfig.json index 1d04dfd1..7fd5a7b8 100644 --- a/packages/redux-devtools-test-generator/demo/config/tsconfig.json +++ b/packages/redux-devtools-test-generator/demo/config/tsconfig.json @@ -1,4 +1,7 @@ { "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "resolveJsonModule": true + }, "include": ["webpack.config.ts"] } diff --git a/packages/redux-devtools-test-generator/demo/config/webpack.config.ts b/packages/redux-devtools-test-generator/demo/config/webpack.config.ts index 12d29a8a..d0b4137b 100644 --- a/packages/redux-devtools-test-generator/demo/config/webpack.config.ts +++ b/packages/redux-devtools-test-generator/demo/config/webpack.config.ts @@ -1,14 +1,14 @@ -const path = require('path'); -const webpack = require('webpack'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const { CleanWebpackPlugin } = require('clean-webpack-plugin'); - -const pkg = require('./package.json'); +import * as path from 'path'; +import * as webpack from 'webpack'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import { CleanWebpackPlugin } from 'clean-webpack-plugin'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import pkg from '../../package.json'; const isProduction = process.env.NODE_ENV === 'production'; module.exports = { - devtool: 'eval-source-map', + mode: process.env.NODE_ENV || 'development', entry: isProduction ? ['./demo/src/js/index'] : [ @@ -20,39 +20,14 @@ module.exports = { path: path.join(__dirname, 'demo/dist'), filename: 'js/bundle.js', }, - plugins: [ - new CleanWebpackPlugin(), - new HtmlWebpackPlugin({ - inject: true, - template: 'demo/src/index.html', - package: pkg, - }), - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify(process.env.NODE_ENV), - }, - }), - ].concat( - isProduction - ? [ - new webpack.optimize.UglifyJsPlugin({ - compress: { warnings: false }, - output: { comments: false }, - }), - ] - : [new webpack.HotModuleReplacementPlugin()] - ), - resolve: { - extensions: ['.js', '.jsx'], - }, module: { rules: [ { - test: /\.jsx?$/, + test: /\.(js|ts)x?$/, loader: 'babel-loader', include: [ - path.join(__dirname, 'src'), - path.join(__dirname, 'demo/src/js'), + path.join(__dirname, '../../src'), + path.join(__dirname, '../src/js'), ], }, { @@ -66,6 +41,22 @@ module.exports = { }, ], }, + resolve: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + plugins: [ + new CleanWebpackPlugin(), + new HtmlWebpackPlugin({ + inject: true, + template: 'demo/src/index.html', + package: pkg, + }), + new ForkTsCheckerWebpackPlugin({ + typescript: { + configFile: 'demo/tsconfig.json', + }, + }), + ].concat(isProduction ? [] : [new webpack.HotModuleReplacementPlugin()]), devServer: isProduction ? null : { @@ -78,4 +69,5 @@ module.exports = { }, historyApiFallback: true, }, + devtool: 'eval-source-map', }; diff --git a/packages/redux-devtools-test-generator/demo/src/js/DemoApp.jsx b/packages/redux-devtools-test-generator/demo/src/js/DemoApp.tsx similarity index 55% rename from packages/redux-devtools-test-generator/demo/src/js/DemoApp.jsx rename to packages/redux-devtools-test-generator/demo/src/js/DemoApp.tsx index 8b6cb822..90b4f0cb 100644 --- a/packages/redux-devtools-test-generator/demo/src/js/DemoApp.jsx +++ b/packages/redux-devtools-test-generator/demo/src/js/DemoApp.tsx @@ -1,11 +1,35 @@ -import React from 'react'; +import React, { CSSProperties } from 'react'; import { connect } from 'react-redux'; -import pkg from '../../../package.json'; import { Button, Toolbar, Spacer } from 'devui'; -import getOptions from './getOptions'; import { push as pushRoute } from 'connected-react-router'; +import pkg from '../../../package.json'; +import getOptions from './getOptions'; +import { DemoAppState } from './reducers'; +import { + AddFunctionAction, + AddHugeObjectAction, + AddImmutableMapAction, + AddIteratorAction, + AddRecursiveAction, + AddSymbolAction, + ChangeImmutableNestedAction, + ChangeNestedAction, + HugePayloadAction, + IncrementAction, + PopAction, + PushAction, + PushHugeArrayAction, + ReplaceAction, + ShuffleArrayAction, + TimeoutUpdateAction, + ToggleTimeoutUpdateAction, +} from './reducers'; -const styles = { +const styles: { + wrapper: CSSProperties; + muted: CSSProperties; + link: CSSProperties; +} = { wrapper: { height: '100vh', width: '450px', @@ -24,7 +48,30 @@ const styles = { const ROOT = '/'; // process.env.NODE_ENV === 'production' ? '/' : '/'; -class DemoApp extends React.Component { +interface Props + extends Omit { + toggleTimeoutUpdate: (timeoutUpdateEnabled: boolean) => void; + timeoutUpdate: () => void; + increment: () => void; + push: () => void; + pop: () => void; + replace: () => void; + changeNested: () => void; + pushHugeArray: () => void; + addIterator: () => void; + addHugeObject: () => void; + addRecursive: () => void; + addImmutableMap: () => void; + changeImmutableNested: () => void; + hugePayload: () => void; + addFunction: () => void; + addSymbol: () => void; + shuffleArray: () => void; +} + +class DemoApp extends React.Component { + timeout?: number; + render() { const options = getOptions(this.props.router.location); @@ -48,7 +95,7 @@ class DemoApp extends React.Component { - + @@ -98,36 +145,40 @@ class DemoApp extends React.Component { this.props.toggleTimeoutUpdate(enabled); if (enabled) { - this.timeout = setInterval(this.props.timeoutUpdate, 1000); + this.timeout = window.setInterval(this.props.timeoutUpdate, 1000); } else { clearTimeout(this.timeout); } }; } -export default connect((state) => state, { - toggleTimeoutUpdate: (timeoutUpdateEnabled) => ({ +export default connect((state: DemoAppState) => state, { + toggleTimeoutUpdate: ( + timeoutUpdateEnabled: boolean + ): ToggleTimeoutUpdateAction => ({ type: 'TOGGLE_TIMEOUT_UPDATE', timeoutUpdateEnabled, }), - timeoutUpdate: () => ({ type: 'TIMEOUT_UPDATE' }), - increment: () => ({ type: 'INCREMENT' }), - push: () => ({ type: 'PUSH' }), - pop: () => ({ type: 'POP' }), - replace: () => ({ type: 'REPLACE' }), - changeNested: () => ({ type: 'CHANGE_NESTED' }), - pushHugeArray: () => ({ type: 'PUSH_HUGE_ARRAY' }), - addIterator: () => ({ type: 'ADD_ITERATOR' }), - addHugeObect: () => ({ type: 'ADD_HUGE_OBJECT' }), - addRecursive: () => ({ type: 'ADD_RECURSIVE' }), - addImmutableMap: () => ({ type: 'ADD_IMMUTABLE_MAP' }), - changeImmutableNested: () => ({ type: 'CHANGE_IMMUTABLE_NESTED' }), - hugePayload: () => ({ + timeoutUpdate: (): TimeoutUpdateAction => ({ type: 'TIMEOUT_UPDATE' }), + increment: (): IncrementAction => ({ type: 'INCREMENT' }), + push: (): PushAction => ({ type: 'PUSH' }), + pop: (): PopAction => ({ type: 'POP' }), + replace: (): ReplaceAction => ({ type: 'REPLACE' }), + changeNested: (): ChangeNestedAction => ({ type: 'CHANGE_NESTED' }), + pushHugeArray: (): PushHugeArrayAction => ({ type: 'PUSH_HUGE_ARRAY' }), + addIterator: (): AddIteratorAction => ({ type: 'ADD_ITERATOR' }), + addHugeObject: (): AddHugeObjectAction => ({ type: 'ADD_HUGE_OBJECT' }), + addRecursive: (): AddRecursiveAction => ({ type: 'ADD_RECURSIVE' }), + addImmutableMap: (): AddImmutableMapAction => ({ type: 'ADD_IMMUTABLE_MAP' }), + changeImmutableNested: (): ChangeImmutableNestedAction => ({ + type: 'CHANGE_IMMUTABLE_NESTED', + }), + hugePayload: (): HugePayloadAction => ({ type: 'HUGE_PAYLOAD', payload: Array.from({ length: 10000 }).map((_, i) => i), }), - addFunction: () => ({ type: 'ADD_FUNCTION' }), - addSymbol: () => ({ type: 'ADD_SYMBOL' }), - shuffleArray: () => ({ type: 'SHUFFLE_ARRAY' }), + addFunction: (): AddFunctionAction => ({ type: 'ADD_FUNCTION' }), + addSymbol: (): AddSymbolAction => ({ type: 'ADD_SYMBOL' }), + shuffleArray: (): ShuffleArrayAction => ({ type: 'SHUFFLE_ARRAY' }), pushRoute, })(DemoApp); diff --git a/packages/redux-devtools-test-generator/demo/src/js/DevTools.jsx b/packages/redux-devtools-test-generator/demo/src/js/DevTools.tsx similarity index 53% rename from packages/redux-devtools-test-generator/demo/src/js/DevTools.jsx rename to packages/redux-devtools-test-generator/demo/src/js/DevTools.tsx index 5fc41048..d34e7b35 100644 --- a/packages/redux-devtools-test-generator/demo/src/js/DevTools.jsx +++ b/packages/redux-devtools-test-generator/demo/src/js/DevTools.tsx @@ -1,12 +1,18 @@ import React from 'react'; import { connect } from 'react-redux'; import { createDevTools } from 'redux-devtools'; -import InspectorMonitor from 'redux-devtools-inspector-monitor'; +import InspectorMonitor, { + base16Themes, + Tab, +} from 'redux-devtools-inspector-monitor'; import DockMonitor from 'redux-devtools-dock-monitor'; +import { Location } from 'history'; import getOptions from './getOptions'; import TestGenerator from '../../../src'; +import { DemoAppState } from './reducers'; +import { Action } from 'redux'; -export const getDevTools = (location) => +export const getDevTools = (location: { search: string }) => createDevTools( changeMonitorKey="ctrl-m" > [ - { - name: 'Test', - component: TestGenerator, - }, - ...defaultTabs, - ]} + tabs={(defaultTabs) => + [ + { + name: 'Test', + component: TestGenerator, + }, + ...defaultTabs, + ] as Tab>[] + } /> ); -const UnconnectedDevTools = ({ location }) => { +const UnconnectedDevTools = ({ location }: { location: Location }) => { const DevTools = getDevTools(location); return ; }; -const mapStateToProps = (state) => ({ +const mapStateToProps = (state: DemoAppState) => ({ location: state.router.location, }); diff --git a/packages/redux-devtools-test-generator/demo/src/js/getOptions.js b/packages/redux-devtools-test-generator/demo/src/js/getOptions.js deleted file mode 100644 index b26e8222..00000000 --- a/packages/redux-devtools-test-generator/demo/src/js/getOptions.js +++ /dev/null @@ -1,11 +0,0 @@ -export default function getOptions(location) { - return { - useExtension: location.search.indexOf('ext') !== -1, - supportImmutable: location.search.indexOf('immutable') !== -1, - theme: do { - const match = location.search.match(/theme=([^&]+)/); - match ? match[1] : 'inspector'; - }, - dark: location.search.indexOf('dark') !== -1, - }; -} diff --git a/packages/redux-devtools-test-generator/demo/src/js/getOptions.ts b/packages/redux-devtools-test-generator/demo/src/js/getOptions.ts new file mode 100644 index 00000000..2b8a0071 --- /dev/null +++ b/packages/redux-devtools-test-generator/demo/src/js/getOptions.ts @@ -0,0 +1,20 @@ +export interface Options { + useExtension: boolean; + supportImmutable: boolean; + theme: string; + dark: boolean; +} + +export default function getOptions(location: { search: string }) { + return { + useExtension: location.search.indexOf('ext') !== -1, + supportImmutable: location.search.indexOf('immutable') !== -1, + theme: getTheme(), + dark: location.search.indexOf('dark') !== -1, + }; +} + +function getTheme() { + const match = /theme=([^&]+)/.exec(location.search); + return match ? match[1] : 'inspector'; +} diff --git a/packages/redux-devtools-test-generator/demo/src/js/index.js b/packages/redux-devtools-test-generator/demo/src/js/index.tsx similarity index 74% rename from packages/redux-devtools-test-generator/demo/src/js/index.js rename to packages/redux-devtools-test-generator/demo/src/js/index.tsx index 2a24a49b..419e93d4 100644 --- a/packages/redux-devtools-test-generator/demo/src/js/index.js +++ b/packages/redux-devtools-test-generator/demo/src/js/index.tsx @@ -2,20 +2,26 @@ import 'devui/lib/presets'; import React from 'react'; import { render } from 'react-dom'; import { Container } from 'devui'; -import DemoApp from './DemoApp'; import { Provider } from 'react-redux'; -import createRootReducer from './reducers'; -import { createStore, applyMiddleware, compose } from 'redux'; +import { + createStore, + applyMiddleware, + compose, + StoreEnhancer, + StoreEnhancerStoreCreator, +} from 'redux'; import logger from 'redux-logger'; import { Route } from 'react-router'; import { createBrowserHistory } from 'history'; import { ConnectedRouter, routerMiddleware } from 'connected-react-router'; import { persistState } from 'redux-devtools'; +import DemoApp from './DemoApp'; +import createRootReducer from './reducers'; import getOptions from './getOptions'; import { ConnectedDevTools, getDevTools } from './DevTools'; function getDebugSessionKey() { - const matches = window.location.href.match(/[?&]debug_session=([^&#]+)\b/); + const matches = /[?&]debug_session=([^&#]+)\b/.exec(window.location.href); return matches && matches.length > 0 ? matches[1] : null; } @@ -29,21 +35,23 @@ const DevTools = getDevTools(window.location); const history = createBrowserHistory(); const useDevtoolsExtension = - !!window.__REDUX_DEVTOOLS_EXTENSION__ && + !!((window as unknown) as { __REDUX_DEVTOOLS_EXTENSION__: unknown }) && getOptions(window.location).useExtension; const enhancer = compose( applyMiddleware(logger, routerMiddleware(history)), - (...args) => { + (next: StoreEnhancerStoreCreator) => { const instrument = useDevtoolsExtension - ? window.__REDUX_DEVTOOLS_EXTENSION__() + ? ((window as unknown) as { + __REDUX_DEVTOOLS_EXTENSION__(): StoreEnhancer; + }).__REDUX_DEVTOOLS_EXTENSION__() : DevTools.instrument(); - return instrument(...args); + return instrument(next); }, persistState(getDebugSessionKey()) ); -const store = createStore(createRootReducer(history), {}, enhancer); +const store = createStore(createRootReducer(history), enhancer); render( diff --git a/packages/redux-devtools-test-generator/demo/src/js/reducers.js b/packages/redux-devtools-test-generator/demo/src/js/reducers.js deleted file mode 100644 index c82bc80c..00000000 --- a/packages/redux-devtools-test-generator/demo/src/js/reducers.js +++ /dev/null @@ -1,125 +0,0 @@ -import Immutable from 'immutable'; -import shuffle from 'lodash.shuffle'; -import { combineReducers } from 'redux'; -import { connectRouter } from 'connected-react-router'; - -const NESTED = { - long: { - nested: [ - { - path: { - to: { - a: 'key', - }, - }, - }, - ], - }, -}; - -const IMMUTABLE_NESTED = Immutable.fromJS(NESTED); - -/* eslint-disable babel/new-cap */ - -const IMMUTABLE_MAP = Immutable.Map({ - map: Immutable.Map({ a: 1, b: 2, c: 3 }), - list: Immutable.List(['a', 'b', 'c']), - set: Immutable.Set(['a', 'b', 'c']), - stack: Immutable.Stack(['a', 'b', 'c']), - seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]), -}); - -/* eslint-enable babel/new-cap */ - -const HUGE_ARRAY = Array.from({ length: 5000 }).map((_, key) => ({ - str: 'key ' + key, -})); - -const HUGE_OBJECT = Array.from({ length: 5000 }).reduce( - (o, _, key) => ((o['key ' + key] = 'item ' + key), o), - {} -); - -const FUNC = function (a, b, c) { - return a + b + c; -}; - -const RECURSIVE = {}; -RECURSIVE.obj = RECURSIVE; - -function createIterator() { - const iterable = {}; - iterable[window.Symbol.iterator] = function* iterator() { - for (var i = 0; i < 333; i++) { - yield 'item ' + i; - } - }; - - return iterable; -} - -const DEFAULT_SHUFFLE_ARRAY = [0, 1, null, { id: 1 }, { id: 2 }, 'string']; - -const createRootReducer = (history) => - combineReducers({ - router: connectRouter(history), - timeoutUpdateEnabled: (state = false, action) => - action.type === 'TOGGLE_TIMEOUT_UPDATE' - ? action.timeoutUpdateEnabled - : state, - store: (state = 0, action) => - action.type === 'INCREMENT' ? state + 1 : state, - undefined: (state = { val: undefined }) => state, - null: (state = null) => state, - func: (state = () => {}) => state, - array: (state = [], action) => - action.type === 'PUSH' - ? [...state, Math.random()] - : action.type === 'POP' - ? state.slice(0, state.length - 1) - : action.type === 'REPLACE' - ? [Math.random(), ...state.slice(1)] - : state, - hugeArrays: (state = [], action) => - action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state, - hugeObjects: (state = [], action) => - action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state, - iterators: (state = [], action) => - action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state, - nested: (state = NESTED, action) => - action.type === 'CHANGE_NESTED' - ? { - ...state, - long: { - nested: [ - { - path: { - to: { - a: state.long.nested[0].path.to.a + '!', - }, - }, - }, - ], - }, - } - : state, - recursive: (state = [], action) => - action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state, - immutables: (state = [], action) => - action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state, - immutableNested: (state = IMMUTABLE_NESTED, action) => - action.type === 'CHANGE_IMMUTABLE_NESTED' - ? state.updateIn( - ['long', 'nested', 0, 'path', 'to', 'a'], - (str) => str + '!' - ) - : state, - addFunction: (state = null, action) => - action.type === 'ADD_FUNCTION' ? { f: FUNC } : state, - addSymbol: (state = null, action) => - action.type === 'ADD_SYMBOL' ? { s: window.Symbol('symbol') } : state, - shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) => - action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state, - }); - -export default createRootReducer; diff --git a/packages/redux-devtools-test-generator/demo/src/js/reducers.ts b/packages/redux-devtools-test-generator/demo/src/js/reducers.ts new file mode 100644 index 00000000..a98fe86d --- /dev/null +++ b/packages/redux-devtools-test-generator/demo/src/js/reducers.ts @@ -0,0 +1,232 @@ +import Immutable from 'immutable'; +import shuffle from 'lodash.shuffle'; +import { combineReducers, Reducer } from 'redux'; +import { + connectRouter, + LocationChangeAction, + RouterState, +} from 'connected-react-router'; +import { History } from 'history'; + +type Nested = { long: { nested: { path: { to: { a: string } } }[] } }; + +const NESTED = { + long: { + nested: [ + { + path: { + to: { + a: 'key', + }, + }, + }, + ], + }, +}; + +const IMMUTABLE_NESTED = Immutable.fromJS(NESTED); + +const IMMUTABLE_MAP = Immutable.Map({ + map: Immutable.Map({ a: 1, b: 2, c: 3 }), + list: Immutable.List(['a', 'b', 'c']), + set: Immutable.Set(['a', 'b', 'c']), + stack: Immutable.Stack(['a', 'b', 'c']), + seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]), +}); + +const HUGE_ARRAY = Array.from({ length: 5000 }).map((_, key) => ({ + str: `key ${key}`, +})); + +const HUGE_OBJECT = Array.from({ length: 5000 }).reduce( + (o: { [key: string]: string }, _, key) => ( + (o[`key ${key}`] = `item ${key}`), o + ), + {} +); + +const FUNC = function (a: number, b: number, c: number) { + return a + b + c; +}; + +const RECURSIVE: { obj?: unknown } = {}; +RECURSIVE.obj = RECURSIVE; + +function createIterator() { + const iterable: { [Symbol.iterator](): IterableIterator } = { + [Symbol.iterator]: function* iterator() { + for (let i = 0; i < 333; i++) { + yield `item ${i}`; + } + }, + }; + + return iterable; +} + +const DEFAULT_SHUFFLE_ARRAY = [0, 1, null, { id: 1 }, { id: 2 }, 'string']; + +export interface ToggleTimeoutUpdateAction { + type: 'TOGGLE_TIMEOUT_UPDATE'; + timeoutUpdateEnabled: boolean; +} +export interface TimeoutUpdateAction { + type: 'TIMEOUT_UPDATE'; +} +export interface IncrementAction { + type: 'INCREMENT'; +} +export interface PushAction { + type: 'PUSH'; +} +export interface PopAction { + type: 'POP'; +} +export interface ReplaceAction { + type: 'REPLACE'; +} +export interface ChangeNestedAction { + type: 'CHANGE_NESTED'; +} +export interface PushHugeArrayAction { + type: 'PUSH_HUGE_ARRAY'; +} +export interface AddIteratorAction { + type: 'ADD_ITERATOR'; +} +export interface AddHugeObjectAction { + type: 'ADD_HUGE_OBJECT'; +} +export interface AddRecursiveAction { + type: 'ADD_RECURSIVE'; +} +export interface AddImmutableMapAction { + type: 'ADD_IMMUTABLE_MAP'; +} +export interface ChangeImmutableNestedAction { + type: 'CHANGE_IMMUTABLE_NESTED'; +} +export interface HugePayloadAction { + type: 'HUGE_PAYLOAD'; + payload: number[]; +} +export interface AddFunctionAction { + type: 'ADD_FUNCTION'; +} +export interface AddSymbolAction { + type: 'ADD_SYMBOL'; +} +export interface ShuffleArrayAction { + type: 'SHUFFLE_ARRAY'; +} +type DemoAppAction = + | ToggleTimeoutUpdateAction + | TimeoutUpdateAction + | IncrementAction + | PushAction + | PopAction + | ReplaceAction + | ChangeNestedAction + | PushHugeArrayAction + | AddIteratorAction + | AddHugeObjectAction + | AddRecursiveAction + | AddImmutableMapAction + | ChangeImmutableNestedAction + | HugePayloadAction + | AddFunctionAction + | AddSymbolAction + | ShuffleArrayAction + | LocationChangeAction; + +export interface DemoAppState { + router: RouterState; + timeoutUpdateEnabled: boolean; + store: number; + undefined: { val: undefined }; + null: null; + func: () => void; + array: number[]; + hugeArrays: { str: string }[]; + hugeObjects: { [key: string]: string }[]; + iterators: { [Symbol.iterator](): IterableIterator }[]; + nested: Nested; + recursive: { obj?: unknown }[]; + immutables: Immutable.Map[]; + immutableNested: Immutable.Map; + addFunction: { f: (a: number, b: number, c: number) => number } | null; + addSymbol: { s: symbol; error: Error } | null; + shuffleArray: unknown[]; +} + +const createRootReducer = ( + history: History +): Reducer => + combineReducers({ + router: connectRouter(history) as Reducer, + timeoutUpdateEnabled: (state = false, action) => + action.type === 'TOGGLE_TIMEOUT_UPDATE' + ? action.timeoutUpdateEnabled + : state, + store: (state = 0, action) => + action.type === 'INCREMENT' ? state + 1 : state, + undefined: (state = { val: undefined }) => state, + null: (state = null) => state, + func: ( + state = () => { + // noop + } + ) => state, + array: (state = [], action) => + action.type === 'PUSH' + ? [...state, Math.random()] + : action.type === 'POP' + ? state.slice(0, state.length - 1) + : action.type === 'REPLACE' + ? [Math.random(), ...state.slice(1)] + : state, + hugeArrays: (state = [], action) => + action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state, + hugeObjects: (state = [], action) => + action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state, + iterators: (state = [], action) => + action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state, + nested: (state = NESTED, action) => + action.type === 'CHANGE_NESTED' + ? { + ...state, + long: { + nested: [ + { + path: { + to: { + a: state.long.nested[0].path.to.a + '!', + }, + }, + }, + ], + }, + } + : state, + recursive: (state = [], action) => + action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state, + immutables: (state = [], action) => + action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state, + immutableNested: (state = IMMUTABLE_NESTED, action) => + action.type === 'CHANGE_IMMUTABLE_NESTED' + ? state.updateIn( + ['long', 'nested', 0, 'path', 'to', 'a'], + (str: string) => str + '!' + ) + : state, + addFunction: (state = null, action) => + action.type === 'ADD_FUNCTION' ? { f: FUNC } : state, + addSymbol: (state = null, action) => + action.type === 'ADD_SYMBOL' + ? { s: window.Symbol('symbol'), error: new Error('TEST') } + : state, + shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) => + action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state, + }); + +export default createRootReducer; diff --git a/packages/redux-devtools-test-generator/demo/tsconfig.json b/packages/redux-devtools-test-generator/demo/tsconfig.json index 2d04eaee..420884ce 100644 --- a/packages/redux-devtools-test-generator/demo/tsconfig.json +++ b/packages/redux-devtools-test-generator/demo/tsconfig.json @@ -1,4 +1,7 @@ { "extends": "../../../tsconfig.react.base.json", + "compilerOptions": { + "resolveJsonModule": true + }, "include": ["../src", "src"] } diff --git a/packages/redux-devtools-test-generator/tsconfig.json b/packages/redux-devtools-test-generator/tsconfig.json index 7b7d1492..5c73f98c 100644 --- a/packages/redux-devtools-test-generator/tsconfig.json +++ b/packages/redux-devtools-test-generator/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.react.base.json", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "resolveJsonModule": true }, "include": ["src"] }