cross-state 0.6.10 → 0.7.2
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/dist/cjs/hash.cjs +0 -682
- package/dist/cjs/hash.cjs.map +1 -1
- package/dist/cjs/immer/index.cjs +6 -0
- package/dist/cjs/immer/index.cjs.map +1 -0
- package/dist/cjs/immer/register.cjs +6 -0
- package/dist/cjs/immer/register.cjs.map +1 -0
- package/dist/cjs/immerMethods.cjs +23 -0
- package/dist/cjs/immerMethods.cjs.map +1 -0
- package/dist/cjs/index.cjs +387 -278
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/react/index.cjs +54 -0
- package/dist/cjs/react/index.cjs.map +1 -0
- package/dist/cjs/react/register.cjs +30 -0
- package/dist/cjs/react/register.cjs.map +1 -0
- package/dist/cjs/scope.cjs +399 -0
- package/dist/cjs/scope.cjs.map +1 -0
- package/dist/cjs/scope2.cjs +513 -0
- package/dist/cjs/scope2.cjs.map +1 -0
- package/dist/cjs/store.cjs +798 -0
- package/dist/cjs/store.cjs.map +1 -0
- package/dist/es/hash.mjs +1 -683
- package/dist/es/hash.mjs.map +1 -1
- package/dist/es/immer/index.mjs +6 -0
- package/dist/es/immer/index.mjs.map +1 -0
- package/dist/es/immer/register.mjs +5 -0
- package/dist/es/immer/register.mjs.map +1 -0
- package/dist/es/immerMethods.mjs +24 -0
- package/dist/es/immerMethods.mjs.map +1 -0
- package/dist/es/index.mjs +383 -273
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/react/index.mjs +55 -0
- package/dist/es/react/index.mjs.map +1 -0
- package/dist/es/react/register.mjs +29 -0
- package/dist/es/react/register.mjs.map +1 -0
- package/dist/es/scope.mjs +400 -0
- package/dist/es/scope.mjs.map +1 -0
- package/dist/es/scope2.mjs +514 -0
- package/dist/es/scope2.mjs.map +1 -0
- package/dist/es/store.mjs +799 -0
- package/dist/es/store.mjs.map +1 -0
- package/dist/types/core/cache.d.ts +7 -2
- package/dist/types/core/commonTypes.d.ts +8 -0
- package/dist/types/core/index.d.ts +6 -6
- package/dist/types/core/resourceGroup.d.ts +2 -2
- package/dist/types/core/scope.d.ts +5 -0
- package/dist/types/core/store.d.ts +8 -10
- package/dist/types/core/subscriptionCache.d.ts +51 -0
- package/dist/types/core/urlStore.d.ts +26 -0
- package/dist/types/immer/immerMethods.d.ts +10 -0
- package/dist/types/immer/index.d.ts +1 -1
- package/dist/types/immer/register.d.ts +7 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/lib/calculationHelper.d.ts +15 -10
- package/dist/types/lib/equals.d.ts +3 -3
- package/dist/types/lib/path.d.ts +3 -3
- package/dist/types/lib/promiseWithState.d.ts +9 -0
- package/dist/types/lib/standardMethods.d.ts +2 -1
- package/dist/types/lib/trackingProxy.d.ts +2 -1
- package/dist/types/lib/typeHelpers.d.ts +3 -1
- package/dist/types/lib/updateHelpers.d.ts +1 -0
- package/dist/types/react/index.d.ts +3 -1
- package/dist/types/react/reactMethods.d.ts +9 -0
- package/dist/types/react/register.d.ts +29 -0
- package/dist/types/react/scope.d.ts +16 -0
- package/dist/types/react/useCache.d.ts +2 -1
- package/dist/types/react/useDecoupledState.d.ts +7 -0
- package/dist/types/react/useProp.d.ts +1 -2
- package/package.json +105 -27
- package/dist/cjs/immer.cjs +0 -10
- package/dist/cjs/immer.cjs.map +0 -1
- package/dist/cjs/react.cjs +0 -292
- package/dist/cjs/react.cjs.map +0 -1
- package/dist/es/immer.mjs +0 -10
- package/dist/es/immer.mjs.map +0 -1
- package/dist/es/react.mjs +0 -292
- package/dist/es/react.mjs.map +0 -1
- package/dist/types/core/storeScope.d.ts +0 -4
- package/dist/types/immer/immerActions.d.ts +0 -5
- package/dist/types/react/storeScope.d.ts +0 -12
package/dist/es/index.mjs
CHANGED
|
@@ -1,280 +1,67 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
this.
|
|
10
|
-
this.invalidateAll = this.invalidateAll.bind(this);
|
|
11
|
-
this.clearAll = this.clearAll.bind(this);
|
|
12
|
-
}
|
|
13
|
-
add(resource) {
|
|
14
|
-
const ref = new WeakRef(resource);
|
|
15
|
-
this.refMap.set(resource, ref);
|
|
16
|
-
this.refSet.add(ref);
|
|
17
|
-
}
|
|
18
|
-
delete(resource) {
|
|
19
|
-
const ref = this.refMap.get(resource);
|
|
20
|
-
if (ref) {
|
|
21
|
-
this.refMap.delete(resource);
|
|
22
|
-
this.refSet.delete(ref);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
invalidateAll() {
|
|
26
|
-
for (const ref of this.refSet) {
|
|
27
|
-
const resource = ref.deref();
|
|
28
|
-
if (resource) {
|
|
29
|
-
resource.invalidate();
|
|
30
|
-
} else {
|
|
31
|
-
this.refSet.delete(ref);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
clearAll() {
|
|
36
|
-
for (const ref of this.refSet) {
|
|
37
|
-
const resource = ref.deref();
|
|
38
|
-
if (resource) {
|
|
39
|
-
resource.clear();
|
|
40
|
-
} else {
|
|
41
|
-
this.refSet.delete(ref);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
const allResources = /* @__PURE__ */ new ResourceGroup();
|
|
47
|
-
function createResourceGroup(name) {
|
|
48
|
-
return new ResourceGroup(name);
|
|
49
|
-
}
|
|
50
|
-
class InstanceCache {
|
|
51
|
-
constructor(factory, cacheTime) {
|
|
52
|
-
this.factory = factory;
|
|
53
|
-
this.cacheTime = cacheTime;
|
|
54
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
55
|
-
this.interval = this.cacheTime ? setInterval(() => this.cleanup(), Math.max(this.cacheTime / 10, 1)) : void 0;
|
|
56
|
-
}
|
|
57
|
-
cleanup() {
|
|
58
|
-
var _a;
|
|
59
|
-
const cutoff = this.now() - (this.cacheTime ?? 0);
|
|
60
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
61
|
-
if (entry.ref && entry.t <= cutoff) {
|
|
62
|
-
delete entry.ref;
|
|
63
|
-
}
|
|
64
|
-
if (!entry.ref && !((_a = entry.weakRef) == null ? void 0 : _a.deref())) {
|
|
65
|
-
this.cache.delete(key);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
get(...args) {
|
|
70
|
-
var _a;
|
|
71
|
-
const key = hash(args);
|
|
72
|
-
let entry = this.cache.get(key);
|
|
73
|
-
let value = (entry == null ? void 0 : entry.ref) ?? ((_a = entry == null ? void 0 : entry.weakRef) == null ? void 0 : _a.deref());
|
|
74
|
-
if (!entry || !value) {
|
|
75
|
-
value = this.factory(...args);
|
|
76
|
-
entry = {
|
|
77
|
-
t: this.now(),
|
|
78
|
-
ref: value,
|
|
79
|
-
weakRef: new WeakRef(value)
|
|
80
|
-
};
|
|
81
|
-
this.cache.set(key, entry);
|
|
82
|
-
} else {
|
|
83
|
-
entry.t = this.now();
|
|
84
|
-
entry.ref ?? (entry.ref = value);
|
|
85
|
-
}
|
|
86
|
-
return value;
|
|
87
|
-
}
|
|
88
|
-
values() {
|
|
89
|
-
return [...this.cache.values()].map((entry) => {
|
|
90
|
-
var _a;
|
|
91
|
-
return entry.ref ?? ((_a = entry.weakRef) == null ? void 0 : _a.deref());
|
|
92
|
-
}).filter((value) => !!value);
|
|
93
|
-
}
|
|
94
|
-
stop() {
|
|
95
|
-
if (this.interval) {
|
|
96
|
-
clearInterval(this.interval);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
stats() {
|
|
100
|
-
return {
|
|
101
|
-
count: this.cache.size,
|
|
102
|
-
withRef: [...this.cache.values()].filter((x) => !!x.ref).length,
|
|
103
|
-
withWeakRef: [...this.cache.values()].filter((x) => {
|
|
104
|
-
var _a;
|
|
105
|
-
return !!((_a = x.weakRef) == null ? void 0 : _a.deref());
|
|
106
|
-
}).length
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
now() {
|
|
110
|
-
return performance.now();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
class Cache extends Store {
|
|
114
|
-
constructor(getter, options = {}, derivedFromCache, _call) {
|
|
115
|
-
super(getter, options, void 0, _call);
|
|
1
|
+
import { I as InstanceCache, a as allResources } from "./scope.mjs";
|
|
2
|
+
import { C, R, S, c, b, d } from "./scope.mjs";
|
|
3
|
+
import { S as Store, c as createStore, a as calcDuration, q as queue, b as castArrayPath, s as shallowEqual, g as get, d as set } from "./store.mjs";
|
|
4
|
+
import { e, m, r, f } from "./store.mjs";
|
|
5
|
+
import "./hash.mjs";
|
|
6
|
+
class SubstriptionCache extends Store {
|
|
7
|
+
constructor(connectFunction, options = {}, derivedFromSubscriptionCache, _call) {
|
|
8
|
+
super(void 0, options, void 0, _call);
|
|
9
|
+
this.connectFunction = connectFunction;
|
|
116
10
|
this.options = options;
|
|
117
|
-
this.
|
|
11
|
+
this.derivedFromSubscriptionCache = derivedFromSubscriptionCache;
|
|
118
12
|
this.state = createStore({
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
isUpdating: false
|
|
13
|
+
connectionState: "closed",
|
|
14
|
+
error: void 0
|
|
122
15
|
});
|
|
123
|
-
this.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
16
|
+
this.calculationHelper.options = {
|
|
17
|
+
...this.calculationHelper.options,
|
|
18
|
+
calculate: (helpers) => {
|
|
19
|
+
let result = connectFunction.apply(helpers);
|
|
20
|
+
if (result instanceof Function && result.length > 0) {
|
|
21
|
+
result = result(helpers);
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
},
|
|
25
|
+
onValue: (value) => {
|
|
26
|
+
this.set(value);
|
|
27
|
+
},
|
|
28
|
+
onError: (error) => {
|
|
29
|
+
this.state.set("error", error);
|
|
30
|
+
},
|
|
31
|
+
onConnectionState: (state) => {
|
|
32
|
+
this.state.set("connectionState", state);
|
|
33
|
+
},
|
|
34
|
+
onInvalidate: () => {
|
|
35
|
+
this.invalidate();
|
|
137
36
|
}
|
|
138
|
-
}
|
|
139
|
-
if (!promise || stalePromise && backgroundUpdate) {
|
|
140
|
-
return stalePromise;
|
|
141
|
-
}
|
|
142
|
-
return promise;
|
|
37
|
+
};
|
|
143
38
|
}
|
|
144
39
|
invalidate({ invalidateDependencies = true } = {}) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (clearOnInvalidation) {
|
|
40
|
+
const { clearOnInvalidate = defaultOptions.clearOnInvalidate } = this.options;
|
|
41
|
+
if (clearOnInvalidate) {
|
|
148
42
|
return this.clear({ invalidateDependencies });
|
|
149
43
|
}
|
|
150
44
|
if (invalidateDependencies) {
|
|
151
45
|
this.calculationHelper.invalidateDependencies();
|
|
152
46
|
}
|
|
153
|
-
|
|
154
|
-
if (
|
|
155
|
-
this.
|
|
47
|
+
this.calculationHelper.stop();
|
|
48
|
+
if (this.isActive()) {
|
|
49
|
+
this.calculationHelper.execute();
|
|
156
50
|
}
|
|
157
|
-
this.state.set((state) => ({
|
|
158
|
-
...state,
|
|
159
|
-
isStale: true,
|
|
160
|
-
isUpdating: false
|
|
161
|
-
}));
|
|
162
|
-
super.reset();
|
|
163
51
|
}
|
|
164
52
|
clear({ invalidateDependencies = true } = {}) {
|
|
165
53
|
if (invalidateDependencies) {
|
|
166
54
|
this.calculationHelper.invalidateDependencies();
|
|
167
55
|
}
|
|
168
|
-
this.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
isUpdating: false
|
|
172
|
-
});
|
|
173
|
-
delete this.stalePromise;
|
|
174
|
-
super.reset();
|
|
175
|
-
}
|
|
176
|
-
mapValue(_selector) {
|
|
177
|
-
const selector = makeSelector(_selector);
|
|
178
|
-
const derivedFromCache = {
|
|
179
|
-
cache: this.derivedFromCache ? this.derivedFromCache.cache : this,
|
|
180
|
-
selectors: this.derivedFromCache ? [...this.derivedFromCache.selectors, _selector] : [_selector]
|
|
181
|
-
};
|
|
182
|
-
const that = this;
|
|
183
|
-
return new Cache(
|
|
184
|
-
async function() {
|
|
185
|
-
const value = await this.use(that);
|
|
186
|
-
return selector(value);
|
|
187
|
-
},
|
|
188
|
-
{},
|
|
189
|
-
derivedFromCache
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
watchPromise() {
|
|
193
|
-
this.sub(
|
|
194
|
-
async (promise) => {
|
|
195
|
-
var _a, _b;
|
|
196
|
-
this.state.set((state) => ({
|
|
197
|
-
...state,
|
|
198
|
-
isUpdating: true
|
|
199
|
-
}));
|
|
200
|
-
this.setTimers();
|
|
201
|
-
try {
|
|
202
|
-
const value = await promise;
|
|
203
|
-
if (promise !== ((_a = this._value) == null ? void 0 : _a.v)) {
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
this.state.set({
|
|
207
|
-
status: "value",
|
|
208
|
-
value,
|
|
209
|
-
isStale: false,
|
|
210
|
-
isUpdating: false
|
|
211
|
-
});
|
|
212
|
-
delete this.stalePromise;
|
|
213
|
-
this.setTimers();
|
|
214
|
-
} catch (error) {
|
|
215
|
-
if (promise !== ((_b = this._value) == null ? void 0 : _b.v)) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
this.state.set({
|
|
219
|
-
status: "error",
|
|
220
|
-
error,
|
|
221
|
-
isStale: false,
|
|
222
|
-
isUpdating: false
|
|
223
|
-
});
|
|
224
|
-
delete this.stalePromise;
|
|
225
|
-
this.setTimers();
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
{ passive: true }
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
setTimers() {
|
|
232
|
-
if (this.invalidationTimer) {
|
|
233
|
-
clearTimeout(this.invalidationTimer);
|
|
234
|
-
}
|
|
235
|
-
this.invalidationTimer = void 0;
|
|
236
|
-
const state = this.state.get();
|
|
237
|
-
let { invalidateAfter = defaultOptions.invalidateAfter } = this.options;
|
|
238
|
-
const ref = new WeakRef(this);
|
|
239
|
-
if (state.status === "pending") {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
if (invalidateAfter instanceof Function) {
|
|
243
|
-
invalidateAfter = invalidateAfter(state);
|
|
244
|
-
}
|
|
245
|
-
if (invalidateAfter !== null && invalidateAfter !== void 0) {
|
|
246
|
-
this.invalidationTimer = setTimeout(
|
|
247
|
-
() => {
|
|
248
|
-
var _a;
|
|
249
|
-
return (_a = ref == null ? void 0 : ref.deref()) == null ? void 0 : _a.invalidate();
|
|
250
|
-
},
|
|
251
|
-
calcDuration(invalidateAfter)
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
watchFocus() {
|
|
256
|
-
const { invalidateOnWindowFocus = defaultOptions.invalidateOnWindowFocus } = this.options;
|
|
257
|
-
if (!invalidateOnWindowFocus || typeof document === "undefined" || typeof document.addEventListener === "undefined") {
|
|
258
|
-
return;
|
|
56
|
+
this.calculationHelper.stop();
|
|
57
|
+
if (this.isActive()) {
|
|
58
|
+
this.calculationHelper.execute();
|
|
259
59
|
}
|
|
260
|
-
const ref = new WeakRef(this);
|
|
261
|
-
const onFocus = () => {
|
|
262
|
-
const that = ref == null ? void 0 : ref.deref();
|
|
263
|
-
if (!that) {
|
|
264
|
-
document.removeEventListener("visibilitychange", onFocus);
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
if (!document.hidden) {
|
|
268
|
-
that.invalidate();
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
document.addEventListener("visibilitychange", onFocus);
|
|
272
60
|
}
|
|
273
61
|
}
|
|
274
62
|
const defaultOptions = {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
clearUnusedAfter: { days: 1 }
|
|
63
|
+
clearUnusedAfter: { days: 1 },
|
|
64
|
+
retain: { seconds: 1 }
|
|
278
65
|
};
|
|
279
66
|
function create(cacheFunction, options) {
|
|
280
67
|
const { clearUnusedAfter = defaultOptions.clearUnusedAfter, resourceGroup } = options ?? {};
|
|
@@ -284,13 +71,13 @@ function create(cacheFunction, options) {
|
|
|
284
71
|
if (args.length === 0 && baseInstance) {
|
|
285
72
|
return baseInstance;
|
|
286
73
|
}
|
|
287
|
-
return new
|
|
74
|
+
return new SubstriptionCache(function() {
|
|
288
75
|
return cacheFunction.apply(this, args);
|
|
289
76
|
}, options);
|
|
290
77
|
},
|
|
291
78
|
clearUnusedAfter ? calcDuration(clearUnusedAfter) : void 0
|
|
292
79
|
);
|
|
293
|
-
const
|
|
80
|
+
const get2 = (...args) => {
|
|
294
81
|
return instanceCache.get(...args);
|
|
295
82
|
};
|
|
296
83
|
const invalidateAll = () => {
|
|
@@ -303,43 +90,366 @@ function create(cacheFunction, options) {
|
|
|
303
90
|
instance.clear();
|
|
304
91
|
}
|
|
305
92
|
};
|
|
306
|
-
const groups = Array.isArray(resourceGroup) ? resourceGroup : resourceGroup ? [resourceGroup] : [];
|
|
307
|
-
for (const group of groups.concat(allResources)) {
|
|
308
|
-
group.add({ invalidate: invalidateAll, clear: clearAll });
|
|
309
|
-
}
|
|
310
93
|
baseInstance = Object.assign(
|
|
311
|
-
new
|
|
94
|
+
new SubstriptionCache(
|
|
312
95
|
function() {
|
|
313
96
|
return cacheFunction.apply(this);
|
|
314
97
|
},
|
|
315
98
|
options,
|
|
316
99
|
void 0,
|
|
317
|
-
|
|
100
|
+
get2
|
|
318
101
|
),
|
|
319
102
|
{
|
|
320
103
|
invalidateAll,
|
|
321
104
|
clearAll
|
|
322
105
|
}
|
|
323
106
|
);
|
|
324
|
-
|
|
107
|
+
const groups = Array.isArray(resourceGroup) ? resourceGroup : resourceGroup ? [resourceGroup] : [];
|
|
108
|
+
for (const group of groups.concat(allResources)) {
|
|
109
|
+
group.add(baseInstance);
|
|
110
|
+
}
|
|
111
|
+
get2(...[]);
|
|
325
112
|
return baseInstance;
|
|
326
113
|
}
|
|
327
|
-
const
|
|
114
|
+
const createSubscriptionCache = /* @__PURE__ */ Object.assign(create, {
|
|
328
115
|
defaultOptions
|
|
329
116
|
});
|
|
117
|
+
class UrlStore extends Store {
|
|
118
|
+
constructor(options) {
|
|
119
|
+
super(() => {
|
|
120
|
+
const url = new URL(window.location.href);
|
|
121
|
+
const parameters = new URLSearchParams(url[options.type].slice(1));
|
|
122
|
+
const urlValue = parameters.get(options.key);
|
|
123
|
+
const deserialize = options.deserialize ?? defaultDeserializer;
|
|
124
|
+
return urlValue !== null ? deserialize(urlValue) : options.defaultValue;
|
|
125
|
+
});
|
|
126
|
+
this.options = options;
|
|
127
|
+
this.serializedDefaultValue = this.options.serialize(this.options.defaultValue);
|
|
128
|
+
this.addEffect(() => this.watchUrl());
|
|
129
|
+
}
|
|
130
|
+
set(...args) {
|
|
131
|
+
super.set.apply(this, args);
|
|
132
|
+
this.updateUrl(super.get());
|
|
133
|
+
}
|
|
134
|
+
watchUrl() {
|
|
135
|
+
const originalPushState = window.history.pushState;
|
|
136
|
+
const originalReplaceState = window.history.replaceState;
|
|
137
|
+
window.history.pushState = (...args) => {
|
|
138
|
+
originalPushState.apply(window.history, args);
|
|
139
|
+
this.reset();
|
|
140
|
+
};
|
|
141
|
+
window.history.replaceState = (...args) => {
|
|
142
|
+
originalReplaceState.apply(window.history, args);
|
|
143
|
+
this.reset();
|
|
144
|
+
};
|
|
145
|
+
return () => {
|
|
146
|
+
window.history.pushState = originalPushState;
|
|
147
|
+
window.history.replaceState = originalReplaceState;
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
updateUrl(value) {
|
|
151
|
+
var _a, _b;
|
|
152
|
+
const url = new URL(window.location.href);
|
|
153
|
+
const parameters = new URLSearchParams(url[this.options.type].slice(1));
|
|
154
|
+
const serializedValue = value !== void 0 ? this.options.serialize(value) : void 0;
|
|
155
|
+
if (serializedValue === void 0 || serializedValue === this.serializedDefaultValue) {
|
|
156
|
+
parameters.delete(this.options.key);
|
|
157
|
+
} else {
|
|
158
|
+
parameters.set(this.options.key, serializedValue);
|
|
159
|
+
}
|
|
160
|
+
url[this.options.type] = parameters.toString();
|
|
161
|
+
window.history.replaceState(null, "", url.toString());
|
|
162
|
+
(_b = (_a = this.options).onCommit) == null ? void 0 : _b.call(_a, value);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function defaultDeserializer(value) {
|
|
166
|
+
if (value === void 0) {
|
|
167
|
+
return void 0;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
return JSON.parse(value, (_k, v) => {
|
|
171
|
+
if (typeof v === "object" && v !== null && "__set" in v) {
|
|
172
|
+
return new Set(v.__set);
|
|
173
|
+
}
|
|
174
|
+
if (typeof v === "object" && v !== null && "__map" in v) {
|
|
175
|
+
return new Map(v.__map);
|
|
176
|
+
}
|
|
177
|
+
return v;
|
|
178
|
+
});
|
|
179
|
+
} catch {
|
|
180
|
+
return void 0;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function defaultSerializer(value) {
|
|
184
|
+
return JSON.stringify(value, (_k, v) => {
|
|
185
|
+
if (v instanceof Set) {
|
|
186
|
+
return { __set: Array.from(v) };
|
|
187
|
+
}
|
|
188
|
+
if (v instanceof Map) {
|
|
189
|
+
return { __map: Array.from(v) };
|
|
190
|
+
}
|
|
191
|
+
return v;
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function createUrlStore(options) {
|
|
195
|
+
return new UrlStore({
|
|
196
|
+
...options,
|
|
197
|
+
type: options.type ?? "search",
|
|
198
|
+
serialize: options.serialize ?? defaultSerializer,
|
|
199
|
+
deserialize: options.deserialize ?? defaultDeserializer,
|
|
200
|
+
defaultValue: options.defaultValue ?? void 0
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function findOrDefault(array, predicate, defaultValue) {
|
|
204
|
+
const index = array.findIndex(predicate);
|
|
205
|
+
if (index >= 0) {
|
|
206
|
+
return array[index];
|
|
207
|
+
}
|
|
208
|
+
const value = defaultValue instanceof Function ? defaultValue() : defaultValue;
|
|
209
|
+
array.push(value);
|
|
210
|
+
return value;
|
|
211
|
+
}
|
|
212
|
+
const isAncestor = (ancestor, path) => {
|
|
213
|
+
return ancestor.length <= path.length && ancestor.every((v, i) => v === "*" || path[i] === "*" || v === path[i]);
|
|
214
|
+
};
|
|
215
|
+
function maybeAsync(value, action) {
|
|
216
|
+
if (value instanceof Promise) {
|
|
217
|
+
return value.then(action);
|
|
218
|
+
}
|
|
219
|
+
return action(value);
|
|
220
|
+
}
|
|
221
|
+
function maybeAsyncArray(values) {
|
|
222
|
+
const run = (remainingValues, results) => {
|
|
223
|
+
const [first, ...rest] = remainingValues;
|
|
224
|
+
if (!first) {
|
|
225
|
+
return results;
|
|
226
|
+
}
|
|
227
|
+
return maybeAsync(first(), (result) => run(rest, results.concat(result)));
|
|
228
|
+
};
|
|
229
|
+
return run(values, []);
|
|
230
|
+
}
|
|
231
|
+
function normalizeStorage(storage) {
|
|
232
|
+
return {
|
|
233
|
+
getItem: storage.getItem.bind(storage),
|
|
234
|
+
setItem: storage.setItem.bind(storage),
|
|
235
|
+
removeItem: storage.removeItem.bind(storage),
|
|
236
|
+
keys() {
|
|
237
|
+
if ("keys" in storage) {
|
|
238
|
+
return storage.keys();
|
|
239
|
+
}
|
|
240
|
+
return maybeAsync(
|
|
241
|
+
storage.length instanceof Function ? storage.length() : storage.length,
|
|
242
|
+
(length) => {
|
|
243
|
+
const keyPromises = maybeAsyncArray(
|
|
244
|
+
Array.from({ length }, (_, index) => () => storage.key(index))
|
|
245
|
+
);
|
|
246
|
+
return maybeAsync(
|
|
247
|
+
keyPromises,
|
|
248
|
+
(keys) => keys.filter((key) => typeof key === "string")
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function diff(a, b2) {
|
|
256
|
+
const result = [..._diff(a, b2)];
|
|
257
|
+
const patches = result.map(([patch]) => patch);
|
|
258
|
+
const reversePatches = result.map(([, reversePatch]) => reversePatch);
|
|
259
|
+
return [patches, reversePatches];
|
|
260
|
+
}
|
|
261
|
+
function* _diff(a, b2, prefix = []) {
|
|
262
|
+
if (a === b2) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (a instanceof Map && b2 instanceof Map) {
|
|
266
|
+
return yield* mapDiff(a, b2, prefix);
|
|
267
|
+
}
|
|
268
|
+
if (a instanceof Set && b2 instanceof Set) {
|
|
269
|
+
a = [...a];
|
|
270
|
+
b2 = [...b2];
|
|
271
|
+
}
|
|
272
|
+
if (a instanceof Object && b2 instanceof Object && Array.isArray(a) === Array.isArray(b2)) {
|
|
273
|
+
return yield* objectDiff(a, b2, prefix);
|
|
274
|
+
}
|
|
275
|
+
yield [
|
|
276
|
+
{ op: "replace", path: prefix, value: b2 },
|
|
277
|
+
{ op: "replace", path: prefix, value: a }
|
|
278
|
+
];
|
|
279
|
+
}
|
|
280
|
+
function* mapDiff(a, b2, prefix) {
|
|
281
|
+
for (const [key, value] of a) {
|
|
282
|
+
if (!b2.has(key)) {
|
|
283
|
+
yield [
|
|
284
|
+
{ op: "remove", path: [...prefix, key] },
|
|
285
|
+
{ op: "add", path: [...prefix, key], value }
|
|
286
|
+
];
|
|
287
|
+
} else {
|
|
288
|
+
yield* _diff(value, b2.get(key), [...prefix, key]);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
for (const [key, value] of b2) {
|
|
292
|
+
if (!a.has(key)) {
|
|
293
|
+
yield [
|
|
294
|
+
{ op: "add", path: [...prefix, key], value },
|
|
295
|
+
{ op: "remove", path: [...prefix, key] }
|
|
296
|
+
];
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function* objectDiff(a, b2, prefix) {
|
|
301
|
+
const castKey = (key) => Array.isArray(a) ? Number(key) : key;
|
|
302
|
+
for (const [key, value] of Object.entries(a)) {
|
|
303
|
+
if (!(key in b2)) {
|
|
304
|
+
yield [
|
|
305
|
+
{ op: "remove", path: [...prefix, castKey(key)] },
|
|
306
|
+
{ op: "add", path: [...prefix, castKey(key)], value }
|
|
307
|
+
];
|
|
308
|
+
} else {
|
|
309
|
+
yield* _diff(value, b2[key], [...prefix, castKey(key)]);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
for (const [key, value] of Object.entries(b2)) {
|
|
313
|
+
if (!(key in a)) {
|
|
314
|
+
yield [
|
|
315
|
+
{ op: "add", path: [...prefix, castKey(key)], value },
|
|
316
|
+
{ op: "remove", path: [...prefix, castKey(key)] }
|
|
317
|
+
];
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
class Persist {
|
|
322
|
+
constructor(store, options) {
|
|
323
|
+
this.store = store;
|
|
324
|
+
this.options = options;
|
|
325
|
+
this.queue = queue();
|
|
326
|
+
this.handles = /* @__PURE__ */ new Set();
|
|
327
|
+
this.stopped = false;
|
|
328
|
+
this.storage = normalizeStorage(options.storage);
|
|
329
|
+
this.channel = new BroadcastChannel(`cross-state-persist_${options.id}`);
|
|
330
|
+
this.paths = (options.paths ?? []).map(
|
|
331
|
+
(p) => typeof p === "string" || Array.isArray(p) ? {
|
|
332
|
+
path: castArrayPath(p)
|
|
333
|
+
} : {
|
|
334
|
+
path: castArrayPath(p.path),
|
|
335
|
+
throttleMs: p.throttleMs
|
|
336
|
+
}
|
|
337
|
+
).sort((a, b2) => b2.path.length - a.path.length);
|
|
338
|
+
if (this.paths.length === 0) {
|
|
339
|
+
this.paths.push({ path: ["*"] });
|
|
340
|
+
}
|
|
341
|
+
this.watchStore();
|
|
342
|
+
this.watchStorage();
|
|
343
|
+
}
|
|
344
|
+
watchStore() {
|
|
345
|
+
let committed = this.store.get();
|
|
346
|
+
const cancel = this.store.subscribe(
|
|
347
|
+
(value) => {
|
|
348
|
+
const [patches] = diff(committed, value);
|
|
349
|
+
committed = value;
|
|
350
|
+
for (const patch of patches) {
|
|
351
|
+
if (this.updateInProgress && shallowEqual(this.updateInProgress[0], patch.path) && this.updateInProgress[1] === (patch.op === "remove" ? void 0 : patch.value)) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
const ancestor = this.paths.find((p) => isAncestor(p.path, patch.path));
|
|
355
|
+
if (!ancestor) {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
const pathToSave = patch.path.slice(0, ancestor.path.length);
|
|
359
|
+
this.queue(() => this.save(pathToSave), pathToSave);
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
{ runNow: false }
|
|
363
|
+
);
|
|
364
|
+
this.handles.add(cancel);
|
|
365
|
+
}
|
|
366
|
+
async watchStorage() {
|
|
367
|
+
let keys = this.storage.keys();
|
|
368
|
+
if (keys instanceof Promise) {
|
|
369
|
+
keys = await keys;
|
|
370
|
+
}
|
|
371
|
+
if (this.stopped) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
for (const key of keys) {
|
|
375
|
+
const path = JSON.parse(key);
|
|
376
|
+
this.queue(() => this.load(path));
|
|
377
|
+
}
|
|
378
|
+
const listener = (event) => {
|
|
379
|
+
this.queue(() => this.load(event.data));
|
|
380
|
+
};
|
|
381
|
+
this.channel.addEventListener("message", listener);
|
|
382
|
+
this.handles.add(() => this.channel.removeEventListener("message", listener));
|
|
383
|
+
}
|
|
384
|
+
load(path) {
|
|
385
|
+
const matchingPath = this.paths.find(
|
|
386
|
+
(p) => p.path.length === path.length && isAncestor(p.path, path)
|
|
387
|
+
);
|
|
388
|
+
if (!matchingPath) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const key = JSON.stringify(path);
|
|
392
|
+
return maybeAsync(this.storage.getItem(key), (value) => {
|
|
393
|
+
if (this.stopped || !value) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const inSaveQueue = this.queue.getRefs().find((ref) => isAncestor(ref, path) || isAncestor(path, ref));
|
|
397
|
+
if (inSaveQueue) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const parsedValue = value === "undefined" ? void 0 : JSON.parse(value);
|
|
401
|
+
this.updateInProgress = [path, parsedValue];
|
|
402
|
+
this.store.set((state) => set(state, path, parsedValue));
|
|
403
|
+
this.updateInProgress = void 0;
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
save(path) {
|
|
407
|
+
const key = JSON.stringify(path);
|
|
408
|
+
const value = get(this.store.get(), path);
|
|
409
|
+
const serializedValue = value === void 0 ? "undefined" : JSON.stringify(value);
|
|
410
|
+
return maybeAsync(this.storage.setItem(key, serializedValue), () => {
|
|
411
|
+
this.channel.postMessage(path);
|
|
412
|
+
return maybeAsync(this.storage.keys(), (keys) => {
|
|
413
|
+
const toRemove = keys.filter((k) => {
|
|
414
|
+
const parsedKey = JSON.parse(k);
|
|
415
|
+
return parsedKey.length > path.length && isAncestor(path, parsedKey);
|
|
416
|
+
});
|
|
417
|
+
return maybeAsyncArray(toRemove.map((k) => () => this.storage.removeItem(k)));
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
async stop() {
|
|
422
|
+
this.stopped = true;
|
|
423
|
+
for (const handle of this.handles) {
|
|
424
|
+
handle();
|
|
425
|
+
}
|
|
426
|
+
await this.queue.whenDone();
|
|
427
|
+
this.channel.close();
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function persist(store, options) {
|
|
431
|
+
return new Persist(store, options);
|
|
432
|
+
}
|
|
330
433
|
export {
|
|
331
|
-
Cache,
|
|
434
|
+
C as Cache,
|
|
332
435
|
InstanceCache,
|
|
333
|
-
ResourceGroup,
|
|
436
|
+
R as ResourceGroup,
|
|
437
|
+
S as Scope,
|
|
334
438
|
Store,
|
|
439
|
+
SubstriptionCache,
|
|
335
440
|
allResources,
|
|
336
|
-
|
|
441
|
+
e as arrayMethods,
|
|
337
442
|
calcDuration,
|
|
338
|
-
createCache,
|
|
339
|
-
createResourceGroup,
|
|
443
|
+
c as createCache,
|
|
444
|
+
b as createResourceGroup,
|
|
445
|
+
d as createScope,
|
|
340
446
|
createStore,
|
|
341
|
-
|
|
447
|
+
createSubscriptionCache,
|
|
448
|
+
createUrlStore,
|
|
449
|
+
findOrDefault,
|
|
450
|
+
m as mapMethods,
|
|
451
|
+
persist,
|
|
342
452
|
r as recordMethods,
|
|
343
|
-
|
|
453
|
+
f as setMethods
|
|
344
454
|
};
|
|
345
455
|
//# sourceMappingURL=index.mjs.map
|