Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'use strict'
- import {
- EventEmitter
- } from 'events'
- const keyRegExp = /\{(\w+)\}/g
- const sep = '.'
- function resolveParam(keyPath, payload){
- return keyPath
- .replace(
- keyRegExp
- , (_,$1) => payload[$1]
- )
- .split(sep)
- }
- function walk(cur, tiers, lvl = 0){
- if(tiers.length === 0){
- return cur
- }
- let prop = cur[tiers[0]]
- let tails = tiers.slice(1)
- if(tails.length === 0){
- return prop
- }else if(prop === undefined || prop === null){
- throw new Error(` {lvl} `)
- }else{
- return walk(prop, tails, lvl + 1)
- }
- }
- const evName = 'change'
- function deepMerge(tiers, source, patch){
- //FIXME Immutable!
- let target = source
- let locationTiers = tiers.slice(0,tiers.length - 1)
- let patchKey = tiers[tiers.length - 1]
- walk(target, locationTiers)[patchKey] = patch
- return target
- }
- export default function Effector(initialState = {}){
- let currentState = initialState
- let broadcastMap = {}
- const emitter = new EventEmitter()
- const getState = () => currentState
- const subscribe = (fn) => {
- let cb = (nextState) => fn(nextState)
- emitter.addListener(evName, cb)
- return () => emitter.removeListener(evName, cb)
- }
- const createAction = (keyPath, fn, deps = []) => {
- let action = (payload, options = {}) => {
- let tiers = resolveParam(keyPath, payload)
- let source = walk(currentState, tiers)
- let args = [payload, source].concat(deps.map((dp) => {
- return walk(currentState, resolveParam(dp, payload))
- }))
- args.push(function resolve(target){
- currentState = deepMerge(tiers, currentState, target)
- Object.keys(broadcastMap).forEach((path) => {
- if(keyPath.indexOf(path) > 0){
- broadcastMap[path].forEach((subcriber) => {
- subcriber(payload, {trigger:false})
- })
- }
- })
- if(options.trigger !== false){
- emitter.emit(evName, currentState)
- }
- })
- return fn.apply(null, args)
- }
- action.listenTo = (path) => {
- var subcribers;
- if(!broadcastMap[path]){
- subcribers = broadcastMap[path] = [action]
- }else{
- subcribers = broadcastMap[path]
- }
- return action
- }
- return action
- }
- return {
- createAction,
- subscribe,
- getState
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement