cross-state 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cjs/hash.cjs +373 -293
- package/dist/cjs/hash.cjs.map +1 -1
- package/dist/cjs/immer.cjs +1 -1
- package/dist/cjs/immer.cjs.map +1 -1
- package/dist/cjs/index.cjs +174 -167
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/react.cjs +69 -22
- package/dist/cjs/react.cjs.map +1 -1
- package/dist/es/hash.mjs +374 -294
- package/dist/es/hash.mjs.map +1 -1
- package/dist/es/immer.mjs +1 -1
- package/dist/es/immer.mjs.map +1 -1
- package/dist/es/index.mjs +177 -170
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/react.mjs +77 -30
- package/dist/es/react.mjs.map +1 -1
- package/dist/types/core/cache.d.ts +56 -0
- package/dist/types/core/commonTypes.d.ts +5 -5
- package/dist/types/core/index.d.ts +5 -8
- package/dist/types/core/resourceGroup.d.ts +10 -3
- package/dist/types/core/store.d.ts +40 -21
- package/dist/types/immer/immerActions.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/lib/applyPatches.d.ts +2 -0
- package/dist/types/lib/cacheState.d.ts +19 -0
- package/dist/types/lib/calculationHelper.d.ts +3 -3
- package/dist/types/lib/clone.d.ts +1 -0
- package/dist/types/lib/debounce.d.ts +6 -0
- package/dist/types/lib/diff.d.ts +14 -7
- package/dist/types/lib/{cache.d.ts → instanceCache.d.ts} +1 -1
- package/dist/types/lib/makeSelector.d.ts +2 -1
- package/dist/types/lib/maybeAsync.d.ts +3 -0
- package/dist/types/lib/path.d.ts +14 -0
- package/dist/types/lib/propAccess.d.ts +5 -12
- package/dist/types/lib/queue.d.ts +4 -2
- package/dist/types/lib/standardMethods.d.ts +25 -0
- package/dist/types/lib/throttle.d.ts +2 -1
- package/dist/types/lib/typeHelpers.d.ts +8 -0
- package/dist/types/persist/index.d.ts +3 -0
- package/dist/types/persist/persist.d.ts +33 -0
- package/dist/types/persist/persistPathHelpers.d.ts +6 -0
- package/dist/types/persist/persistStorage.d.ts +14 -0
- package/dist/types/react/index.d.ts +4 -4
- package/dist/types/react/read.d.ts +3 -4
- package/dist/types/react/storeScope.d.ts +1 -1
- package/dist/types/react/useCache.d.ts +14 -0
- package/dist/types/react/useProp.d.ts +3 -3
- package/dist/types/react/useStore.d.ts +1 -1
- package/package.json +53 -44
- package/dist/types/core/derivedStore.d.ts +0 -39
- package/dist/types/core/fetchStore.d.ts +0 -76
- package/dist/types/core/once.d.ts +0 -13
- package/dist/types/lib/storeActions.d.ts +0 -28
- package/react.d.ts +0 -1
- package/react.js +0 -1
package/dist/cjs/hash.cjs
CHANGED
|
@@ -1,8 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
const getAllProperties = (object) => {
|
|
3
|
+
const properties = /* @__PURE__ */ new Set();
|
|
4
|
+
do {
|
|
5
|
+
for (const key of Reflect.ownKeys(object)) {
|
|
6
|
+
properties.add([object, key]);
|
|
7
|
+
}
|
|
8
|
+
} while ((object = Reflect.getPrototypeOf(object)) && object !== Object.prototype);
|
|
9
|
+
return properties;
|
|
10
|
+
};
|
|
11
|
+
function bind(self) {
|
|
12
|
+
for (const [object, key] of getAllProperties(self.constructor.prototype)) {
|
|
13
|
+
if (key === "constructor") {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(object, key);
|
|
17
|
+
if (descriptor && typeof descriptor.value === "function") {
|
|
18
|
+
self[key] = self[key].bind(self);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const calcDuration = (t) => {
|
|
23
|
+
if (typeof t === "number")
|
|
24
|
+
return t;
|
|
25
|
+
return (t.milliseconds ?? 0) + (t.seconds ?? 0) * 1e3 + (t.minutes ?? 0) * 60 * 1e3 + (t.hours ?? 0) * 60 * 60 * 1e3 + (t.days ?? 0) * 24 * 60 * 60 * 1e3;
|
|
26
|
+
};
|
|
2
27
|
function queue() {
|
|
3
28
|
const q = [];
|
|
4
|
-
|
|
29
|
+
const completionListeners = /* @__PURE__ */ new Set();
|
|
5
30
|
let active = false;
|
|
31
|
+
const notify = () => {
|
|
32
|
+
for (const listener of completionListeners) {
|
|
33
|
+
listener();
|
|
34
|
+
}
|
|
35
|
+
completionListeners.clear();
|
|
36
|
+
};
|
|
6
37
|
const run = async () => {
|
|
7
38
|
if (!active) {
|
|
8
39
|
active = true;
|
|
@@ -14,42 +45,50 @@ function queue() {
|
|
|
14
45
|
result = await result;
|
|
15
46
|
}
|
|
16
47
|
next.resolve(result);
|
|
17
|
-
} catch (
|
|
18
|
-
next.reject(
|
|
48
|
+
} catch (error) {
|
|
49
|
+
next.reject(error);
|
|
19
50
|
}
|
|
20
51
|
}
|
|
21
52
|
active = false;
|
|
22
|
-
|
|
53
|
+
notify();
|
|
23
54
|
}
|
|
24
55
|
};
|
|
25
56
|
return Object.assign(
|
|
26
|
-
(action) => {
|
|
27
|
-
return new Promise((
|
|
28
|
-
q.push({ action, resolve
|
|
57
|
+
(action, ref) => {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
q.push({ action, resolve, reject, ref });
|
|
29
60
|
run();
|
|
30
61
|
});
|
|
31
62
|
},
|
|
32
63
|
{
|
|
33
64
|
clear() {
|
|
34
65
|
q.length = 0;
|
|
35
|
-
resolve == null ? void 0 : resolve();
|
|
36
66
|
},
|
|
37
|
-
|
|
38
|
-
if (!
|
|
39
|
-
|
|
40
|
-
resolve = () => {
|
|
41
|
-
promise = void 0;
|
|
42
|
-
resolve = void 0;
|
|
43
|
-
r();
|
|
44
|
-
};
|
|
45
|
-
});
|
|
67
|
+
whenDone() {
|
|
68
|
+
if (!active) {
|
|
69
|
+
return Promise.resolve();
|
|
46
70
|
}
|
|
47
|
-
return
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
completionListeners.add(resolve);
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
get size() {
|
|
76
|
+
return q.length;
|
|
77
|
+
},
|
|
78
|
+
getRefs() {
|
|
79
|
+
return q.map((item) => item.ref).filter((x) => x !== void 0);
|
|
48
80
|
}
|
|
49
81
|
}
|
|
50
82
|
);
|
|
51
83
|
}
|
|
52
|
-
const ProxyKeys = [
|
|
84
|
+
const ProxyKeys = [
|
|
85
|
+
"get",
|
|
86
|
+
"getOwnPropertyDescriptor",
|
|
87
|
+
"getPrototypeOf",
|
|
88
|
+
"has",
|
|
89
|
+
"isExtensible",
|
|
90
|
+
"ownKeys"
|
|
91
|
+
];
|
|
53
92
|
const isPlainObject = (value) => typeof value === "object" && value !== null && Object.getPrototypeOf(value) === Object.prototype;
|
|
54
93
|
function trackingProxy(value) {
|
|
55
94
|
if (!isPlainObject(value) && !Array.isArray(value)) {
|
|
@@ -61,14 +100,14 @@ function trackingProxy(value) {
|
|
|
61
100
|
Object.fromEntries(
|
|
62
101
|
ProxyKeys.map((key) => [
|
|
63
102
|
key,
|
|
64
|
-
(
|
|
65
|
-
const
|
|
66
|
-
const [proxiedValue, equals] = trackingProxy(
|
|
103
|
+
(currentValue, ...args) => {
|
|
104
|
+
const function_ = Reflect[key];
|
|
105
|
+
const [proxiedValue, equals] = trackingProxy(function_(currentValue, ...args));
|
|
67
106
|
deps.push((otherValue) => {
|
|
68
107
|
if (!isPlainObject(otherValue) && !Array.isArray(otherValue)) {
|
|
69
108
|
return false;
|
|
70
109
|
}
|
|
71
|
-
return equals(
|
|
110
|
+
return equals(function_(otherValue, ...args));
|
|
72
111
|
});
|
|
73
112
|
return proxiedValue;
|
|
74
113
|
}
|
|
@@ -114,17 +153,22 @@ class CalculationHelper {
|
|
|
114
153
|
cancelEffect();
|
|
115
154
|
delete this.current;
|
|
116
155
|
};
|
|
117
|
-
const
|
|
118
|
-
if (!checks.every((
|
|
156
|
+
const checkAll = () => {
|
|
157
|
+
if (!checks.every((check) => check())) {
|
|
119
158
|
cancel();
|
|
120
159
|
onInvalidate == null ? void 0 : onInvalidate();
|
|
121
160
|
}
|
|
122
161
|
};
|
|
123
|
-
const
|
|
162
|
+
const invalidateDependencies = () => {
|
|
163
|
+
for (const dep of deps.values()) {
|
|
164
|
+
dep.invalidate();
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const use = (store, { disableProxy } = {}) => {
|
|
124
168
|
if (isCancled) {
|
|
125
|
-
return
|
|
169
|
+
return store.get();
|
|
126
170
|
}
|
|
127
|
-
let value =
|
|
171
|
+
let value = store.get();
|
|
128
172
|
let equals = (newValue) => {
|
|
129
173
|
return newValue === value;
|
|
130
174
|
};
|
|
@@ -135,44 +179,23 @@ class CalculationHelper {
|
|
|
135
179
|
const dep = {
|
|
136
180
|
on() {
|
|
137
181
|
this.off();
|
|
138
|
-
sub =
|
|
182
|
+
sub = store.sub(checkAll, { runNow: false });
|
|
139
183
|
},
|
|
140
184
|
off() {
|
|
141
185
|
sub == null ? void 0 : sub();
|
|
142
186
|
sub = void 0;
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
if (isActive) {
|
|
146
|
-
dep.on();
|
|
147
|
-
}
|
|
148
|
-
checks.push(() => equals(store2.get()));
|
|
149
|
-
deps.set(store2, dep);
|
|
150
|
-
return value;
|
|
151
|
-
};
|
|
152
|
-
const useFetch = (store2) => {
|
|
153
|
-
if (isCancled) {
|
|
154
|
-
return store2.fetch();
|
|
155
|
-
}
|
|
156
|
-
const value = store2.fetch();
|
|
157
|
-
const ref = store2.get().ref;
|
|
158
|
-
let sub;
|
|
159
|
-
const dep = {
|
|
160
|
-
on() {
|
|
161
|
-
this.off();
|
|
162
|
-
sub = store2.sub(check, { runNow: false });
|
|
163
187
|
},
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
188
|
+
invalidate() {
|
|
189
|
+
if ("invalidate" in store && store.invalidate instanceof Function) {
|
|
190
|
+
store.invalidate();
|
|
191
|
+
}
|
|
167
192
|
}
|
|
168
193
|
};
|
|
169
194
|
if (isActive) {
|
|
170
195
|
dep.on();
|
|
171
196
|
}
|
|
172
|
-
checks.push(() =>
|
|
173
|
-
|
|
174
|
-
});
|
|
175
|
-
deps.set(store2, dep);
|
|
197
|
+
checks.push(() => equals(store.get()));
|
|
198
|
+
deps.set(store, dep);
|
|
176
199
|
return value;
|
|
177
200
|
};
|
|
178
201
|
const updateValue = (update) => q(async () => {
|
|
@@ -181,7 +204,7 @@ class CalculationHelper {
|
|
|
181
204
|
}
|
|
182
205
|
if (update instanceof Function) {
|
|
183
206
|
try {
|
|
184
|
-
update = update(getValue());
|
|
207
|
+
update = update(getValue == null ? void 0 : getValue());
|
|
185
208
|
} catch (error) {
|
|
186
209
|
setError == null ? void 0 : setError(error);
|
|
187
210
|
return;
|
|
@@ -208,11 +231,11 @@ class CalculationHelper {
|
|
|
208
231
|
});
|
|
209
232
|
let cancelSubscription;
|
|
210
233
|
try {
|
|
211
|
-
cancelSubscription = calculate({ use,
|
|
234
|
+
cancelSubscription = calculate({ use, updateValue, updateError });
|
|
212
235
|
} catch (error) {
|
|
213
236
|
setError == null ? void 0 : setError(error);
|
|
214
237
|
}
|
|
215
|
-
this.current = { cancel, check };
|
|
238
|
+
this.current = { cancel, check: checkAll, invalidateDependencies };
|
|
216
239
|
}
|
|
217
240
|
stop() {
|
|
218
241
|
var _a;
|
|
@@ -222,57 +245,113 @@ class CalculationHelper {
|
|
|
222
245
|
var _a;
|
|
223
246
|
(_a = this.current) == null ? void 0 : _a.check();
|
|
224
247
|
}
|
|
248
|
+
invalidateDependencies() {
|
|
249
|
+
var _a;
|
|
250
|
+
(_a = this.current) == null ? void 0 : _a.invalidateDependencies();
|
|
251
|
+
}
|
|
225
252
|
}
|
|
226
|
-
function
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
253
|
+
function debounce(action, options) {
|
|
254
|
+
const wait = typeof options === "object" && "wait" in options ? calcDuration(options.wait) : calcDuration(options);
|
|
255
|
+
const maxWait = typeof options === "object" && "maxWait" in options && options.maxWait !== void 0 ? calcDuration(options.maxWait) : void 0;
|
|
256
|
+
let timeout;
|
|
257
|
+
let timeoutStarted;
|
|
258
|
+
return (...args) => {
|
|
259
|
+
const now = Date.now();
|
|
260
|
+
timeoutStarted ?? (timeoutStarted = now);
|
|
261
|
+
const deadline = Math.min(
|
|
262
|
+
//
|
|
263
|
+
now + wait,
|
|
264
|
+
timeoutStarted + (maxWait ?? Number.POSITIVE_INFINITY)
|
|
265
|
+
);
|
|
266
|
+
if (timeout !== void 0) {
|
|
267
|
+
clearTimeout(timeout);
|
|
240
268
|
}
|
|
241
|
-
|
|
269
|
+
timeout = setTimeout(() => {
|
|
270
|
+
timeout = void 0;
|
|
271
|
+
timeoutStarted = void 0;
|
|
272
|
+
action(...args);
|
|
273
|
+
}, deadline - now);
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
const defaultEquals = (a, b) => a === b;
|
|
277
|
+
function forwardError(error) {
|
|
278
|
+
setTimeout(() => {
|
|
279
|
+
throw error;
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
function flatClone(object) {
|
|
283
|
+
if (object instanceof Map) {
|
|
284
|
+
return new Map(object);
|
|
242
285
|
}
|
|
243
|
-
|
|
286
|
+
if (object instanceof Set) {
|
|
287
|
+
return new Set(object);
|
|
288
|
+
}
|
|
289
|
+
if (Array.isArray(object)) {
|
|
290
|
+
return [...object];
|
|
291
|
+
}
|
|
292
|
+
if (object instanceof Object) {
|
|
293
|
+
return { ...object };
|
|
294
|
+
}
|
|
295
|
+
return object;
|
|
244
296
|
}
|
|
245
|
-
function
|
|
297
|
+
function castArrayPath(path) {
|
|
298
|
+
if (Array.isArray(path)) {
|
|
299
|
+
return path;
|
|
300
|
+
}
|
|
246
301
|
if (path === "") {
|
|
302
|
+
return [];
|
|
303
|
+
}
|
|
304
|
+
return path.split(".");
|
|
305
|
+
}
|
|
306
|
+
function get(object, path) {
|
|
307
|
+
const _path = castArrayPath(path);
|
|
308
|
+
const [first, ...rest] = _path;
|
|
309
|
+
if (first === void 0 || !object) {
|
|
310
|
+
return object;
|
|
311
|
+
}
|
|
312
|
+
if (object instanceof Map) {
|
|
313
|
+
return get(object.get(first), rest);
|
|
314
|
+
}
|
|
315
|
+
if (object instanceof Set) {
|
|
316
|
+
return get(Array.from(object)[Number(first)], rest);
|
|
317
|
+
}
|
|
318
|
+
if (object instanceof Object) {
|
|
319
|
+
return get(object[first], rest);
|
|
320
|
+
}
|
|
321
|
+
throw new Error(`Could not get ${path} of ${object}`);
|
|
322
|
+
}
|
|
323
|
+
function set(object, path, value, rootPath = path) {
|
|
324
|
+
const _path = castArrayPath(path);
|
|
325
|
+
const [first, ...rest] = _path;
|
|
326
|
+
if (first === void 0) {
|
|
247
327
|
return value;
|
|
248
328
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (index >= 0) {
|
|
255
|
-
key = path.slice(0, index);
|
|
256
|
-
const rest = path.slice(index + 1);
|
|
257
|
-
const subObj = obj[key];
|
|
258
|
-
if (!subObj) {
|
|
259
|
-
const prefix = rootPath.slice(0, -rest.length - 1);
|
|
260
|
-
throw Error(`Cannot set ${rootPath} because ${prefix} is ${subObj}`);
|
|
329
|
+
const updateChild = (child) => {
|
|
330
|
+
if (!child && rest.length > 0) {
|
|
331
|
+
const _rootPath = castArrayPath(rootPath);
|
|
332
|
+
const prefix = _rootPath.slice(0, -rest.length);
|
|
333
|
+
throw new Error(`Cannot set ${rootPath} because ${prefix.join(".")} is ${child}`);
|
|
261
334
|
}
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const copy = Array.from(obj);
|
|
269
|
-
copy[key] = update;
|
|
335
|
+
return set(child, rest, value, rootPath);
|
|
336
|
+
};
|
|
337
|
+
if (object instanceof Map) {
|
|
338
|
+
const copy = flatClone(object);
|
|
339
|
+
const child = copy.get(first);
|
|
340
|
+
copy.set(first, updateChild(child));
|
|
270
341
|
return copy;
|
|
271
342
|
}
|
|
272
|
-
|
|
273
|
-
...
|
|
274
|
-
[
|
|
275
|
-
|
|
343
|
+
if (object instanceof Set) {
|
|
344
|
+
const copy = [...object];
|
|
345
|
+
const child = copy[Number(first)];
|
|
346
|
+
copy[Number(first)] = updateChild(child);
|
|
347
|
+
return new Set(copy);
|
|
348
|
+
}
|
|
349
|
+
if (object instanceof Object) {
|
|
350
|
+
const copy = flatClone(object);
|
|
351
|
+
copy[first] = updateChild(copy[first]);
|
|
352
|
+
return copy;
|
|
353
|
+
}
|
|
354
|
+
throw new Error(`Could not set ${path} of ${object}`);
|
|
276
355
|
}
|
|
277
356
|
function makeSelector(selector) {
|
|
278
357
|
if (!selector) {
|
|
@@ -283,122 +362,79 @@ function makeSelector(selector) {
|
|
|
283
362
|
}
|
|
284
363
|
return (x) => get(x, selector);
|
|
285
364
|
}
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
properties.add([object, key]);
|
|
291
|
-
}
|
|
292
|
-
} while ((object = Reflect.getPrototypeOf(object)) && object !== Object.prototype);
|
|
293
|
-
return properties;
|
|
294
|
-
};
|
|
295
|
-
function bind(self) {
|
|
296
|
-
for (const [object, key] of getAllProperties(self.constructor.prototype)) {
|
|
297
|
-
if (key === "constructor") {
|
|
298
|
-
continue;
|
|
299
|
-
}
|
|
300
|
-
const descriptor = Reflect.getOwnPropertyDescriptor(object, key);
|
|
301
|
-
if (descriptor && typeof descriptor.value === "function") {
|
|
302
|
-
self[key] = self[key].bind(self);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
const calcDuration = (t) => {
|
|
307
|
-
if (typeof t === "number")
|
|
308
|
-
return t;
|
|
309
|
-
return (t.milliseconds ?? 0) + (t.seconds ?? 0) * 1e3 + (t.minutes ?? 0) * 60 * 1e3 + (t.hours ?? 0) * 60 * 60 * 1e3 + (t.days ?? 0) * 24 * 60 * 60 * 1e3;
|
|
310
|
-
};
|
|
311
|
-
const defaultEquals = (a, b) => a === b;
|
|
312
|
-
const simpleShallowEquals = (a, b) => {
|
|
313
|
-
if (a === b) {
|
|
314
|
-
return true;
|
|
315
|
-
}
|
|
316
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
317
|
-
return a.length === b.length && a.every((value, i) => value === b[i]);
|
|
318
|
-
}
|
|
319
|
-
if (typeof a === "object" && typeof b === "object") {
|
|
320
|
-
if (a === null || b === null) {
|
|
321
|
-
return false;
|
|
322
|
-
}
|
|
323
|
-
const e1 = Object.entries(a);
|
|
324
|
-
const e2 = Object.entries(b);
|
|
325
|
-
return e1.length === e2.length && e1.every(([key, value]) => value === b[key]);
|
|
326
|
-
}
|
|
327
|
-
return false;
|
|
328
|
-
};
|
|
329
|
-
function forwardError(error) {
|
|
330
|
-
setTimeout(() => {
|
|
331
|
-
throw error;
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
const arrMod = (prop) => function(...args) {
|
|
335
|
-
const newArr = this.get().slice();
|
|
336
|
-
const result = newArr[prop](...args);
|
|
337
|
-
this.update(newArr);
|
|
365
|
+
const createArrayAction = (prop) => function arrayAction(...args) {
|
|
366
|
+
const newArray = this.get().slice();
|
|
367
|
+
const result = newArray[prop](...args);
|
|
368
|
+
this.set(newArray);
|
|
338
369
|
return result;
|
|
339
370
|
};
|
|
340
|
-
const
|
|
341
|
-
splice:
|
|
342
|
-
push:
|
|
343
|
-
pop:
|
|
344
|
-
shift:
|
|
345
|
-
unshift:
|
|
346
|
-
reverse:
|
|
347
|
-
sort:
|
|
371
|
+
const arrayMethods = {
|
|
372
|
+
splice: createArrayAction("splice"),
|
|
373
|
+
push: createArrayAction("push"),
|
|
374
|
+
pop: createArrayAction("pop"),
|
|
375
|
+
shift: createArrayAction("shift"),
|
|
376
|
+
unshift: createArrayAction("unshift"),
|
|
377
|
+
reverse: createArrayAction("reverse"),
|
|
378
|
+
sort: createArrayAction("sort")
|
|
348
379
|
};
|
|
349
|
-
const
|
|
350
|
-
set
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
380
|
+
const recordMethods = {
|
|
381
|
+
// set<T extends Record<any, any>, P extends Path<T>>(
|
|
382
|
+
// this: Store<T>,
|
|
383
|
+
// path: P,
|
|
384
|
+
// value: Update<Value<T, P>>,
|
|
385
|
+
// ) {
|
|
386
|
+
// if (value instanceof Function) {
|
|
387
|
+
// value = value(get(this.get(), path));
|
|
388
|
+
// }
|
|
389
|
+
// this.set(set(this.get(), path, value));
|
|
390
|
+
// return this;
|
|
391
|
+
// },
|
|
357
392
|
delete(key) {
|
|
358
393
|
const copy = { ...this.get() };
|
|
359
394
|
delete copy[key];
|
|
360
|
-
this.
|
|
395
|
+
this.set(copy);
|
|
361
396
|
},
|
|
362
397
|
clear() {
|
|
363
|
-
this.
|
|
398
|
+
this.set({});
|
|
364
399
|
}
|
|
365
400
|
};
|
|
366
|
-
const
|
|
367
|
-
set(key, value) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
},
|
|
401
|
+
const mapMethods = {
|
|
402
|
+
// set<K, V>(this: Store<Map<K, V>>, key: K, value: UpdateFrom<V, [V | undefined]>) {
|
|
403
|
+
// if (value instanceof Function) {
|
|
404
|
+
// value = value(this.get().get(key));
|
|
405
|
+
// }
|
|
406
|
+
// const newMap = new Map(this.get());
|
|
407
|
+
// newMap.set(key, value);
|
|
408
|
+
// this.set(newMap);
|
|
409
|
+
// return this;
|
|
410
|
+
// },
|
|
376
411
|
delete(key) {
|
|
377
412
|
const newMap = new Map(this.get());
|
|
378
413
|
const result = newMap.delete(key);
|
|
379
|
-
this.
|
|
414
|
+
this.set(newMap);
|
|
380
415
|
return result;
|
|
381
416
|
},
|
|
382
417
|
clear() {
|
|
383
|
-
this.
|
|
418
|
+
this.set(/* @__PURE__ */ new Map());
|
|
384
419
|
}
|
|
385
420
|
};
|
|
386
|
-
const
|
|
421
|
+
const setMethods = {
|
|
387
422
|
add(value) {
|
|
388
423
|
const newSet = new Set(this.get());
|
|
389
424
|
newSet.add(value);
|
|
390
|
-
this.
|
|
425
|
+
this.set(newSet);
|
|
391
426
|
},
|
|
392
427
|
delete(value) {
|
|
393
428
|
const newSet = new Set(this.get());
|
|
394
429
|
newSet.delete(value);
|
|
395
|
-
this.
|
|
430
|
+
this.set(newSet);
|
|
396
431
|
},
|
|
397
432
|
clear() {
|
|
398
|
-
this.
|
|
433
|
+
this.set(/* @__PURE__ */ new Set());
|
|
399
434
|
}
|
|
400
435
|
};
|
|
401
|
-
function throttle(
|
|
436
|
+
function throttle(action, duration) {
|
|
437
|
+
const ms = calcDuration(duration);
|
|
402
438
|
let t = 0;
|
|
403
439
|
let timeout;
|
|
404
440
|
return (...args) => {
|
|
@@ -407,44 +443,96 @@ function throttle(fn, ms) {
|
|
|
407
443
|
}
|
|
408
444
|
const dt = t + ms - Date.now();
|
|
409
445
|
if (dt <= 0) {
|
|
410
|
-
|
|
446
|
+
action(...args);
|
|
411
447
|
t = Date.now();
|
|
412
448
|
return;
|
|
413
449
|
}
|
|
414
450
|
timeout = setTimeout(() => {
|
|
415
|
-
|
|
451
|
+
action(...args);
|
|
416
452
|
t = Date.now();
|
|
417
453
|
}, dt);
|
|
418
454
|
};
|
|
419
455
|
}
|
|
420
456
|
const noop = () => void 0;
|
|
421
457
|
class Store {
|
|
422
|
-
constructor(
|
|
423
|
-
this.
|
|
458
|
+
constructor(getter, options = {}, derivedFrom) {
|
|
459
|
+
this.getter = getter;
|
|
424
460
|
this.options = options;
|
|
425
|
-
this.
|
|
426
|
-
this.listeners = /* @__PURE__ */ new
|
|
461
|
+
this.derivedFrom = derivedFrom;
|
|
462
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
427
463
|
this.effects = /* @__PURE__ */ new Map();
|
|
428
464
|
this.notifyId = {};
|
|
465
|
+
this.calculationHelper = new CalculationHelper({
|
|
466
|
+
calculate: ({ use }) => {
|
|
467
|
+
if (this.getter instanceof Function) {
|
|
468
|
+
const value = this.getter.apply({ use }, [{ use }]);
|
|
469
|
+
this._value = { v: value };
|
|
470
|
+
this.notify();
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
addEffect: this.addEffect.bind(this),
|
|
474
|
+
onInvalidate: this.reset.bind(this)
|
|
475
|
+
});
|
|
429
476
|
bind(this);
|
|
477
|
+
if (!(getter instanceof Function)) {
|
|
478
|
+
this._value = { v: getter };
|
|
479
|
+
}
|
|
430
480
|
}
|
|
431
481
|
get() {
|
|
432
|
-
|
|
482
|
+
this.calculationHelper.check();
|
|
483
|
+
if (!this._value) {
|
|
484
|
+
this.calculationHelper.execute();
|
|
485
|
+
return this.get();
|
|
486
|
+
}
|
|
487
|
+
return this._value.v;
|
|
433
488
|
}
|
|
434
|
-
|
|
489
|
+
set(...args) {
|
|
490
|
+
const path = args.length > 1 ? args[0] : [];
|
|
491
|
+
let update = args.length > 1 ? args[1] : args[0];
|
|
435
492
|
if (update instanceof Function) {
|
|
436
|
-
|
|
493
|
+
const before = this.get();
|
|
494
|
+
const valueBefore = get(before, path);
|
|
495
|
+
const valueAfter = update(valueBefore);
|
|
496
|
+
update = set(before, path, valueAfter);
|
|
497
|
+
} else if (path.length > 0) {
|
|
498
|
+
update = set(this.get(), path, update);
|
|
499
|
+
}
|
|
500
|
+
if (this.derivedFrom && this.derivedFrom.selectors.every((selector) => typeof selector === "string")) {
|
|
501
|
+
const derivationPath = this.derivedFrom.selectors.join(".");
|
|
502
|
+
this.derivedFrom.store.set((before) => set(before, derivationPath, update));
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
if (this.derivedFrom) {
|
|
506
|
+
throw new TypeError(
|
|
507
|
+
"Can only updated computed stores that are derived from other stores using string selectors"
|
|
508
|
+
);
|
|
437
509
|
}
|
|
438
|
-
this.
|
|
510
|
+
this._value = { v: update };
|
|
439
511
|
this.notify();
|
|
440
512
|
}
|
|
513
|
+
reset() {
|
|
514
|
+
this._value = void 0;
|
|
515
|
+
if (this.isActive) {
|
|
516
|
+
this.calculationHelper.execute();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
441
519
|
sub(listener, options) {
|
|
442
|
-
|
|
443
|
-
|
|
520
|
+
var _a;
|
|
521
|
+
const {
|
|
522
|
+
passive,
|
|
523
|
+
runNow = true,
|
|
524
|
+
throttle: throttleOption,
|
|
525
|
+
debounce: debounceOption,
|
|
526
|
+
equals = defaultEquals
|
|
527
|
+
} = options ?? {};
|
|
528
|
+
let compareToValue = (_a = this._value) == null ? void 0 : _a.v;
|
|
444
529
|
let previousValue;
|
|
445
530
|
let hasRun = false;
|
|
446
531
|
let innerListener = (force) => {
|
|
447
|
-
|
|
532
|
+
if (!this._value) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
const value = this._value.v;
|
|
448
536
|
if (!force && equals(value, compareToValue)) {
|
|
449
537
|
return;
|
|
450
538
|
}
|
|
@@ -459,45 +547,88 @@ class Store {
|
|
|
459
547
|
}
|
|
460
548
|
};
|
|
461
549
|
if (throttleOption) {
|
|
462
|
-
innerListener = throttle(innerListener,
|
|
550
|
+
innerListener = throttle(innerListener, throttleOption);
|
|
551
|
+
} else if (debounceOption) {
|
|
552
|
+
innerListener = debounce(innerListener, debounceOption);
|
|
553
|
+
}
|
|
554
|
+
this.listeners.set(innerListener, !passive);
|
|
555
|
+
if (!passive) {
|
|
556
|
+
this.onSubscribe();
|
|
463
557
|
}
|
|
464
|
-
this.listeners.add(innerListener);
|
|
465
|
-
this.onSubscribe();
|
|
466
558
|
if (runNow && !hasRun) {
|
|
467
559
|
innerListener(true);
|
|
468
560
|
}
|
|
469
561
|
return () => {
|
|
470
562
|
this.listeners.delete(innerListener);
|
|
471
|
-
|
|
563
|
+
if (!passive) {
|
|
564
|
+
this.onUnsubscribe();
|
|
565
|
+
}
|
|
472
566
|
};
|
|
473
567
|
}
|
|
568
|
+
once(condition = (value) => !!value) {
|
|
569
|
+
return new Promise((resolve) => {
|
|
570
|
+
let stopped = false;
|
|
571
|
+
const cancel = this.sub(
|
|
572
|
+
(value) => {
|
|
573
|
+
if (stopped || condition && !condition(value)) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
resolve(value);
|
|
577
|
+
stopped = true;
|
|
578
|
+
setTimeout(() => cancel());
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
runNow: !!condition
|
|
582
|
+
}
|
|
583
|
+
);
|
|
584
|
+
});
|
|
585
|
+
}
|
|
474
586
|
map(_selector, options) {
|
|
475
587
|
const selector = makeSelector(_selector);
|
|
476
588
|
const derivedFrom = { store: this, selectors: [_selector] };
|
|
477
|
-
return new
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
589
|
+
return new Store(
|
|
590
|
+
({ use }) => {
|
|
591
|
+
return selector(use(this, options));
|
|
592
|
+
},
|
|
593
|
+
this.options,
|
|
594
|
+
derivedFrom
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
/** Add an effect that will be executed when the store becomes active, which means when it has at least one subscriber.
|
|
598
|
+
* @param effect
|
|
599
|
+
* If there is already a subscriber, the effect will be executed immediately.
|
|
600
|
+
* Otherweise it will be executed as soon as the first subscription is created.
|
|
601
|
+
* Every time all subscriptions are removed and the first is created again, the effect will be executed again.
|
|
602
|
+
* @param retain
|
|
603
|
+
* If provided, delay tearing down effects when the last subscriber is removed. This is useful if a short gap in subscriber coverage is supposed to be ignored. E.g. when switching pages, the old page might unsubscribe, while the new page subscribes immediately after.
|
|
604
|
+
* @returns
|
|
605
|
+
* The effect can return a teardown callback, which will be executed when the last subscription is removed and potentially the ratain time has passed.
|
|
606
|
+
*/
|
|
481
607
|
addEffect(effect, retain) {
|
|
482
608
|
this.effects.set(effect, {
|
|
483
|
-
handle: this.
|
|
609
|
+
handle: this.isActive ? effect() ?? noop : void 0,
|
|
484
610
|
retain: retain !== void 0 ? calcDuration(retain) : void 0
|
|
485
611
|
});
|
|
486
612
|
return () => {
|
|
487
613
|
const { handle, timeout } = this.effects.get(effect) ?? {};
|
|
488
614
|
handle == null ? void 0 : handle();
|
|
489
|
-
timeout !== void 0
|
|
615
|
+
if (timeout !== void 0) {
|
|
616
|
+
clearTimeout(timeout);
|
|
617
|
+
}
|
|
490
618
|
this.effects.delete(effect);
|
|
491
619
|
};
|
|
492
620
|
}
|
|
621
|
+
/** Return whether the store is currently active, which means whether it has at least one subscriber. */
|
|
493
622
|
get isActive() {
|
|
494
|
-
return this.listeners.
|
|
623
|
+
return [...this.listeners.values()].some(Boolean);
|
|
495
624
|
}
|
|
496
625
|
onSubscribe() {
|
|
497
|
-
if (this.listeners.
|
|
626
|
+
if ([...this.listeners.values()].filter(Boolean).length > 1)
|
|
498
627
|
return;
|
|
499
628
|
for (const [effect, { handle, retain, timeout }] of this.effects.entries()) {
|
|
500
|
-
timeout !== void 0
|
|
629
|
+
if (timeout !== void 0) {
|
|
630
|
+
clearTimeout(timeout);
|
|
631
|
+
}
|
|
501
632
|
this.effects.set(effect, {
|
|
502
633
|
handle: handle ?? effect() ?? noop,
|
|
503
634
|
retain,
|
|
@@ -506,11 +637,15 @@ class Store {
|
|
|
506
637
|
}
|
|
507
638
|
}
|
|
508
639
|
onUnsubscribe() {
|
|
509
|
-
if (this.listeners.
|
|
640
|
+
if ([...this.listeners.values()].some(Boolean))
|
|
510
641
|
return;
|
|
511
642
|
for (const [effect, { handle, retain, timeout }] of this.effects.entries()) {
|
|
512
|
-
!retain
|
|
513
|
-
|
|
643
|
+
if (!retain) {
|
|
644
|
+
handle == null ? void 0 : handle();
|
|
645
|
+
}
|
|
646
|
+
if (timeout !== void 0) {
|
|
647
|
+
clearTimeout(timeout);
|
|
648
|
+
}
|
|
514
649
|
this.effects.set(effect, {
|
|
515
650
|
handle: retain ? handle : void 0,
|
|
516
651
|
retain,
|
|
@@ -519,8 +654,10 @@ class Store {
|
|
|
519
654
|
}
|
|
520
655
|
}
|
|
521
656
|
notify() {
|
|
522
|
-
const n =
|
|
523
|
-
|
|
657
|
+
const n = {};
|
|
658
|
+
this.notifyId = n;
|
|
659
|
+
const snapshot = [...this.listeners.keys()];
|
|
660
|
+
for (const listener of snapshot) {
|
|
524
661
|
listener();
|
|
525
662
|
if (n !== this.notifyId)
|
|
526
663
|
break;
|
|
@@ -528,81 +665,27 @@ class Store {
|
|
|
528
665
|
}
|
|
529
666
|
}
|
|
530
667
|
const defaultOptions = {};
|
|
531
|
-
function
|
|
668
|
+
function create(initialState, options) {
|
|
669
|
+
const store = new Store(initialState, options);
|
|
532
670
|
if (initialState instanceof Function) {
|
|
533
|
-
return
|
|
671
|
+
return store;
|
|
534
672
|
}
|
|
535
673
|
let methods = options == null ? void 0 : options.methods;
|
|
536
674
|
if (initialState instanceof Map) {
|
|
537
|
-
methods = { ...
|
|
675
|
+
methods = { ...mapMethods, ...methods };
|
|
538
676
|
} else if (initialState instanceof Set) {
|
|
539
|
-
methods = { ...
|
|
677
|
+
methods = { ...setMethods, ...methods };
|
|
540
678
|
} else if (Array.isArray(initialState)) {
|
|
541
|
-
methods = { ...
|
|
679
|
+
methods = { ...arrayMethods, ...methods };
|
|
542
680
|
} else if (initialState instanceof Object) {
|
|
543
|
-
methods = { ...
|
|
681
|
+
methods = { ...recordMethods, ...methods };
|
|
544
682
|
}
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
Object.entries(methods ?? {}).filter(([name]) => !(name in store2)).map(([name, fn]) => [name, fn.bind(store2)])
|
|
683
|
+
const boundMethods = Object.fromEntries(
|
|
684
|
+
Object.entries(methods ?? {}).filter(([name]) => !(name in store)).map(([name, action]) => [name, action.bind(store)])
|
|
548
685
|
);
|
|
549
|
-
return Object.assign(
|
|
550
|
-
}
|
|
551
|
-
const store = Object.assign(_store, { defaultOptions });
|
|
552
|
-
class DerivedStore extends Store {
|
|
553
|
-
constructor(calculate, derivedFrom) {
|
|
554
|
-
super(void 0);
|
|
555
|
-
this.calculate = calculate;
|
|
556
|
-
this.derivedFrom = derivedFrom;
|
|
557
|
-
this.calculationHelper = new CalculationHelper({
|
|
558
|
-
calculate: ({ use }) => {
|
|
559
|
-
const value = this.calculate.apply({ use }, [{ use }]);
|
|
560
|
-
this.valid = true;
|
|
561
|
-
super.update(value);
|
|
562
|
-
},
|
|
563
|
-
addEffect: this.addEffect,
|
|
564
|
-
getValue: () => this.value,
|
|
565
|
-
onInvalidate: this.invalidate
|
|
566
|
-
});
|
|
567
|
-
this.valid = false;
|
|
568
|
-
}
|
|
569
|
-
get() {
|
|
570
|
-
if (!this.valid) {
|
|
571
|
-
this.calculationHelper.execute();
|
|
572
|
-
}
|
|
573
|
-
return super.get();
|
|
574
|
-
}
|
|
575
|
-
update(update) {
|
|
576
|
-
if (this.derivedFrom && this.derivedFrom.selectors.every((selector) => typeof selector === "string")) {
|
|
577
|
-
const path = this.derivedFrom.selectors.join(".");
|
|
578
|
-
if (update instanceof Function) {
|
|
579
|
-
const before = get(this.derivedFrom.store, path);
|
|
580
|
-
update = update(before);
|
|
581
|
-
}
|
|
582
|
-
this.derivedFrom.store.update((before) => set(before, path, update));
|
|
583
|
-
} else {
|
|
584
|
-
throw new Error("Can only updated computed stores that are derived from other stores using string selectors");
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
map(_selector) {
|
|
588
|
-
const selector = makeSelector(_selector);
|
|
589
|
-
const derivedFrom = this.derivedFrom ?? { store: this, selectors: [] };
|
|
590
|
-
const newDerivedFrom = { ...derivedFrom, selectors: derivedFrom.selectors.concat(_selector) };
|
|
591
|
-
return new DerivedStore(({ use }) => {
|
|
592
|
-
return selector(use(this));
|
|
593
|
-
}, newDerivedFrom);
|
|
594
|
-
}
|
|
595
|
-
invalidate() {
|
|
596
|
-
this.valid = false;
|
|
597
|
-
if (this.isActive) {
|
|
598
|
-
this.calculationHelper.execute();
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
function _derivedStore(calculate) {
|
|
603
|
-
return new DerivedStore(calculate);
|
|
686
|
+
return Object.assign(store, boundMethods);
|
|
604
687
|
}
|
|
605
|
-
const
|
|
688
|
+
const createStore = Object.assign(create, { defaultOptions });
|
|
606
689
|
function hash(value) {
|
|
607
690
|
if (value instanceof Set) {
|
|
608
691
|
return `s[${[...value].map(hash).sort().join(",")}]`;
|
|
@@ -610,7 +693,7 @@ function hash(value) {
|
|
|
610
693
|
if (value instanceof Map) {
|
|
611
694
|
return `m[${[...value.entries()].map(hash).sort().join(",")}]`;
|
|
612
695
|
}
|
|
613
|
-
if (value
|
|
696
|
+
if (Array.isArray(value)) {
|
|
614
697
|
return `[${value.map(hash).join(",")}]`;
|
|
615
698
|
}
|
|
616
699
|
if (value instanceof Object) {
|
|
@@ -618,18 +701,15 @@ function hash(value) {
|
|
|
618
701
|
}
|
|
619
702
|
return JSON.stringify(value);
|
|
620
703
|
}
|
|
621
|
-
exports.CalculationHelper = CalculationHelper;
|
|
622
704
|
exports.Store = Store;
|
|
623
|
-
exports.
|
|
705
|
+
exports.arrayMethods = arrayMethods;
|
|
706
|
+
exports.bind = bind;
|
|
624
707
|
exports.calcDuration = calcDuration;
|
|
625
|
-
exports.
|
|
626
|
-
exports.derivedStore = derivedStore;
|
|
708
|
+
exports.createStore = createStore;
|
|
627
709
|
exports.hash = hash;
|
|
628
710
|
exports.makeSelector = makeSelector;
|
|
629
|
-
exports.
|
|
630
|
-
exports.
|
|
631
|
-
exports.
|
|
632
|
-
exports.simpleShallowEquals = simpleShallowEquals;
|
|
633
|
-
exports.store = store;
|
|
711
|
+
exports.mapMethods = mapMethods;
|
|
712
|
+
exports.recordMethods = recordMethods;
|
|
713
|
+
exports.setMethods = setMethods;
|
|
634
714
|
exports.trackingProxy = trackingProxy;
|
|
635
715
|
//# sourceMappingURL=hash.cjs.map
|