@legendapp/state 3.0.0-beta.4 → 3.0.0-beta.41
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/crud.mjs
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import { isPromise,
|
|
1
|
+
import { isPromise, isNullOrUndefined, applyChanges, setAtPath, symbolDelete, isArray, internal, getNodeValue } from '@legendapp/state';
|
|
2
2
|
import { synced, deepEqual, internal as internal$1, diffObjects } from '@legendapp/state/sync';
|
|
3
3
|
|
|
4
4
|
// src/sync-plugins/crud.ts
|
|
5
|
-
var { clone } = internal;
|
|
6
|
-
var { waitForSet } = internal$1;
|
|
5
|
+
var { clone, getKeys, setNodeValue, getChildNode } = internal;
|
|
6
|
+
var { waitForSet, runWithRetry } = internal$1;
|
|
7
7
|
function transformOut(data, transform) {
|
|
8
8
|
return transform ? transform(clone(data)) : data;
|
|
9
9
|
}
|
|
10
|
-
function ensureId(obj, fieldId, generateId) {
|
|
10
|
+
function ensureId(obj, fieldId, generateId, node) {
|
|
11
11
|
if (!obj[fieldId]) {
|
|
12
12
|
obj[fieldId] = generateId();
|
|
13
|
+
if (node) {
|
|
14
|
+
setNodeValue(node, obj);
|
|
15
|
+
}
|
|
13
16
|
}
|
|
14
|
-
return obj[fieldId];
|
|
15
17
|
}
|
|
16
18
|
function computeLastSync(data, fieldUpdatedAt, fieldCreatedAt) {
|
|
17
19
|
let newLastSync = 0;
|
|
@@ -23,6 +25,47 @@ function computeLastSync(data, fieldUpdatedAt, fieldCreatedAt) {
|
|
|
23
25
|
}
|
|
24
26
|
return newLastSync;
|
|
25
27
|
}
|
|
28
|
+
function arrayToRecord(arr, keyField) {
|
|
29
|
+
const record = {};
|
|
30
|
+
if (arr == null ? void 0 : arr.length) {
|
|
31
|
+
for (let i = 0; i < arr.length; i++) {
|
|
32
|
+
const v = arr[i];
|
|
33
|
+
const key = v[keyField];
|
|
34
|
+
record[key] = v;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return record;
|
|
38
|
+
}
|
|
39
|
+
function retrySet(params, retry, action, itemKey, itemValue, change, queuedRetries, itemValueFull, actionFn, saveResult) {
|
|
40
|
+
if (action === "delete") {
|
|
41
|
+
if (queuedRetries.create.has(itemKey)) {
|
|
42
|
+
queuedRetries.create.delete(itemKey);
|
|
43
|
+
}
|
|
44
|
+
if (queuedRetries.update.has(itemKey)) {
|
|
45
|
+
queuedRetries.update.delete(itemKey);
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
if (queuedRetries.delete.has(itemKey)) {
|
|
49
|
+
queuedRetries.delete.delete(itemKey);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const queuedRetry = queuedRetries[action].get(itemKey);
|
|
53
|
+
if (queuedRetry) {
|
|
54
|
+
itemValue = Object.assign(queuedRetry, itemValue);
|
|
55
|
+
}
|
|
56
|
+
queuedRetries[action].set(itemKey, itemValue);
|
|
57
|
+
const clonedValue = clone(itemValueFull);
|
|
58
|
+
const paramsWithChanges = { ...params, changes: [change] };
|
|
59
|
+
return runWithRetry(
|
|
60
|
+
paramsWithChanges,
|
|
61
|
+
retry,
|
|
62
|
+
"create_" + itemKey,
|
|
63
|
+
() => actionFn(itemValue, paramsWithChanges).then((result) => {
|
|
64
|
+
queuedRetries[action].delete(itemKey);
|
|
65
|
+
return saveResult(itemKey, clonedValue, result, true, change);
|
|
66
|
+
})
|
|
67
|
+
);
|
|
68
|
+
}
|
|
26
69
|
function syncedCrud(props) {
|
|
27
70
|
const {
|
|
28
71
|
get: getFn,
|
|
@@ -43,10 +86,16 @@ function syncedCrud(props) {
|
|
|
43
86
|
changesSince,
|
|
44
87
|
generateId,
|
|
45
88
|
waitForSet: waitForSetParam,
|
|
89
|
+
retry,
|
|
46
90
|
...rest
|
|
47
91
|
} = props;
|
|
48
92
|
const fieldId = fieldIdProp || "id";
|
|
49
93
|
const pendingCreates = /* @__PURE__ */ new Set();
|
|
94
|
+
const queuedRetries = {
|
|
95
|
+
create: /* @__PURE__ */ new Map(),
|
|
96
|
+
update: /* @__PURE__ */ new Map(),
|
|
97
|
+
delete: /* @__PURE__ */ new Map()
|
|
98
|
+
};
|
|
50
99
|
let asType = props.as;
|
|
51
100
|
if (!asType) {
|
|
52
101
|
asType = getFn ? "value" : "object";
|
|
@@ -75,69 +124,76 @@ function syncedCrud(props) {
|
|
|
75
124
|
return out;
|
|
76
125
|
};
|
|
77
126
|
const transformRows = (data) => {
|
|
78
|
-
return Promise.all(
|
|
127
|
+
return data.length ? Promise.all(
|
|
79
128
|
data.map(
|
|
80
129
|
(value) => (
|
|
81
130
|
// Skip transforming any children with symbolDelete or fieldDeleted because they'll get deleted by resultsToOutType
|
|
82
131
|
value[symbolDelete] || fieldDeleted && value[fieldDeleted] || fieldDeletedList && value[fieldDeletedList] ? value : transform.load(value, "get")
|
|
83
132
|
)
|
|
84
133
|
)
|
|
85
|
-
);
|
|
134
|
+
) : [];
|
|
86
135
|
};
|
|
87
136
|
const get = getFn || listFn ? (getParams) => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const listPromise = listFn(getParams);
|
|
95
|
-
const toOut = (transformed) => {
|
|
96
|
-
var _a;
|
|
97
|
-
if (asType === "value") {
|
|
98
|
-
return transformed.length > 0 ? transformed[0] : (_a = (isLastSyncMode && lastSync || fieldDeleted) && value) != null ? _a : null;
|
|
99
|
-
} else {
|
|
100
|
-
return resultsToOutType(transformed);
|
|
137
|
+
return runWithRetry(getParams, retry, getFn || listFn, () => {
|
|
138
|
+
const { updateLastSync, lastSync, value } = getParams;
|
|
139
|
+
if (listFn) {
|
|
140
|
+
const isLastSyncMode = changesSince === "last-sync";
|
|
141
|
+
if (isLastSyncMode && lastSync) {
|
|
142
|
+
getParams.mode = modeParam || (asType === "array" ? "append" : asType === "value" ? "set" : "assign");
|
|
101
143
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
144
|
+
const listPromise = listFn(getParams);
|
|
145
|
+
const toOut = (transformed) => {
|
|
146
|
+
if (asType === "value") {
|
|
147
|
+
if (transformed.length > 0) {
|
|
148
|
+
return transformed[0];
|
|
149
|
+
} else {
|
|
150
|
+
return value ? void 0 : null;
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
return resultsToOutType(transformed);
|
|
109
154
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
} else if (getFn) {
|
|
119
|
-
const dataPromise = getFn(getParams);
|
|
120
|
-
const processData = (data) => {
|
|
121
|
-
let transformed = data;
|
|
122
|
-
if (data) {
|
|
123
|
-
const newLastSync = data[fieldUpdatedAt] || data[fieldCreatedAt];
|
|
124
|
-
if (newLastSync && newLastSync !== lastSync) {
|
|
125
|
-
updateLastSync(newLastSync);
|
|
155
|
+
};
|
|
156
|
+
const processResults = (data) => {
|
|
157
|
+
data || (data = []);
|
|
158
|
+
if (fieldUpdatedAt) {
|
|
159
|
+
const newLastSync = computeLastSync(data, fieldUpdatedAt, fieldCreatedAt);
|
|
160
|
+
if (newLastSync && newLastSync !== lastSync) {
|
|
161
|
+
updateLastSync(newLastSync);
|
|
162
|
+
}
|
|
126
163
|
}
|
|
164
|
+
let transformed = data;
|
|
127
165
|
if (transform == null ? void 0 : transform.load) {
|
|
128
|
-
transformed =
|
|
166
|
+
transformed = transformRows(data);
|
|
129
167
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
168
|
+
return isPromise(transformed) ? transformed.then(toOut) : toOut(transformed);
|
|
169
|
+
};
|
|
170
|
+
return isPromise(listPromise) ? listPromise.then(processResults) : processResults(listPromise);
|
|
171
|
+
} else if (getFn) {
|
|
172
|
+
const dataPromise = getFn(getParams);
|
|
173
|
+
const processData = (data) => {
|
|
174
|
+
let transformed = data;
|
|
175
|
+
if (data) {
|
|
176
|
+
const newLastSync = data[fieldUpdatedAt] || data[fieldCreatedAt];
|
|
177
|
+
if (newLastSync && newLastSync !== lastSync) {
|
|
178
|
+
updateLastSync(newLastSync);
|
|
179
|
+
}
|
|
180
|
+
if (transform == null ? void 0 : transform.load) {
|
|
181
|
+
transformed = transform.load(data, "get");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return transformed;
|
|
185
|
+
};
|
|
186
|
+
return isPromise(dataPromise) ? dataPromise.then(processData) : processData(dataPromise);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
135
189
|
} : void 0;
|
|
136
190
|
const set = createFn || updateFn || deleteFn ? async (params) => {
|
|
137
191
|
const { value, changes, update, retryAsCreate, node } = params;
|
|
138
192
|
const creates = /* @__PURE__ */ new Map();
|
|
139
193
|
const updates = /* @__PURE__ */ new Map();
|
|
194
|
+
const updateFullValues = /* @__PURE__ */ new Map();
|
|
140
195
|
const deletes = /* @__PURE__ */ new Set();
|
|
196
|
+
const changesById = /* @__PURE__ */ new Map();
|
|
141
197
|
const getUpdateValue = (itemValue, prev) => {
|
|
142
198
|
return updatePartial ? Object.assign(
|
|
143
199
|
diffObjects(
|
|
@@ -146,19 +202,21 @@ function syncedCrud(props) {
|
|
|
146
202
|
/*deep*/
|
|
147
203
|
true
|
|
148
204
|
),
|
|
149
|
-
itemValue[fieldId] ? { [fieldId]: itemValue[fieldId] } : {}
|
|
205
|
+
!isNullOrUndefined(itemValue[fieldId]) ? { [fieldId]: itemValue[fieldId] } : {}
|
|
150
206
|
) : itemValue;
|
|
151
207
|
};
|
|
152
208
|
changes.forEach((change) => {
|
|
209
|
+
var _a, _b;
|
|
153
210
|
const { path, prevAtPath, valueAtPath, pathTypes } = change;
|
|
154
211
|
if (asType === "value") {
|
|
155
212
|
if (value) {
|
|
156
|
-
let id = value == null ? void 0 : value[fieldId];
|
|
157
213
|
let isCreate = fieldCreatedAt ? !value[fieldCreatedAt] : !prevAtPath;
|
|
158
|
-
if (
|
|
159
|
-
|
|
214
|
+
if (isNullOrUndefined(value[fieldId]) && generateId) {
|
|
215
|
+
ensureId(value, fieldId, generateId, node);
|
|
160
216
|
}
|
|
161
|
-
|
|
217
|
+
const id = value[fieldId];
|
|
218
|
+
if (!isNullOrUndefined(id)) {
|
|
219
|
+
changesById.set(id, change);
|
|
162
220
|
if (pendingCreates.has(id)) {
|
|
163
221
|
isCreate = false;
|
|
164
222
|
}
|
|
@@ -171,6 +229,7 @@ function syncedCrud(props) {
|
|
|
171
229
|
} else if (path.length === 0) {
|
|
172
230
|
if (valueAtPath) {
|
|
173
231
|
updates.set(id, getUpdateValue(valueAtPath, prevAtPath));
|
|
232
|
+
updateFullValues.set(id, valueAtPath);
|
|
174
233
|
} else if (prevAtPath) {
|
|
175
234
|
deletes.add(prevAtPath);
|
|
176
235
|
}
|
|
@@ -182,27 +241,50 @@ function syncedCrud(props) {
|
|
|
182
241
|
true
|
|
183
242
|
);
|
|
184
243
|
updates.set(id, getUpdateValue(value, previous));
|
|
244
|
+
updateFullValues.set(id, value);
|
|
185
245
|
}
|
|
186
246
|
} else {
|
|
187
247
|
console.error("[legend-state]: added synced item without an id");
|
|
188
248
|
}
|
|
189
249
|
} else if (path.length === 0) {
|
|
190
250
|
deletes.add(prevAtPath);
|
|
251
|
+
changesById.set(prevAtPath[fieldId], change);
|
|
191
252
|
}
|
|
192
253
|
} else {
|
|
193
254
|
let itemsChanged = [];
|
|
194
255
|
if (path.length === 0) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
256
|
+
if (asArray && generateId) {
|
|
257
|
+
for (let i = 0; i < valueAtPath.length; i++) {
|
|
258
|
+
const value2 = valueAtPath[i];
|
|
259
|
+
if (value2 && !value2[fieldId]) {
|
|
260
|
+
ensureId(value2, fieldId, generateId, getChildNode(node, i + ""));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const valueAsObject = asArray ? arrayToRecord(valueAtPath, fieldId) : valueAtPath;
|
|
265
|
+
const prevAsObject = asArray ? arrayToRecord(prevAtPath, fieldId) : prevAtPath;
|
|
266
|
+
const keys = getKeys(valueAsObject, false, asMap, false);
|
|
267
|
+
const keysPrev = getKeys(prevAsObject, false, asMap, false);
|
|
268
|
+
const keysSet = new Set(keys);
|
|
269
|
+
const length = ((_a = keys || valueAsObject) == null ? void 0 : _a.length) || 0;
|
|
270
|
+
const lengthPrev = ((_b = keysPrev || prevAsObject) == null ? void 0 : _b.length) || 0;
|
|
271
|
+
for (let i = 0; i < lengthPrev; i++) {
|
|
272
|
+
const key = keysPrev[i];
|
|
273
|
+
if (!keysSet.has(key)) {
|
|
274
|
+
deletes.add(prevAsObject[key]);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
for (let i = 0; i < length; i++) {
|
|
278
|
+
const key = keys[i];
|
|
279
|
+
const value2 = asMap ? valueAsObject.get(key) : valueAsObject[key];
|
|
280
|
+
const prev = prevAsObject ? asMap ? prevAsObject.get(key) : prevAsObject[key] : void 0;
|
|
199
281
|
if (isNullOrUndefined(value2) && !isNullOrUndefined(prev)) {
|
|
200
282
|
deletes.add(prev);
|
|
201
283
|
return false;
|
|
202
284
|
} else {
|
|
203
|
-
const isDiff = !
|
|
285
|
+
const isDiff = !prevAsObject || !deepEqual(value2, prev);
|
|
204
286
|
if (isDiff) {
|
|
205
|
-
itemsChanged.push([getUpdateValue(value2, prev), prev]);
|
|
287
|
+
itemsChanged.push([getUpdateValue(value2, prev), prev, value2]);
|
|
206
288
|
}
|
|
207
289
|
}
|
|
208
290
|
}
|
|
@@ -212,37 +294,43 @@ function syncedCrud(props) {
|
|
|
212
294
|
if (!itemValue) {
|
|
213
295
|
if (path.length === 1 && prevAtPath) {
|
|
214
296
|
deletes.add(prevAtPath);
|
|
297
|
+
changesById.set(prevAtPath[fieldId], change);
|
|
215
298
|
}
|
|
216
299
|
} else {
|
|
300
|
+
if (generateId) {
|
|
301
|
+
ensureId(itemValue, fieldId, generateId, getChildNode(node, itemKey + ""));
|
|
302
|
+
}
|
|
217
303
|
const previous = setAtPath(
|
|
218
304
|
clone(itemValue),
|
|
219
305
|
path.slice(1),
|
|
220
306
|
pathTypes.slice(1),
|
|
221
307
|
prevAtPath
|
|
222
308
|
);
|
|
223
|
-
itemsChanged = [[getUpdateValue(itemValue, previous), previous]];
|
|
309
|
+
itemsChanged = [[getUpdateValue(itemValue, previous), previous, itemValue]];
|
|
224
310
|
}
|
|
225
311
|
}
|
|
226
|
-
itemsChanged == null ? void 0 : itemsChanged.forEach(([item, prev]) => {
|
|
312
|
+
itemsChanged == null ? void 0 : itemsChanged.forEach(([item, prev, fullValue]) => {
|
|
227
313
|
const isCreate = !pendingCreates.has(item[fieldId]) && (fieldCreatedAt ? !item[fieldCreatedAt] && !(prev == null ? void 0 : prev[fieldCreatedAt]) : fieldUpdatedAt ? !item[fieldUpdatedAt] && !(prev == null ? void 0 : prev[fieldCreatedAt]) : isNullOrUndefined(prev));
|
|
228
314
|
if (isCreate) {
|
|
229
|
-
if (generateId) {
|
|
230
|
-
ensureId(item, fieldId, generateId);
|
|
231
|
-
}
|
|
232
315
|
if (!item[fieldId]) {
|
|
233
316
|
console.error("[legend-state]: added item without an id");
|
|
234
317
|
}
|
|
235
318
|
if (createFn) {
|
|
236
|
-
|
|
237
|
-
|
|
319
|
+
const id = item[fieldId];
|
|
320
|
+
changesById.set(id, change);
|
|
321
|
+
pendingCreates.add(id);
|
|
322
|
+
creates.set(id, item);
|
|
238
323
|
} else {
|
|
239
324
|
console.warn("[legend-state] missing create function");
|
|
240
325
|
}
|
|
241
326
|
} else {
|
|
242
327
|
if (updateFn) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
328
|
+
const id = item[fieldId];
|
|
329
|
+
changesById.set(id, change);
|
|
330
|
+
updates.set(id, updates.has(id) ? Object.assign(updates.get(id), item) : item);
|
|
331
|
+
updateFullValues.set(
|
|
332
|
+
id,
|
|
333
|
+
updateFullValues.has(id) ? Object.assign(updateFullValues.get(id), fullValue) : fullValue
|
|
246
334
|
);
|
|
247
335
|
} else {
|
|
248
336
|
console.warn("[legend-state] missing update function");
|
|
@@ -251,93 +339,149 @@ function syncedCrud(props) {
|
|
|
251
339
|
});
|
|
252
340
|
}
|
|
253
341
|
});
|
|
254
|
-
const saveResult = async (itemKey, input, data, isCreate) => {
|
|
342
|
+
const saveResult = async (itemKey, input, data, isCreate, change) => {
|
|
255
343
|
var _a;
|
|
256
344
|
if (data) {
|
|
257
|
-
|
|
345
|
+
let saved = (transform == null ? void 0 : transform.load) ? await transform.load(data, "set") : data;
|
|
258
346
|
const isChild = itemKey !== "undefined" && asType !== "value";
|
|
259
347
|
const currentPeeked = getNodeValue(node);
|
|
260
|
-
const currentValue = isChild ? (_a = asType === "array" && isArray(currentPeeked) ? currentPeeked.find((v) => v[fieldId] === itemKey) : void 0) != null ? _a : currentPeeked[itemKey] : currentPeeked;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
348
|
+
const currentValue = isChild ? (_a = asType === "array" && isArray(currentPeeked) ? currentPeeked.find((v) => v[fieldId] === itemKey) : void 0) != null ? _a : asType === "Map" ? currentPeeked.get(itemKey) : currentPeeked[itemKey] : currentPeeked;
|
|
349
|
+
if (saved && !isNullOrUndefined(currentValue)) {
|
|
350
|
+
if (onSaved) {
|
|
351
|
+
const ret = onSaved({
|
|
352
|
+
saved,
|
|
353
|
+
input,
|
|
354
|
+
currentValue,
|
|
355
|
+
isCreate,
|
|
356
|
+
props
|
|
357
|
+
});
|
|
358
|
+
if (ret) {
|
|
359
|
+
saved = ret;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
saved = clone(saved);
|
|
363
|
+
Object.keys(saved).forEach((key) => {
|
|
272
364
|
const i = input[key];
|
|
273
365
|
const c = currentValue[key];
|
|
274
366
|
if (
|
|
275
367
|
// value is already the new value, can ignore
|
|
276
|
-
|
|
277
|
-
key !==
|
|
368
|
+
saved[key] === c || // user has changed local value
|
|
369
|
+
key !== fieldId && i !== void 0 && i !== c
|
|
278
370
|
) {
|
|
279
|
-
delete
|
|
371
|
+
delete saved[key];
|
|
280
372
|
}
|
|
281
373
|
});
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
374
|
+
let value2;
|
|
375
|
+
if (asType === "array") {
|
|
376
|
+
const index = currentPeeked.findIndex(
|
|
377
|
+
(cur) => cur[fieldId] === itemKey
|
|
378
|
+
);
|
|
379
|
+
if (index < 0) {
|
|
380
|
+
console.warn("[legend-state] Item saved that does not exist in array", saved);
|
|
381
|
+
} else {
|
|
382
|
+
value2 = { [index < 0 ? 0 : index]: saved };
|
|
286
383
|
}
|
|
384
|
+
} else {
|
|
385
|
+
value2 = itemKey !== "undefined" && asType !== "value" ? { [itemKey]: saved } : saved;
|
|
386
|
+
}
|
|
387
|
+
if (value2 !== void 0) {
|
|
388
|
+
update({
|
|
389
|
+
value: value2,
|
|
390
|
+
mode: "merge",
|
|
391
|
+
changes: [change]
|
|
392
|
+
});
|
|
287
393
|
}
|
|
288
|
-
const createdAt = fieldCreatedAt ? savedOut[fieldCreatedAt] : void 0;
|
|
289
|
-
const updatedAt = fieldUpdatedAt ? savedOut[fieldUpdatedAt] : void 0;
|
|
290
|
-
const value2 = itemKey !== "undefined" && asType !== "value" ? { [itemKey]: savedOut } : savedOut;
|
|
291
|
-
update({
|
|
292
|
-
value: value2,
|
|
293
|
-
lastSync: updatedAt || createdAt ? +new Date(updatedAt || createdAt) : void 0,
|
|
294
|
-
mode: "merge"
|
|
295
|
-
});
|
|
296
394
|
}
|
|
297
395
|
}
|
|
298
396
|
};
|
|
299
397
|
return Promise.all([
|
|
398
|
+
// Handle creates
|
|
300
399
|
...Array.from(creates).map(async ([itemKey, itemValue]) => {
|
|
301
400
|
if (waitForSetParam) {
|
|
302
401
|
await waitForSet(waitForSetParam, changes, itemValue, { type: "create" });
|
|
303
402
|
}
|
|
304
403
|
const createObj = await transformOut(itemValue, transform == null ? void 0 : transform.save);
|
|
305
|
-
return
|
|
306
|
-
|
|
307
|
-
|
|
404
|
+
return retrySet(
|
|
405
|
+
params,
|
|
406
|
+
retry,
|
|
407
|
+
"create",
|
|
408
|
+
itemKey,
|
|
409
|
+
createObj,
|
|
410
|
+
changesById.get(itemKey),
|
|
411
|
+
queuedRetries,
|
|
412
|
+
createObj,
|
|
413
|
+
createFn,
|
|
414
|
+
saveResult
|
|
415
|
+
).then(() => {
|
|
308
416
|
pendingCreates.delete(itemKey);
|
|
309
417
|
});
|
|
310
418
|
}),
|
|
419
|
+
// Handle updates
|
|
311
420
|
...Array.from(updates).map(async ([itemKey, itemValue]) => {
|
|
421
|
+
const fullValue = updateFullValues.get(itemKey);
|
|
312
422
|
if (waitForSetParam) {
|
|
313
|
-
await waitForSet(waitForSetParam, changes,
|
|
423
|
+
await waitForSet(waitForSetParam, changes, fullValue, { type: "update" });
|
|
314
424
|
}
|
|
315
|
-
const
|
|
316
|
-
const
|
|
425
|
+
const changed = await transformOut(itemValue, transform == null ? void 0 : transform.save);
|
|
426
|
+
const fullValueTransformed = await transformOut(
|
|
427
|
+
fullValue,
|
|
428
|
+
transform == null ? void 0 : transform.save
|
|
429
|
+
);
|
|
317
430
|
if (Object.keys(changed).length > 0) {
|
|
318
|
-
return
|
|
319
|
-
|
|
431
|
+
return retrySet(
|
|
432
|
+
params,
|
|
433
|
+
retry,
|
|
434
|
+
"update",
|
|
435
|
+
itemKey,
|
|
436
|
+
changed,
|
|
437
|
+
changesById.get(itemKey),
|
|
438
|
+
queuedRetries,
|
|
439
|
+
fullValueTransformed,
|
|
440
|
+
updateFn,
|
|
441
|
+
saveResult
|
|
320
442
|
);
|
|
321
443
|
}
|
|
322
444
|
}),
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
445
|
+
// Handle deletes
|
|
446
|
+
...Array.from(deletes).filter((val) => val !== symbolDelete).map(async (valuePrevious) => {
|
|
447
|
+
if (waitForSetParam) {
|
|
448
|
+
await waitForSet(waitForSetParam, changes, valuePrevious, { type: "delete" });
|
|
449
|
+
}
|
|
450
|
+
const itemKey = valuePrevious[fieldId];
|
|
451
|
+
if (!itemKey) {
|
|
452
|
+
console.error("[legend-state]: deleting item without an id");
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
if (deleteFn) {
|
|
456
|
+
return retrySet(
|
|
457
|
+
params,
|
|
458
|
+
retry,
|
|
459
|
+
"delete",
|
|
460
|
+
itemKey,
|
|
461
|
+
valuePrevious,
|
|
462
|
+
changesById.get(itemKey),
|
|
463
|
+
queuedRetries,
|
|
464
|
+
valuePrevious,
|
|
465
|
+
deleteFn,
|
|
466
|
+
saveResult
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
if (fieldDeleted && updateFn) {
|
|
470
|
+
const value2 = { [fieldId]: itemKey, [fieldDeleted]: true };
|
|
471
|
+
return retrySet(
|
|
472
|
+
params,
|
|
473
|
+
retry,
|
|
474
|
+
"delete",
|
|
475
|
+
itemKey,
|
|
476
|
+
value2,
|
|
477
|
+
changesById.get(itemKey),
|
|
478
|
+
queuedRetries,
|
|
479
|
+
value2,
|
|
480
|
+
updateFn,
|
|
481
|
+
saveResult
|
|
482
|
+
);
|
|
340
483
|
}
|
|
484
|
+
console.warn("[legend-state] missing delete function");
|
|
341
485
|
})
|
|
342
486
|
]);
|
|
343
487
|
} : void 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FieldTransforms } from '@legendapp/state/sync';
|
|
1
|
+
import { FieldTransforms, SyncedErrorParams } from '@legendapp/state/sync';
|
|
2
2
|
export { FieldTransforms } from '@legendapp/state/sync';
|
|
3
3
|
import { CrudAsOption, SyncedCrudPropsMany, SyncedCrudPropsBase, SyncedCrudReturnType } from '@legendapp/state/sync-plugins/crud';
|
|
4
4
|
import { DatabaseReference, Query } from 'firebase/database';
|
|
@@ -6,11 +6,12 @@ import { DatabaseReference, Query } from 'firebase/database';
|
|
|
6
6
|
declare function transformObjectFields(dataIn: Record<string, any>, map: Record<string, any>): any;
|
|
7
7
|
declare function invertFieldMap(obj: Record<string, any>): any;
|
|
8
8
|
|
|
9
|
-
interface SyncedFirebaseProps<TRemote extends object, TLocal, TAs extends CrudAsOption = 'value'> extends Omit<SyncedCrudPropsMany<TRemote, TLocal, TAs>, 'list' | 'retry'>, SyncedCrudPropsBase<TRemote, TLocal> {
|
|
9
|
+
interface SyncedFirebaseProps<TRemote extends object, TLocal, TAs extends CrudAsOption = 'value'> extends Omit<SyncedCrudPropsMany<TRemote, TLocal, TAs>, 'list' | 'retry'>, Omit<SyncedCrudPropsBase<TRemote, TLocal>, 'onError'> {
|
|
10
10
|
refPath: (uid: string | undefined) => string;
|
|
11
11
|
query?: (ref: DatabaseReference) => DatabaseReference | Query;
|
|
12
12
|
fieldId?: string;
|
|
13
13
|
fieldTransforms?: FieldTransforms<TRemote>;
|
|
14
|
+
onError?: (error: Error, params: FirebaseErrorParams) => void;
|
|
14
15
|
realtime?: boolean;
|
|
15
16
|
requireAuth?: boolean;
|
|
16
17
|
readonly?: boolean;
|
|
@@ -22,6 +23,9 @@ interface SyncedFirebaseConfiguration {
|
|
|
22
23
|
enabled?: boolean;
|
|
23
24
|
}
|
|
24
25
|
declare function configureSyncedFirebase(config: SyncedFirebaseConfiguration): void;
|
|
26
|
+
interface FirebaseErrorParams extends Omit<SyncedErrorParams, 'source'> {
|
|
27
|
+
source: 'list' | 'get' | 'create' | 'update' | 'delete';
|
|
28
|
+
}
|
|
25
29
|
declare function syncedFirebase<TRemote extends object, TLocal = TRemote, TAs extends CrudAsOption = 'object'>(props: SyncedFirebaseProps<TRemote, TLocal, TAs>): SyncedCrudReturnType<TLocal, TAs>;
|
|
26
30
|
|
|
27
|
-
export { type SyncedFirebaseProps, configureSyncedFirebase, invertFieldMap, syncedFirebase, transformObjectFields };
|
|
31
|
+
export { type FirebaseErrorParams, type SyncedFirebaseProps, configureSyncedFirebase, invertFieldMap, syncedFirebase, transformObjectFields };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FieldTransforms } from '@legendapp/state/sync';
|
|
1
|
+
import { FieldTransforms, SyncedErrorParams } from '@legendapp/state/sync';
|
|
2
2
|
export { FieldTransforms } from '@legendapp/state/sync';
|
|
3
3
|
import { CrudAsOption, SyncedCrudPropsMany, SyncedCrudPropsBase, SyncedCrudReturnType } from '@legendapp/state/sync-plugins/crud';
|
|
4
4
|
import { DatabaseReference, Query } from 'firebase/database';
|
|
@@ -6,11 +6,12 @@ import { DatabaseReference, Query } from 'firebase/database';
|
|
|
6
6
|
declare function transformObjectFields(dataIn: Record<string, any>, map: Record<string, any>): any;
|
|
7
7
|
declare function invertFieldMap(obj: Record<string, any>): any;
|
|
8
8
|
|
|
9
|
-
interface SyncedFirebaseProps<TRemote extends object, TLocal, TAs extends CrudAsOption = 'value'> extends Omit<SyncedCrudPropsMany<TRemote, TLocal, TAs>, 'list' | 'retry'>, SyncedCrudPropsBase<TRemote, TLocal> {
|
|
9
|
+
interface SyncedFirebaseProps<TRemote extends object, TLocal, TAs extends CrudAsOption = 'value'> extends Omit<SyncedCrudPropsMany<TRemote, TLocal, TAs>, 'list' | 'retry'>, Omit<SyncedCrudPropsBase<TRemote, TLocal>, 'onError'> {
|
|
10
10
|
refPath: (uid: string | undefined) => string;
|
|
11
11
|
query?: (ref: DatabaseReference) => DatabaseReference | Query;
|
|
12
12
|
fieldId?: string;
|
|
13
13
|
fieldTransforms?: FieldTransforms<TRemote>;
|
|
14
|
+
onError?: (error: Error, params: FirebaseErrorParams) => void;
|
|
14
15
|
realtime?: boolean;
|
|
15
16
|
requireAuth?: boolean;
|
|
16
17
|
readonly?: boolean;
|
|
@@ -22,6 +23,9 @@ interface SyncedFirebaseConfiguration {
|
|
|
22
23
|
enabled?: boolean;
|
|
23
24
|
}
|
|
24
25
|
declare function configureSyncedFirebase(config: SyncedFirebaseConfiguration): void;
|
|
26
|
+
interface FirebaseErrorParams extends Omit<SyncedErrorParams, 'source'> {
|
|
27
|
+
source: 'list' | 'get' | 'create' | 'update' | 'delete';
|
|
28
|
+
}
|
|
25
29
|
declare function syncedFirebase<TRemote extends object, TLocal = TRemote, TAs extends CrudAsOption = 'object'>(props: SyncedFirebaseProps<TRemote, TLocal, TAs>): SyncedCrudReturnType<TLocal, TAs>;
|
|
26
30
|
|
|
27
|
-
export { type SyncedFirebaseProps, configureSyncedFirebase, invertFieldMap, syncedFirebase, transformObjectFields };
|
|
31
|
+
export { type FirebaseErrorParams, type SyncedFirebaseProps, configureSyncedFirebase, invertFieldMap, syncedFirebase, transformObjectFields };
|