@legendapp/state 3.0.0-beta.3 → 3.0.0-beta.30

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