feat: redux
This commit is contained in:
parent
2d2625a3cb
commit
bce8b74d5d
3
packages/redux/.gitignore
vendored
Normal file
3
packages/redux/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/*.js
|
||||
/*.js.map
|
||||
!/webpack.config.js
|
42
packages/redux/package.json
Normal file
42
packages/redux/package.json
Normal file
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"name": "@latus/redux",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"author": "cha0s",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "NODE_PATH=./node_modules webpack --mode production",
|
||||
"clean": "rm -f yarn.lock && yarn",
|
||||
"dev": "NODE_PATH=./node_modules webpack --mode development",
|
||||
"forcepub": "npm unpublish --force $(node -e 'process.stdout.write(require(`./package.json`).name)') && npm publish",
|
||||
"lint": "NODE_PATH=./node_modules eslint --format codeframe --ext mjs,js .",
|
||||
"test": "NODE_PATH=./node_modules mocha --config ../../config/.mocharc.js",
|
||||
"watch": "NODE_PATH=./node_modules webpack --watch --mode development"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.js.map"
|
||||
],
|
||||
"dependencies": {
|
||||
"@latus/core": "^1.0.0",
|
||||
"@reduxjs/toolkit": "^1.5.0",
|
||||
"debug": "4.3.1",
|
||||
"deepmerge": "^4.2.2",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"react-redux": "^7.2.2",
|
||||
"redux": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@neutrinojs/airbnb-base": "^9.4.0",
|
||||
"@neutrinojs/copy": "9.4.0",
|
||||
"@neutrinojs/library": "^9.4.0",
|
||||
"@neutrinojs/mocha": "^9.4.0",
|
||||
"chai": "4.2.0",
|
||||
"eslint": "^7",
|
||||
"eslint-import-resolver-webpack": "0.13.0",
|
||||
"mocha": "^8",
|
||||
"neutrino": "^9.4.0",
|
||||
"webpack": "^4",
|
||||
"webpack-cli": "^3"
|
||||
}
|
||||
}
|
15
packages/redux/src/client/effects.js
vendored
Normal file
15
packages/redux/src/client/effects.js
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
export default (latus) => {
|
||||
const effects = latus.invokeFlat('@latus/redux/effects');
|
||||
const effect = (store, action) => {
|
||||
effects.forEach((map) => {
|
||||
if (map[action.type]) {
|
||||
map[action.type](store, action);
|
||||
}
|
||||
});
|
||||
};
|
||||
return (store) => (next) => (action) => {
|
||||
const result = next(action);
|
||||
setTimeout(() => effect(store, action, latus), 0);
|
||||
return result;
|
||||
};
|
||||
};
|
18
packages/redux/src/client/index.js
Normal file
18
packages/redux/src/client/index.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
import {Provider} from 'react-redux';
|
||||
|
||||
import configureStore from './store';
|
||||
|
||||
export * from './storage';
|
||||
export {default as storage} from './storage';
|
||||
export {configureStore};
|
||||
|
||||
export default {
|
||||
hooks: {
|
||||
'@latus/react/client/providers': async (latus) => {
|
||||
const store = await configureStore(latus, latus.invokeReduce('@latus/redux/store'));
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
latus.config['%store'] = store;
|
||||
return [Provider, {store}];
|
||||
},
|
||||
},
|
||||
};
|
35
packages/redux/src/client/storage.js
Normal file
35
packages/redux/src/client/storage.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
import throttle from 'lodash.throttle';
|
||||
import {createAction} from '@reduxjs/toolkit';
|
||||
|
||||
export const localStorage = createAction('@latus/redux/localStorage');
|
||||
|
||||
const hasStorage = (() => {
|
||||
try {
|
||||
window.localStorage.setItem('__redux-test', true);
|
||||
window.localStorage.removeItem('__redux-test');
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
|
||||
export const storageSubscription = (store, reducer) => (
|
||||
!hasStorage ? (() => {}) : throttle(
|
||||
() => (
|
||||
window.localStorage.setItem(
|
||||
'@latus/redux/state',
|
||||
JSON.stringify(reducer(store.getState(), localStorage())),
|
||||
)
|
||||
),
|
||||
1000,
|
||||
)
|
||||
);
|
||||
|
||||
export default (selector) => {
|
||||
const state = hasStorage && window.localStorage.getItem('@latus/redux/state');
|
||||
if (!state) {
|
||||
return undefined;
|
||||
}
|
||||
return selector(JSON.parse(state));
|
||||
};
|
33
packages/redux/src/client/store.js
Normal file
33
packages/redux/src/client/store.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import {ensureUniqueReduction} from '@latus/core/client';
|
||||
import {configureStore as configureStoreR, getDefaultMiddleware} from '@reduxjs/toolkit';
|
||||
import merge from 'deepmerge';
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import effectsMiddleware from './effects';
|
||||
import {storageSubscription} from './storage';
|
||||
|
||||
export default async function configureStore(latus, options = {}) {
|
||||
const reducers = await ensureUniqueReduction(latus, '@latus/redux/reducers', options);
|
||||
const {defaultState} = latus.config['@latus/redux/client'];
|
||||
const reducer = combineReducers(reducers);
|
||||
const store = configureStoreR(
|
||||
merge(
|
||||
{
|
||||
middleware: [
|
||||
...getDefaultMiddleware(),
|
||||
effectsMiddleware(latus),
|
||||
],
|
||||
preloadedState: reducer(defaultState, {type: null}),
|
||||
reducer,
|
||||
},
|
||||
options,
|
||||
),
|
||||
);
|
||||
const subscriptionReducers = Object.entries(reducers).map(([key, reducer]) => [
|
||||
key,
|
||||
reducer.subscription || (() => null),
|
||||
]);
|
||||
const subscriptionReducer = combineReducers(subscriptionReducers);
|
||||
store.subscribe((store) => storageSubscription(store, subscriptionReducer));
|
||||
return store;
|
||||
}
|
0
packages/redux/src/index.js
Normal file
0
packages/redux/src/index.js
Normal file
8
packages/redux/webpack.config.js
Normal file
8
packages/redux/webpack.config.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Whilst the configuration object can be modified here, the recommended way of making
|
||||
// changes is via the presets' options or Neutrino's API in `.neutrinorc.js` instead.
|
||||
// Neutrino's inspect feature can be used to view/export the generated configuration.
|
||||
const neutrino = require('neutrino');
|
||||
|
||||
const configOfConfigs = require(`${__dirname}/.neutrinorc`);
|
||||
const configs = Array.isArray(configOfConfigs) ? configOfConfigs : [configOfConfigs];
|
||||
module.exports = configs.map((config) => neutrino(config).webpack());
|
5454
packages/redux/yarn.lock
Normal file
5454
packages/redux/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user