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