1 | import { deepClone } from '@graphix/merge';
|
2 |
|
3 | function _extends() {
|
4 | _extends = Object.assign || function (target) {
|
5 | for (var i = 1; i < arguments.length; i++) {
|
6 | var source = arguments[i];
|
7 |
|
8 | for (var key in source) {
|
9 | if (Object.prototype.hasOwnProperty.call(source, key)) {
|
10 | target[key] = source[key];
|
11 | }
|
12 | }
|
13 | }
|
14 |
|
15 | return target;
|
16 | };
|
17 |
|
18 | return _extends.apply(this, arguments);
|
19 | }
|
20 |
|
21 | function _inheritsLoose(subClass, superClass) {
|
22 | subClass.prototype = Object.create(superClass.prototype);
|
23 | subClass.prototype.constructor = subClass;
|
24 | subClass.__proto__ = superClass;
|
25 | }
|
26 |
|
27 | function _getPrototypeOf(o) {
|
28 | _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
|
29 | return o.__proto__ || Object.getPrototypeOf(o);
|
30 | };
|
31 | return _getPrototypeOf(o);
|
32 | }
|
33 |
|
34 | function _setPrototypeOf(o, p) {
|
35 | _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
|
36 | o.__proto__ = p;
|
37 | return o;
|
38 | };
|
39 |
|
40 | return _setPrototypeOf(o, p);
|
41 | }
|
42 |
|
43 | function _isNativeReflectConstruct() {
|
44 | if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
45 | if (Reflect.construct.sham) return false;
|
46 | if (typeof Proxy === "function") return true;
|
47 |
|
48 | try {
|
49 | Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
|
50 | return true;
|
51 | } catch (e) {
|
52 | return false;
|
53 | }
|
54 | }
|
55 |
|
56 | function _construct(Parent, args, Class) {
|
57 | if (_isNativeReflectConstruct()) {
|
58 | _construct = Reflect.construct;
|
59 | } else {
|
60 | _construct = function _construct(Parent, args, Class) {
|
61 | var a = [null];
|
62 | a.push.apply(a, args);
|
63 | var Constructor = Function.bind.apply(Parent, a);
|
64 | var instance = new Constructor();
|
65 | if (Class) _setPrototypeOf(instance, Class.prototype);
|
66 | return instance;
|
67 | };
|
68 | }
|
69 |
|
70 | return _construct.apply(null, arguments);
|
71 | }
|
72 |
|
73 | function _isNativeFunction(fn) {
|
74 | return Function.toString.call(fn).indexOf("[native code]") !== -1;
|
75 | }
|
76 |
|
77 | function _wrapNativeSuper(Class) {
|
78 | var _cache = typeof Map === "function" ? new Map() : undefined;
|
79 |
|
80 | _wrapNativeSuper = function _wrapNativeSuper(Class) {
|
81 | if (Class === null || !_isNativeFunction(Class)) return Class;
|
82 |
|
83 | if (typeof Class !== "function") {
|
84 | throw new TypeError("Super expression must either be null or a function");
|
85 | }
|
86 |
|
87 | if (typeof _cache !== "undefined") {
|
88 | if (_cache.has(Class)) return _cache.get(Class);
|
89 |
|
90 | _cache.set(Class, Wrapper);
|
91 | }
|
92 |
|
93 | function Wrapper() {
|
94 | return _construct(Class, arguments, _getPrototypeOf(this).constructor);
|
95 | }
|
96 |
|
97 | Wrapper.prototype = Object.create(Class.prototype, {
|
98 | constructor: {
|
99 | value: Wrapper,
|
100 | enumerable: false,
|
101 | writable: true,
|
102 | configurable: true
|
103 | }
|
104 | });
|
105 | return _setPrototypeOf(Wrapper, Class);
|
106 | };
|
107 |
|
108 | return _wrapNativeSuper(Class);
|
109 | }
|
110 |
|
111 | function _unsupportedIterableToArray(o, minLen) {
|
112 | if (!o) return;
|
113 | if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
114 | var n = Object.prototype.toString.call(o).slice(8, -1);
|
115 | if (n === "Object" && o.constructor) n = o.constructor.name;
|
116 | if (n === "Map" || n === "Set") return Array.from(o);
|
117 | if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
118 | }
|
119 |
|
120 | function _arrayLikeToArray(arr, len) {
|
121 | if (len == null || len > arr.length) len = arr.length;
|
122 |
|
123 | for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
124 |
|
125 | return arr2;
|
126 | }
|
127 |
|
128 | function _createForOfIteratorHelperLoose(o, allowArrayLike) {
|
129 | var it;
|
130 |
|
131 | if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
|
132 | if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
133 | if (it) o = it;
|
134 | var i = 0;
|
135 | return function () {
|
136 | if (i >= o.length) return {
|
137 | done: true
|
138 | };
|
139 | return {
|
140 | done: false,
|
141 | value: o[i++]
|
142 | };
|
143 | };
|
144 | }
|
145 |
|
146 | throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
147 | }
|
148 |
|
149 | it = o[Symbol.iterator]();
|
150 | return it.next.bind(it);
|
151 | }
|
152 |
|
153 | var isObject = function isObject(variable) {
|
154 | return Object.prototype.toString.call(variable) === '[object Object]';
|
155 | };
|
156 | var Select = function Select(value) {
|
157 | if (arguments.length) this.value = value;
|
158 | };
|
159 | var SELECT = new Select();
|
160 | function select(value) {
|
161 | return arguments.length ? new Select(value) : new Select();
|
162 | }
|
163 | var StateSetter = function () {
|
164 | function StateSetter(setState, deepSelector, componentName) {
|
165 | Object.assign(this, {
|
166 | setState: setState,
|
167 | deepSelector: deepSelector,
|
168 | componentName: componentName
|
169 | });
|
170 | }
|
171 |
|
172 | var _proto = StateSetter.prototype;
|
173 |
|
174 | _proto.setFromGlobal = function setFromGlobal(newGlobalState) {
|
175 | this.setState(selectFromState(newGlobalState, this.deepSelector));
|
176 | };
|
177 |
|
178 | return StateSetter;
|
179 | }();
|
180 |
|
181 | var StateSetters = function (_Array) {
|
182 | _inheritsLoose(StateSetters, _Array);
|
183 |
|
184 | function StateSetters() {
|
185 | return _Array.apply(this, arguments) || this;
|
186 | }
|
187 |
|
188 | return StateSetters;
|
189 | }( _wrapNativeSuper(Array));
|
190 |
|
191 | var generateStateSetters = function generateStateSetters(state) {
|
192 | var setters = {};
|
193 | generateStateSettersR(state, setters);
|
194 | return setters;
|
195 |
|
196 | function generateStateSettersR(state, setters) {
|
197 | for (var _i = 0, _Object$entries = Object.entries(state); _i < _Object$entries.length; _i++) {
|
198 | var _Object$entries$_i = _Object$entries[_i],
|
199 | k = _Object$entries$_i[0],
|
200 | subState = _Object$entries$_i[1];
|
201 |
|
202 | if (isObject(subState)) {
|
203 | setters[k] = {};
|
204 | generateStateSettersR(subState, setters[k]);
|
205 | continue;
|
206 | }
|
207 |
|
208 | setters[k] = new StateSetters();
|
209 | }
|
210 | }
|
211 | };
|
212 | var getDeepSelector = function getDeepSelector(selectedState) {
|
213 | var selector = {};
|
214 | getDeepSelectorR(selectedState, selector);
|
215 | return selector;
|
216 |
|
217 | function getDeepSelectorR(selected, selector) {
|
218 | for (var _i2 = 0, _Object$entries2 = Object.entries(selected); _i2 < _Object$entries2.length; _i2++) {
|
219 | var _Object$entries2$_i = _Object$entries2[_i2],
|
220 | k = _Object$entries2$_i[0],
|
221 | subSelectedState = _Object$entries2$_i[1];
|
222 |
|
223 | if (isObject(subSelectedState)) {
|
224 | getDeepSelectorR(subSelectedState, selector[k] = {});
|
225 | continue;
|
226 | }
|
227 |
|
228 | selector[k] = SELECT;
|
229 | }
|
230 | }
|
231 | };
|
232 | function selectFromState(state, deepSelector) {
|
233 | var selectedState = {};
|
234 | selectFromStateR(state, deepSelector, selectedState);
|
235 | return selectedState;
|
236 |
|
237 | function selectFromStateR(state, deepSelector, selected) {
|
238 | for (var _i3 = 0, _Object$entries3 = Object.entries(deepSelector); _i3 < _Object$entries3.length; _i3++) {
|
239 | var _Object$entries3$_i = _Object$entries3[_i3],
|
240 | k = _Object$entries3$_i[0],
|
241 | subDeepSelector = _Object$entries3$_i[1];
|
242 |
|
243 | if (subDeepSelector instanceof Select) {
|
244 | selected[k] = state[k];
|
245 | continue;
|
246 | }
|
247 |
|
248 | selectFromStateR(state[k], subDeepSelector, selected[k] = {});
|
249 | }
|
250 | }
|
251 | }
|
252 | var registerNewStateSetter = function registerNewStateSetter(setter, newSetter, deepSelector) {
|
253 | var exploringPath = 'state';
|
254 | registerNewStateSetterR(deepSelector, setter);
|
255 |
|
256 | function registerNewStateSetterR(selector, setter) {
|
257 | for (var _i4 = 0, _Object$entries4 = Object.entries(selector); _i4 < _Object$entries4.length; _i4++) {
|
258 | var _Object$entries4$_i = _Object$entries4[_i4],
|
259 | k = _Object$entries4$_i[0],
|
260 | subDeepSelector = _Object$entries4$_i[1];
|
261 | var subSetter = setter[k];
|
262 |
|
263 | if (!(subDeepSelector instanceof Select)) {
|
264 | var previousExploringPath = exploringPath;
|
265 | exploringPath += '.' + k;
|
266 | registerNewStateSetterR(subDeepSelector, subSetter);
|
267 | exploringPath = previousExploringPath;
|
268 | continue;
|
269 | }
|
270 |
|
271 | if (!(subSetter instanceof StateSetters)) console.error('graph-reducer ERROR!', "subSetter isn't instanceof StateSetters! This means deepSelector hasn't been deep enough!\n", {
|
272 | exploringPath: exploringPath,
|
273 | k: k,
|
274 | subDeepSelector: subDeepSelector,
|
275 | newSetter: newSetter
|
276 | });
|
277 | if (subSetter.indexOf(newSetter) !== -1) console.error('`newSetter` already registered!', {
|
278 | exploringPath: exploringPath,
|
279 | k: k,
|
280 | subDeepSelector: subDeepSelector,
|
281 | newSetter: newSetter
|
282 | });else subSetter.push(newSetter);
|
283 | }
|
284 | }
|
285 | };
|
286 |
|
287 | var _process$env$DEBUG$sp, _process$env$DEBUG;
|
288 | var debugEnv = (_process$env$DEBUG$sp = (_process$env$DEBUG = process.env.DEBUG) === null || _process$env$DEBUG === void 0 ? void 0 : _process$env$DEBUG.split(',')) != null ? _process$env$DEBUG$sp : [];
|
289 | debugEnv.indexOf('graph-reducer') !== -1 || debugEnv.indexOf('*') !== -1 && debugEnv.indexOf('-graph-reducer') === -1;
|
290 | var dr = Object.fromEntries(['group', 'groupCollapsed', 'groupEnd', 'debug', 'log', 'info', 'warn', 'error', 'trace'].map(function (x) {
|
291 | return [x, console[x].bind(console, 'GRAPH-REDUCER:') ];
|
292 | }));
|
293 | var graphReducer = function graphReducer(srcState, paylector, stateSetters, _temp) {
|
294 | var _ref = _temp === void 0 ? {} : _temp,
|
295 | _ref$maxExploreDepth = _ref.maxExploreDepth,
|
296 | maxExploreDepth = _ref$maxExploreDepth === void 0 ? 64 : _ref$maxExploreDepth,
|
297 | _ref$mismatchWarning = _ref.mismatchWarning,
|
298 | mismatchWarning = _ref$mismatchWarning === void 0 ? true : _ref$mismatchWarning;
|
299 |
|
300 | if (!isObject(paylector)) throw new Error("payload is not an Object:\n" + paylector);
|
301 | var toFireStateSetters = [];
|
302 | var onlySelectionHappened = true;
|
303 | var noTransform = true;
|
304 | var badTransform = false;
|
305 | var exploringDepth = 0;
|
306 | var exploringPath = 'state';
|
307 |
|
308 | var newState = _extends({}, srcState);
|
309 |
|
310 | var selected = {};
|
311 | reduceR(newState, paylector, selected, 'state', stateSetters, mismatchWarning);
|
312 |
|
313 | if (badTransform) {
|
314 | noTransform = null;
|
315 | onlySelectionHappened = null;
|
316 | }
|
317 |
|
318 | return {
|
319 | newState: newState,
|
320 | selectedState: selected,
|
321 | noTransform: noTransform,
|
322 | onlySelectionHappened: onlySelectionHappened,
|
323 | toFireStateSetters: Array.from(new Set(toFireStateSetters))
|
324 | };
|
325 |
|
326 | function reduceR(state, paylector, selected, key, stateSetters, mismatchWarning) {
|
327 | {
|
328 | var _deepClone;
|
329 |
|
330 | dr.groupCollapsed(exploringDepth, exploringPath);
|
331 | dr.debug(deepClone((_deepClone = {}, _deepClone[key] = state, _deepClone.paylector = paylector, _deepClone.selected = selected, _deepClone.stateSetters = stateSetters, _deepClone)));
|
332 | }
|
333 |
|
334 | if (exploringDepth > maxExploreDepth) {
|
335 | dr.groupEnd();
|
336 | console.error('exploringDepth (%d) exceeds maxExploreDepth (%d)', exploringDepth, maxExploreDepth);
|
337 | badTransform = true;
|
338 | return;
|
339 | }
|
340 |
|
341 | for (var _i = 0, _Object$entries = Object.entries(state); _i < _Object$entries.length; _i++) {
|
342 | var _Object$entries$_i = _Object$entries[_i],
|
343 | k = _Object$entries$_i[0],
|
344 | subState = _Object$entries$_i[1];
|
345 | var subPaylector = void 0;
|
346 | var selectMode = void 0;
|
347 |
|
348 | if (paylector === SELECT) {
|
349 | subPaylector = SELECT;
|
350 | selectMode = true;
|
351 | } else {
|
352 | subPaylector = paylector[k];
|
353 | if (typeof subPaylector === 'function') subPaylector = subPaylector(subState, srcState);
|
354 | if (subPaylector instanceof Select) selectMode = true;
|
355 | }
|
356 |
|
357 | var subStateIsObject = isObject(subState);
|
358 |
|
359 | deepExploring: {
|
360 | if (selectMode) {
|
361 | if (!subStateIsObject) {
|
362 | if ('value' in subPaylector) {
|
363 | selected[k] = subPaylector = typeof subPaylector.value === 'function' ? subPaylector.value(subState) : subPaylector.value;
|
364 | break deepExploring;
|
365 | }
|
366 |
|
367 | selected[k] = subState;
|
368 | continue;
|
369 | }
|
370 |
|
371 | if ('value' in subPaylector) console.error('`subPaylector` can have `value` property only at leaf (final) nodes.', 'The `value` was ignored.', {
|
372 | subPaylector: subPaylector,
|
373 | subState: subState,
|
374 | exploringPath: exploringPath
|
375 | });
|
376 | selected[k] = _extends({}, subState);
|
377 | } else if (isObject(subPaylector)) {
|
378 | if (!subStateIsObject) {
|
379 | console.error('Mismatched types! `subPaylector` is a %s, but `subState` is a %s\n%o', Object.prototype.toString.call(subPaylector), Object.prototype.toString.call(subState), {
|
380 | subPaylector: subPaylector,
|
381 | subState: subState,
|
382 | exploringPath: exploringPath
|
383 | });
|
384 | continue;
|
385 | }
|
386 |
|
387 | selected[k] = {};
|
388 | }
|
389 |
|
390 | if (subStateIsObject) {
|
391 | state[k] = _extends({}, subState);
|
392 |
|
393 | if (!isObject(subPaylector)) {
|
394 | if (k in paylector) console.error('Mismatched types! `subPaylector` is a %s, but `subState` is a %s. ' + '`subPaylector` was ignored\n%o', Object.prototype.toString.call(subPaylector), Object.prototype.toString.call(subState), {
|
395 | subPaylector: subPaylector,
|
396 | subState: subState,
|
397 | exploringPath: exploringPath
|
398 | });
|
399 | subPaylector = {};
|
400 | }
|
401 |
|
402 | exploringDepth++;
|
403 | var previousExploringPath = exploringPath;
|
404 | exploringPath += '.' + k;
|
405 | reduceR(state[k], subPaylector, selected === null || selected === void 0 ? void 0 : selected[k], k, stateSetters[k], mismatchWarning);
|
406 | if (selected && !Object.keys(selected).length) delete selected[k];
|
407 | exploringPath = previousExploringPath;
|
408 | exploringDepth--;
|
409 | continue;
|
410 | }
|
411 |
|
412 | if (!(k in paylector)) continue;
|
413 | }
|
414 |
|
415 | onlySelectionHappened = false;
|
416 | var anyDifference = false;
|
417 |
|
418 | if (subPaylector instanceof Array) {
|
419 | if (!(subState instanceof Array)) {
|
420 | if (mismatchWarning) console.warn('Mismatched types! `subPaylector` is an Array, but `subState` is a %s\n%o', Object.prototype.toString.call(subState), {
|
421 | subPaylector: subPaylector,
|
422 | subState: subState,
|
423 | exploringPath: exploringPath
|
424 | });
|
425 | subState = state[k] = [];
|
426 | }
|
427 |
|
428 | for (var _iterator = _createForOfIteratorHelperLoose(subPaylector.entries()), _step; !(_step = _iterator()).done;) {
|
429 | var _step$value = _step.value,
|
430 | i = _step$value[0],
|
431 | value = _step$value[1];
|
432 |
|
433 | if (subState[i] !== value) {
|
434 | anyDifference = true;
|
435 | subState[i] = value;
|
436 | }
|
437 | }
|
438 | } else {
|
439 | anyDifference = subState !== subPaylector;
|
440 | state[k] = subPaylector;
|
441 | }
|
442 |
|
443 | if (anyDifference) {
|
444 | noTransform = false;
|
445 | toFireStateSetters.push.apply(toFireStateSetters, stateSetters[k]);
|
446 | }
|
447 | }
|
448 |
|
449 | {
|
450 | var _dr$debug;
|
451 |
|
452 | dr.debug((_dr$debug = {}, _dr$debug[key] = state, _dr$debug.selected = selected, _dr$debug.toFireStateSetters = toFireStateSetters, _dr$debug));
|
453 | dr.groupEnd();
|
454 | }
|
455 | }
|
456 | };
|
457 |
|
458 | export default graphReducer;
|
459 | export { SELECT, StateSetter, generateStateSetters, getDeepSelector, graphReducer, isObject, registerNewStateSetter, select, selectFromState };
|
460 |
|