@legendapp/state 3.0.0-beta.2 → 3.0.0-beta.20
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/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 +13 -4
- package/index.d.ts +13 -4
- package/index.js +70 -22
- package/index.mjs +70 -22
- package/package.json +22 -1
- package/persist-plugins/async-storage.js +17 -9
- package/persist-plugins/async-storage.mjs +17 -9
- 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 +6 -0
- package/react-web.d.ts +6 -0
- package/react-web.js +39 -0
- package/react-web.mjs +37 -0
- package/react.d.mts +38 -20
- package/react.d.ts +38 -20
- package/react.js +36 -23
- package/react.mjs +37 -25
- package/sync-plugins/crud.d.mts +24 -9
- package/sync-plugins/crud.d.ts +24 -9
- package/sync-plugins/crud.js +199 -108
- package/sync-plugins/crud.mjs +200 -109
- package/sync-plugins/firebase.d.mts +7 -3
- package/sync-plugins/firebase.d.ts +7 -3
- package/sync-plugins/firebase.js +4 -2
- package/sync-plugins/firebase.mjs +4 -2
- package/sync-plugins/keel.d.mts +9 -13
- package/sync-plugins/keel.d.ts +9 -13
- package/sync-plugins/keel.js +52 -41
- package/sync-plugins/keel.mjs +53 -37
- package/sync-plugins/supabase.d.mts +7 -3
- package/sync-plugins/supabase.d.ts +7 -3
- package/sync-plugins/supabase.js +87 -31
- package/sync-plugins/supabase.mjs +88 -32
- package/sync-plugins/tanstack-query.d.mts +5 -5
- package/sync-plugins/tanstack-query.d.ts +5 -5
- package/sync-plugins/tanstack-query.js +10 -1
- package/sync-plugins/tanstack-query.mjs +10 -1
- package/sync-plugins/tanstack-react-query.d.mts +4 -2
- package/sync-plugins/tanstack-react-query.d.ts +4 -2
- package/sync.d.mts +16 -8
- package/sync.d.ts +16 -8
- package/sync.js +267 -174
- package/sync.mjs +266 -174
- 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,9 +1,9 @@
|
|
|
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
5
|
var { clone } = internal;
|
|
6
|
-
var { waitForSet } = internal$1;
|
|
6
|
+
var { waitForSet, runWithRetry } = internal$1;
|
|
7
7
|
function transformOut(data, transform) {
|
|
8
8
|
return transform ? transform(clone(data)) : data;
|
|
9
9
|
}
|
|
@@ -23,6 +23,35 @@ function computeLastSync(data, fieldUpdatedAt, fieldCreatedAt) {
|
|
|
23
23
|
}
|
|
24
24
|
return newLastSync;
|
|
25
25
|
}
|
|
26
|
+
function retrySet(params, retry, action, itemKey, itemValue, change, queuedRetries, actionFn, saveResult) {
|
|
27
|
+
if (action === "delete") {
|
|
28
|
+
if (queuedRetries.create.has(itemKey)) {
|
|
29
|
+
queuedRetries.create.delete(itemKey);
|
|
30
|
+
}
|
|
31
|
+
if (queuedRetries.update.has(itemKey)) {
|
|
32
|
+
queuedRetries.update.delete(itemKey);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
if (queuedRetries.delete.has(itemKey)) {
|
|
36
|
+
queuedRetries.delete.delete(itemKey);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const queuedRetry = queuedRetries[action].get(itemKey);
|
|
40
|
+
if (queuedRetry) {
|
|
41
|
+
itemValue = Object.assign(queuedRetry, itemValue);
|
|
42
|
+
}
|
|
43
|
+
queuedRetries[action].set(itemKey, itemValue);
|
|
44
|
+
const paramsWithChanges = { ...params, changes: [change] };
|
|
45
|
+
return runWithRetry(
|
|
46
|
+
paramsWithChanges,
|
|
47
|
+
retry,
|
|
48
|
+
"create_" + itemKey,
|
|
49
|
+
() => actionFn(itemValue, paramsWithChanges).then((result) => {
|
|
50
|
+
queuedRetries[action].delete(itemKey);
|
|
51
|
+
return saveResult(itemKey, itemValue, result, true, change);
|
|
52
|
+
})
|
|
53
|
+
);
|
|
54
|
+
}
|
|
26
55
|
function syncedCrud(props) {
|
|
27
56
|
const {
|
|
28
57
|
get: getFn,
|
|
@@ -43,10 +72,16 @@ function syncedCrud(props) {
|
|
|
43
72
|
changesSince,
|
|
44
73
|
generateId,
|
|
45
74
|
waitForSet: waitForSetParam,
|
|
75
|
+
retry,
|
|
46
76
|
...rest
|
|
47
77
|
} = props;
|
|
48
78
|
const fieldId = fieldIdProp || "id";
|
|
49
79
|
const pendingCreates = /* @__PURE__ */ new Set();
|
|
80
|
+
const queuedRetries = {
|
|
81
|
+
create: /* @__PURE__ */ new Map(),
|
|
82
|
+
update: /* @__PURE__ */ new Map(),
|
|
83
|
+
delete: /* @__PURE__ */ new Map()
|
|
84
|
+
};
|
|
50
85
|
let asType = props.as;
|
|
51
86
|
if (!asType) {
|
|
52
87
|
asType = getFn ? "value" : "object";
|
|
@@ -75,69 +110,75 @@ function syncedCrud(props) {
|
|
|
75
110
|
return out;
|
|
76
111
|
};
|
|
77
112
|
const transformRows = (data) => {
|
|
78
|
-
return Promise.all(
|
|
113
|
+
return data.length ? Promise.all(
|
|
79
114
|
data.map(
|
|
80
115
|
(value) => (
|
|
81
116
|
// Skip transforming any children with symbolDelete or fieldDeleted because they'll get deleted by resultsToOutType
|
|
82
117
|
value[symbolDelete] || fieldDeleted && value[fieldDeleted] || fieldDeletedList && value[fieldDeletedList] ? value : transform.load(value, "get")
|
|
83
118
|
)
|
|
84
119
|
)
|
|
85
|
-
);
|
|
120
|
+
) : [];
|
|
86
121
|
};
|
|
87
122
|
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);
|
|
123
|
+
return runWithRetry(getParams, retry, getFn || listFn, () => {
|
|
124
|
+
const { updateLastSync, lastSync, value } = getParams;
|
|
125
|
+
if (listFn) {
|
|
126
|
+
const isLastSyncMode = changesSince === "last-sync";
|
|
127
|
+
if (isLastSyncMode && lastSync) {
|
|
128
|
+
getParams.mode = modeParam || (asType === "array" ? "append" : asType === "value" ? "set" : "assign");
|
|
101
129
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
130
|
+
const listPromise = listFn(getParams);
|
|
131
|
+
const toOut = (transformed) => {
|
|
132
|
+
if (asType === "value") {
|
|
133
|
+
if (transformed.length > 0) {
|
|
134
|
+
return transformed[0];
|
|
135
|
+
} else {
|
|
136
|
+
return value ? void 0 : null;
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
return resultsToOutType(transformed);
|
|
109
140
|
}
|
|
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);
|
|
141
|
+
};
|
|
142
|
+
const processResults = (data) => {
|
|
143
|
+
data || (data = []);
|
|
144
|
+
if (fieldUpdatedAt) {
|
|
145
|
+
const newLastSync = computeLastSync(data, fieldUpdatedAt, fieldCreatedAt);
|
|
146
|
+
if (newLastSync && newLastSync !== lastSync) {
|
|
147
|
+
updateLastSync(newLastSync);
|
|
148
|
+
}
|
|
126
149
|
}
|
|
150
|
+
let transformed = data;
|
|
127
151
|
if (transform == null ? void 0 : transform.load) {
|
|
128
|
-
transformed =
|
|
152
|
+
transformed = transformRows(data);
|
|
129
153
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
154
|
+
return isPromise(transformed) ? transformed.then(toOut) : toOut(transformed);
|
|
155
|
+
};
|
|
156
|
+
return isPromise(listPromise) ? listPromise.then(processResults) : processResults(listPromise);
|
|
157
|
+
} else if (getFn) {
|
|
158
|
+
const dataPromise = getFn(getParams);
|
|
159
|
+
const processData = (data) => {
|
|
160
|
+
let transformed = data;
|
|
161
|
+
if (data) {
|
|
162
|
+
const newLastSync = data[fieldUpdatedAt] || data[fieldCreatedAt];
|
|
163
|
+
if (newLastSync && newLastSync !== lastSync) {
|
|
164
|
+
updateLastSync(newLastSync);
|
|
165
|
+
}
|
|
166
|
+
if (transform == null ? void 0 : transform.load) {
|
|
167
|
+
transformed = transform.load(data, "get");
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return transformed;
|
|
171
|
+
};
|
|
172
|
+
return isPromise(dataPromise) ? dataPromise.then(processData) : processData(dataPromise);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
135
175
|
} : void 0;
|
|
136
176
|
const set = createFn || updateFn || deleteFn ? async (params) => {
|
|
137
177
|
const { value, changes, update, retryAsCreate, node } = params;
|
|
138
178
|
const creates = /* @__PURE__ */ new Map();
|
|
139
179
|
const updates = /* @__PURE__ */ new Map();
|
|
140
180
|
const deletes = /* @__PURE__ */ new Set();
|
|
181
|
+
const changesById = /* @__PURE__ */ new Map();
|
|
141
182
|
const getUpdateValue = (itemValue, prev) => {
|
|
142
183
|
return updatePartial ? Object.assign(
|
|
143
184
|
diffObjects(
|
|
@@ -146,7 +187,7 @@ function syncedCrud(props) {
|
|
|
146
187
|
/*deep*/
|
|
147
188
|
true
|
|
148
189
|
),
|
|
149
|
-
itemValue[fieldId] ? { [fieldId]: itemValue[fieldId] } : {}
|
|
190
|
+
!isNullOrUndefined(itemValue[fieldId]) ? { [fieldId]: itemValue[fieldId] } : {}
|
|
150
191
|
) : itemValue;
|
|
151
192
|
};
|
|
152
193
|
changes.forEach((change) => {
|
|
@@ -155,10 +196,11 @@ function syncedCrud(props) {
|
|
|
155
196
|
if (value) {
|
|
156
197
|
let id = value == null ? void 0 : value[fieldId];
|
|
157
198
|
let isCreate = fieldCreatedAt ? !value[fieldCreatedAt] : !prevAtPath;
|
|
158
|
-
if (!id && generateId) {
|
|
199
|
+
if (!isNullOrUndefined(id) && generateId) {
|
|
159
200
|
id = ensureId(value, fieldId, generateId);
|
|
160
201
|
}
|
|
161
|
-
if (id) {
|
|
202
|
+
if (!isNullOrUndefined(id)) {
|
|
203
|
+
changesById.set(id, change);
|
|
162
204
|
if (pendingCreates.has(id)) {
|
|
163
205
|
isCreate = false;
|
|
164
206
|
}
|
|
@@ -188,6 +230,7 @@ function syncedCrud(props) {
|
|
|
188
230
|
}
|
|
189
231
|
} else if (path.length === 0) {
|
|
190
232
|
deletes.add(prevAtPath);
|
|
233
|
+
changesById.set(prevAtPath[fieldId], change);
|
|
191
234
|
}
|
|
192
235
|
} else {
|
|
193
236
|
let itemsChanged = [];
|
|
@@ -195,7 +238,7 @@ function syncedCrud(props) {
|
|
|
195
238
|
const changed = asMap ? Array.from(valueAtPath.entries()) : Object.entries(valueAtPath);
|
|
196
239
|
for (let i = 0; i < changed.length; i++) {
|
|
197
240
|
const [key, value2] = changed[i];
|
|
198
|
-
const prev = asMap ? prevAtPath.get(key) : prevAtPath[key];
|
|
241
|
+
const prev = prevAtPath ? asMap ? prevAtPath.get(key) : prevAtPath[key] : void 0;
|
|
199
242
|
if (isNullOrUndefined(value2) && !isNullOrUndefined(prev)) {
|
|
200
243
|
deletes.add(prev);
|
|
201
244
|
return false;
|
|
@@ -212,6 +255,7 @@ function syncedCrud(props) {
|
|
|
212
255
|
if (!itemValue) {
|
|
213
256
|
if (path.length === 1 && prevAtPath) {
|
|
214
257
|
deletes.add(prevAtPath);
|
|
258
|
+
changesById.set(prevAtPath[fieldId], change);
|
|
215
259
|
}
|
|
216
260
|
} else {
|
|
217
261
|
const previous = setAtPath(
|
|
@@ -233,17 +277,18 @@ function syncedCrud(props) {
|
|
|
233
277
|
console.error("[legend-state]: added item without an id");
|
|
234
278
|
}
|
|
235
279
|
if (createFn) {
|
|
236
|
-
|
|
237
|
-
|
|
280
|
+
const id = item[fieldId];
|
|
281
|
+
changesById.set(id, change);
|
|
282
|
+
pendingCreates.add(id);
|
|
283
|
+
creates.set(id, item);
|
|
238
284
|
} else {
|
|
239
285
|
console.warn("[legend-state] missing create function");
|
|
240
286
|
}
|
|
241
287
|
} else {
|
|
242
288
|
if (updateFn) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
);
|
|
289
|
+
const id = item[fieldId];
|
|
290
|
+
changesById.set(id, change);
|
|
291
|
+
updates.set(id, updates.has(id) ? Object.assign(updates.get(id), item) : item);
|
|
247
292
|
} else {
|
|
248
293
|
console.warn("[legend-state] missing update function");
|
|
249
294
|
}
|
|
@@ -251,93 +296,139 @@ function syncedCrud(props) {
|
|
|
251
296
|
});
|
|
252
297
|
}
|
|
253
298
|
});
|
|
254
|
-
const saveResult = async (itemKey, input, data, isCreate) => {
|
|
299
|
+
const saveResult = async (itemKey, input, data, isCreate, change) => {
|
|
255
300
|
var _a;
|
|
256
301
|
if (data) {
|
|
257
|
-
|
|
302
|
+
let saved = (transform == null ? void 0 : transform.load) ? await transform.load(data, "set") : data;
|
|
258
303
|
const isChild = itemKey !== "undefined" && asType !== "value";
|
|
259
304
|
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
|
-
|
|
305
|
+
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;
|
|
306
|
+
if (saved && !isNullOrUndefined(currentValue)) {
|
|
307
|
+
if (onSaved) {
|
|
308
|
+
const ret = onSaved({
|
|
309
|
+
saved,
|
|
310
|
+
input,
|
|
311
|
+
currentValue,
|
|
312
|
+
isCreate,
|
|
313
|
+
props
|
|
314
|
+
});
|
|
315
|
+
if (ret) {
|
|
316
|
+
saved = ret;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
saved = clone(saved);
|
|
320
|
+
Object.keys(saved).forEach((key) => {
|
|
272
321
|
const i = input[key];
|
|
273
322
|
const c = currentValue[key];
|
|
274
323
|
if (
|
|
275
324
|
// value is already the new value, can ignore
|
|
276
|
-
|
|
277
|
-
key !==
|
|
325
|
+
saved[key] === c || // user has changed local value
|
|
326
|
+
key !== fieldId && i !== void 0 && i !== c
|
|
278
327
|
) {
|
|
279
|
-
delete
|
|
328
|
+
delete saved[key];
|
|
280
329
|
}
|
|
281
330
|
});
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
331
|
+
let value2;
|
|
332
|
+
if (asType === "array") {
|
|
333
|
+
const index = currentPeeked.findIndex(
|
|
334
|
+
(cur) => cur[fieldId] === itemKey
|
|
335
|
+
);
|
|
336
|
+
if (index < 0) {
|
|
337
|
+
console.warn("[legend-state] Item saved that does not exist in array", saved);
|
|
338
|
+
} else {
|
|
339
|
+
value2 = { [index < 0 ? 0 : index]: saved };
|
|
286
340
|
}
|
|
341
|
+
} else {
|
|
342
|
+
value2 = itemKey !== "undefined" && asType !== "value" ? { [itemKey]: saved } : saved;
|
|
343
|
+
}
|
|
344
|
+
if (value2 !== void 0) {
|
|
345
|
+
update({
|
|
346
|
+
value: value2,
|
|
347
|
+
mode: "merge",
|
|
348
|
+
changes: [change]
|
|
349
|
+
});
|
|
287
350
|
}
|
|
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
351
|
}
|
|
297
352
|
}
|
|
298
353
|
};
|
|
299
354
|
return Promise.all([
|
|
355
|
+
// Handle creates
|
|
300
356
|
...Array.from(creates).map(async ([itemKey, itemValue]) => {
|
|
301
357
|
if (waitForSetParam) {
|
|
302
358
|
await waitForSet(waitForSetParam, changes, itemValue, { type: "create" });
|
|
303
359
|
}
|
|
304
360
|
const createObj = await transformOut(itemValue, transform == null ? void 0 : transform.save);
|
|
305
|
-
return
|
|
306
|
-
|
|
307
|
-
|
|
361
|
+
return retrySet(
|
|
362
|
+
params,
|
|
363
|
+
retry,
|
|
364
|
+
"create",
|
|
365
|
+
itemKey,
|
|
366
|
+
createObj,
|
|
367
|
+
changesById.get(itemKey),
|
|
368
|
+
queuedRetries,
|
|
369
|
+
createFn,
|
|
370
|
+
saveResult
|
|
371
|
+
).then(() => {
|
|
308
372
|
pendingCreates.delete(itemKey);
|
|
309
373
|
});
|
|
310
374
|
}),
|
|
375
|
+
// Handle updates
|
|
311
376
|
...Array.from(updates).map(async ([itemKey, itemValue]) => {
|
|
312
377
|
if (waitForSetParam) {
|
|
313
378
|
await waitForSet(waitForSetParam, changes, itemValue, { type: "update" });
|
|
314
379
|
}
|
|
315
|
-
const
|
|
316
|
-
const changed = await transformOut(toSave, transform == null ? void 0 : transform.save);
|
|
380
|
+
const changed = await transformOut(itemValue, transform == null ? void 0 : transform.save);
|
|
317
381
|
if (Object.keys(changed).length > 0) {
|
|
318
|
-
return
|
|
319
|
-
|
|
382
|
+
return retrySet(
|
|
383
|
+
params,
|
|
384
|
+
retry,
|
|
385
|
+
"update",
|
|
386
|
+
itemKey,
|
|
387
|
+
changed,
|
|
388
|
+
changesById.get(itemKey),
|
|
389
|
+
queuedRetries,
|
|
390
|
+
updateFn,
|
|
391
|
+
saveResult
|
|
320
392
|
);
|
|
321
393
|
}
|
|
322
394
|
}),
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
395
|
+
// Handle deletes
|
|
396
|
+
...Array.from(deletes).filter((val) => val !== symbolDelete).map(async (valuePrevious) => {
|
|
397
|
+
if (waitForSetParam) {
|
|
398
|
+
await waitForSet(waitForSetParam, changes, valuePrevious, { type: "delete" });
|
|
399
|
+
}
|
|
400
|
+
const itemKey = valuePrevious[fieldId];
|
|
401
|
+
if (!itemKey) {
|
|
402
|
+
console.error("[legend-state]: deleting item without an id");
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
if (deleteFn) {
|
|
406
|
+
return retrySet(
|
|
407
|
+
params,
|
|
408
|
+
retry,
|
|
409
|
+
"delete",
|
|
410
|
+
itemKey,
|
|
411
|
+
valuePrevious,
|
|
412
|
+
changesById.get(itemKey),
|
|
413
|
+
queuedRetries,
|
|
414
|
+
deleteFn,
|
|
415
|
+
saveResult
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
if (fieldDeleted && updateFn) {
|
|
419
|
+
return retrySet(
|
|
420
|
+
params,
|
|
421
|
+
retry,
|
|
422
|
+
"delete",
|
|
423
|
+
itemKey,
|
|
424
|
+
{ [fieldId]: itemKey, [fieldDeleted]: true },
|
|
425
|
+
changesById.get(itemKey),
|
|
426
|
+
queuedRetries,
|
|
427
|
+
updateFn,
|
|
428
|
+
saveResult
|
|
429
|
+
);
|
|
340
430
|
}
|
|
431
|
+
console.warn("[legend-state] missing delete function");
|
|
341
432
|
})
|
|
342
433
|
]);
|
|
343
434
|
} : 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 };
|
package/sync-plugins/firebase.js
CHANGED
|
@@ -185,7 +185,8 @@ function syncedFirebase(props) {
|
|
|
185
185
|
}
|
|
186
186
|
return ref;
|
|
187
187
|
};
|
|
188
|
-
const list = async (
|
|
188
|
+
const list = async (getParams) => {
|
|
189
|
+
const { lastSync, onError } = getParams;
|
|
189
190
|
const ref = computeRef(lastSync);
|
|
190
191
|
return new Promise((resolve) => {
|
|
191
192
|
fns.once(
|
|
@@ -204,7 +205,7 @@ function syncedFirebase(props) {
|
|
|
204
205
|
didList = true;
|
|
205
206
|
resolve(values);
|
|
206
207
|
},
|
|
207
|
-
onError
|
|
208
|
+
(error) => onError(error, { source: "list", type: "get", retry: getParams })
|
|
208
209
|
);
|
|
209
210
|
});
|
|
210
211
|
};
|
|
@@ -354,6 +355,7 @@ function syncedFirebase(props) {
|
|
|
354
355
|
}
|
|
355
356
|
return crud.syncedCrud({
|
|
356
357
|
...rest,
|
|
358
|
+
// Workaround for type errors
|
|
357
359
|
list,
|
|
358
360
|
subscribe,
|
|
359
361
|
create,
|
|
@@ -183,7 +183,8 @@ function syncedFirebase(props) {
|
|
|
183
183
|
}
|
|
184
184
|
return ref;
|
|
185
185
|
};
|
|
186
|
-
const list = async (
|
|
186
|
+
const list = async (getParams) => {
|
|
187
|
+
const { lastSync, onError } = getParams;
|
|
187
188
|
const ref = computeRef(lastSync);
|
|
188
189
|
return new Promise((resolve) => {
|
|
189
190
|
fns.once(
|
|
@@ -202,7 +203,7 @@ function syncedFirebase(props) {
|
|
|
202
203
|
didList = true;
|
|
203
204
|
resolve(values);
|
|
204
205
|
},
|
|
205
|
-
onError
|
|
206
|
+
(error) => onError(error, { source: "list", type: "get", retry: getParams })
|
|
206
207
|
);
|
|
207
208
|
});
|
|
208
209
|
};
|
|
@@ -352,6 +353,7 @@ function syncedFirebase(props) {
|
|
|
352
353
|
}
|
|
353
354
|
return syncedCrud({
|
|
354
355
|
...rest,
|
|
356
|
+
// Workaround for type errors
|
|
355
357
|
list,
|
|
356
358
|
subscribe,
|
|
357
359
|
create,
|
package/sync-plugins/keel.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SyncedGetSetSubscribeBaseParams
|
|
2
|
-
import { SyncedCrudPropsBase, SyncedCrudReturnType, CrudAsOption, SyncedCrudPropsSingle, CrudResult, SyncedCrudPropsMany } from '@legendapp/state/sync-plugins/crud';
|
|
1
|
+
import { SyncedGetSetSubscribeBaseParams } from '@legendapp/state/sync';
|
|
2
|
+
import { CrudErrorParams, SyncedCrudPropsBase, SyncedCrudReturnType, CrudAsOption, SyncedCrudPropsSingle, CrudResult, SyncedCrudPropsMany } from '@legendapp/state/sync-plugins/crud';
|
|
3
3
|
|
|
4
4
|
interface KeelObjectBase {
|
|
5
5
|
id: string;
|
|
@@ -13,6 +13,7 @@ type APIError = {
|
|
|
13
13
|
type: string;
|
|
14
14
|
message: string;
|
|
15
15
|
requestId?: string;
|
|
16
|
+
error?: unknown;
|
|
16
17
|
};
|
|
17
18
|
type APIResult<T> = Result<T, APIError>;
|
|
18
19
|
type Data<T> = {
|
|
@@ -24,7 +25,6 @@ type Err<U> = {
|
|
|
24
25
|
error: U;
|
|
25
26
|
};
|
|
26
27
|
type Result<T, U> = NonNullable<Data<T> | Err<U>>;
|
|
27
|
-
declare function generateKeelId(): string;
|
|
28
28
|
interface KeelGetParams {
|
|
29
29
|
}
|
|
30
30
|
interface KeelListParams<Where = {}> {
|
|
@@ -62,7 +62,7 @@ interface SyncedKeelPropsManyWhere<TRemote extends {
|
|
|
62
62
|
}, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
|
|
63
63
|
list?: (params: KeelListParams<NoInfer<Where>>) => Promise<CrudResult<APIResult<{
|
|
64
64
|
results: TRemote[];
|
|
65
|
-
pageInfo
|
|
65
|
+
pageInfo?: any;
|
|
66
66
|
}>>>;
|
|
67
67
|
where?: Where | (() => Where);
|
|
68
68
|
}
|
|
@@ -71,7 +71,7 @@ interface SyncedKeelPropsManyNoWhere<TRemote extends {
|
|
|
71
71
|
}, TLocal, AOption extends CrudAsOption> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
|
|
72
72
|
list?: (params: KeelListParams<{}>) => Promise<CrudResult<APIResult<{
|
|
73
73
|
results: TRemote[];
|
|
74
|
-
pageInfo
|
|
74
|
+
pageInfo?: any;
|
|
75
75
|
}>>>;
|
|
76
76
|
where?: never | {};
|
|
77
77
|
}
|
|
@@ -88,12 +88,8 @@ interface SyncedKeelPropsSingle<TRemote extends {
|
|
|
88
88
|
list?: never;
|
|
89
89
|
as?: never;
|
|
90
90
|
}
|
|
91
|
-
interface
|
|
92
|
-
type: 'create' | 'update' | 'delete';
|
|
93
|
-
params: SyncedSetParams<any>;
|
|
94
|
-
input: any;
|
|
91
|
+
interface KeelErrorParams extends CrudErrorParams {
|
|
95
92
|
action: string;
|
|
96
|
-
error: APIResult<any>['error'];
|
|
97
93
|
}
|
|
98
94
|
interface SyncedKeelPropsBase<TRemote extends {
|
|
99
95
|
id: string;
|
|
@@ -102,7 +98,7 @@ interface SyncedKeelPropsBase<TRemote extends {
|
|
|
102
98
|
create?: (i: NoInfer<Partial<TRemote>>) => Promise<APIResult<NoInfer<TRemote>>>;
|
|
103
99
|
update?: (params: {
|
|
104
100
|
where: any;
|
|
105
|
-
values?: Partial<TRemote
|
|
101
|
+
values?: Partial<NoInfer<TRemote>>;
|
|
106
102
|
}) => Promise<APIResult<TRemote>>;
|
|
107
103
|
delete?: (params: {
|
|
108
104
|
id: string;
|
|
@@ -113,7 +109,7 @@ interface SyncedKeelPropsBase<TRemote extends {
|
|
|
113
109
|
};
|
|
114
110
|
refreshAuth?: () => void | Promise<void>;
|
|
115
111
|
requireAuth?: boolean;
|
|
116
|
-
onError?: (error: Error,
|
|
112
|
+
onError?: (error: Error, params: KeelErrorParams) => void;
|
|
117
113
|
}
|
|
118
114
|
declare function syncedKeel<TRemote extends {
|
|
119
115
|
id: string;
|
|
@@ -122,4 +118,4 @@ declare function syncedKeel<TRemote extends {
|
|
|
122
118
|
id: string;
|
|
123
119
|
}, TLocal = TRemote, TOption extends CrudAsOption = 'object', Where extends Record<string, any> = {}>(props: SyncedKeelPropsBase<TRemote, TLocal> & SyncedKeelPropsMany<TRemote, TLocal, TOption, Where>): SyncedCrudReturnType<TLocal, Exclude<TOption, 'value'>>;
|
|
124
120
|
|
|
125
|
-
export { type KeelClient, type KeelGetParams, type KeelKey, KeelKeys, type KeelListParams, type KeelObjectBase, type KeelRealtimePlugin, type OmitKeelBuiltins, type SyncedKeelPropsBase,
|
|
121
|
+
export { type KeelClient, type KeelErrorParams, type KeelGetParams, type KeelKey, KeelKeys, type KeelListParams, type KeelObjectBase, type KeelRealtimePlugin, type OmitKeelBuiltins, type SyncedKeelPropsBase, syncedKeel };
|