@legendapp/state 3.0.0-alpha.3 → 3.0.0-alpha.31

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/CHANGELOG.md +831 -1
  2. package/LICENSE +21 -1
  3. package/README.md +141 -1
  4. package/babel.js +0 -2
  5. package/babel.mjs +0 -2
  6. package/config/enable$GetSet.js +2 -1
  7. package/config/enable$GetSet.mjs +2 -1
  8. package/config/enableReactTracking.js +2 -1
  9. package/config/enableReactTracking.mjs +2 -1
  10. package/config/enableReactUse.js +2 -1
  11. package/config/enableReactUse.mjs +2 -1
  12. package/config/enable_PeekAssign.js +2 -1
  13. package/config/enable_PeekAssign.mjs +2 -1
  14. package/config.d.mts +13 -0
  15. package/config.d.ts +13 -0
  16. package/config.js +2066 -0
  17. package/config.mjs +2064 -0
  18. package/helpers/trackHistory.js +2 -2
  19. package/helpers/trackHistory.mjs +2 -2
  20. package/index.d.mts +25 -302
  21. package/index.d.ts +25 -302
  22. package/index.js +293 -322
  23. package/index.mjs +294 -321
  24. package/observableInterfaces-CZR3_8mM.d.mts +283 -0
  25. package/observableInterfaces-CZR3_8mM.d.ts +283 -0
  26. package/package.json +11 -1
  27. package/persist-plugins/async-storage.d.mts +6 -3
  28. package/persist-plugins/async-storage.d.ts +6 -3
  29. package/persist-plugins/async-storage.js +12 -4
  30. package/persist-plugins/async-storage.mjs +12 -5
  31. package/persist-plugins/indexeddb.d.mts +6 -4
  32. package/persist-plugins/indexeddb.d.ts +6 -4
  33. package/persist-plugins/indexeddb.js +16 -6
  34. package/persist-plugins/indexeddb.mjs +16 -7
  35. package/persist-plugins/mmkv.d.mts +5 -1
  36. package/persist-plugins/mmkv.d.ts +5 -1
  37. package/persist-plugins/mmkv.js +14 -5
  38. package/persist-plugins/mmkv.mjs +14 -6
  39. package/react.d.mts +18 -14
  40. package/react.d.ts +18 -14
  41. package/react.js +57 -32
  42. package/react.mjs +58 -33
  43. package/sync-plugins/crud.d.mts +21 -24
  44. package/sync-plugins/crud.d.ts +21 -24
  45. package/sync-plugins/crud.js +240 -139
  46. package/sync-plugins/crud.mjs +242 -141
  47. package/sync-plugins/fetch.js +12 -8
  48. package/sync-plugins/fetch.mjs +13 -9
  49. package/sync-plugins/firebase.d.mts +27 -0
  50. package/sync-plugins/firebase.d.ts +27 -0
  51. package/sync-plugins/firebase.js +373 -0
  52. package/sync-plugins/firebase.mjs +368 -0
  53. package/sync-plugins/keel.d.mts +27 -10
  54. package/sync-plugins/keel.d.ts +27 -10
  55. package/sync-plugins/keel.js +51 -32
  56. package/sync-plugins/keel.mjs +52 -33
  57. package/sync-plugins/supabase.d.mts +12 -7
  58. package/sync-plugins/supabase.d.ts +12 -7
  59. package/sync-plugins/supabase.js +24 -13
  60. package/sync-plugins/supabase.mjs +25 -14
  61. package/sync-plugins/tanstack-query.d.mts +2 -2
  62. package/sync-plugins/tanstack-query.d.ts +2 -2
  63. package/sync-plugins/tanstack-query.js +3 -2
  64. package/sync-plugins/tanstack-query.mjs +3 -2
  65. package/sync-plugins/tanstack-react-query.d.mts +1 -1
  66. package/sync-plugins/tanstack-react-query.d.ts +1 -1
  67. package/sync.d.mts +71 -197
  68. package/sync.d.ts +71 -197
  69. package/sync.js +465 -284
  70. package/sync.mjs +471 -290
  71. package/types/babel.d.ts +12 -1
  72. package/.DS_Store +0 -0
  73. /package/config/{enable_GetSet.d.mts → enable$GetSet.d.mts} +0 -0
  74. /package/config/{enable_GetSet.d.ts → enable$GetSet.d.ts} +0 -0
@@ -0,0 +1,368 @@
1
+ import { observable, symbolDelete, isString, isArray, isObject, computeSelector, isFunction, isNullOrUndefined, isPromise, isNumber, when } from '@legendapp/state';
2
+ import { syncedCrud } from '@legendapp/state/sync-plugins/crud';
3
+ import { getAuth } from 'firebase/auth';
4
+ import { ref, getDatabase, query, orderByChild, startAt, update, onValue, onChildAdded, onChildChanged, onChildRemoved, serverTimestamp, remove, push } from 'firebase/database';
5
+
6
+ // src/sync-plugins/firebase.ts
7
+ var validateMap;
8
+ function transformObjectFields(dataIn, map) {
9
+ if (process.env.NODE_ENV === "development") {
10
+ validateMap(map);
11
+ }
12
+ let ret = dataIn;
13
+ if (dataIn) {
14
+ if (dataIn === symbolDelete)
15
+ return dataIn;
16
+ if (isString(dataIn)) {
17
+ return map[dataIn];
18
+ }
19
+ ret = {};
20
+ const dict = Object.keys(map).length === 1 && map["_dict"];
21
+ for (const key in dataIn) {
22
+ let v = dataIn[key];
23
+ if (dict) {
24
+ ret[key] = transformObjectFields(v, dict);
25
+ } else {
26
+ const mapped = map[key];
27
+ if (mapped === void 0) {
28
+ if (key !== "@") {
29
+ ret[key] = v;
30
+ if (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") {
31
+ console.error("A fatal field transformation error has occurred", key, dataIn, map);
32
+ }
33
+ }
34
+ } else if (mapped !== null) {
35
+ if (v !== void 0 && v !== null) {
36
+ if (map[key + "_val"]) {
37
+ const mapChild = map[key + "_val"];
38
+ if (isArray(v)) {
39
+ v = v.map((vChild) => mapChild[vChild]);
40
+ } else {
41
+ v = mapChild[v];
42
+ }
43
+ } else if (map[key + "_arr"] && isArray(v)) {
44
+ const mapChild = map[key + "_arr"];
45
+ v = v.map((vChild) => transformObjectFields(vChild, mapChild));
46
+ } else if (isObject(v)) {
47
+ if (map[key + "_obj"]) {
48
+ v = transformObjectFields(v, map[key + "_obj"]);
49
+ } else if (map[key + "_dict"]) {
50
+ const mapChild = map[key + "_dict"];
51
+ const out = {};
52
+ for (const keyChild in v) {
53
+ out[keyChild] = transformObjectFields(v[keyChild], mapChild);
54
+ }
55
+ v = out;
56
+ }
57
+ }
58
+ }
59
+ ret[mapped] = v;
60
+ }
61
+ }
62
+ }
63
+ }
64
+ return ret;
65
+ }
66
+ var invertedMaps = /* @__PURE__ */ new WeakMap();
67
+ function invertFieldMap(obj) {
68
+ const existing = invertedMaps.get(obj);
69
+ if (existing)
70
+ return existing;
71
+ const target = {};
72
+ for (const key in obj) {
73
+ const val = obj[key];
74
+ if (key === "_dict") {
75
+ target[key] = invertFieldMap(val);
76
+ } else if (key.endsWith("_obj") || key.endsWith("_dict") || key.endsWith("_arr") || key.endsWith("_val")) {
77
+ const keyMapped = obj[key.replace(/_obj|_dict|_arr|_val$/, "")];
78
+ const suffix = key.match(/_obj|_dict|_arr|_val$/)[0];
79
+ target[keyMapped + suffix] = invertFieldMap(val);
80
+ } else if (typeof val === "string") {
81
+ target[val] = key;
82
+ }
83
+ }
84
+ invertedMaps.set(obj, target);
85
+ return target;
86
+ }
87
+ if (process.env.NODE_ENV === "development") {
88
+ validateMap = function(record) {
89
+ const values = Object.values(record).filter((value) => {
90
+ if (isObject(value)) {
91
+ validateMap(value);
92
+ } else {
93
+ return isString(value);
94
+ }
95
+ });
96
+ const uniques = Array.from(new Set(values));
97
+ if (values.length !== uniques.length) {
98
+ console.error("Field transform map has duplicate values", record, values.length, uniques.length);
99
+ }
100
+ return record;
101
+ };
102
+ }
103
+
104
+ // src/sync-plugins/firebase.ts
105
+ var isEnabled$ = observable(true);
106
+ var firebaseConfig = {};
107
+ function configureSyncedFirebase(config) {
108
+ const { enabled, ...rest } = config;
109
+ Object.assign(firebaseConfig, rest);
110
+ if (enabled !== void 0) {
111
+ isEnabled$.set(enabled);
112
+ }
113
+ }
114
+ function joinPaths(str1, str2) {
115
+ return str2 ? [str1, str2].join("/").replace(/\/\//g, "/") : str1;
116
+ }
117
+ var fns = {
118
+ isInitialized: () => {
119
+ try {
120
+ return !!getAuth().app;
121
+ } catch (e) {
122
+ return false;
123
+ }
124
+ },
125
+ getCurrentUser: () => {
126
+ var _a;
127
+ return (_a = getAuth().currentUser) == null ? void 0 : _a.uid;
128
+ },
129
+ ref: (path) => ref(getDatabase(), path),
130
+ orderByChild: (ref, child, start) => query(ref, orderByChild(child), startAt(start)),
131
+ update: (ref, object) => update(ref, object),
132
+ once: (ref, callback, callbackError) => {
133
+ let unsubscribe;
134
+ const cb = (snap) => {
135
+ if (unsubscribe) {
136
+ unsubscribe();
137
+ unsubscribe = void 0;
138
+ }
139
+ callback(snap);
140
+ };
141
+ unsubscribe = onValue(ref, cb, callbackError);
142
+ return unsubscribe;
143
+ },
144
+ onChildAdded,
145
+ onChildChanged,
146
+ onChildRemoved,
147
+ onValue,
148
+ serverTimestamp,
149
+ remove: remove,
150
+ onAuthStateChanged: (cb) => getAuth().onAuthStateChanged(cb),
151
+ generateId: () => push(ref(getDatabase())).key
152
+ };
153
+ function syncedFirebase(props) {
154
+ props = { ...firebaseConfig, ...props };
155
+ const saving$ = observable({});
156
+ const pendingOutgoing$ = observable({});
157
+ const pendingIncoming$ = observable({});
158
+ let didList = false;
159
+ const {
160
+ refPath,
161
+ query,
162
+ fieldId,
163
+ realtime,
164
+ requireAuth,
165
+ readonly,
166
+ transform: transformProp,
167
+ fieldTransforms,
168
+ waitFor,
169
+ waitForSet,
170
+ ...rest
171
+ } = props;
172
+ const { fieldCreatedAt, changesSince } = props;
173
+ const asType = props.as || "value";
174
+ const fieldUpdatedAt = props.fieldUpdatedAt || "@";
175
+ const computeRef = (lastSync) => {
176
+ const pathFirebase = refPath(fns.getCurrentUser());
177
+ let ref = fns.ref(pathFirebase);
178
+ if (query) {
179
+ ref = query(ref);
180
+ }
181
+ if (changesSince === "last-sync" && lastSync && fieldUpdatedAt && isNumber(lastSync)) {
182
+ ref = fns.orderByChild(ref, fieldUpdatedAt, lastSync + 1);
183
+ }
184
+ return ref;
185
+ };
186
+ const list = async ({ lastSync, onError }) => {
187
+ const ref = computeRef(lastSync);
188
+ return new Promise((resolve) => {
189
+ fns.once(
190
+ ref,
191
+ async (snap) => {
192
+ const val = snap.val();
193
+ let values = [];
194
+ if (!isNullOrUndefined(val)) {
195
+ values = asType === "value" ? [val] : Object.entries(val).map(([key, value]) => {
196
+ if (fieldId && !value[fieldId]) {
197
+ value[fieldId] = key;
198
+ }
199
+ return value;
200
+ });
201
+ }
202
+ didList = true;
203
+ resolve(values);
204
+ },
205
+ onError
206
+ );
207
+ });
208
+ };
209
+ const subscribe = realtime ? ({ lastSync, update: update2, onError }) => {
210
+ const ref = computeRef(lastSync);
211
+ let unsubscribes;
212
+ if (asType === "value") {
213
+ const onValue2 = (snap) => {
214
+ if (!didList)
215
+ return;
216
+ const val = snap.val();
217
+ if (saving$[""].get()) {
218
+ pendingIncoming$[""].set(val);
219
+ } else {
220
+ update2({
221
+ value: [val],
222
+ mode: "set"
223
+ });
224
+ }
225
+ };
226
+ unsubscribes = [fns.onValue(ref, onValue2, onError)];
227
+ } else {
228
+ const onChildChange = (snap) => {
229
+ if (!didList)
230
+ return;
231
+ const key = snap.key;
232
+ const val = snap.val();
233
+ if (fieldId && !val[fieldId]) {
234
+ val[fieldId] = key;
235
+ }
236
+ if (saving$[key].get()) {
237
+ pendingIncoming$[key].set(val);
238
+ } else {
239
+ update2({
240
+ value: [val],
241
+ mode: "assign"
242
+ });
243
+ }
244
+ };
245
+ const onChildDelete = (snap) => {
246
+ if (!didList)
247
+ return;
248
+ const key = snap.key;
249
+ const val = snap.val();
250
+ if (fieldId && !val[fieldId]) {
251
+ val[fieldId] = key;
252
+ }
253
+ val[symbolDelete] = true;
254
+ update2({
255
+ value: [val],
256
+ mode: "assign"
257
+ });
258
+ };
259
+ unsubscribes = [
260
+ fns.onChildAdded(ref, onChildChange, onError),
261
+ fns.onChildChanged(ref, onChildChange, onError),
262
+ fns.onChildRemoved(ref, onChildDelete, onError)
263
+ ];
264
+ }
265
+ return () => {
266
+ unsubscribes.forEach((fn) => fn());
267
+ };
268
+ } : void 0;
269
+ const addUpdatedAt = (input) => {
270
+ if (fieldUpdatedAt) {
271
+ input[fieldUpdatedAt] = serverTimestamp();
272
+ }
273
+ };
274
+ const addCreatedAt = (input) => {
275
+ if (fieldCreatedAt && !input[fieldCreatedAt]) {
276
+ input[fieldCreatedAt] = serverTimestamp();
277
+ }
278
+ return addUpdatedAt(input);
279
+ };
280
+ const upsert = async (input) => {
281
+ const id = fieldId ? input[fieldId] : "";
282
+ if (saving$[id].get()) {
283
+ pendingOutgoing$[id].set(input);
284
+ } else {
285
+ saving$[id].set(true);
286
+ const path = joinPaths(refPath(fns.getCurrentUser()), fieldId ? id : "");
287
+ await fns.update(fns.ref(path), input);
288
+ saving$[id].set(false);
289
+ flushAfterSave();
290
+ }
291
+ return when(
292
+ () => !pendingOutgoing$[id].get(),
293
+ () => {
294
+ const value = pendingIncoming$[id].get();
295
+ if (value) {
296
+ pendingIncoming$[id].delete();
297
+ return value;
298
+ }
299
+ }
300
+ );
301
+ };
302
+ const flushAfterSave = () => {
303
+ const outgoing = pendingOutgoing$.get();
304
+ Object.values(outgoing).forEach((value) => {
305
+ upsert(value);
306
+ });
307
+ pendingOutgoing$.set({});
308
+ };
309
+ const create = readonly ? void 0 : (input) => {
310
+ addCreatedAt(input);
311
+ return upsert(input);
312
+ };
313
+ const update = readonly ? void 0 : (input) => {
314
+ addUpdatedAt(input);
315
+ return upsert(input);
316
+ };
317
+ const deleteFn = readonly ? void 0 : (input) => {
318
+ const path = joinPaths(
319
+ refPath(fns.getCurrentUser()),
320
+ fieldId && asType !== "value" ? input[fieldId] : ""
321
+ );
322
+ return fns.remove(fns.ref(path));
323
+ };
324
+ let isAuthedIfRequired$;
325
+ if (requireAuth) {
326
+ if (fns.isInitialized()) {
327
+ isAuthedIfRequired$ = observable(false);
328
+ fns.onAuthStateChanged((user) => {
329
+ isAuthedIfRequired$.set(!!user);
330
+ });
331
+ }
332
+ }
333
+ let transform = transformProp;
334
+ if (fieldTransforms) {
335
+ const inverted = invertFieldMap(fieldTransforms);
336
+ transform = {
337
+ load(value, method) {
338
+ const fieldTransformed = transformObjectFields(value, inverted);
339
+ return (transformProp == null ? void 0 : transformProp.load) ? transformProp.load(fieldTransformed, method) : fieldTransformed;
340
+ },
341
+ save(value) {
342
+ const transformed = (transformProp == null ? void 0 : transformProp.save) ? transformProp.save(value) : value;
343
+ if (isPromise(transformed)) {
344
+ return transformed.then((transformedValue) => {
345
+ return transformObjectFields(transformedValue, fieldTransforms);
346
+ });
347
+ } else {
348
+ return transformObjectFields(transformed, fieldTransforms);
349
+ }
350
+ }
351
+ };
352
+ }
353
+ return syncedCrud({
354
+ ...rest,
355
+ list,
356
+ subscribe,
357
+ create,
358
+ update,
359
+ delete: deleteFn,
360
+ waitFor: () => isEnabled$.get() && (isAuthedIfRequired$ ? isAuthedIfRequired$.get() : true) && (waitFor ? computeSelector(waitFor) : true),
361
+ waitForSet: (params) => isEnabled$.get() && (isAuthedIfRequired$ ? isAuthedIfRequired$.get() : true) && (waitForSet ? isFunction(waitForSet) ? waitForSet(params) : waitForSet : true),
362
+ generateId: fns.generateId,
363
+ transform,
364
+ as: asType
365
+ });
366
+ }
367
+
368
+ export { configureSyncedFirebase, invertFieldMap, syncedFirebase, transformObjectFields };
@@ -1,4 +1,4 @@
1
- import { SyncedOptions } from '@legendapp/state/sync';
1
+ import { SyncedGetSetSubscribeBaseParams, SyncedOptions, SyncedSetParams } from '@legendapp/state/sync';
2
2
  import { SyncedCrudPropsBase, CrudAsOption, SyncedCrudReturnType, SyncedCrudPropsSingle, CrudResult, SyncedCrudPropsMany } from '@legendapp/state/sync-plugins/crud';
3
3
 
4
4
  interface KeelObjectBase {
@@ -39,14 +39,14 @@ interface KeelListParams<Where = {}> {
39
39
  before?: string;
40
40
  }
41
41
  interface KeelRealtimePlugin {
42
- subscribe: (realtimeKey: string, refresh: () => void) => void;
42
+ subscribe: (realtimeKey: string, params: SyncedGetSetSubscribeBaseParams) => void;
43
43
  setLatestChange: (realtimeKey: string, time: Date) => void;
44
44
  }
45
45
  interface SyncedKeelConfiguration extends Omit<SyncedCrudPropsBase<any>, keyof SyncedOptions | 'create' | 'update' | 'delete' | 'onSaved' | 'updatePartial' | 'fieldCreatedAt' | 'fieldUpdatedAt' | 'generateId'> {
46
46
  client: {
47
47
  auth: {
48
- refresh: () => Promise<boolean>;
49
- isAuthenticated: () => Promise<boolean>;
48
+ refresh: () => Promise<APIResult<boolean>>;
49
+ isAuthenticated: () => Promise<APIResult<boolean>>;
50
50
  };
51
51
  api: {
52
52
  queries: Record<string, (i: any) => Promise<any>>;
@@ -55,20 +55,33 @@ interface SyncedKeelConfiguration extends Omit<SyncedCrudPropsBase<any>, keyof S
55
55
  realtimePlugin?: KeelRealtimePlugin;
56
56
  as?: Exclude<CrudAsOption, 'value'>;
57
57
  enabled?: boolean;
58
- onError?: (params: APIResult<any>['error']) => void;
58
+ onError?: (params: {
59
+ type: 'create' | 'update' | 'delete';
60
+ params: SyncedSetParams<any>;
61
+ input: any;
62
+ action: string;
63
+ error: APIResult<any>['error'];
64
+ }) => void;
65
+ refreshAuth?: () => void | Promise<void>;
59
66
  }
60
- interface SyncedKeelPropsManyBase<TRemote, TLocal, AOption extends CrudAsOption> extends Omit<SyncedCrudPropsMany<TRemote, TLocal, AOption>, 'list'> {
67
+ interface SyncedKeelPropsManyBase<TRemote extends {
68
+ id: string;
69
+ }, TLocal, AOption extends CrudAsOption> extends Omit<SyncedCrudPropsMany<TRemote, TLocal, AOption>, 'list'> {
61
70
  first?: number;
62
71
  get?: never;
63
72
  }
64
- interface SyncedKeelPropsManyWhere<TRemote, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
73
+ interface SyncedKeelPropsManyWhere<TRemote extends {
74
+ id: string;
75
+ }, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
65
76
  list?: (params: KeelListParams<NoInfer<Where>>) => Promise<CrudResult<APIResult<{
66
77
  results: TRemote[];
67
78
  pageInfo: any;
68
79
  }>>>;
69
80
  where?: Where | (() => Where);
70
81
  }
71
- interface SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption extends CrudAsOption> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
82
+ interface SyncedKeelPropsManyNoWhere<TRemote extends {
83
+ id: string;
84
+ }, TLocal, AOption extends CrudAsOption> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
72
85
  list?: (params: KeelListParams<{}>) => Promise<CrudResult<APIResult<{
73
86
  results: TRemote[];
74
87
  pageInfo: any;
@@ -76,8 +89,12 @@ interface SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption extends CrudAsOpti
76
89
  where?: never | {};
77
90
  }
78
91
  type HasAnyKeys<T> = keyof T extends never ? false : true;
79
- type SyncedKeelPropsMany<TRemote, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> = HasAnyKeys<Where> extends true ? SyncedKeelPropsManyWhere<TRemote, TLocal, AOption, Where> : SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption>;
80
- interface SyncedKeelPropsSingle<TRemote, TLocal> extends Omit<SyncedCrudPropsSingle<TRemote, TLocal>, 'get'> {
92
+ type SyncedKeelPropsMany<TRemote extends {
93
+ id: string;
94
+ }, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> = HasAnyKeys<Where> extends true ? SyncedKeelPropsManyWhere<TRemote, TLocal, AOption, Where> : SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption>;
95
+ interface SyncedKeelPropsSingle<TRemote extends {
96
+ id: string;
97
+ }, TLocal> extends Omit<SyncedCrudPropsSingle<TRemote, TLocal>, 'get'> {
81
98
  get?: (params: KeelGetParams) => Promise<APIResult<TRemote>>;
82
99
  first?: never;
83
100
  where?: never;
@@ -1,4 +1,4 @@
1
- import { SyncedOptions } from '@legendapp/state/sync';
1
+ import { SyncedGetSetSubscribeBaseParams, SyncedOptions, SyncedSetParams } from '@legendapp/state/sync';
2
2
  import { SyncedCrudPropsBase, CrudAsOption, SyncedCrudReturnType, SyncedCrudPropsSingle, CrudResult, SyncedCrudPropsMany } from '@legendapp/state/sync-plugins/crud';
3
3
 
4
4
  interface KeelObjectBase {
@@ -39,14 +39,14 @@ interface KeelListParams<Where = {}> {
39
39
  before?: string;
40
40
  }
41
41
  interface KeelRealtimePlugin {
42
- subscribe: (realtimeKey: string, refresh: () => void) => void;
42
+ subscribe: (realtimeKey: string, params: SyncedGetSetSubscribeBaseParams) => void;
43
43
  setLatestChange: (realtimeKey: string, time: Date) => void;
44
44
  }
45
45
  interface SyncedKeelConfiguration extends Omit<SyncedCrudPropsBase<any>, keyof SyncedOptions | 'create' | 'update' | 'delete' | 'onSaved' | 'updatePartial' | 'fieldCreatedAt' | 'fieldUpdatedAt' | 'generateId'> {
46
46
  client: {
47
47
  auth: {
48
- refresh: () => Promise<boolean>;
49
- isAuthenticated: () => Promise<boolean>;
48
+ refresh: () => Promise<APIResult<boolean>>;
49
+ isAuthenticated: () => Promise<APIResult<boolean>>;
50
50
  };
51
51
  api: {
52
52
  queries: Record<string, (i: any) => Promise<any>>;
@@ -55,20 +55,33 @@ interface SyncedKeelConfiguration extends Omit<SyncedCrudPropsBase<any>, keyof S
55
55
  realtimePlugin?: KeelRealtimePlugin;
56
56
  as?: Exclude<CrudAsOption, 'value'>;
57
57
  enabled?: boolean;
58
- onError?: (params: APIResult<any>['error']) => void;
58
+ onError?: (params: {
59
+ type: 'create' | 'update' | 'delete';
60
+ params: SyncedSetParams<any>;
61
+ input: any;
62
+ action: string;
63
+ error: APIResult<any>['error'];
64
+ }) => void;
65
+ refreshAuth?: () => void | Promise<void>;
59
66
  }
60
- interface SyncedKeelPropsManyBase<TRemote, TLocal, AOption extends CrudAsOption> extends Omit<SyncedCrudPropsMany<TRemote, TLocal, AOption>, 'list'> {
67
+ interface SyncedKeelPropsManyBase<TRemote extends {
68
+ id: string;
69
+ }, TLocal, AOption extends CrudAsOption> extends Omit<SyncedCrudPropsMany<TRemote, TLocal, AOption>, 'list'> {
61
70
  first?: number;
62
71
  get?: never;
63
72
  }
64
- interface SyncedKeelPropsManyWhere<TRemote, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
73
+ interface SyncedKeelPropsManyWhere<TRemote extends {
74
+ id: string;
75
+ }, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
65
76
  list?: (params: KeelListParams<NoInfer<Where>>) => Promise<CrudResult<APIResult<{
66
77
  results: TRemote[];
67
78
  pageInfo: any;
68
79
  }>>>;
69
80
  where?: Where | (() => Where);
70
81
  }
71
- interface SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption extends CrudAsOption> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
82
+ interface SyncedKeelPropsManyNoWhere<TRemote extends {
83
+ id: string;
84
+ }, TLocal, AOption extends CrudAsOption> extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
72
85
  list?: (params: KeelListParams<{}>) => Promise<CrudResult<APIResult<{
73
86
  results: TRemote[];
74
87
  pageInfo: any;
@@ -76,8 +89,12 @@ interface SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption extends CrudAsOpti
76
89
  where?: never | {};
77
90
  }
78
91
  type HasAnyKeys<T> = keyof T extends never ? false : true;
79
- type SyncedKeelPropsMany<TRemote, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> = HasAnyKeys<Where> extends true ? SyncedKeelPropsManyWhere<TRemote, TLocal, AOption, Where> : SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption>;
80
- interface SyncedKeelPropsSingle<TRemote, TLocal> extends Omit<SyncedCrudPropsSingle<TRemote, TLocal>, 'get'> {
92
+ type SyncedKeelPropsMany<TRemote extends {
93
+ id: string;
94
+ }, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>> = HasAnyKeys<Where> extends true ? SyncedKeelPropsManyWhere<TRemote, TLocal, AOption, Where> : SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption>;
95
+ interface SyncedKeelPropsSingle<TRemote extends {
96
+ id: string;
97
+ }, TLocal> extends Omit<SyncedCrudPropsSingle<TRemote, TLocal>, 'get'> {
81
98
  get?: (params: KeelGetParams) => Promise<APIResult<TRemote>>;
82
99
  first?: never;
83
100
  where?: never;