-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
164 lines (140 loc) · 5.02 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
var EventEmitter = require('events');
var inherits = require('inherits');
var utils = require('./utils.js');
/*
Constructing Store
*/
inherits(Store, EventEmitter);
module.exports = Store;
module.exports.createStore = Store;
function Store(reducers, initialState, previous) {
if (!(this instanceof Store)) return new Store(reducers, initialState, previous);
this.reducers = {};
this.did = 0;
if (reducers) this.register(reducers);
this.setInitialState(initialState);
}
/*
API functions, also check `events` API, since Store inherits from `events`.
*/
Store.prototype.setInitialState = function setInitialState(initialState) {
if (this.did) throw new NotAllowedError('not allowed to set initialState after dispatch');
this._state = typeof initialState !== 'undefined' ? initialState : {};
return this;
};
Store.prototype.module =
Store.prototype.component =
Store.prototype.ns =
Store.prototype.begin = function begin(ns) {
var self = this;
return Object.create(self, {
namespace: { value: ns },
_self: { value: self }
});
};
Store.prototype.end = function end() {
if (this._self) return this._self;
return this;
};
Store.prototype.register =
Store.prototype.add =
Store.prototype.define =
Store.prototype.reducer =
Store.prototype.addReducer = function addReducers(name, reducer) {
return this._add(name, reducer, true);
};
Store.prototype.update =
Store.prototype.replaceReducer = function replaceReducer(name, reducer) {
return this._add(name, reducer, true);
};
Store.prototype.upsert =
Store.prototype.addOrReplaceReducer = function addOrReplaceReducer(name, reducer) {
return this._add(name, reducer);
};
Store.prototype.remove =
Store.prototype.deregister = function remove(name) {
return delete this.reducers[this._getName(name)];
};
Store.prototype.do =
Store.prototype.act =
Store.prototype.dispatch = function dispatch(name, action) {
var n = this._getName(name);
if (!this.reducers[n]) throw new DoesNotExistError('there is no reducer with the name: ' + n);
this.willDispatch(this._state, this.did);
var currentState = utils.fill(n, this._state);
var currentParent = utils.nestedParent(n, this._state);
var nextState = this.reducers[n](currentState, action);
this.didCallReducer(nextState, action, currentState, currentParent.state, currentParent.key);
this._send(name);
if (this.namespace && this._self) this._self._send.call(this._self, n);
return this;
};
Store.prototype.get =
Store.prototype.getState = function getState(namespace) {
if (!namespace && !this.namespace) return this._state;
return utils.nested(this._getName(namespace), this._state, true);
};
Store.prototype.previous =
Store.prototype.getPrevious =
Store.prototype.getPreviousState = function getPreviousState(namespace) {
if (!namespace) return this._previousState;
return utils.nested(this._getName(namespace), this._previousState);
};
Store.prototype.willDispatch = function willDispatch(currentState, did) {
did++;
this._previousState = currentState;
};
Store.prototype.didCallReducer = function didCallReducer(nextState, action, currentState, currentParentState, currentParentKey) {
// TODOs check overwrite parent
if (typeof currentState === 'object' && typeof nextState === 'object' && !Array.isArray(nextState)) {
Object.assign(currentState, nextState);
} else if (typeof currentParentKey !== 'undefined') {
currentParentState[currentParentKey] = nextState;
} else {
this._state = nextState;
}
};
Store.prototype.clearCache = function clearCache() {
utils.clearCache();
return this;
};
/*
Kind of private Stuff
*/
Store.prototype._getName = function _getName(name) {
return this.namespace ? [this.namespace, name].join('.') : name;
};
Store.prototype._add = function _add(name, reducer, check) {
if (typeof name === 'string' && !reducer) return this.reducers[name];
if (typeof name === 'string') return this._addSingle(name, reducer, check);
var self = this, reducers = name;
Object.keys(reducers).map(function (key) {
self._addSingle(key, reducers[key], check);
});
return this;
};
Store.prototype._addSingle = function _addSingle(name, reducer, check) {
var n = this._getName(name);
if (check === true && this.reducers[n]) throw new AlreadyExistsError('reducer with name: ' + n + ' already exists');
if (check === false && !this.reducers[n]) throw new DoesNotExistError('there is no reducer with the name: ' + n);
this.reducers[n] = reducer;
return this;
};
Store.prototype._send = function _send(name) {
var self = this;
utils.bubble(name, this._state).forEach(function (namespace, i) {
self.emit(namespace, utils.nested(self._getName(namespace), self._state, i > 0));
});
};
inherits(DoesNotExistError, Error);
function DoesNotExistError(message) {
this.message = message || '';
}
inherits(AlreadyExistsError, Error);
function AlreadyExistsError(message) {
this.message = message || '';
}
inherits(NotAllowedError, Error);
function NotAllowedError(message) {
this.message = message || '';
}