gf-event-store
Version:
a lightweight state maneger
150 lines (140 loc) • 4.69 kB
JavaScript
const GFEventBus = require("./event-bus")
const { isObject } = require("./utils")
class GfEventStore {
constructor(store) {
if (!isObject(store.state)) {
throw new Erroe("~")
}
this.state = store.state
if (store.actions && isObject(store.actions)) {
const actions = Object.values(store.actions)
for (const action of actions) {
if (typeof action !== "function") {
throw new Erroe("~")
}
}
this.actions = store.actions
}
this._observe(store.state)
this.eventBus = new GfEventBus()
this.eventBus2 = new GfEventBus()
}
_observe(state) {
const _this = this
Object.keys(state).forEach((key) => {
let _value = state[key]
Object.defineProperty(state, key, {
get() {
return _value
},
set(newValue) {
if (_value === newValue) return
_value = newValue
_this.eventBus.emit(key, _value)
_this.eventBus2.emit(key, { [key]: _value })
},
})
})
}
onState(stateKey, stateCallback, thisArg = null) {
if (typeof stateKey !== "string" || !stateKey) {
throw new TypeError(
"the action name must be string type and event name not be null string"
)
}
if (!(stateKey in this.state)) {
throw new Error("stateKey is not found in state")
}
if (typeof stateCallback !== "function") {
throw new TypeError("the event callback must be function type")
}
thisArg = this.state
this.eventBus.on(stateKey, stateCallback, thisArg)
const value = this.state[stateKey]
stateCallback.apply(thisArg, [value])
}
onStates(stateKeys, stateCallback, thisArg = null) {
if (!(stateKeys instanceof Array)) {
throw new TypeError("the stateKeys must be array type")
}
if (typeof stateCallback !== "function") {
throw new TypeError("the event callback must be function type")
}
const value = {}
thisArg = this.state
for (const stateKey of stateKeys) {
if (typeof stateKey !== "string" || !stateKey) {
throw new TypeError(
"the action name must be string type and event name not be null string"
)
}
if (!(stateKey in this.state)) {
throw new Error("stateKey is not found in state")
}
value[stateKey] = this.state[stateKey]
this.eventBus2.on(stateKey, stateCallback, thisArg)
}
stateCallback.apply(thisArg, [value])
}
offState(stateKey, stateCallback) {
if (!(stateKey in this.state)) {
throw new Error("stateKey is not found in state")
}
if (typeof stateKey !== "string" || !stateKey) {
throw new TypeError(
"the action name must be string type and event name not be null string"
)
}
if (typeof callbackName === "boolean" && callbackName === true) {
this.eventBus.off(stateKey, true)
return
}
if (typeof stateCallback !== "function") {
throw new TypeError("the event callback must be function type")
}
this.EventBus.off(stateKey, stateCallback)
}
offStates(stateKeys, stateCallback) {
if (!(stateKeys instanceof Array)) {
throw new TypeError("the stateKeys must be array type")
}
if (
typeof stateCallback !== "function" ||
(typeof callbackName === "boolean" && callbackName === true)
) {
throw new TypeError("the event callback must be function type")
}
for (const stateKey of stateKeys) {
if (typeof stateKey !== "string" || !stateKey) {
throw new TypeError(
"the action name must be string type and event name not be null string"
)
}
if (!(stateKey in this.state)) {
throw new Error("stateKey is not found in state")
}
this.EventBus2.off(stateKey, stateCallback)
}
}
setState(stateKey, stateValue) {
if (typeof stateKey !== "string" || !stateKey) {
throw new TypeError(
"the action name must be string type and event name not be null string"
)
}
this.state[stateKey] = stateValue
}
dispatch(actionName, ...payload) {
if (typeof actionName !== "string" || !actionName) {
throw new TypeError(
"the action name must be string type and event name not be null string"
)
}
if (!(actionName in this.actions)) {
throw new Error("actionName is not found in actions")
}
const actionFn = this.actions[actionName]
actionFn.apply(this, [this.state, ...payload])
}
}
module.exports = GfEventStore