@instantdb/core 0.22.56 → 0.22.57

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 (57) hide show
  1. package/dist/commonjs/Reactor.d.ts +5 -0
  2. package/dist/commonjs/Reactor.d.ts.map +1 -1
  3. package/dist/commonjs/Reactor.js +43 -5
  4. package/dist/commonjs/Reactor.js.map +1 -1
  5. package/dist/commonjs/SyncTable.d.ts +140 -0
  6. package/dist/commonjs/SyncTable.d.ts.map +1 -0
  7. package/dist/commonjs/SyncTable.js +538 -0
  8. package/dist/commonjs/SyncTable.js.map +1 -0
  9. package/dist/commonjs/index.d.ts +21 -1
  10. package/dist/commonjs/index.d.ts.map +1 -1
  11. package/dist/commonjs/index.js +19 -1
  12. package/dist/commonjs/index.js.map +1 -1
  13. package/dist/commonjs/instaql.d.ts +1 -0
  14. package/dist/commonjs/instaql.d.ts.map +1 -1
  15. package/dist/commonjs/instaql.js +9 -5
  16. package/dist/commonjs/instaql.js.map +1 -1
  17. package/dist/commonjs/store.d.ts +5 -0
  18. package/dist/commonjs/store.d.ts.map +1 -1
  19. package/dist/commonjs/store.js +11 -0
  20. package/dist/commonjs/store.js.map +1 -1
  21. package/dist/commonjs/utils/PersistedObject.d.ts +11 -5
  22. package/dist/commonjs/utils/PersistedObject.d.ts.map +1 -1
  23. package/dist/commonjs/utils/PersistedObject.js +12 -2
  24. package/dist/commonjs/utils/PersistedObject.js.map +1 -1
  25. package/dist/esm/Reactor.d.ts +5 -0
  26. package/dist/esm/Reactor.d.ts.map +1 -1
  27. package/dist/esm/Reactor.js +43 -5
  28. package/dist/esm/Reactor.js.map +1 -1
  29. package/dist/esm/SyncTable.d.ts +140 -0
  30. package/dist/esm/SyncTable.d.ts.map +1 -0
  31. package/dist/esm/SyncTable.js +498 -0
  32. package/dist/esm/SyncTable.js.map +1 -0
  33. package/dist/esm/index.d.ts +21 -1
  34. package/dist/esm/index.d.ts.map +1 -1
  35. package/dist/esm/index.js +19 -1
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/instaql.d.ts +1 -0
  38. package/dist/esm/instaql.d.ts.map +1 -1
  39. package/dist/esm/instaql.js +8 -5
  40. package/dist/esm/instaql.js.map +1 -1
  41. package/dist/esm/store.d.ts +5 -0
  42. package/dist/esm/store.d.ts.map +1 -1
  43. package/dist/esm/store.js +9 -3
  44. package/dist/esm/store.js.map +1 -1
  45. package/dist/esm/utils/PersistedObject.d.ts +11 -5
  46. package/dist/esm/utils/PersistedObject.d.ts.map +1 -1
  47. package/dist/esm/utils/PersistedObject.js +12 -2
  48. package/dist/esm/utils/PersistedObject.js.map +1 -1
  49. package/dist/standalone/index.js +1579 -1135
  50. package/dist/standalone/index.umd.cjs +3 -3
  51. package/package.json +2 -2
  52. package/src/Reactor.js +60 -4
  53. package/src/SyncTable.ts +821 -0
  54. package/src/index.ts +48 -0
  55. package/src/instaql.js +11 -5
  56. package/src/store.js +11 -3
  57. package/src/utils/PersistedObject.ts +15 -6
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  import weakHash from './utils/weakHash.js';
11
11
  import id from './utils/uuid.js';
12
12
  import IndexedDBStorage from './IndexedDBStorage.ts';
13
+ import { coerceToDate } from './utils/dates.js';
13
14
  import WindowNetworkListener from './WindowNetworkListener.js';
14
15
  import { i } from './schema.js';
15
16
  import { createDevtool } from './devtool.js';
@@ -111,11 +112,25 @@ import type {
111
112
  import { InstantAPIError, type InstantIssue } from './utils/fetch.js';
112
113
  import { InstantError } from './InstantError.ts';
113
114
  import { EventSourceType } from './Connection.ts';
115
+ import { CallbackEventType as SyncTableCallbackEventType } from './SyncTable.ts';
116
+ import type {
117
+ SyncTableCallback,
118
+ CallbackEvent as SyncTableCallbackEvent,
119
+ InitialSyncBatch as SyncTableInitialSyncBatch,
120
+ InitialSyncComplete as SyncTableInitialSyncComplete,
121
+ SyncTransaction as SyncTableSyncTransaction,
122
+ LoadFromStorage as SyncTableLoadFromStorage,
123
+ SetupError as SyncTableSetupError,
124
+ } from './SyncTable.ts';
114
125
 
115
126
  const defaultOpenDevtool = true;
116
127
 
117
128
  // types
118
129
 
130
+ type ExactlyOne<T> = {
131
+ [K in keyof T]: Pick<T, K> & Partial<Record<Exclude<keyof T, K>, never>>;
132
+ }[keyof T];
133
+
119
134
  export type Config = {
120
135
  appId: string;
121
136
  websocketURI?: string;
@@ -710,6 +725,26 @@ class InstantCoreDatabase<
710
725
  }> {
711
726
  return this._reactor.queryOnce(query, opts);
712
727
  }
728
+
729
+ /**
730
+ * @deprecated This is an experimental function that is not yet ready for production use.
731
+ * Use this function to sync an entire namespace.
732
+ * It has many limitations that will be removed in the future:
733
+ * 1. Must be used with an admin token
734
+ * 2. Does not support permissions
735
+ * 3. Does not support where clauses
736
+ * 4. Does not support links
737
+ * It also does not support multiple top-level namespaces. For example,
738
+ * {posts: {}, users: {}} is invalid. Only `posts` or `users` is allowed, but not both.
739
+ */
740
+ _syncTableExperimental<Q extends ValidQuery<Q, Schema>>(
741
+ query: ExactlyOne<Q>,
742
+ cb: SyncTableCallback<Schema, Q, UseDates>,
743
+ ): (
744
+ opts?: { keepSubscription: boolean | null | undefined } | null | undefined,
745
+ ) => void {
746
+ return this._reactor.subscribeTable(query, cb);
747
+ }
713
748
  }
714
749
 
715
750
  function schemaHash(schema?: InstantSchemaDef<any, any, any>): string {
@@ -862,6 +897,7 @@ export {
862
897
  getOps,
863
898
  coerceQuery,
864
899
  weakHash,
900
+ coerceToDate,
865
901
  IndexedDBStorage,
866
902
  WindowNetworkListener,
867
903
  InstantCoreDatabase,
@@ -870,6 +906,9 @@ export {
870
906
  version,
871
907
  InstantError,
872
908
 
909
+ // sync table enums
910
+ SyncTableCallbackEventType,
911
+
873
912
  // og types
874
913
  type IDatabase,
875
914
  type RoomSchemaShape,
@@ -963,6 +1002,15 @@ export {
963
1002
  // SSE
964
1003
  type EventSourceType,
965
1004
 
1005
+ // sync table types
1006
+ type SyncTableCallback,
1007
+ type SyncTableCallbackEvent,
1008
+ type SyncTableInitialSyncBatch,
1009
+ type SyncTableInitialSyncComplete,
1010
+ type SyncTableSyncTransaction,
1011
+ type SyncTableLoadFromStorage,
1012
+ type SyncTableSetupError,
1013
+
966
1014
  // error types
967
1015
  type InstantIssue,
968
1016
  };
package/src/instaql.js CHANGED
@@ -497,7 +497,7 @@ function compareDisparateValues(a, b, dataType) {
497
497
  return -1;
498
498
  }
499
499
 
500
- function compareOrder([id_a, v_a], [id_b, v_b], dataType) {
500
+ export function compareOrder(id_a, v_a, id_b, v_b, dataType) {
501
501
  if (v_a === v_b || (v_a == null && v_b == null)) {
502
502
  return uuidCompare(id_a, id_b);
503
503
  }
@@ -512,6 +512,10 @@ function compareOrder([id_a, v_a], [id_b, v_b], dataType) {
512
512
  return compareDisparateValues(v_a, v_b, dataType);
513
513
  }
514
514
 
515
+ function compareOrderTriples([id_a, v_a], [id_b, v_b], dataType) {
516
+ return compareOrder(id_a, v_a, id_b, v_b, dataType);
517
+ }
518
+
515
519
  function comparableDate(x) {
516
520
  if (x == null) {
517
521
  return x;
@@ -523,14 +527,16 @@ function isBefore(startCursor, orderAttr, direction, idVec) {
523
527
  const [c_e, _c_a, c_v, c_t] = startCursor;
524
528
  const compareVal = direction === 'desc' ? 1 : -1;
525
529
  if (orderAttr['forward-identity']?.[2] === 'id') {
526
- return compareOrder(idVec, [c_e, c_t], null) === compareVal;
530
+ return compareOrderTriples(idVec, [c_e, c_t], null) === compareVal;
527
531
  }
528
532
  const [e, v] = idVec;
529
533
  const dataType = orderAttr['checked-data-type'];
530
534
  const v_new = dataType === 'date' ? comparableDate(v) : v;
531
535
  const c_v_new = dataType === 'date' ? comparableDate(c_v) : c_v;
532
536
 
533
- return compareOrder([e, v_new], [c_e, c_v_new], dataType) === compareVal;
537
+ return (
538
+ compareOrderTriples([e, v_new], [c_e, c_v_new], dataType) === compareVal
539
+ );
534
540
  }
535
541
 
536
542
  function orderAttrFromCursor(store, cursor) {
@@ -605,10 +611,10 @@ function runDataloadAndReturnObjects(store, { etype, pageInfo, dq, form }) {
605
611
  idVecs.sort(
606
612
  direction === 'asc'
607
613
  ? function compareIdVecs(a, b) {
608
- return compareOrder(a, b, orderAttr?.['checked-data-type']);
614
+ return compareOrderTriples(a, b, orderAttr?.['checked-data-type']);
609
615
  }
610
616
  : function compareIdVecs(a, b) {
611
- return compareOrder(b, a, orderAttr?.['checked-data-type']);
617
+ return compareOrderTriples(b, a, orderAttr?.['checked-data-type']);
612
618
  },
613
619
  );
614
620
 
package/src/store.js CHANGED
@@ -18,7 +18,7 @@ function getAttr(attrs, attrId) {
18
18
  return attrs[attrId];
19
19
  }
20
20
 
21
- function getInMap(obj, path) {
21
+ export function getInMap(obj, path) {
22
22
  return path.reduce((acc, key) => acc && acc.get(key), obj);
23
23
  }
24
24
 
@@ -126,6 +126,14 @@ export function fromJSON(storeJSON) {
126
126
  );
127
127
  }
128
128
 
129
+ export function hasTriple(store, [e, a, v]) {
130
+ return getInMap(store.eav, [e, a, v]) !== undefined;
131
+ }
132
+
133
+ export function hasEntity(store, e) {
134
+ return getInMap(store.eav, [e]) !== undefined;
135
+ }
136
+
129
137
  function resetAttrIndexes(store) {
130
138
  store.attrIndexes = createAttrIndexes(store.attrs);
131
139
  }
@@ -205,7 +213,7 @@ function resolveLookupRefs(store, triple) {
205
213
  }
206
214
  }
207
215
 
208
- function retractTriple(store, rawTriple) {
216
+ export function retractTriple(store, rawTriple) {
209
217
  const triple = resolveLookupRefs(store, rawTriple);
210
218
  if (!triple) {
211
219
  return;
@@ -256,7 +264,7 @@ function getCreatedAt(store, attr, triple) {
256
264
  return createdAt || Date.now() * 10 + _seed++;
257
265
  }
258
266
 
259
- function addTriple(store, rawTriple) {
267
+ export function addTriple(store, rawTriple) {
260
268
  const triple = resolveLookupRefs(store, rawTriple);
261
269
  if (!triple) {
262
270
  return;
@@ -27,12 +27,12 @@ export class PersistedObject<T> {
27
27
  _subs = [];
28
28
  _persister: Storage;
29
29
  _key: string;
30
- _onMerge: (fromStorage: T, inMemoryValue: T) => any;
30
+ _onMerge: (fromStorage: T, inMemoryValue: T) => T | void;
31
31
  _loadedCbs: Array<() => void>;
32
32
  _isLoading: boolean;
33
33
  currentValue: T;
34
- serialize: (T) => any;
35
- parse: (any) => T;
34
+ serialize: (input: T) => any;
35
+ parse: (input: any) => T;
36
36
  _saveThrottleMs: number;
37
37
  _idleCallbackMaxWaitMs: number;
38
38
  _pendingSaveCbs: Array<() => void>;
@@ -43,7 +43,12 @@ export class PersistedObject<T> {
43
43
  persister: Storage,
44
44
  key: string,
45
45
  defaultValue: T,
46
- onMerge: (fromStorage: T, inMemoryValue: T) => any,
46
+ /**
47
+ * Merges data from storage with in-memory value on load.
48
+ * If a value is returned from onMerge, that value that will
49
+ * become the current value.
50
+ */
51
+ onMerge: (fromStorage: T, inMemoryValue: T) => T | void,
47
52
  serialize = (x: T): any => {
48
53
  return x;
49
54
  },
@@ -84,7 +89,10 @@ export class PersistedObject<T> {
84
89
  const fromStorage = await this._getFromStorage();
85
90
  this._isLoading = false;
86
91
 
87
- this._onMerge(fromStorage, this.currentValue);
92
+ const mergeResult = this._onMerge(fromStorage, this.currentValue);
93
+ if (mergeResult) {
94
+ this.currentValue = mergeResult;
95
+ }
88
96
  for (const cb of this._loadedCbs) {
89
97
  cb();
90
98
  }
@@ -149,7 +157,7 @@ export class PersistedObject<T> {
149
157
  }, this._saveThrottleMs);
150
158
  }
151
159
 
152
- set(f, cb) {
160
+ set(f: (prev: T) => T, cb?: () => void): T {
153
161
  this._version++;
154
162
  this.currentValue = f(this.currentValue);
155
163
  if (this._isLoading) {
@@ -160,6 +168,7 @@ export class PersistedObject<T> {
160
168
  for (const sub of this._subs) {
161
169
  sub(this.currentValue);
162
170
  }
171
+ return this.currentValue;
163
172
  }
164
173
 
165
174
  subscribe(cb) {