@instantdb/core 0.22.88 → 0.22.89-experimental.drewh-fix-export.20277749804.1

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 (65) hide show
  1. package/__tests__/src/Reactor.test.js +18 -11
  2. package/__tests__/src/{datalog.test.js → datalog.test.ts} +17 -5
  3. package/__tests__/src/{instaml.test.js → instaml.test.ts} +183 -119
  4. package/__tests__/src/instaql.bench.ts +34 -0
  5. package/__tests__/src/{instaql.test.js → instaql.test.ts} +342 -455
  6. package/__tests__/src/instaqlInference.test.js +13 -9
  7. package/__tests__/src/{store.test.js → store.test.ts} +215 -212
  8. package/dist/commonjs/Reactor.d.ts +23 -6
  9. package/dist/commonjs/Reactor.d.ts.map +1 -1
  10. package/dist/commonjs/Reactor.js +110 -45
  11. package/dist/commonjs/Reactor.js.map +1 -1
  12. package/dist/commonjs/SyncTable.d.ts +4 -1
  13. package/dist/commonjs/SyncTable.d.ts.map +1 -1
  14. package/dist/commonjs/SyncTable.js +35 -37
  15. package/dist/commonjs/SyncTable.js.map +1 -1
  16. package/dist/commonjs/instaml.d.ts +17 -4
  17. package/dist/commonjs/instaml.d.ts.map +1 -1
  18. package/dist/commonjs/instaml.js +115 -82
  19. package/dist/commonjs/instaml.js.map +1 -1
  20. package/dist/commonjs/instaql.d.ts +4 -3
  21. package/dist/commonjs/instaql.d.ts.map +1 -1
  22. package/dist/commonjs/instaql.js +65 -63
  23. package/dist/commonjs/instaql.js.map +1 -1
  24. package/dist/commonjs/reactorTypes.d.ts +29 -0
  25. package/dist/commonjs/reactorTypes.d.ts.map +1 -0
  26. package/dist/commonjs/reactorTypes.js +3 -0
  27. package/dist/commonjs/reactorTypes.js.map +1 -0
  28. package/dist/commonjs/store.d.ts +67 -25
  29. package/dist/commonjs/store.d.ts.map +1 -1
  30. package/dist/commonjs/store.js +177 -81
  31. package/dist/commonjs/store.js.map +1 -1
  32. package/dist/esm/Reactor.d.ts +23 -6
  33. package/dist/esm/Reactor.d.ts.map +1 -1
  34. package/dist/esm/Reactor.js +111 -46
  35. package/dist/esm/Reactor.js.map +1 -1
  36. package/dist/esm/SyncTable.d.ts +4 -1
  37. package/dist/esm/SyncTable.d.ts.map +1 -1
  38. package/dist/esm/SyncTable.js +35 -37
  39. package/dist/esm/SyncTable.js.map +1 -1
  40. package/dist/esm/instaml.d.ts +17 -4
  41. package/dist/esm/instaml.d.ts.map +1 -1
  42. package/dist/esm/instaml.js +112 -77
  43. package/dist/esm/instaml.js.map +1 -1
  44. package/dist/esm/instaql.d.ts +4 -3
  45. package/dist/esm/instaql.d.ts.map +1 -1
  46. package/dist/esm/instaql.js +65 -63
  47. package/dist/esm/instaql.js.map +1 -1
  48. package/dist/esm/reactorTypes.d.ts +29 -0
  49. package/dist/esm/reactorTypes.d.ts.map +1 -0
  50. package/dist/esm/reactorTypes.js +2 -0
  51. package/dist/esm/reactorTypes.js.map +1 -0
  52. package/dist/esm/store.d.ts +67 -25
  53. package/dist/esm/store.d.ts.map +1 -1
  54. package/dist/esm/store.js +174 -81
  55. package/dist/esm/store.js.map +1 -1
  56. package/dist/standalone/index.js +1605 -1415
  57. package/dist/standalone/index.umd.cjs +3 -3
  58. package/package.json +2 -2
  59. package/src/Reactor.js +152 -75
  60. package/src/SyncTable.ts +85 -45
  61. package/src/{instaml.js → instaml.ts} +201 -96
  62. package/src/instaql.ts +88 -62
  63. package/src/reactorTypes.ts +32 -0
  64. package/src/store.ts +257 -101
  65. package/__tests__/src/instaql.bench.js +0 -29
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instantdb/core",
3
- "version": "0.22.88",
3
+ "version": "0.22.89-experimental.drewh-fix-export.20277749804.1",
4
4
  "description": "Instant's core local abstraction",
5
5
  "homepage": "https://github.com/instantdb/instant/tree/main/client/packages/core",
6
6
  "repository": {
@@ -53,7 +53,7 @@
53
53
  "dependencies": {
54
54
  "mutative": "^1.0.10",
55
55
  "uuid": "^11.1.0",
56
- "@instantdb/version": "0.22.88"
56
+ "@instantdb/version": "0.22.89-experimental.drewh-fix-export.20277749804.1"
57
57
  },
58
58
  "scripts": {
59
59
  "test": "vitest",
package/src/Reactor.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // @ts-check
2
2
  import weakHash from './utils/weakHash.ts';
3
3
  import instaql from './instaql.ts';
4
- import * as instaml from './instaml.js';
4
+ import * as instaml from './instaml.ts';
5
5
  import * as s from './store.ts';
6
6
  import uuid from './utils/uuid.ts';
7
7
  import IndexedDBStorage from './IndexedDBStorage.ts';
@@ -36,6 +36,8 @@ import { SyncTable } from './SyncTable.ts';
36
36
  /** @typedef {import('./Connection.ts').Connection} Connection */
37
37
  /** @typedef {import('./Connection.ts').TransportType} TransportType */
38
38
  /** @typedef {import('./Connection.ts').EventSourceConstructor} EventSourceConstructor */
39
+ /** @typedef {import('./reactorTypes.ts').QuerySub} QuerySub */
40
+ /** @typedef {import('./reactorTypes.ts').QuerySubInStorage} QuerySubInStorage */
39
41
 
40
42
  const STATUS = {
41
43
  CONNECTING: 'connecting',
@@ -107,27 +109,52 @@ const ignoreLogging = {
107
109
  'patch-presence': true,
108
110
  };
109
111
 
112
+ /**
113
+ * @param {QuerySubInStorage} x
114
+ * @param {boolean | null} useDateObjects
115
+ * @returns {QuerySub}
116
+ */
110
117
  function querySubFromStorage(x, useDateObjects) {
111
118
  const v = typeof x === 'string' ? JSON.parse(x) : x;
112
119
 
113
120
  if (v?.result?.store) {
114
- const storeJSON = v.result.store;
115
- v.result.store = s.fromJSON({
116
- ...storeJSON,
117
- useDateObjects: useDateObjects,
118
- });
121
+ const attrsStore = s.attrsStoreFromJSON(
122
+ v.result.attrsStore,
123
+ v.result.store,
124
+ );
125
+ if (attrsStore) {
126
+ const storeJSON = v.result.store;
127
+ v.result.store = s.fromJSON(attrsStore, {
128
+ ...storeJSON,
129
+ useDateObjects: useDateObjects,
130
+ });
131
+ v.result.attrsStore = attrsStore;
132
+ }
119
133
  }
120
134
 
121
135
  return v;
122
136
  }
123
137
 
138
+ /**
139
+ *
140
+ * @param {string} _key
141
+ * @param {QuerySub} sub
142
+ * @returns QuerySubInStorage
143
+ */
124
144
  function querySubToStorage(_key, sub) {
125
- const jsonSub = { ...sub };
126
- if (sub.result?.store) {
127
- jsonSub.result = {
128
- ...sub.result,
129
- store: s.toJSON(sub.result.store),
145
+ const { result, ...rest } = sub;
146
+ const jsonSub = /** @type {import('./reactorTypes.ts').QuerySubInStorage} */ (
147
+ rest
148
+ );
149
+ if (result) {
150
+ /** @type {import('./reactorTypes.ts').QuerySubResultInStorage} */
151
+ const jsonResult = {
152
+ ...result,
153
+ store: s.toJSON(result.store),
154
+ attrsStore: result.attrsStore.toJSON(),
130
155
  };
156
+
157
+ jsonSub.result = jsonResult;
131
158
  }
132
159
  return jsonSub;
133
160
  }
@@ -176,12 +203,13 @@ function sortedMutationEntries(entries) {
176
203
  * @template {import('./presence.ts').RoomSchemaShape} [RoomSchema = {}]
177
204
  */
178
205
  export default class Reactor {
206
+ /** @type {s.AttrsStore | undefined} */
179
207
  attrs;
180
208
  _isOnline = true;
181
209
  _isShutdown = false;
182
210
  status = STATUS.CONNECTING;
183
211
 
184
- /** @type {PersistedObject} */
212
+ /** @type {PersistedObject<string, QuerySub, QuerySubInStorage>} */
185
213
  querySubs;
186
214
 
187
215
  /** @type {PersistedObject} */
@@ -306,14 +334,15 @@ export default class Reactor {
306
334
  useDateObjects: this.config.useDateObjects,
307
335
  },
308
336
  this._log,
309
- (triples) =>
310
- s.createStore(
311
- this.attrs,
337
+ (triples) => {
338
+ return s.createStore(
339
+ this.ensureAttrs(),
312
340
  triples,
313
341
  this.config.enableCardinalityInference,
314
- this._linkIndex,
315
342
  this.config.useDateObjects,
316
- ),
343
+ );
344
+ },
345
+ () => this.ensureAttrs(),
317
346
  );
318
347
 
319
348
  this._oauthCallbackResponse = this._oauthLoginInit();
@@ -353,6 +382,13 @@ export default class Reactor {
353
382
  }
354
383
  }
355
384
 
385
+ ensureAttrs() {
386
+ if (!this.attrs) {
387
+ throw new Error('attrs have not loaded.');
388
+ }
389
+ return this.attrs;
390
+ }
391
+
356
392
  updateSchema(schema) {
357
393
  this.config = {
358
394
  ...this.config,
@@ -383,7 +419,7 @@ export default class Reactor {
383
419
  serialize: querySubToStorage,
384
420
  parse: (_key, x) => querySubFromStorage(x, this.config.useDateObjects),
385
421
  // objectSize
386
- objectSize: (x) => x.result?.store?.triples?.length ?? 0,
422
+ objectSize: (x) => x?.result?.store?.triples?.length ?? 0,
387
423
  logger: this._log,
388
424
  preloadEntryCount: 10,
389
425
  gc: {
@@ -552,13 +588,14 @@ export default class Reactor {
552
588
  const pageInfo = result?.[0]?.data?.['page-info'];
553
589
  const aggregate = result?.[0]?.data?.['aggregate'];
554
590
  const triples = extractTriples(result);
591
+ const attrsStore = this.ensureAttrs();
555
592
  const store = s.createStore(
556
- this.attrs,
593
+ attrsStore,
557
594
  triples,
558
595
  enableCardinalityInference,
559
- this._linkIndex,
560
596
  this.config.useDateObjects,
561
597
  );
598
+
562
599
  this.querySubs.updateInPlace((prev) => {
563
600
  if (!prev[hash]) {
564
601
  this._log.info('Missing value in querySubs', { hash, q });
@@ -566,6 +603,7 @@ export default class Reactor {
566
603
  }
567
604
  prev[hash].result = {
568
605
  store,
606
+ attrsStore,
569
607
  pageInfo,
570
608
  aggregate,
571
609
  processedTxId: msg['processed-tx-id'],
@@ -603,7 +641,7 @@ export default class Reactor {
603
641
  this._cleanupPendingMutationsTimeout();
604
642
 
605
643
  const rewrittenMutations = this._rewriteMutations(
606
- this.attrs,
644
+ this.ensureAttrs(),
607
645
  this._pendingMutations(),
608
646
  processedTxId,
609
647
  );
@@ -624,32 +662,49 @@ export default class Reactor {
624
662
  const result = x['instaql-result'];
625
663
  const hash = weakHash(q);
626
664
  const triples = extractTriples(result);
665
+ const attrsStore = this.ensureAttrs();
627
666
  const store = s.createStore(
628
- this.attrs,
667
+ attrsStore,
629
668
  triples,
630
669
  enableCardinalityInference,
631
- this._linkIndex,
632
670
  this.config.useDateObjects,
633
671
  );
634
- const newStore = this._applyOptimisticUpdates(
635
- store,
636
- mutations,
637
- processedTxId,
638
- );
672
+ const { store: newStore, attrsStore: newAttrsStore } =
673
+ this._applyOptimisticUpdates(
674
+ store,
675
+ attrsStore,
676
+ mutations,
677
+ processedTxId,
678
+ );
639
679
  const pageInfo = result?.[0]?.data?.['page-info'];
640
680
  const aggregate = result?.[0]?.data?.['aggregate'];
641
- return { q, hash, store: newStore, pageInfo, aggregate };
681
+ return {
682
+ q,
683
+ hash,
684
+ store: newStore,
685
+ attrsStore: newAttrsStore,
686
+ pageInfo,
687
+ aggregate,
688
+ };
642
689
  });
643
690
 
644
- updates.forEach(({ hash, q, store, pageInfo, aggregate }) => {
645
- this.querySubs.updateInPlace((prev) => {
646
- if (!prev[hash]) {
647
- this._log.error('Missing value in querySubs', { hash, q });
648
- return;
649
- }
650
- prev[hash].result = { store, pageInfo, aggregate, processedTxId };
651
- });
652
- });
691
+ updates.forEach(
692
+ ({ hash, q, store, attrsStore, pageInfo, aggregate }) => {
693
+ this.querySubs.updateInPlace((prev) => {
694
+ if (!prev[hash]) {
695
+ this._log.error('Missing value in querySubs', { hash, q });
696
+ return;
697
+ }
698
+ prev[hash].result = {
699
+ store,
700
+ attrsStore,
701
+ pageInfo,
702
+ aggregate,
703
+ processedTxId,
704
+ };
705
+ });
706
+ },
707
+ );
653
708
 
654
709
  this._cleanupPendingMutationsQueries();
655
710
 
@@ -664,7 +719,7 @@ export default class Reactor {
664
719
  this._inFlightMutationEventIds.delete(eventId);
665
720
 
666
721
  const muts = this._rewriteMutations(
667
- this.attrs,
722
+ this.ensureAttrs(),
668
723
  this._pendingMutations(),
669
724
  );
670
725
  const prevMutation = muts.get(eventId);
@@ -681,12 +736,17 @@ export default class Reactor {
681
736
  });
682
737
  });
683
738
 
684
- const newAttrs = prevMutation['tx-steps']
685
- .filter(([action, ..._args]) => action === 'add-attr')
686
- .map(([_action, attr]) => attr)
687
- .concat(Object.values(this.attrs));
688
-
689
- this._setAttrs(newAttrs);
739
+ const newAttrs = [];
740
+ for (const step of prevMutation['tx-steps']) {
741
+ if (step[0] === 'add-attr') {
742
+ const attr = step[1];
743
+ newAttrs.push(attr);
744
+ }
745
+ }
746
+ if (newAttrs.length) {
747
+ const existingAttrs = Object.values(this.ensureAttrs().attrs);
748
+ this._setAttrs([...existingAttrs, ...newAttrs]);
749
+ }
690
750
 
691
751
  this._finishTransaction('synced', eventId);
692
752
 
@@ -870,10 +930,13 @@ export default class Reactor {
870
930
  }
871
931
 
872
932
  _setAttrs(attrs) {
873
- this.attrs = attrs.reduce((acc, attr) => {
874
- acc[attr.id] = attr;
875
- return acc;
876
- }, {});
933
+ this.attrs = new s.AttrsStoreClass(
934
+ attrs.reduce((acc, attr) => {
935
+ acc[attr.id] = attr;
936
+ return acc;
937
+ }, {}),
938
+ this._linkIndex,
939
+ );
877
940
 
878
941
  this.notifyAttrsSubs();
879
942
  }
@@ -1022,17 +1085,23 @@ export default class Reactor {
1022
1085
  // We remove `add-attr` commands for attrs that already exist.
1023
1086
  // We update `add-triple` and `retract-triple` commands to use the
1024
1087
  // server attr-ids.
1088
+ /**
1089
+ *
1090
+ * @param {s.AttrsStore} attrs
1091
+ * @param {any} muts
1092
+ * @param {number} [processedTxId]
1093
+ */
1025
1094
  _rewriteMutations(attrs, muts, processedTxId) {
1026
1095
  if (!attrs) return muts;
1027
1096
  if (!muts) return new Map();
1028
1097
  const findExistingAttr = (attr) => {
1029
1098
  const [_, etype, label] = attr['forward-identity'];
1030
- const existing = instaml.getAttrByFwdIdentName(attrs, etype, label);
1099
+ const existing = s.getAttrByFwdIdentName(attrs, etype, label);
1031
1100
  return existing;
1032
1101
  };
1033
1102
  const findReverseAttr = (attr) => {
1034
1103
  const [_, etype, label] = attr['forward-identity'];
1035
- const revAttr = instaml.getAttrByReverseIdentName(attrs, etype, label);
1104
+ const revAttr = s.getAttrByReverseIdentName(attrs, etype, label);
1036
1105
  return revAttr;
1037
1106
  };
1038
1107
  const mapping = { attrIdMap: {}, refSwapAttrIds: new Set() };
@@ -1109,6 +1178,9 @@ export default class Reactor {
1109
1178
  // ---------------------------
1110
1179
  // Transact
1111
1180
 
1181
+ /**
1182
+ * @returns {s.AttrsStore}
1183
+ */
1112
1184
  optimisticAttrs() {
1113
1185
  const pendingMutationSteps = [...this._pendingMutations().values()] // hack due to Map()
1114
1186
  .flatMap((x) => x['tx-steps']);
@@ -1126,23 +1198,26 @@ export default class Reactor {
1126
1198
  } else if (
1127
1199
  _action === 'update-attr' &&
1128
1200
  attr.id &&
1129
- this.attrs?.[attr.id]
1201
+ this.attrs?.getAttr(attr.id)
1130
1202
  ) {
1131
- const fullAttr = { ...this.attrs[attr.id], ...attr };
1203
+ const fullAttr = { ...this.attrs.getAttr(attr.id), ...attr };
1132
1204
  pendingAttrs.push(fullAttr);
1133
1205
  }
1134
1206
  }
1135
1207
 
1136
- const attrsWithoutDeleted = [
1137
- ...Object.values(this.attrs || {}),
1138
- ...pendingAttrs,
1139
- ].filter((a) => !deletedAttrIds.has(a.id));
1208
+ if (!deletedAttrIds.size && !pendingAttrs.length) {
1209
+ return this.attrs || new s.AttrsStoreClass({}, this._linkIndex);
1210
+ }
1140
1211
 
1141
- const attrsRecord = Object.fromEntries(
1142
- attrsWithoutDeleted.map((a) => [a.id, a]),
1143
- );
1212
+ const attrs = { ...(this.attrs?.attrs || {}) };
1213
+ for (const attr of pendingAttrs) {
1214
+ attrs[attr.id] = attr;
1215
+ }
1216
+ for (const id of deletedAttrIds) {
1217
+ delete attrs[id];
1218
+ }
1144
1219
 
1145
- return attrsRecord;
1220
+ return new s.AttrsStoreClass(attrs, this._linkIndex);
1146
1221
  }
1147
1222
 
1148
1223
  /** Runs instaql on a query and a store */
@@ -1170,28 +1245,30 @@ export default class Reactor {
1170
1245
  return cached;
1171
1246
  }
1172
1247
 
1173
- const { store, pageInfo, aggregate, processedTxId } = result;
1248
+ const { store, attrsStore, pageInfo, aggregate, processedTxId } = result;
1174
1249
  const mutations = this._rewriteMutationsSorted(
1175
- store.attrs,
1250
+ attrsStore,
1176
1251
  pendingMutations,
1177
1252
  );
1178
- const newStore = this._applyOptimisticUpdates(
1179
- store,
1180
- mutations,
1181
- processedTxId,
1253
+ const { store: newStore, attrsStore: newAttrsStore } =
1254
+ this._applyOptimisticUpdates(store, attrsStore, mutations, processedTxId);
1255
+ const resp = instaql(
1256
+ { store: newStore, attrsStore: newAttrsStore, pageInfo, aggregate },
1257
+ q,
1182
1258
  );
1183
- const resp = instaql({ store: newStore, pageInfo, aggregate }, q);
1184
1259
 
1185
1260
  return { data: resp, querySubVersion, pendingMutationsVersion };
1186
1261
  }
1187
1262
 
1188
- _applyOptimisticUpdates(store, mutations, processedTxId) {
1263
+ _applyOptimisticUpdates(store, attrsStore, mutations, processedTxId) {
1189
1264
  for (const [_, mut] of mutations) {
1190
1265
  if (!mut['tx-id'] || (processedTxId && mut['tx-id'] > processedTxId)) {
1191
- store = s.transact(store, mut['tx-steps']);
1266
+ const result = s.transact(store, attrsStore, mut['tx-steps']);
1267
+ store = result.store;
1268
+ attrsStore = result.attrsStore;
1192
1269
  }
1193
1270
  }
1194
- return store;
1271
+ return { store, attrsStore };
1195
1272
  }
1196
1273
 
1197
1274
  /** Re-run instaql and call all callbacks with new data */
@@ -1248,7 +1325,7 @@ export default class Reactor {
1248
1325
  try {
1249
1326
  const txSteps = instaml.transform(
1250
1327
  {
1251
- attrs: this.optimisticAttrs(),
1328
+ attrsStore: this.optimisticAttrs(),
1252
1329
  schema: this.config.schema,
1253
1330
  stores: Object.values(this.querySubs.currentValue).map(
1254
1331
  (sub) => sub?.result?.store,
@@ -1366,7 +1443,7 @@ export default class Reactor {
1366
1443
  });
1367
1444
 
1368
1445
  const muts = this._rewriteMutationsSorted(
1369
- this.attrs,
1446
+ this.ensureAttrs(),
1370
1447
  this._pendingMutations(),
1371
1448
  );
1372
1449
  muts.forEach(([eventId, mut]) => {
@@ -1822,7 +1899,7 @@ export default class Reactor {
1822
1899
  this.attrsCbs.push(cb);
1823
1900
 
1824
1901
  if (this.attrs) {
1825
- cb(this.attrs);
1902
+ cb(this.attrs.attrs);
1826
1903
  }
1827
1904
 
1828
1905
  return () => {
@@ -1841,7 +1918,7 @@ export default class Reactor {
1841
1918
  notifyAttrsSubs() {
1842
1919
  if (!this.attrs) return;
1843
1920
  const oas = this.optimisticAttrs();
1844
- this.attrsCbs.forEach((cb) => cb(oas));
1921
+ this.attrsCbs.forEach((cb) => cb(oas.attrs));
1845
1922
  }
1846
1923
 
1847
1924
  notifyConnectionStatusSubs(status) {