@jupri-lab/store-core
Version:
A lightweight, easy-to-integrate, and type-safe state management library
81 lines (77 loc) • 2.4 kB
JavaScript
class CombineStores {
constructor(stores) {
this.stores = stores;
}
getStore(selector) {
return selector(this.stores);
}
}
class MiddlewareManager {
constructor(middlewares) {
this.middlewareFns = new Set(middlewares);
}
apply(params) {
const middlewareArray = Array.from(this.middlewareFns);
if (middlewareArray.length === 0)
return true;
const middlewareResults = middlewareArray.map((middleware) => {
const next = () => true;
const result = middleware(params, next);
return !result ? false : true;
});
return middlewareResults.every((x) => x);
}
}
class Store {
constructor(configs) {
this.subscribers = new Set();
this.states = configs.initialState;
this.actions = configs.actions;
this.middleware = new MiddlewareManager(configs.middlewares || []);
}
get() {
return this.states;
}
dispatch(actionName, ...payload) {
const action = this.actions[actionName];
if (action) {
const middlewareChainSuccessful = this.middleware.apply({
action,
actionName: action.name,
payload,
state: this.states,
});
if (middlewareChainSuccessful) {
const result = action(this.states, payload[0]);
if (result instanceof Promise) {
result
.then((newState) => {
this.states = newState;
this.notify();
})
.catch(() => {
throw new Error(`Error in async action ${String(actionName)}:`);
});
}
else {
this.states = result;
this.notify();
}
}
}
else {
throw new Error(`Action ${String(actionName)} is not defined`);
}
}
subscribe(callback) {
this.subscribers.add(callback);
return () => this.unsubscribe(callback);
}
unsubscribe(callback) {
this.subscribers.delete(callback);
}
notify() {
this.subscribers.forEach((callback) => callback(this.states));
}
}
export { CombineStores, Store };