feat: redux

This commit is contained in:
cha0s 2020-12-20 12:10:56 -06:00
parent 2d2625a3cb
commit bce8b74d5d
9 changed files with 5608 additions and 0 deletions

3
packages/redux/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/*.js
/*.js.map
!/webpack.config.js

View 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
View 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;
};
};

View 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}];
},
},
};

View 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));
};

View 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;
}

View File

View 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

File diff suppressed because it is too large Load Diff