@legendapp/state 3.0.0-beta.34 → 3.0.0-beta.36
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/index.js +5 -1
- package/index.mjs +5 -1
- package/package.json +1 -1
- package/react.d.mts +1 -1
- package/react.d.ts +1 -1
- package/react.js +11 -3
- package/react.mjs +10 -4
- package/sync-plugins/firebase.js +210 -62
- package/sync-plugins/firebase.mjs +211 -63
- package/sync-plugins/tanstack-query.js +1 -1
- package/sync-plugins/tanstack-query.mjs +1 -1
- package/sync.js +36 -15
- package/sync.mjs +36 -15
package/index.js
CHANGED
|
@@ -1637,7 +1637,11 @@ var proxyHandler = {
|
|
|
1637
1637
|
return { configurable: false, enumerable: false };
|
|
1638
1638
|
}
|
|
1639
1639
|
const value = getNodeValue(node);
|
|
1640
|
-
|
|
1640
|
+
if (isPrimitive(value)) {
|
|
1641
|
+
return void 0;
|
|
1642
|
+
}
|
|
1643
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(value, prop);
|
|
1644
|
+
return descriptor ? { ...descriptor, configurable: true } : void 0;
|
|
1641
1645
|
},
|
|
1642
1646
|
set(node, prop, value) {
|
|
1643
1647
|
if (node.isSetting) {
|
package/index.mjs
CHANGED
|
@@ -1635,7 +1635,11 @@ var proxyHandler = {
|
|
|
1635
1635
|
return { configurable: false, enumerable: false };
|
|
1636
1636
|
}
|
|
1637
1637
|
const value = getNodeValue(node);
|
|
1638
|
-
|
|
1638
|
+
if (isPrimitive(value)) {
|
|
1639
|
+
return void 0;
|
|
1640
|
+
}
|
|
1641
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(value, prop);
|
|
1642
|
+
return descriptor ? { ...descriptor, configurable: true } : void 0;
|
|
1639
1643
|
},
|
|
1640
1644
|
set(node, prop, value) {
|
|
1641
1645
|
if (node.isSetting) {
|
package/package.json
CHANGED
package/react.d.mts
CHANGED
|
@@ -187,4 +187,4 @@ declare function configureReactive({ components, binders, }: {
|
|
|
187
187
|
binders?: Record<string, BindKeys>;
|
|
188
188
|
}): void;
|
|
189
189
|
|
|
190
|
-
export { type BindKey, type BindKeys, Computed, type ExtractFCPropsType, type FCReactive, type FCReactiveObject, For, type IReactive, Memo, type ObjectShapeWith$, type ReactifyProps, Reactive, type ShapeWith$, type ShapeWithNew$, type ShapeWithPick$, Show, Switch, type UseObserveOptions, type UseSelectorOptions, configureReactive, hasSymbol, observer, reactive, reactiveComponents, reactiveObserver, useSelector as use$, useComputed, useEffectOnce, useIsMounted, useMount, useMountOnce, useObservable, useObservableReducer, useObserve, useObserveEffect, usePauseProvider, useSelector, useUnmount, useUnmountOnce, useWhen, useWhenReady };
|
|
190
|
+
export { type BindKey, type BindKeys, Computed, type ExtractFCPropsType, type FCReactive, type FCReactiveObject, For, type IReactive, Memo, type ObjectShapeWith$, type ReactifyProps, Reactive, type ShapeWith$, type ShapeWithNew$, type ShapeWithPick$, Show, Switch, type UseObserveOptions, type UseSelectorOptions, configureReactive, hasSymbol, observer, reactive, reactiveComponents, reactiveObserver, useSelector as use$, useComputed, useEffectOnce, useIsMounted, useObservable as useLocalObservable, useMount, useMountOnce, useObservable, useObservableReducer, useObserve, useObserveEffect, usePauseProvider, useSelector, useUnmount, useUnmountOnce, useSelector as useValue, useWhen, useWhenReady };
|
package/react.d.ts
CHANGED
|
@@ -187,4 +187,4 @@ declare function configureReactive({ components, binders, }: {
|
|
|
187
187
|
binders?: Record<string, BindKeys>;
|
|
188
188
|
}): void;
|
|
189
189
|
|
|
190
|
-
export { type BindKey, type BindKeys, Computed, type ExtractFCPropsType, type FCReactive, type FCReactiveObject, For, type IReactive, Memo, type ObjectShapeWith$, type ReactifyProps, Reactive, type ShapeWith$, type ShapeWithNew$, type ShapeWithPick$, Show, Switch, type UseObserveOptions, type UseSelectorOptions, configureReactive, hasSymbol, observer, reactive, reactiveComponents, reactiveObserver, useSelector as use$, useComputed, useEffectOnce, useIsMounted, useMount, useMountOnce, useObservable, useObservableReducer, useObserve, useObserveEffect, usePauseProvider, useSelector, useUnmount, useUnmountOnce, useWhen, useWhenReady };
|
|
190
|
+
export { type BindKey, type BindKeys, Computed, type ExtractFCPropsType, type FCReactive, type FCReactiveObject, For, type IReactive, Memo, type ObjectShapeWith$, type ReactifyProps, Reactive, type ShapeWith$, type ShapeWithNew$, type ShapeWithPick$, Show, Switch, type UseObserveOptions, type UseSelectorOptions, configureReactive, hasSymbol, observer, reactive, reactiveComponents, reactiveObserver, useSelector as use$, useComputed, useEffectOnce, useIsMounted, useObservable as useLocalObservable, useMount, useMountOnce, useObservable, useObservableReducer, useObserve, useObserveEffect, usePauseProvider, useSelector, useUnmount, useUnmountOnce, useSelector as useValue, useWhen, useWhenReady };
|
package/react.js
CHANGED
|
@@ -510,9 +510,15 @@ function useIsMounted() {
|
|
|
510
510
|
return obs;
|
|
511
511
|
}
|
|
512
512
|
function useObservableReducer(reducer, initializerArg, initializer) {
|
|
513
|
-
const obs = useObservable(
|
|
514
|
-
|
|
515
|
-
|
|
513
|
+
const obs = useObservable(() => {
|
|
514
|
+
if (initializer) {
|
|
515
|
+
return initializer(initializerArg);
|
|
516
|
+
}
|
|
517
|
+
if (state.isFunction(initializerArg)) {
|
|
518
|
+
return initializerArg();
|
|
519
|
+
}
|
|
520
|
+
return initializerArg;
|
|
521
|
+
});
|
|
516
522
|
const dispatch = (action) => {
|
|
517
523
|
obs.set(reducer(obs.get(), action));
|
|
518
524
|
};
|
|
@@ -622,6 +628,7 @@ exports.use$ = useSelector;
|
|
|
622
628
|
exports.useComputed = useComputed;
|
|
623
629
|
exports.useEffectOnce = useEffectOnce;
|
|
624
630
|
exports.useIsMounted = useIsMounted;
|
|
631
|
+
exports.useLocalObservable = useObservable;
|
|
625
632
|
exports.useMount = useMount;
|
|
626
633
|
exports.useMountOnce = useMountOnce;
|
|
627
634
|
exports.useObservable = useObservable;
|
|
@@ -632,5 +639,6 @@ exports.usePauseProvider = usePauseProvider;
|
|
|
632
639
|
exports.useSelector = useSelector;
|
|
633
640
|
exports.useUnmount = useUnmount;
|
|
634
641
|
exports.useUnmountOnce = useUnmountOnce;
|
|
642
|
+
exports.useValue = useSelector;
|
|
635
643
|
exports.useWhen = useWhen;
|
|
636
644
|
exports.useWhenReady = useWhenReady;
|
package/react.mjs
CHANGED
|
@@ -504,9 +504,15 @@ function useIsMounted() {
|
|
|
504
504
|
return obs;
|
|
505
505
|
}
|
|
506
506
|
function useObservableReducer(reducer, initializerArg, initializer) {
|
|
507
|
-
const obs = useObservable(
|
|
508
|
-
|
|
509
|
-
|
|
507
|
+
const obs = useObservable(() => {
|
|
508
|
+
if (initializer) {
|
|
509
|
+
return initializer(initializerArg);
|
|
510
|
+
}
|
|
511
|
+
if (isFunction(initializerArg)) {
|
|
512
|
+
return initializerArg();
|
|
513
|
+
}
|
|
514
|
+
return initializerArg;
|
|
515
|
+
});
|
|
510
516
|
const dispatch = (action) => {
|
|
511
517
|
obs.set(reducer(obs.get(), action));
|
|
512
518
|
};
|
|
@@ -600,4 +606,4 @@ function useWhenReady(predicate, effect) {
|
|
|
600
606
|
return useMemo(() => whenReady(predicate, effect), []);
|
|
601
607
|
}
|
|
602
608
|
|
|
603
|
-
export { Computed, For, Memo, Reactive, Show, Switch, configureReactive, hasSymbol, observer, reactive, reactiveComponents, reactiveObserver, useSelector as use$, useComputed, useEffectOnce, useIsMounted, useMount, useMountOnce, useObservable, useObservableReducer, useObserve, useObserveEffect, usePauseProvider, useSelector, useUnmount, useUnmountOnce, useWhen, useWhenReady };
|
|
609
|
+
export { Computed, For, Memo, Reactive, Show, Switch, configureReactive, hasSymbol, observer, reactive, reactiveComponents, reactiveObserver, useSelector as use$, useComputed, useEffectOnce, useIsMounted, useObservable as useLocalObservable, useMount, useMountOnce, useObservable, useObservableReducer, useObserve, useObserveEffect, usePauseProvider, useSelector, useUnmount, useUnmountOnce, useSelector as useValue, useWhen, useWhenReady };
|
package/sync-plugins/firebase.js
CHANGED
|
@@ -103,6 +103,61 @@ if (process.env.NODE_ENV === "development") {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
// src/is.ts
|
|
107
|
+
function isMap(obj) {
|
|
108
|
+
return obj instanceof Map || obj instanceof WeakMap;
|
|
109
|
+
}
|
|
110
|
+
var globalState = {
|
|
111
|
+
pendingNodes: /* @__PURE__ */ new Map(),
|
|
112
|
+
dirtyNodes: /* @__PURE__ */ new Set()
|
|
113
|
+
};
|
|
114
|
+
function replacer(key, value) {
|
|
115
|
+
if (isMap(value)) {
|
|
116
|
+
return {
|
|
117
|
+
__LSType: "Map",
|
|
118
|
+
value: Array.from(value.entries())
|
|
119
|
+
// or with spread: value: [...value]
|
|
120
|
+
};
|
|
121
|
+
} else if (value instanceof Set) {
|
|
122
|
+
return {
|
|
123
|
+
__LSType: "Set",
|
|
124
|
+
value: Array.from(value)
|
|
125
|
+
// or with spread: value: [...value]
|
|
126
|
+
};
|
|
127
|
+
} else if (globalState.replacer) {
|
|
128
|
+
value = globalState.replacer(key, value);
|
|
129
|
+
}
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
var ISO8601 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/;
|
|
133
|
+
function reviver(key, value) {
|
|
134
|
+
if (value) {
|
|
135
|
+
if (typeof value === "string" && ISO8601.test(value)) {
|
|
136
|
+
return new Date(value);
|
|
137
|
+
}
|
|
138
|
+
if (typeof value === "object") {
|
|
139
|
+
if (value.__LSType === "Map") {
|
|
140
|
+
return new Map(value.value);
|
|
141
|
+
} else if (value.__LSType === "Set") {
|
|
142
|
+
return new Set(value.value);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (globalState.reviver) {
|
|
146
|
+
value = globalState.reviver(key, value);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
function safeStringify(value) {
|
|
152
|
+
return value ? JSON.stringify(value, replacer) : value;
|
|
153
|
+
}
|
|
154
|
+
function safeParse(value) {
|
|
155
|
+
return value ? JSON.parse(value, reviver) : value;
|
|
156
|
+
}
|
|
157
|
+
function clone(value) {
|
|
158
|
+
return safeParse(safeStringify(value));
|
|
159
|
+
}
|
|
160
|
+
|
|
106
161
|
// src/sync-plugins/firebase.ts
|
|
107
162
|
var isEnabled$ = state.observable(true);
|
|
108
163
|
var firebaseConfig = {};
|
|
@@ -154,9 +209,6 @@ var fns = {
|
|
|
154
209
|
};
|
|
155
210
|
function syncedFirebase(props) {
|
|
156
211
|
props = { ...firebaseConfig, ...props };
|
|
157
|
-
const saving$ = state.observable({});
|
|
158
|
-
const pendingOutgoing$ = state.observable({});
|
|
159
|
-
const pendingIncoming$ = state.observable({});
|
|
160
212
|
let didList = false;
|
|
161
213
|
const {
|
|
162
214
|
refPath,
|
|
@@ -174,6 +226,102 @@ function syncedFirebase(props) {
|
|
|
174
226
|
const { fieldCreatedAt, changesSince } = props;
|
|
175
227
|
const asType = props.as || "value";
|
|
176
228
|
const fieldUpdatedAt = props.fieldUpdatedAt || "@";
|
|
229
|
+
const isRealtime = realtime !== false;
|
|
230
|
+
const pendingWrites = /* @__PURE__ */ new Map();
|
|
231
|
+
const enqueuePendingWrite = (key) => {
|
|
232
|
+
let resolveFn;
|
|
233
|
+
let rejectFn;
|
|
234
|
+
const promise = new Promise((resolve, reject) => {
|
|
235
|
+
resolveFn = resolve;
|
|
236
|
+
rejectFn = reject;
|
|
237
|
+
});
|
|
238
|
+
const entry = {
|
|
239
|
+
resolve: resolveFn,
|
|
240
|
+
reject: rejectFn
|
|
241
|
+
};
|
|
242
|
+
const state = pendingWrites.get(key);
|
|
243
|
+
if (state) {
|
|
244
|
+
state.waiting.push(entry);
|
|
245
|
+
state.pendingCount += 1;
|
|
246
|
+
} else {
|
|
247
|
+
pendingWrites.set(key, {
|
|
248
|
+
waiting: [entry],
|
|
249
|
+
ready: [],
|
|
250
|
+
pendingCount: 1
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
return { promise, entry };
|
|
254
|
+
};
|
|
255
|
+
const flushPending = (key) => {
|
|
256
|
+
const state = pendingWrites.get(key);
|
|
257
|
+
if (!state) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (state.pendingCount === 0 && state.staged) {
|
|
261
|
+
const { value, apply } = state.staged;
|
|
262
|
+
state.staged = void 0;
|
|
263
|
+
while (state.ready.length) {
|
|
264
|
+
const entry = state.ready.shift();
|
|
265
|
+
entry.resolve(value);
|
|
266
|
+
}
|
|
267
|
+
if (!state.waiting.length && !state.ready.length) {
|
|
268
|
+
pendingWrites.delete(key);
|
|
269
|
+
}
|
|
270
|
+
apply == null ? void 0 : apply(value);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
const resolvePendingWrite = (key, entry) => {
|
|
274
|
+
const state = pendingWrites.get(key);
|
|
275
|
+
if (!state) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const waitingIndex = state.waiting.indexOf(entry);
|
|
279
|
+
if (waitingIndex >= 0) {
|
|
280
|
+
state.waiting.splice(waitingIndex, 1);
|
|
281
|
+
state.pendingCount = Math.max(0, state.pendingCount - 1);
|
|
282
|
+
}
|
|
283
|
+
state.ready.push(entry);
|
|
284
|
+
flushPending(key);
|
|
285
|
+
};
|
|
286
|
+
const rejectPendingWrite = (key, entry, error) => {
|
|
287
|
+
const state = pendingWrites.get(key);
|
|
288
|
+
if (state) {
|
|
289
|
+
const waitingIndex = state.waiting.indexOf(entry);
|
|
290
|
+
if (waitingIndex >= 0) {
|
|
291
|
+
state.waiting.splice(waitingIndex, 1);
|
|
292
|
+
state.pendingCount = Math.max(0, state.pendingCount - 1);
|
|
293
|
+
} else {
|
|
294
|
+
const readyIndex = state.ready.indexOf(entry);
|
|
295
|
+
if (readyIndex >= 0) {
|
|
296
|
+
state.ready.splice(readyIndex, 1);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (!state.waiting.length && !state.ready.length) {
|
|
300
|
+
pendingWrites.delete(key);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
entry.reject(error);
|
|
304
|
+
};
|
|
305
|
+
const handleServerValue = (key, value, apply) => {
|
|
306
|
+
var _a;
|
|
307
|
+
const state = pendingWrites.get(key);
|
|
308
|
+
if (!state || !state.waiting.length && !state.ready.length) {
|
|
309
|
+
pendingWrites.delete(key);
|
|
310
|
+
apply == null ? void 0 : apply(value);
|
|
311
|
+
} else {
|
|
312
|
+
state.staged = {
|
|
313
|
+
value: value && typeof value === "object" ? clone(value) : value,
|
|
314
|
+
apply: apply != null ? apply : (_a = state.staged) == null ? void 0 : _a.apply
|
|
315
|
+
};
|
|
316
|
+
flushPending(key);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
const ensureFieldId = (key, value) => {
|
|
320
|
+
if (fieldId && key && value && typeof value === "object" && !value[fieldId]) {
|
|
321
|
+
value[fieldId] = key;
|
|
322
|
+
}
|
|
323
|
+
return value;
|
|
324
|
+
};
|
|
177
325
|
const computeRef = (lastSync) => {
|
|
178
326
|
const pathFirebase = refPath(fns.getCurrentUser());
|
|
179
327
|
let ref = fns.ref(pathFirebase);
|
|
@@ -196,10 +344,7 @@ function syncedFirebase(props) {
|
|
|
196
344
|
let values = [];
|
|
197
345
|
if (!state.isNullOrUndefined(val)) {
|
|
198
346
|
values = asType === "value" ? [val] : Object.entries(val).map(([key, value]) => {
|
|
199
|
-
|
|
200
|
-
value[fieldId] = key;
|
|
201
|
-
}
|
|
202
|
-
return value;
|
|
347
|
+
return ensureFieldId(key, value);
|
|
203
348
|
});
|
|
204
349
|
}
|
|
205
350
|
didList = true;
|
|
@@ -209,7 +354,7 @@ function syncedFirebase(props) {
|
|
|
209
354
|
);
|
|
210
355
|
});
|
|
211
356
|
};
|
|
212
|
-
const subscribe =
|
|
357
|
+
const subscribe = isRealtime ? ({ lastSync, update: update2, onError }) => {
|
|
213
358
|
const ref = computeRef(lastSync);
|
|
214
359
|
let unsubscribes;
|
|
215
360
|
if (asType === "value") {
|
|
@@ -217,14 +362,12 @@ function syncedFirebase(props) {
|
|
|
217
362
|
if (!didList)
|
|
218
363
|
return;
|
|
219
364
|
const val = snap.val();
|
|
220
|
-
|
|
221
|
-
pendingIncoming$[""].set(val);
|
|
222
|
-
} else {
|
|
365
|
+
handleServerValue("", val, (resolvedValue) => {
|
|
223
366
|
update2({
|
|
224
|
-
value: [
|
|
367
|
+
value: [resolvedValue],
|
|
225
368
|
mode: "set"
|
|
226
369
|
});
|
|
227
|
-
}
|
|
370
|
+
});
|
|
228
371
|
};
|
|
229
372
|
unsubscribes = [fns.onValue(ref, onValue2, onError)];
|
|
230
373
|
} else {
|
|
@@ -232,31 +375,26 @@ function syncedFirebase(props) {
|
|
|
232
375
|
if (!didList)
|
|
233
376
|
return;
|
|
234
377
|
const key = snap.key;
|
|
235
|
-
const val = snap.val();
|
|
236
|
-
|
|
237
|
-
val[fieldId] = key;
|
|
238
|
-
}
|
|
239
|
-
if (saving$[key].get()) {
|
|
240
|
-
pendingIncoming$[key].set(val);
|
|
241
|
-
} else {
|
|
378
|
+
const val = ensureFieldId(key, snap.val());
|
|
379
|
+
handleServerValue(key, val, (resolvedValue) => {
|
|
242
380
|
update2({
|
|
243
|
-
value: [
|
|
244
|
-
mode: "
|
|
381
|
+
value: [resolvedValue],
|
|
382
|
+
mode: "merge"
|
|
245
383
|
});
|
|
246
|
-
}
|
|
384
|
+
});
|
|
247
385
|
};
|
|
248
386
|
const onChildDelete = (snap) => {
|
|
249
387
|
if (!didList)
|
|
250
388
|
return;
|
|
251
389
|
const key = snap.key;
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
390
|
+
const valueRaw = snap.val();
|
|
391
|
+
const valueWithId = ensureFieldId(key, state.isNullOrUndefined(valueRaw) ? {} : valueRaw);
|
|
392
|
+
valueWithId[state.symbolDelete] = true;
|
|
393
|
+
handleServerValue(key, valueWithId, (resolvedValue) => {
|
|
394
|
+
update2({
|
|
395
|
+
value: [resolvedValue],
|
|
396
|
+
mode: "merge"
|
|
397
|
+
});
|
|
260
398
|
});
|
|
261
399
|
};
|
|
262
400
|
unsubscribes = [
|
|
@@ -280,42 +418,52 @@ function syncedFirebase(props) {
|
|
|
280
418
|
}
|
|
281
419
|
return addUpdatedAt(input);
|
|
282
420
|
};
|
|
283
|
-
const upsert =
|
|
284
|
-
const id = fieldId ? input[fieldId] : "";
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
(
|
|
297
|
-
const value = pendingIncoming$[id].get();
|
|
298
|
-
if (value) {
|
|
299
|
-
pendingIncoming$[id].delete();
|
|
300
|
-
return value;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
);
|
|
304
|
-
};
|
|
305
|
-
const flushAfterSave = () => {
|
|
306
|
-
const outgoing = pendingOutgoing$.get();
|
|
307
|
-
Object.values(outgoing).forEach((value) => {
|
|
308
|
-
upsert(value);
|
|
421
|
+
const upsert = (input, params) => {
|
|
422
|
+
const id = fieldId && asType !== "value" ? input[fieldId] : "";
|
|
423
|
+
const pendingKey = fieldId && asType !== "value" ? String(id != null ? id : "") : "";
|
|
424
|
+
const { promise, entry } = enqueuePendingWrite(pendingKey);
|
|
425
|
+
const userId = fns.getCurrentUser();
|
|
426
|
+
const basePath = refPath(userId);
|
|
427
|
+
const childPath = fieldId && asType !== "value" ? pendingKey : "";
|
|
428
|
+
const path = joinPaths(basePath, childPath);
|
|
429
|
+
const ref = fns.ref(path);
|
|
430
|
+
const updatePromise = fns.update(ref, input);
|
|
431
|
+
updatePromise.then(() => {
|
|
432
|
+
resolvePendingWrite(pendingKey, entry);
|
|
433
|
+
}).catch((error) => {
|
|
434
|
+
rejectPendingWrite(pendingKey, entry, error);
|
|
309
435
|
});
|
|
310
|
-
|
|
436
|
+
if (!isRealtime) {
|
|
437
|
+
updatePromise.then(() => {
|
|
438
|
+
const onceRef = fieldId && asType !== "value" ? ref : fns.ref(basePath);
|
|
439
|
+
fns.once(
|
|
440
|
+
onceRef,
|
|
441
|
+
(snap) => {
|
|
442
|
+
const rawValue = snap.val();
|
|
443
|
+
const value = fieldId && asType !== "value" ? ensureFieldId(pendingKey, state.isNullOrUndefined(rawValue) ? {} : rawValue) : rawValue;
|
|
444
|
+
handleServerValue(pendingKey, value, (resolvedValue) => {
|
|
445
|
+
params.update({
|
|
446
|
+
value: resolvedValue,
|
|
447
|
+
mode: "merge"
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
},
|
|
451
|
+
(error) => {
|
|
452
|
+
rejectPendingWrite(pendingKey, entry, error);
|
|
453
|
+
}
|
|
454
|
+
);
|
|
455
|
+
}).catch(() => {
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
return promise;
|
|
311
459
|
};
|
|
312
|
-
const create = readonly ? void 0 : (input) => {
|
|
460
|
+
const create = readonly ? void 0 : (input, params) => {
|
|
313
461
|
addCreatedAt(input);
|
|
314
|
-
return upsert(input);
|
|
462
|
+
return upsert(input, params);
|
|
315
463
|
};
|
|
316
|
-
const update = readonly ? void 0 : (input) => {
|
|
464
|
+
const update = readonly ? void 0 : (input, params) => {
|
|
317
465
|
addUpdatedAt(input);
|
|
318
|
-
return upsert(input);
|
|
466
|
+
return upsert(input, params);
|
|
319
467
|
};
|
|
320
468
|
const deleteFn = readonly ? void 0 : (input) => {
|
|
321
469
|
const path = joinPaths(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { observable, symbolDelete, isString, isArray, isObject, computeSelector, isFunction, isNullOrUndefined, isPromise, isNumber
|
|
1
|
+
import { observable, symbolDelete, isString, isArray, isObject, computeSelector, isFunction, isNullOrUndefined, isPromise, isNumber } from '@legendapp/state';
|
|
2
2
|
import { syncedCrud } from '@legendapp/state/sync-plugins/crud';
|
|
3
3
|
import { getAuth } from 'firebase/auth';
|
|
4
4
|
import { ref, getDatabase, query, orderByChild, startAt, update, onValue, onChildAdded, onChildChanged, onChildRemoved, serverTimestamp, remove, push } from 'firebase/database';
|
|
@@ -101,6 +101,61 @@ if (process.env.NODE_ENV === "development") {
|
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
// src/is.ts
|
|
105
|
+
function isMap(obj) {
|
|
106
|
+
return obj instanceof Map || obj instanceof WeakMap;
|
|
107
|
+
}
|
|
108
|
+
var globalState = {
|
|
109
|
+
pendingNodes: /* @__PURE__ */ new Map(),
|
|
110
|
+
dirtyNodes: /* @__PURE__ */ new Set()
|
|
111
|
+
};
|
|
112
|
+
function replacer(key, value) {
|
|
113
|
+
if (isMap(value)) {
|
|
114
|
+
return {
|
|
115
|
+
__LSType: "Map",
|
|
116
|
+
value: Array.from(value.entries())
|
|
117
|
+
// or with spread: value: [...value]
|
|
118
|
+
};
|
|
119
|
+
} else if (value instanceof Set) {
|
|
120
|
+
return {
|
|
121
|
+
__LSType: "Set",
|
|
122
|
+
value: Array.from(value)
|
|
123
|
+
// or with spread: value: [...value]
|
|
124
|
+
};
|
|
125
|
+
} else if (globalState.replacer) {
|
|
126
|
+
value = globalState.replacer(key, value);
|
|
127
|
+
}
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
130
|
+
var ISO8601 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/;
|
|
131
|
+
function reviver(key, value) {
|
|
132
|
+
if (value) {
|
|
133
|
+
if (typeof value === "string" && ISO8601.test(value)) {
|
|
134
|
+
return new Date(value);
|
|
135
|
+
}
|
|
136
|
+
if (typeof value === "object") {
|
|
137
|
+
if (value.__LSType === "Map") {
|
|
138
|
+
return new Map(value.value);
|
|
139
|
+
} else if (value.__LSType === "Set") {
|
|
140
|
+
return new Set(value.value);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (globalState.reviver) {
|
|
144
|
+
value = globalState.reviver(key, value);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
function safeStringify(value) {
|
|
150
|
+
return value ? JSON.stringify(value, replacer) : value;
|
|
151
|
+
}
|
|
152
|
+
function safeParse(value) {
|
|
153
|
+
return value ? JSON.parse(value, reviver) : value;
|
|
154
|
+
}
|
|
155
|
+
function clone(value) {
|
|
156
|
+
return safeParse(safeStringify(value));
|
|
157
|
+
}
|
|
158
|
+
|
|
104
159
|
// src/sync-plugins/firebase.ts
|
|
105
160
|
var isEnabled$ = observable(true);
|
|
106
161
|
var firebaseConfig = {};
|
|
@@ -152,9 +207,6 @@ var fns = {
|
|
|
152
207
|
};
|
|
153
208
|
function syncedFirebase(props) {
|
|
154
209
|
props = { ...firebaseConfig, ...props };
|
|
155
|
-
const saving$ = observable({});
|
|
156
|
-
const pendingOutgoing$ = observable({});
|
|
157
|
-
const pendingIncoming$ = observable({});
|
|
158
210
|
let didList = false;
|
|
159
211
|
const {
|
|
160
212
|
refPath,
|
|
@@ -172,6 +224,102 @@ function syncedFirebase(props) {
|
|
|
172
224
|
const { fieldCreatedAt, changesSince } = props;
|
|
173
225
|
const asType = props.as || "value";
|
|
174
226
|
const fieldUpdatedAt = props.fieldUpdatedAt || "@";
|
|
227
|
+
const isRealtime = realtime !== false;
|
|
228
|
+
const pendingWrites = /* @__PURE__ */ new Map();
|
|
229
|
+
const enqueuePendingWrite = (key) => {
|
|
230
|
+
let resolveFn;
|
|
231
|
+
let rejectFn;
|
|
232
|
+
const promise = new Promise((resolve, reject) => {
|
|
233
|
+
resolveFn = resolve;
|
|
234
|
+
rejectFn = reject;
|
|
235
|
+
});
|
|
236
|
+
const entry = {
|
|
237
|
+
resolve: resolveFn,
|
|
238
|
+
reject: rejectFn
|
|
239
|
+
};
|
|
240
|
+
const state = pendingWrites.get(key);
|
|
241
|
+
if (state) {
|
|
242
|
+
state.waiting.push(entry);
|
|
243
|
+
state.pendingCount += 1;
|
|
244
|
+
} else {
|
|
245
|
+
pendingWrites.set(key, {
|
|
246
|
+
waiting: [entry],
|
|
247
|
+
ready: [],
|
|
248
|
+
pendingCount: 1
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
return { promise, entry };
|
|
252
|
+
};
|
|
253
|
+
const flushPending = (key) => {
|
|
254
|
+
const state = pendingWrites.get(key);
|
|
255
|
+
if (!state) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (state.pendingCount === 0 && state.staged) {
|
|
259
|
+
const { value, apply } = state.staged;
|
|
260
|
+
state.staged = void 0;
|
|
261
|
+
while (state.ready.length) {
|
|
262
|
+
const entry = state.ready.shift();
|
|
263
|
+
entry.resolve(value);
|
|
264
|
+
}
|
|
265
|
+
if (!state.waiting.length && !state.ready.length) {
|
|
266
|
+
pendingWrites.delete(key);
|
|
267
|
+
}
|
|
268
|
+
apply == null ? void 0 : apply(value);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
const resolvePendingWrite = (key, entry) => {
|
|
272
|
+
const state = pendingWrites.get(key);
|
|
273
|
+
if (!state) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const waitingIndex = state.waiting.indexOf(entry);
|
|
277
|
+
if (waitingIndex >= 0) {
|
|
278
|
+
state.waiting.splice(waitingIndex, 1);
|
|
279
|
+
state.pendingCount = Math.max(0, state.pendingCount - 1);
|
|
280
|
+
}
|
|
281
|
+
state.ready.push(entry);
|
|
282
|
+
flushPending(key);
|
|
283
|
+
};
|
|
284
|
+
const rejectPendingWrite = (key, entry, error) => {
|
|
285
|
+
const state = pendingWrites.get(key);
|
|
286
|
+
if (state) {
|
|
287
|
+
const waitingIndex = state.waiting.indexOf(entry);
|
|
288
|
+
if (waitingIndex >= 0) {
|
|
289
|
+
state.waiting.splice(waitingIndex, 1);
|
|
290
|
+
state.pendingCount = Math.max(0, state.pendingCount - 1);
|
|
291
|
+
} else {
|
|
292
|
+
const readyIndex = state.ready.indexOf(entry);
|
|
293
|
+
if (readyIndex >= 0) {
|
|
294
|
+
state.ready.splice(readyIndex, 1);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (!state.waiting.length && !state.ready.length) {
|
|
298
|
+
pendingWrites.delete(key);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
entry.reject(error);
|
|
302
|
+
};
|
|
303
|
+
const handleServerValue = (key, value, apply) => {
|
|
304
|
+
var _a;
|
|
305
|
+
const state = pendingWrites.get(key);
|
|
306
|
+
if (!state || !state.waiting.length && !state.ready.length) {
|
|
307
|
+
pendingWrites.delete(key);
|
|
308
|
+
apply == null ? void 0 : apply(value);
|
|
309
|
+
} else {
|
|
310
|
+
state.staged = {
|
|
311
|
+
value: value && typeof value === "object" ? clone(value) : value,
|
|
312
|
+
apply: apply != null ? apply : (_a = state.staged) == null ? void 0 : _a.apply
|
|
313
|
+
};
|
|
314
|
+
flushPending(key);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
const ensureFieldId = (key, value) => {
|
|
318
|
+
if (fieldId && key && value && typeof value === "object" && !value[fieldId]) {
|
|
319
|
+
value[fieldId] = key;
|
|
320
|
+
}
|
|
321
|
+
return value;
|
|
322
|
+
};
|
|
175
323
|
const computeRef = (lastSync) => {
|
|
176
324
|
const pathFirebase = refPath(fns.getCurrentUser());
|
|
177
325
|
let ref = fns.ref(pathFirebase);
|
|
@@ -194,10 +342,7 @@ function syncedFirebase(props) {
|
|
|
194
342
|
let values = [];
|
|
195
343
|
if (!isNullOrUndefined(val)) {
|
|
196
344
|
values = asType === "value" ? [val] : Object.entries(val).map(([key, value]) => {
|
|
197
|
-
|
|
198
|
-
value[fieldId] = key;
|
|
199
|
-
}
|
|
200
|
-
return value;
|
|
345
|
+
return ensureFieldId(key, value);
|
|
201
346
|
});
|
|
202
347
|
}
|
|
203
348
|
didList = true;
|
|
@@ -207,7 +352,7 @@ function syncedFirebase(props) {
|
|
|
207
352
|
);
|
|
208
353
|
});
|
|
209
354
|
};
|
|
210
|
-
const subscribe =
|
|
355
|
+
const subscribe = isRealtime ? ({ lastSync, update: update2, onError }) => {
|
|
211
356
|
const ref = computeRef(lastSync);
|
|
212
357
|
let unsubscribes;
|
|
213
358
|
if (asType === "value") {
|
|
@@ -215,14 +360,12 @@ function syncedFirebase(props) {
|
|
|
215
360
|
if (!didList)
|
|
216
361
|
return;
|
|
217
362
|
const val = snap.val();
|
|
218
|
-
|
|
219
|
-
pendingIncoming$[""].set(val);
|
|
220
|
-
} else {
|
|
363
|
+
handleServerValue("", val, (resolvedValue) => {
|
|
221
364
|
update2({
|
|
222
|
-
value: [
|
|
365
|
+
value: [resolvedValue],
|
|
223
366
|
mode: "set"
|
|
224
367
|
});
|
|
225
|
-
}
|
|
368
|
+
});
|
|
226
369
|
};
|
|
227
370
|
unsubscribes = [fns.onValue(ref, onValue2, onError)];
|
|
228
371
|
} else {
|
|
@@ -230,31 +373,26 @@ function syncedFirebase(props) {
|
|
|
230
373
|
if (!didList)
|
|
231
374
|
return;
|
|
232
375
|
const key = snap.key;
|
|
233
|
-
const val = snap.val();
|
|
234
|
-
|
|
235
|
-
val[fieldId] = key;
|
|
236
|
-
}
|
|
237
|
-
if (saving$[key].get()) {
|
|
238
|
-
pendingIncoming$[key].set(val);
|
|
239
|
-
} else {
|
|
376
|
+
const val = ensureFieldId(key, snap.val());
|
|
377
|
+
handleServerValue(key, val, (resolvedValue) => {
|
|
240
378
|
update2({
|
|
241
|
-
value: [
|
|
242
|
-
mode: "
|
|
379
|
+
value: [resolvedValue],
|
|
380
|
+
mode: "merge"
|
|
243
381
|
});
|
|
244
|
-
}
|
|
382
|
+
});
|
|
245
383
|
};
|
|
246
384
|
const onChildDelete = (snap) => {
|
|
247
385
|
if (!didList)
|
|
248
386
|
return;
|
|
249
387
|
const key = snap.key;
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
388
|
+
const valueRaw = snap.val();
|
|
389
|
+
const valueWithId = ensureFieldId(key, isNullOrUndefined(valueRaw) ? {} : valueRaw);
|
|
390
|
+
valueWithId[symbolDelete] = true;
|
|
391
|
+
handleServerValue(key, valueWithId, (resolvedValue) => {
|
|
392
|
+
update2({
|
|
393
|
+
value: [resolvedValue],
|
|
394
|
+
mode: "merge"
|
|
395
|
+
});
|
|
258
396
|
});
|
|
259
397
|
};
|
|
260
398
|
unsubscribes = [
|
|
@@ -278,42 +416,52 @@ function syncedFirebase(props) {
|
|
|
278
416
|
}
|
|
279
417
|
return addUpdatedAt(input);
|
|
280
418
|
};
|
|
281
|
-
const upsert =
|
|
282
|
-
const id = fieldId ? input[fieldId] : "";
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
(
|
|
295
|
-
const value = pendingIncoming$[id].get();
|
|
296
|
-
if (value) {
|
|
297
|
-
pendingIncoming$[id].delete();
|
|
298
|
-
return value;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
);
|
|
302
|
-
};
|
|
303
|
-
const flushAfterSave = () => {
|
|
304
|
-
const outgoing = pendingOutgoing$.get();
|
|
305
|
-
Object.values(outgoing).forEach((value) => {
|
|
306
|
-
upsert(value);
|
|
419
|
+
const upsert = (input, params) => {
|
|
420
|
+
const id = fieldId && asType !== "value" ? input[fieldId] : "";
|
|
421
|
+
const pendingKey = fieldId && asType !== "value" ? String(id != null ? id : "") : "";
|
|
422
|
+
const { promise, entry } = enqueuePendingWrite(pendingKey);
|
|
423
|
+
const userId = fns.getCurrentUser();
|
|
424
|
+
const basePath = refPath(userId);
|
|
425
|
+
const childPath = fieldId && asType !== "value" ? pendingKey : "";
|
|
426
|
+
const path = joinPaths(basePath, childPath);
|
|
427
|
+
const ref = fns.ref(path);
|
|
428
|
+
const updatePromise = fns.update(ref, input);
|
|
429
|
+
updatePromise.then(() => {
|
|
430
|
+
resolvePendingWrite(pendingKey, entry);
|
|
431
|
+
}).catch((error) => {
|
|
432
|
+
rejectPendingWrite(pendingKey, entry, error);
|
|
307
433
|
});
|
|
308
|
-
|
|
434
|
+
if (!isRealtime) {
|
|
435
|
+
updatePromise.then(() => {
|
|
436
|
+
const onceRef = fieldId && asType !== "value" ? ref : fns.ref(basePath);
|
|
437
|
+
fns.once(
|
|
438
|
+
onceRef,
|
|
439
|
+
(snap) => {
|
|
440
|
+
const rawValue = snap.val();
|
|
441
|
+
const value = fieldId && asType !== "value" ? ensureFieldId(pendingKey, isNullOrUndefined(rawValue) ? {} : rawValue) : rawValue;
|
|
442
|
+
handleServerValue(pendingKey, value, (resolvedValue) => {
|
|
443
|
+
params.update({
|
|
444
|
+
value: resolvedValue,
|
|
445
|
+
mode: "merge"
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
},
|
|
449
|
+
(error) => {
|
|
450
|
+
rejectPendingWrite(pendingKey, entry, error);
|
|
451
|
+
}
|
|
452
|
+
);
|
|
453
|
+
}).catch(() => {
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
return promise;
|
|
309
457
|
};
|
|
310
|
-
const create = readonly ? void 0 : (input) => {
|
|
458
|
+
const create = readonly ? void 0 : (input, params) => {
|
|
311
459
|
addCreatedAt(input);
|
|
312
|
-
return upsert(input);
|
|
460
|
+
return upsert(input, params);
|
|
313
461
|
};
|
|
314
|
-
const update = readonly ? void 0 : (input) => {
|
|
462
|
+
const update = readonly ? void 0 : (input, params) => {
|
|
315
463
|
addUpdatedAt(input);
|
|
316
|
-
return upsert(input);
|
|
464
|
+
return upsert(input, params);
|
|
317
465
|
};
|
|
318
466
|
const deleteFn = readonly ? void 0 : (input) => {
|
|
319
467
|
const path = joinPaths(
|
package/sync.js
CHANGED
|
@@ -179,28 +179,43 @@ function runWithRetry(state, retryOptions, retryId, fn) {
|
|
|
179
179
|
let timeoutRetry;
|
|
180
180
|
if (mapRetryTimeouts.has(retryId)) {
|
|
181
181
|
clearTimeout(mapRetryTimeouts.get(retryId));
|
|
182
|
+
mapRetryTimeouts.delete(retryId);
|
|
182
183
|
}
|
|
184
|
+
const clearRetryState = () => {
|
|
185
|
+
if (timeoutRetry !== void 0) {
|
|
186
|
+
clearTimeout(timeoutRetry);
|
|
187
|
+
timeoutRetry = void 0;
|
|
188
|
+
}
|
|
189
|
+
mapRetryTimeouts.delete(retryId);
|
|
190
|
+
};
|
|
183
191
|
return new Promise((resolve, reject) => {
|
|
184
192
|
const run = () => {
|
|
185
193
|
value.then((val) => {
|
|
194
|
+
state.retryNum = 0;
|
|
195
|
+
clearRetryState();
|
|
186
196
|
resolve(val);
|
|
187
197
|
}).catch((error) => {
|
|
188
|
-
|
|
189
|
-
if (timeoutRetry) {
|
|
198
|
+
if (timeoutRetry !== void 0) {
|
|
190
199
|
clearTimeout(timeoutRetry);
|
|
200
|
+
timeoutRetry = void 0;
|
|
191
201
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
state.retryNum++;
|
|
203
|
+
if (state.cancelRetry) {
|
|
204
|
+
clearRetryState();
|
|
205
|
+
reject(error);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const timeout = createRetryTimeout(retryOptions, state.retryNum, () => {
|
|
209
|
+
value = fn(state);
|
|
210
|
+
run();
|
|
211
|
+
});
|
|
212
|
+
if (timeout === false) {
|
|
213
|
+
state.cancelRetry = true;
|
|
214
|
+
clearRetryState();
|
|
215
|
+
reject(error);
|
|
216
|
+
} else {
|
|
217
|
+
timeoutRetry = timeout;
|
|
218
|
+
mapRetryTimeouts.set(retryId, timeout);
|
|
204
219
|
}
|
|
205
220
|
});
|
|
206
221
|
};
|
|
@@ -209,6 +224,7 @@ function runWithRetry(state, retryOptions, retryId, fn) {
|
|
|
209
224
|
}
|
|
210
225
|
return value;
|
|
211
226
|
} catch (error) {
|
|
227
|
+
mapRetryTimeouts.delete(retryId);
|
|
212
228
|
return Promise.reject(error);
|
|
213
229
|
}
|
|
214
230
|
}
|
|
@@ -325,9 +341,14 @@ function mergeChanges(changes) {
|
|
|
325
341
|
const existing = changesByPath.get(pathStr);
|
|
326
342
|
if (existing) {
|
|
327
343
|
if (change.valueAtPath === existing.prevAtPath) {
|
|
328
|
-
changesOut.
|
|
344
|
+
const idx = changesOut.indexOf(existing);
|
|
345
|
+
if (idx >= 0) {
|
|
346
|
+
changesOut.splice(idx, 1);
|
|
347
|
+
}
|
|
348
|
+
changesByPath.delete(pathStr);
|
|
329
349
|
} else {
|
|
330
350
|
existing.valueAtPath = change.valueAtPath;
|
|
351
|
+
existing.pathTypes = change.pathTypes;
|
|
331
352
|
}
|
|
332
353
|
} else {
|
|
333
354
|
let found = false;
|
package/sync.mjs
CHANGED
|
@@ -177,28 +177,43 @@ function runWithRetry(state, retryOptions, retryId, fn) {
|
|
|
177
177
|
let timeoutRetry;
|
|
178
178
|
if (mapRetryTimeouts.has(retryId)) {
|
|
179
179
|
clearTimeout(mapRetryTimeouts.get(retryId));
|
|
180
|
+
mapRetryTimeouts.delete(retryId);
|
|
180
181
|
}
|
|
182
|
+
const clearRetryState = () => {
|
|
183
|
+
if (timeoutRetry !== void 0) {
|
|
184
|
+
clearTimeout(timeoutRetry);
|
|
185
|
+
timeoutRetry = void 0;
|
|
186
|
+
}
|
|
187
|
+
mapRetryTimeouts.delete(retryId);
|
|
188
|
+
};
|
|
181
189
|
return new Promise((resolve, reject) => {
|
|
182
190
|
const run = () => {
|
|
183
191
|
value.then((val) => {
|
|
192
|
+
state.retryNum = 0;
|
|
193
|
+
clearRetryState();
|
|
184
194
|
resolve(val);
|
|
185
195
|
}).catch((error) => {
|
|
186
|
-
|
|
187
|
-
if (timeoutRetry) {
|
|
196
|
+
if (timeoutRetry !== void 0) {
|
|
188
197
|
clearTimeout(timeoutRetry);
|
|
198
|
+
timeoutRetry = void 0;
|
|
189
199
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
state.retryNum++;
|
|
201
|
+
if (state.cancelRetry) {
|
|
202
|
+
clearRetryState();
|
|
203
|
+
reject(error);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const timeout = createRetryTimeout(retryOptions, state.retryNum, () => {
|
|
207
|
+
value = fn(state);
|
|
208
|
+
run();
|
|
209
|
+
});
|
|
210
|
+
if (timeout === false) {
|
|
211
|
+
state.cancelRetry = true;
|
|
212
|
+
clearRetryState();
|
|
213
|
+
reject(error);
|
|
214
|
+
} else {
|
|
215
|
+
timeoutRetry = timeout;
|
|
216
|
+
mapRetryTimeouts.set(retryId, timeout);
|
|
202
217
|
}
|
|
203
218
|
});
|
|
204
219
|
};
|
|
@@ -207,6 +222,7 @@ function runWithRetry(state, retryOptions, retryId, fn) {
|
|
|
207
222
|
}
|
|
208
223
|
return value;
|
|
209
224
|
} catch (error) {
|
|
225
|
+
mapRetryTimeouts.delete(retryId);
|
|
210
226
|
return Promise.reject(error);
|
|
211
227
|
}
|
|
212
228
|
}
|
|
@@ -323,9 +339,14 @@ function mergeChanges(changes) {
|
|
|
323
339
|
const existing = changesByPath.get(pathStr);
|
|
324
340
|
if (existing) {
|
|
325
341
|
if (change.valueAtPath === existing.prevAtPath) {
|
|
326
|
-
changesOut.
|
|
342
|
+
const idx = changesOut.indexOf(existing);
|
|
343
|
+
if (idx >= 0) {
|
|
344
|
+
changesOut.splice(idx, 1);
|
|
345
|
+
}
|
|
346
|
+
changesByPath.delete(pathStr);
|
|
327
347
|
} else {
|
|
328
348
|
existing.valueAtPath = change.valueAtPath;
|
|
349
|
+
existing.pathTypes = change.pathTypes;
|
|
329
350
|
}
|
|
330
351
|
} else {
|
|
331
352
|
let found = false;
|