cross-state 0.6.3 → 0.6.6
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 +368 -283
- 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 +186 -174
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/react.cjs +73 -12
- package/dist/cjs/react.cjs.map +1 -1
- package/dist/es/hash.mjs +369 -284
- 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 +189 -177
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/react.mjs +79 -18
- package/dist/es/react.mjs.map +1 -1
- package/dist/types/core/cache.d.ts +60 -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 +9 -6
- 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 +3 -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 -38
- 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,105 +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
|
-
|
|
242
|
-
|
|
243
|
-
|
|
269
|
+
timeout = setTimeout(() => {
|
|
270
|
+
timeout = void 0;
|
|
271
|
+
timeoutStarted = void 0;
|
|
272
|
+
action(...args);
|
|
273
|
+
}, deadline - now);
|
|
274
|
+
};
|
|
244
275
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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);
|
|
248
285
|
}
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
const index = path.indexOf(".");
|
|
253
|
-
let key, update;
|
|
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}`);
|
|
261
|
-
}
|
|
262
|
-
update = set(subObj, rest, value, rootPath);
|
|
263
|
-
} else {
|
|
264
|
-
key = path;
|
|
265
|
-
update = value instanceof Function ? value(obj[key]) : value;
|
|
266
|
-
}
|
|
267
|
-
if (Array.isArray(obj)) {
|
|
268
|
-
const copy = Array.from(obj);
|
|
269
|
-
copy[key] = update;
|
|
270
|
-
return copy;
|
|
286
|
+
if (object instanceof Set) {
|
|
287
|
+
return new Set(object);
|
|
271
288
|
}
|
|
272
|
-
|
|
273
|
-
...
|
|
274
|
-
|
|
275
|
-
|
|
289
|
+
if (Array.isArray(object)) {
|
|
290
|
+
return [...object];
|
|
291
|
+
}
|
|
292
|
+
if (object instanceof Object) {
|
|
293
|
+
return { ...object };
|
|
294
|
+
}
|
|
295
|
+
return object;
|
|
276
296
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
} while ((object = Reflect.getPrototypeOf(object)) && object !== Object.prototype);
|
|
284
|
-
return properties;
|
|
285
|
-
};
|
|
286
|
-
function bind(self) {
|
|
287
|
-
for (const [object, key] of getAllProperties(self.constructor.prototype)) {
|
|
288
|
-
if (key === "constructor") {
|
|
289
|
-
continue;
|
|
290
|
-
}
|
|
291
|
-
const descriptor = Reflect.getOwnPropertyDescriptor(object, key);
|
|
292
|
-
if (descriptor && typeof descriptor.value === "function") {
|
|
293
|
-
self[key] = self[key].bind(self);
|
|
294
|
-
}
|
|
297
|
+
function castArrayPath(path) {
|
|
298
|
+
if (Array.isArray(path)) {
|
|
299
|
+
return path;
|
|
300
|
+
}
|
|
301
|
+
if (path === "") {
|
|
302
|
+
return [];
|
|
295
303
|
}
|
|
304
|
+
return path.split(".");
|
|
296
305
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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);
|
|
306
317
|
}
|
|
307
|
-
if (
|
|
308
|
-
return
|
|
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) {
|
|
327
|
+
return value;
|
|
309
328
|
}
|
|
310
|
-
|
|
311
|
-
if (
|
|
312
|
-
|
|
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}`);
|
|
313
334
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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));
|
|
341
|
+
return copy;
|
|
317
342
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
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}`);
|
|
324
355
|
}
|
|
325
356
|
function makeSelector(selector) {
|
|
326
357
|
if (!selector) {
|
|
@@ -331,74 +362,79 @@ function makeSelector(selector) {
|
|
|
331
362
|
}
|
|
332
363
|
return (x) => get(x, selector);
|
|
333
364
|
}
|
|
334
|
-
const
|
|
335
|
-
const
|
|
336
|
-
const result =
|
|
337
|
-
this.
|
|
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);
|
|
437
499
|
}
|
|
438
|
-
this.
|
|
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
|
+
);
|
|
509
|
+
}
|
|
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,22 +547,49 @@ 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
|
-
const derivedFrom = {
|
|
477
|
-
|
|
588
|
+
const derivedFrom = {
|
|
589
|
+
store: this.derivedFrom ? this.derivedFrom.store : this,
|
|
590
|
+
selectors: this.derivedFrom ? [...this.derivedFrom.selectors, _selector] : [_selector]
|
|
591
|
+
};
|
|
592
|
+
return new Store(
|
|
478
593
|
({ use }) => {
|
|
479
594
|
return selector(use(this, options));
|
|
480
595
|
},
|
|
@@ -482,26 +597,41 @@ class Store {
|
|
|
482
597
|
derivedFrom
|
|
483
598
|
);
|
|
484
599
|
}
|
|
600
|
+
/** Add an effect that will be executed when the store becomes active, which means when it has at least one subscriber.
|
|
601
|
+
* @param effect
|
|
602
|
+
* If there is already a subscriber, the effect will be executed immediately.
|
|
603
|
+
* Otherweise it will be executed as soon as the first subscription is created.
|
|
604
|
+
* Every time all subscriptions are removed and the first is created again, the effect will be executed again.
|
|
605
|
+
* @param retain
|
|
606
|
+
* 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.
|
|
607
|
+
* @returns
|
|
608
|
+
* The effect can return a teardown callback, which will be executed when the last subscription is removed and potentially the ratain time has passed.
|
|
609
|
+
*/
|
|
485
610
|
addEffect(effect, retain) {
|
|
486
611
|
this.effects.set(effect, {
|
|
487
|
-
handle: this.
|
|
612
|
+
handle: this.isActive ? effect() ?? noop : void 0,
|
|
488
613
|
retain: retain !== void 0 ? calcDuration(retain) : void 0
|
|
489
614
|
});
|
|
490
615
|
return () => {
|
|
491
616
|
const { handle, timeout } = this.effects.get(effect) ?? {};
|
|
492
617
|
handle == null ? void 0 : handle();
|
|
493
|
-
timeout !== void 0
|
|
618
|
+
if (timeout !== void 0) {
|
|
619
|
+
clearTimeout(timeout);
|
|
620
|
+
}
|
|
494
621
|
this.effects.delete(effect);
|
|
495
622
|
};
|
|
496
623
|
}
|
|
624
|
+
/** Return whether the store is currently active, which means whether it has at least one subscriber. */
|
|
497
625
|
get isActive() {
|
|
498
|
-
return this.listeners.
|
|
626
|
+
return [...this.listeners.values()].some(Boolean);
|
|
499
627
|
}
|
|
500
628
|
onSubscribe() {
|
|
501
|
-
if (this.listeners.
|
|
629
|
+
if ([...this.listeners.values()].filter(Boolean).length > 1)
|
|
502
630
|
return;
|
|
503
631
|
for (const [effect, { handle, retain, timeout }] of this.effects.entries()) {
|
|
504
|
-
timeout !== void 0
|
|
632
|
+
if (timeout !== void 0) {
|
|
633
|
+
clearTimeout(timeout);
|
|
634
|
+
}
|
|
505
635
|
this.effects.set(effect, {
|
|
506
636
|
handle: handle ?? effect() ?? noop,
|
|
507
637
|
retain,
|
|
@@ -510,11 +640,15 @@ class Store {
|
|
|
510
640
|
}
|
|
511
641
|
}
|
|
512
642
|
onUnsubscribe() {
|
|
513
|
-
if (this.listeners.
|
|
643
|
+
if ([...this.listeners.values()].some(Boolean))
|
|
514
644
|
return;
|
|
515
645
|
for (const [effect, { handle, retain, timeout }] of this.effects.entries()) {
|
|
516
|
-
!retain
|
|
517
|
-
|
|
646
|
+
if (!retain) {
|
|
647
|
+
handle == null ? void 0 : handle();
|
|
648
|
+
}
|
|
649
|
+
if (timeout !== void 0) {
|
|
650
|
+
clearTimeout(timeout);
|
|
651
|
+
}
|
|
518
652
|
this.effects.set(effect, {
|
|
519
653
|
handle: retain ? handle : void 0,
|
|
520
654
|
retain,
|
|
@@ -523,8 +657,10 @@ class Store {
|
|
|
523
657
|
}
|
|
524
658
|
}
|
|
525
659
|
notify() {
|
|
526
|
-
const n =
|
|
527
|
-
|
|
660
|
+
const n = {};
|
|
661
|
+
this.notifyId = n;
|
|
662
|
+
const snapshot = [...this.listeners.keys()];
|
|
663
|
+
for (const listener of snapshot) {
|
|
528
664
|
listener();
|
|
529
665
|
if (n !== this.notifyId)
|
|
530
666
|
break;
|
|
@@ -532,75 +668,27 @@ class Store {
|
|
|
532
668
|
}
|
|
533
669
|
}
|
|
534
670
|
const defaultOptions = {};
|
|
535
|
-
function
|
|
671
|
+
function create(initialState, options) {
|
|
672
|
+
const store = new Store(initialState, options);
|
|
536
673
|
if (initialState instanceof Function) {
|
|
537
|
-
return
|
|
674
|
+
return store;
|
|
538
675
|
}
|
|
539
676
|
let methods = options == null ? void 0 : options.methods;
|
|
540
677
|
if (initialState instanceof Map) {
|
|
541
|
-
methods = { ...
|
|
678
|
+
methods = { ...mapMethods, ...methods };
|
|
542
679
|
} else if (initialState instanceof Set) {
|
|
543
|
-
methods = { ...
|
|
680
|
+
methods = { ...setMethods, ...methods };
|
|
544
681
|
} else if (Array.isArray(initialState)) {
|
|
545
|
-
methods = { ...
|
|
682
|
+
methods = { ...arrayMethods, ...methods };
|
|
546
683
|
} else if (initialState instanceof Object) {
|
|
547
|
-
methods = { ...
|
|
684
|
+
methods = { ...recordMethods, ...methods };
|
|
548
685
|
}
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
Object.entries(methods ?? {}).filter(([name]) => !(name in store2)).map(([name, fn]) => [name, fn.bind(store2)])
|
|
686
|
+
const boundMethods = Object.fromEntries(
|
|
687
|
+
Object.entries(methods ?? {}).filter(([name]) => !(name in store)).map(([name, action]) => [name, action.bind(store)])
|
|
552
688
|
);
|
|
553
|
-
return Object.assign(
|
|
554
|
-
}
|
|
555
|
-
const store = Object.assign(_store, { defaultOptions });
|
|
556
|
-
class DerivedStore extends Store {
|
|
557
|
-
constructor(calculate, options = {}, derivedFrom) {
|
|
558
|
-
super(void 0);
|
|
559
|
-
this.calculate = calculate;
|
|
560
|
-
this.options = options;
|
|
561
|
-
this.derivedFrom = derivedFrom;
|
|
562
|
-
this.calculationHelper = new CalculationHelper({
|
|
563
|
-
calculate: ({ use }) => {
|
|
564
|
-
const value = this.calculate.apply({ use }, [{ use }]);
|
|
565
|
-
this.valid = true;
|
|
566
|
-
super.update(value);
|
|
567
|
-
},
|
|
568
|
-
addEffect: this.addEffect,
|
|
569
|
-
getValue: () => this.value,
|
|
570
|
-
onInvalidate: this.invalidate
|
|
571
|
-
});
|
|
572
|
-
this.valid = false;
|
|
573
|
-
}
|
|
574
|
-
get() {
|
|
575
|
-
this.calculationHelper.check();
|
|
576
|
-
if (!this.valid) {
|
|
577
|
-
this.calculationHelper.execute();
|
|
578
|
-
}
|
|
579
|
-
return super.get();
|
|
580
|
-
}
|
|
581
|
-
update(update) {
|
|
582
|
-
if (this.derivedFrom && this.derivedFrom.selectors.every((selector) => typeof selector === "string")) {
|
|
583
|
-
const path = this.derivedFrom.selectors.join(".");
|
|
584
|
-
if (update instanceof Function) {
|
|
585
|
-
const before = this.get();
|
|
586
|
-
update = update(before);
|
|
587
|
-
}
|
|
588
|
-
this.derivedFrom.store.update((before) => set(before, path, update));
|
|
589
|
-
} else {
|
|
590
|
-
throw new Error("Can only updated computed stores that are derived from other stores using string selectors");
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
invalidate() {
|
|
594
|
-
this.valid = false;
|
|
595
|
-
if (this.isActive) {
|
|
596
|
-
this.calculationHelper.execute();
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
function _derivedStore(calculate, options) {
|
|
601
|
-
return new DerivedStore(calculate, options);
|
|
689
|
+
return Object.assign(store, boundMethods);
|
|
602
690
|
}
|
|
603
|
-
const
|
|
691
|
+
const createStore = Object.assign(create, { defaultOptions });
|
|
604
692
|
function hash(value) {
|
|
605
693
|
if (value instanceof Set) {
|
|
606
694
|
return `s[${[...value].map(hash).sort().join(",")}]`;
|
|
@@ -608,7 +696,7 @@ function hash(value) {
|
|
|
608
696
|
if (value instanceof Map) {
|
|
609
697
|
return `m[${[...value.entries()].map(hash).sort().join(",")}]`;
|
|
610
698
|
}
|
|
611
|
-
if (value
|
|
699
|
+
if (Array.isArray(value)) {
|
|
612
700
|
return `[${value.map(hash).join(",")}]`;
|
|
613
701
|
}
|
|
614
702
|
if (value instanceof Object) {
|
|
@@ -616,18 +704,15 @@ function hash(value) {
|
|
|
616
704
|
}
|
|
617
705
|
return JSON.stringify(value);
|
|
618
706
|
}
|
|
619
|
-
exports.CalculationHelper = CalculationHelper;
|
|
620
707
|
exports.Store = Store;
|
|
621
|
-
exports.
|
|
708
|
+
exports.arrayMethods = arrayMethods;
|
|
709
|
+
exports.bind = bind;
|
|
622
710
|
exports.calcDuration = calcDuration;
|
|
623
|
-
exports.
|
|
624
|
-
exports.derivedStore = derivedStore;
|
|
711
|
+
exports.createStore = createStore;
|
|
625
712
|
exports.hash = hash;
|
|
626
713
|
exports.makeSelector = makeSelector;
|
|
627
|
-
exports.
|
|
628
|
-
exports.
|
|
629
|
-
exports.
|
|
630
|
-
exports.simpleShallowEquals = simpleShallowEquals;
|
|
631
|
-
exports.store = store;
|
|
714
|
+
exports.mapMethods = mapMethods;
|
|
715
|
+
exports.recordMethods = recordMethods;
|
|
716
|
+
exports.setMethods = setMethods;
|
|
632
717
|
exports.trackingProxy = trackingProxy;
|
|
633
718
|
//# sourceMappingURL=hash.cjs.map
|