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