Created
March 23, 2022 08:50
-
-
Save osadan/00e20693f1d6c047e4b034d2bab95a19 to your computer and use it in GitHub Desktop.
one store for multiple package instances
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import "regenerator-runtime/runtime"; | |
import { combineReducers, applyMiddleware, createStore,compose } from 'redux'; | |
import createSagaMiddleware from 'redux-saga'; | |
import dynamicMiddlewares from 'redux-dynamic-middlewares'; | |
import { composeWithDevTools } from 'redux-devtools-extension'; | |
import { all } from 'redux-saga/effects'; | |
const defaultConfig = { | |
reducersToSkipFromClearing: [], | |
clearActions: [] | |
} | |
const monitoringReducer = (state = { monitor: [] }, action) => { | |
switch (action.type) { | |
case "@STORE/MONITOR": | |
return { ...state, monitor: monitor.concat(action.payload) }; | |
default: return state | |
} | |
} | |
class Store { | |
static #instance; | |
#sagas; | |
#sagaMiddleware; | |
#asyncReducers; | |
store; | |
dispatch; | |
constructor() { | |
this.#sagas = new Map(); | |
this.#sagaMiddleware = createSagaMiddleware({}); | |
this.#asyncReducers = {}; | |
this.store = this.#createStore([this.#sagaMiddleware]); | |
this.#sagaMiddleware.run(this.initialSaga); | |
this.dispatch = this.store.dispatch; | |
this.#createStoreElement(); | |
} | |
static getInstance() { | |
if (!Store.instance) { | |
if (!Store.#storeInitialized()) { | |
Store.#instance = new Store() | |
} else { | |
Store.#instance = Store.#getStoreInstanceFromElement(); | |
} | |
} | |
return Store.#instance; | |
} | |
static #storeInitialized() { | |
const [store] = document.getElementsByTagName('store'); | |
if (store && store[Symbol.for('store')]) { | |
return true; | |
} | |
return false; | |
} | |
static #getStoreInstanceFromElement() { | |
const [store] = document.getElementsByTagName('store'); | |
if (store && store[Symbol.for('store')]) { | |
return store.instance; | |
} | |
} | |
#createStore() { | |
const composeEnhancers = composeWithDevTools({ | |
// Specify name here, actionsBlacklist, actionsCreators and other options if needed | |
name: 'freightos-store', | |
trace: true, | |
traceLimit: 5, | |
features: { | |
jump: false, | |
}, | |
}); | |
//) | |
return createStore( | |
this.#createReducer(), | |
composeEnhancers(applyMiddleware(dynamicMiddlewares, this.#sagaMiddleware)) | |
); | |
} | |
#createStoreElement() { | |
const storeElement = document.createElement('store'); | |
Object.defineProperty(storeElement, Symbol.for('store'), { | |
writable: true, | |
configurable: false, | |
value: {} | |
}) | |
Object.defineProperty(storeElement, 'instance', { | |
writable: true, | |
configurable: false, | |
value: this | |
}); | |
const [head] = document.getElementsByTagName('head'); | |
if (head) { | |
head.appendChild(storeElement); | |
} | |
return storeElement[Symbol.for('store')]; | |
} | |
* initialSaga(sagas = []) { | |
yield all(sagas.map(sagaItem => sagaItem())) | |
} | |
#createReducer(asyncReducers = {}) { | |
// @todo think of a way to start without active reducers | |
return combineReducers({ | |
monitor: monitoringReducer, | |
...asyncReducers, | |
}); | |
} | |
attachReducer(reducers = {}) { | |
if (!this.store) { | |
return; | |
} | |
// @todo don't add multiple reducers | |
Object.entries(reducers).forEach(([key, reducer]) => { | |
this.#asyncReducers[key] = reducer; | |
}); | |
this.store.replaceReducer(createReducer(this.#asyncReducers)); | |
} | |
attach(reducers, sagas) { | |
if (sagas) { | |
this.injectSaga(sagas); | |
} | |
if (reducers) { | |
this.attachReducer(reducers); | |
} | |
}; | |
injectSage(saga) { | |
if (!this.#sagas) { | |
return; | |
} | |
if (this.#sagas.has(saga.toString())) { | |
return undefined; | |
} | |
this.#sagas.set(saga.toString(), true); | |
return this.#sagaMiddleware.run(saga); | |
} | |
} | |
export default Store; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment