@legendapp/state 3.0.0-beta.4 → 3.0.0-beta.40
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/.DS_Store +0 -0
- package/README.md +2 -2
- package/config/enableReactComponents.js +3 -1
- package/config/enableReactComponents.mjs +3 -1
- package/config/enableReactTracking.d.mts +2 -1
- package/config/enableReactTracking.d.ts +2 -1
- package/config/enableReactTracking.js +32 -13
- package/config/enableReactTracking.mjs +32 -13
- package/index.d.mts +46 -8
- package/index.d.ts +46 -8
- package/index.js +267 -75
- package/index.mjs +267 -75
- package/package.json +35 -1
- package/persist-plugins/async-storage.js +17 -9
- package/persist-plugins/async-storage.mjs +17 -9
- package/persist-plugins/expo-sqlite.d.mts +19 -0
- package/persist-plugins/expo-sqlite.d.ts +19 -0
- package/persist-plugins/expo-sqlite.js +72 -0
- package/persist-plugins/expo-sqlite.mjs +69 -0
- package/persist-plugins/indexeddb.js +13 -3
- package/persist-plugins/indexeddb.mjs +13 -3
- package/react-native.d.mts +4 -0
- package/react-native.d.ts +4 -0
- package/react-native.js +53 -0
- package/react-native.mjs +40 -0
- package/react-reactive/Components.d.mts +19 -0
- package/react-reactive/Components.d.ts +19 -0
- package/react-reactive/Components.js +53 -0
- package/react-reactive/Components.mjs +40 -0
- package/react-reactive/enableReactComponents.d.mts +3 -2
- package/react-reactive/enableReactComponents.d.ts +3 -2
- package/react-reactive/enableReactComponents.js +10 -3
- package/react-reactive/enableReactComponents.mjs +10 -3
- package/react-reactive/enableReactNativeComponents.d.mts +3 -20
- package/react-reactive/enableReactNativeComponents.d.ts +3 -20
- package/react-reactive/enableReactNativeComponents.js +8 -3
- package/react-reactive/enableReactNativeComponents.mjs +8 -3
- package/react-reactive/enableReactive.js +10 -3
- package/react-reactive/enableReactive.mjs +10 -3
- package/react-reactive/enableReactive.native.js +8 -3
- package/react-reactive/enableReactive.native.mjs +8 -3
- package/react-reactive/enableReactive.web.js +8 -3
- package/react-reactive/enableReactive.web.mjs +8 -3
- package/react-web.d.mts +7 -0
- package/react-web.d.ts +7 -0
- package/react-web.js +39 -0
- package/react-web.mjs +37 -0
- package/react.d.mts +59 -26
- package/react.d.ts +59 -26
- package/react.js +136 -87
- package/react.mjs +135 -89
- package/sync-plugins/crud.d.mts +24 -9
- package/sync-plugins/crud.d.ts +24 -9
- package/sync-plugins/crud.js +267 -123
- package/sync-plugins/crud.mjs +268 -124
- package/sync-plugins/firebase.d.mts +7 -3
- package/sync-plugins/firebase.d.ts +7 -3
- package/sync-plugins/firebase.js +214 -64
- package/sync-plugins/firebase.mjs +215 -65
- package/sync-plugins/keel.d.mts +12 -13
- package/sync-plugins/keel.d.ts +12 -13
- package/sync-plugins/keel.js +60 -52
- package/sync-plugins/keel.mjs +61 -48
- package/sync-plugins/supabase.d.mts +10 -5
- package/sync-plugins/supabase.d.ts +10 -5
- package/sync-plugins/supabase.js +90 -33
- package/sync-plugins/supabase.mjs +91 -34
- package/sync-plugins/tanstack-query.d.mts +3 -3
- package/sync-plugins/tanstack-query.d.ts +3 -3
- package/sync-plugins/tanstack-query.js +1 -1
- package/sync-plugins/tanstack-query.mjs +1 -1
- package/sync.d.mts +17 -8
- package/sync.d.ts +17 -8
- package/sync.js +448 -307
- package/sync.mjs +446 -307
- package/trace.js +5 -6
- package/trace.mjs +5 -6
- package/types/reactive-native.d.ts +19 -0
- package/types/reactive-web.d.ts +7 -0
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);
|
|
@@ -185,7 +333,8 @@ function syncedFirebase(props) {
|
|
|
185
333
|
}
|
|
186
334
|
return ref;
|
|
187
335
|
};
|
|
188
|
-
const list = async (
|
|
336
|
+
const list = async (getParams) => {
|
|
337
|
+
const { lastSync, onError } = getParams;
|
|
189
338
|
const ref = computeRef(lastSync);
|
|
190
339
|
return new Promise((resolve) => {
|
|
191
340
|
fns.once(
|
|
@@ -195,20 +344,17 @@ function syncedFirebase(props) {
|
|
|
195
344
|
let values = [];
|
|
196
345
|
if (!state.isNullOrUndefined(val)) {
|
|
197
346
|
values = asType === "value" ? [val] : Object.entries(val).map(([key, value]) => {
|
|
198
|
-
|
|
199
|
-
value[fieldId] = key;
|
|
200
|
-
}
|
|
201
|
-
return value;
|
|
347
|
+
return ensureFieldId(key, value);
|
|
202
348
|
});
|
|
203
349
|
}
|
|
204
350
|
didList = true;
|
|
205
351
|
resolve(values);
|
|
206
352
|
},
|
|
207
|
-
onError
|
|
353
|
+
(error) => onError(error, { source: "list", type: "get", retry: getParams })
|
|
208
354
|
);
|
|
209
355
|
});
|
|
210
356
|
};
|
|
211
|
-
const subscribe =
|
|
357
|
+
const subscribe = isRealtime ? ({ lastSync, update: update2, onError }) => {
|
|
212
358
|
const ref = computeRef(lastSync);
|
|
213
359
|
let unsubscribes;
|
|
214
360
|
if (asType === "value") {
|
|
@@ -216,14 +362,12 @@ function syncedFirebase(props) {
|
|
|
216
362
|
if (!didList)
|
|
217
363
|
return;
|
|
218
364
|
const val = snap.val();
|
|
219
|
-
|
|
220
|
-
pendingIncoming$[""].set(val);
|
|
221
|
-
} else {
|
|
365
|
+
handleServerValue("", val, (resolvedValue) => {
|
|
222
366
|
update2({
|
|
223
|
-
value: [
|
|
367
|
+
value: [resolvedValue],
|
|
224
368
|
mode: "set"
|
|
225
369
|
});
|
|
226
|
-
}
|
|
370
|
+
});
|
|
227
371
|
};
|
|
228
372
|
unsubscribes = [fns.onValue(ref, onValue2, onError)];
|
|
229
373
|
} else {
|
|
@@ -231,31 +375,26 @@ function syncedFirebase(props) {
|
|
|
231
375
|
if (!didList)
|
|
232
376
|
return;
|
|
233
377
|
const key = snap.key;
|
|
234
|
-
const val = snap.val();
|
|
235
|
-
|
|
236
|
-
val[fieldId] = key;
|
|
237
|
-
}
|
|
238
|
-
if (saving$[key].get()) {
|
|
239
|
-
pendingIncoming$[key].set(val);
|
|
240
|
-
} else {
|
|
378
|
+
const val = ensureFieldId(key, snap.val());
|
|
379
|
+
handleServerValue(key, val, (resolvedValue) => {
|
|
241
380
|
update2({
|
|
242
|
-
value: [
|
|
243
|
-
mode: "
|
|
381
|
+
value: [resolvedValue],
|
|
382
|
+
mode: "merge"
|
|
244
383
|
});
|
|
245
|
-
}
|
|
384
|
+
});
|
|
246
385
|
};
|
|
247
386
|
const onChildDelete = (snap) => {
|
|
248
387
|
if (!didList)
|
|
249
388
|
return;
|
|
250
389
|
const key = snap.key;
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
+
});
|
|
259
398
|
});
|
|
260
399
|
};
|
|
261
400
|
unsubscribes = [
|
|
@@ -279,42 +418,52 @@ function syncedFirebase(props) {
|
|
|
279
418
|
}
|
|
280
419
|
return addUpdatedAt(input);
|
|
281
420
|
};
|
|
282
|
-
const upsert =
|
|
283
|
-
const id = fieldId ? input[fieldId] : "";
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
(
|
|
296
|
-
const value = pendingIncoming$[id].get();
|
|
297
|
-
if (value) {
|
|
298
|
-
pendingIncoming$[id].delete();
|
|
299
|
-
return value;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
);
|
|
303
|
-
};
|
|
304
|
-
const flushAfterSave = () => {
|
|
305
|
-
const outgoing = pendingOutgoing$.get();
|
|
306
|
-
Object.values(outgoing).forEach((value) => {
|
|
307
|
-
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);
|
|
308
435
|
});
|
|
309
|
-
|
|
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;
|
|
310
459
|
};
|
|
311
|
-
const create = readonly ? void 0 : (input) => {
|
|
460
|
+
const create = readonly ? void 0 : (input, params) => {
|
|
312
461
|
addCreatedAt(input);
|
|
313
|
-
return upsert(input);
|
|
462
|
+
return upsert(input, params);
|
|
314
463
|
};
|
|
315
|
-
const update = readonly ? void 0 : (input) => {
|
|
464
|
+
const update = readonly ? void 0 : (input, params) => {
|
|
316
465
|
addUpdatedAt(input);
|
|
317
|
-
return upsert(input);
|
|
466
|
+
return upsert(input, params);
|
|
318
467
|
};
|
|
319
468
|
const deleteFn = readonly ? void 0 : (input) => {
|
|
320
469
|
const path = joinPaths(
|
|
@@ -354,6 +503,7 @@ function syncedFirebase(props) {
|
|
|
354
503
|
}
|
|
355
504
|
return crud.syncedCrud({
|
|
356
505
|
...rest,
|
|
506
|
+
// Workaround for type errors
|
|
357
507
|
list,
|
|
358
508
|
subscribe,
|
|
359
509
|
create,
|