@instantdb/core 0.22.86-experimental.separate-attrs.20122276424.1 → 0.22.86-experimental.split-store.20183617880.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} +188 -210
  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 +105 -76
  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 +170 -70
  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 +102 -71
  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 +167 -70
  55. package/dist/esm/store.js.map +1 -1
  56. package/dist/standalone/index.js +1580 -1392
  57. package/dist/standalone/index.umd.cjs +3 -3
  58. package/package.json +2 -2
  59. package/src/Reactor.js +154 -77
  60. package/src/SyncTable.ts +85 -45
  61. package/src/{instaml.js → instaml.ts} +196 -95
  62. package/src/instaql.ts +88 -62
  63. package/src/reactorTypes.ts +32 -0
  64. package/src/store.ts +248 -90
  65. package/__tests__/src/instaql.bench.js +0 -29
@@ -21,8 +21,8 @@ var __rest = (this && this.__rest) || function (s, e) {
21
21
  // @ts-check
22
22
  import weakHash from "./utils/weakHash.js";
23
23
  import instaql from "./instaql.js";
24
- import * as instaml from './instaml.js';
25
- import * as s from "./store.js";
24
+ import * as instaml from "./instaml.js";
25
+ import * as sts from "./store.js";
26
26
  import uuid from "./utils/uuid.js";
27
27
  import IndexedDBStorage from "./IndexedDBStorage.js";
28
28
  import WindowNetworkListener from './WindowNetworkListener.js';
@@ -49,6 +49,8 @@ import { SyncTable } from "./SyncTable.js";
49
49
  /** @typedef {import('./Connection.ts').Connection} Connection */
50
50
  /** @typedef {import('./Connection.ts').TransportType} TransportType */
51
51
  /** @typedef {import('./Connection.ts').EventSourceConstructor} EventSourceConstructor */
52
+ /** @typedef {import('./reactorTypes.ts').QuerySub} QuerySub */
53
+ /** @typedef {import('./reactorTypes.ts').QuerySubInStorage} QuerySubInStorage */
52
54
  const STATUS = {
53
55
  CONNECTING: 'connecting',
54
56
  OPENED: 'opened',
@@ -101,20 +103,37 @@ const ignoreLogging = {
101
103
  'refresh-presence': true,
102
104
  'patch-presence': true,
103
105
  };
106
+ /**
107
+ * @param {QuerySubInStorage} x
108
+ * @param {boolean | null} useDateObjects
109
+ * @returns {QuerySub}
110
+ */
104
111
  function querySubFromStorage(x, useDateObjects) {
105
112
  var _a;
106
113
  const v = typeof x === 'string' ? JSON.parse(x) : x;
107
114
  if ((_a = v === null || v === void 0 ? void 0 : v.result) === null || _a === void 0 ? void 0 : _a.store) {
108
- const storeJSON = v.result.store;
109
- v.result.store = s.fromJSON(Object.assign(Object.assign({}, storeJSON), { useDateObjects: useDateObjects }));
115
+ const attrsStore = sts.attrsStoreFromJSON(v.result.attrsStore, v.result.store);
116
+ if (attrsStore) {
117
+ const storeJSON = v.result.store;
118
+ v.result.store = sts.fromJSON(attrsStore, Object.assign(Object.assign({}, storeJSON), { useDateObjects: useDateObjects }));
119
+ v.result.attrsStore = attrsStore;
120
+ }
110
121
  }
111
122
  return v;
112
123
  }
124
+ /**
125
+ *
126
+ * @param {string} _key
127
+ * @param {QuerySub} sub
128
+ * @returns QuerySubInStorage
129
+ */
113
130
  function querySubToStorage(_key, sub) {
114
- var _a;
115
- const jsonSub = Object.assign({}, sub);
116
- if ((_a = sub.result) === null || _a === void 0 ? void 0 : _a.store) {
117
- jsonSub.result = Object.assign(Object.assign({}, sub.result), { store: s.toJSON(sub.result.store) });
131
+ const { result } = sub, rest = __rest(sub, ["result"]);
132
+ const jsonSub = /** @type {import('./reactorTypes.ts').QuerySubInStorage} */ (rest);
133
+ if (result) {
134
+ /** @type {import('./reactorTypes.ts').QuerySubResultInStorage} */
135
+ const jsonResult = Object.assign(Object.assign({}, result), { store: sts.toJSON(result.store), attrsStore: result.attrsStore.toJSON() });
136
+ jsonSub.result = jsonResult;
118
137
  }
119
138
  return jsonSub;
120
139
  }
@@ -259,7 +278,7 @@ export default class Reactor {
259
278
  }
260
279
  try {
261
280
  const txSteps = instaml.transform({
262
- attrs: this.optimisticAttrs(),
281
+ attrsStore: this.optimisticAttrs(),
263
282
  schema: this.config.schema,
264
283
  stores: Object.values(this.querySubs.currentValue).map((sub) => { var _a; return (_a = sub === null || sub === void 0 ? void 0 : sub.result) === null || _a === void 0 ? void 0 : _a.store; }),
265
284
  useDateObjects: this.config.useDateObjects,
@@ -425,7 +444,9 @@ export default class Reactor {
425
444
  this._initStorage(Storage);
426
445
  this._syncTable = new SyncTable(this._trySendAuthed.bind(this), new Storage(this.config.appId, 'syncSubs'), {
427
446
  useDateObjects: this.config.useDateObjects,
428
- }, this._log, (triples) => s.createStore(this.attrs, triples, this.config.enableCardinalityInference, this._linkIndex, this.config.useDateObjects));
447
+ }, this._log, (triples) => {
448
+ return sts.createStore(this.ensureAttrs(), triples, this.config.enableCardinalityInference, this.config.useDateObjects);
449
+ }, () => this.ensureAttrs());
429
450
  this._oauthCallbackResponse = this._oauthLoginInit();
430
451
  // kick off a request to cache it
431
452
  this.getCurrentUser();
@@ -455,6 +476,12 @@ export default class Reactor {
455
476
  addEventListener('beforeunload', this._beforeUnload);
456
477
  }
457
478
  }
479
+ ensureAttrs() {
480
+ if (!this.attrs) {
481
+ throw new Error('attrs have not loaded.');
482
+ }
483
+ return this.attrs;
484
+ }
458
485
  updateSchema(schema) {
459
486
  this.config = Object.assign(Object.assign({}, this.config), { schema: schema, cardinalityInference: Boolean(schema) });
460
487
  this._linkIndex = schema ? createLinkIndex(this.config.schema) : null;
@@ -478,7 +505,7 @@ export default class Reactor {
478
505
  serialize: querySubToStorage,
479
506
  parse: (_key, x) => querySubFromStorage(x, this.config.useDateObjects),
480
507
  // objectSize
481
- objectSize: (x) => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = x.result) === null || _a === void 0 ? void 0 : _a.store) === null || _b === void 0 ? void 0 : _b.triples) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0; },
508
+ objectSize: (x) => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = x === null || x === void 0 ? void 0 : x.result) === null || _a === void 0 ? void 0 : _a.store) === null || _b === void 0 ? void 0 : _b.triples) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0; },
482
509
  logger: this._log,
483
510
  preloadEntryCount: 10,
484
511
  gc: {
@@ -612,7 +639,7 @@ export default class Reactor {
612
639
  const pageInfo = (_d = (_c = result === null || result === void 0 ? void 0 : result[0]) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d['page-info'];
613
640
  const aggregate = (_f = (_e = result === null || result === void 0 ? void 0 : result[0]) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f['aggregate'];
614
641
  const triples = extractTriples(result);
615
- const store = s.createStore(this.attrs, triples, enableCardinalityInference, this._linkIndex, this.config.useDateObjects);
642
+ const store = sts.createStore(this.ensureAttrs(), triples, enableCardinalityInference, this.config.useDateObjects);
616
643
  this.querySubs.updateInPlace((prev) => {
617
644
  if (!prev[hash]) {
618
645
  this._log.info('Missing value in querySubs', { hash, q });
@@ -620,6 +647,7 @@ export default class Reactor {
620
647
  }
621
648
  prev[hash].result = {
622
649
  store,
650
+ attrsStore: this.ensureAttrs(),
623
651
  pageInfo,
624
652
  aggregate,
625
653
  processedTxId: msg['processed-tx-id'],
@@ -654,7 +682,7 @@ export default class Reactor {
654
682
  this._setAttrs(attrs);
655
683
  }
656
684
  this._cleanupPendingMutationsTimeout();
657
- const rewrittenMutations = this._rewriteMutations(this.attrs, this._pendingMutations(), processedTxId);
685
+ const rewrittenMutations = this._rewriteMutations(this.ensureAttrs(), this._pendingMutations(), processedTxId);
658
686
  if (rewrittenMutations !== this._pendingMutations()) {
659
687
  // We know we've changed the mutations to fix the attr ids and removed
660
688
  // processed attrs, so we'll persist those changes to prevent optimisticAttrs
@@ -670,19 +698,33 @@ export default class Reactor {
670
698
  const result = x['instaql-result'];
671
699
  const hash = weakHash(q);
672
700
  const triples = extractTriples(result);
673
- const store = s.createStore(this.attrs, triples, enableCardinalityInference, this._linkIndex, this.config.useDateObjects);
674
- const newStore = this._applyOptimisticUpdates(store, mutations, processedTxId);
701
+ const attrsStore = this.ensureAttrs();
702
+ const store = sts.createStore(attrsStore, triples, enableCardinalityInference, this.config.useDateObjects);
703
+ const { store: newStore, attrsStore: newAttrsStore } = this._applyOptimisticUpdates(store, attrsStore, mutations, processedTxId);
675
704
  const pageInfo = (_b = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b['page-info'];
676
705
  const aggregate = (_d = (_c = result === null || result === void 0 ? void 0 : result[0]) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d['aggregate'];
677
- return { q, hash, store: newStore, pageInfo, aggregate };
706
+ return {
707
+ q,
708
+ hash,
709
+ store: newStore,
710
+ attrsStore: newAttrsStore,
711
+ pageInfo,
712
+ aggregate,
713
+ };
678
714
  });
679
- updates.forEach(({ hash, q, store, pageInfo, aggregate }) => {
715
+ updates.forEach(({ hash, q, store, attrsStore, pageInfo, aggregate }) => {
680
716
  this.querySubs.updateInPlace((prev) => {
681
717
  if (!prev[hash]) {
682
718
  this._log.error('Missing value in querySubs', { hash, q });
683
719
  return;
684
720
  }
685
- prev[hash].result = { store, pageInfo, aggregate, processedTxId };
721
+ prev[hash].result = {
722
+ store,
723
+ attrsStore,
724
+ pageInfo,
725
+ aggregate,
726
+ processedTxId,
727
+ };
686
728
  });
687
729
  });
688
730
  this._cleanupPendingMutationsQueries();
@@ -694,7 +736,7 @@ export default class Reactor {
694
736
  case 'transact-ok': {
695
737
  const { 'client-event-id': eventId, 'tx-id': txId } = msg;
696
738
  this._inFlightMutationEventIds.delete(eventId);
697
- const muts = this._rewriteMutations(this.attrs, this._pendingMutations());
739
+ const muts = this._rewriteMutations(this.ensureAttrs(), this._pendingMutations());
698
740
  const prevMutation = muts.get(eventId);
699
741
  if (!prevMutation) {
700
742
  break;
@@ -703,11 +745,18 @@ export default class Reactor {
703
745
  this._updatePendingMutations((prev) => {
704
746
  prev.set(eventId, Object.assign(Object.assign({}, prev.get(eventId)), { 'tx-id': txId, confirmed: Date.now() }));
705
747
  });
706
- const newAttrs = prevMutation['tx-steps']
707
- .filter(([action, ..._args]) => action === 'add-attr')
708
- .map(([_action, attr]) => attr)
709
- .concat(Object.values(this.attrs));
710
- this._setAttrs(newAttrs);
748
+ const newAttrs = [];
749
+ for (const step of prevMutation['tx-steps']) {
750
+ if (step[0] === 'add-attr') {
751
+ const attr = step[1];
752
+ newAttrs.push(attr);
753
+ }
754
+ }
755
+ if (newAttrs.length) {
756
+ const existingAttrs = Object.values(this.ensureAttrs());
757
+ this._setAttrs([...existingAttrs, ...newAttrs]);
758
+ this._setAttrs(newAttrs);
759
+ }
711
760
  this._finishTransaction('synced', eventId);
712
761
  this._cleanupPendingMutationsTimeout();
713
762
  break;
@@ -868,10 +917,10 @@ export default class Reactor {
868
917
  this._completeQueryOnce(q, hash, r.dfd);
869
918
  }
870
919
  _setAttrs(attrs) {
871
- this.attrs = attrs.reduce((acc, attr) => {
920
+ this.attrs = new sts.AttrsStoreClass(attrs.reduce((acc, attr) => {
872
921
  acc[attr.id] = attr;
873
922
  return acc;
874
- }, {});
923
+ }, {}), this._linkIndex);
875
924
  this.notifyAttrsSubs();
876
925
  }
877
926
  _startQuerySub(q, hash) {
@@ -977,6 +1026,12 @@ export default class Reactor {
977
1026
  // We remove `add-attr` commands for attrs that already exist.
978
1027
  // We update `add-triple` and `retract-triple` commands to use the
979
1028
  // server attr-ids.
1029
+ /**
1030
+ *
1031
+ * @param {sts.AttrsStore} attrs
1032
+ * @param {any} muts
1033
+ * @param {number} [processedTxId]
1034
+ */
980
1035
  _rewriteMutations(attrs, muts, processedTxId) {
981
1036
  if (!attrs)
982
1037
  return muts;
@@ -984,12 +1039,12 @@ export default class Reactor {
984
1039
  return new Map();
985
1040
  const findExistingAttr = (attr) => {
986
1041
  const [_, etype, label] = attr['forward-identity'];
987
- const existing = instaml.getAttrByFwdIdentName(attrs, etype, label);
1042
+ const existing = sts.getAttrByFwdIdentName(attrs, etype, label);
988
1043
  return existing;
989
1044
  };
990
1045
  const findReverseAttr = (attr) => {
991
1046
  const [_, etype, label] = attr['forward-identity'];
992
- const revAttr = instaml.getAttrByReverseIdentName(attrs, etype, label);
1047
+ const revAttr = sts.getAttrByReverseIdentName(attrs, etype, label);
993
1048
  return revAttr;
994
1049
  };
995
1050
  const mapping = { attrIdMap: {}, refSwapAttrIds: new Set() };
@@ -1052,8 +1107,11 @@ export default class Reactor {
1052
1107
  }
1053
1108
  // ---------------------------
1054
1109
  // Transact
1110
+ /**
1111
+ * @returns {sts.AttrsStore}
1112
+ */
1055
1113
  optimisticAttrs() {
1056
- var _a;
1114
+ var _a, _b;
1057
1115
  const pendingMutationSteps = [...this._pendingMutations().values()] // hack due to Map()
1058
1116
  .flatMap((x) => x['tx-steps']);
1059
1117
  const deletedAttrIds = new Set(pendingMutationSteps
@@ -1066,17 +1124,22 @@ export default class Reactor {
1066
1124
  }
1067
1125
  else if (_action === 'update-attr' &&
1068
1126
  attr.id &&
1069
- ((_a = this.attrs) === null || _a === void 0 ? void 0 : _a[attr.id])) {
1070
- const fullAttr = Object.assign(Object.assign({}, this.attrs[attr.id]), attr);
1127
+ ((_a = this.attrs) === null || _a === void 0 ? void 0 : _a.getAttr(attr.id))) {
1128
+ const fullAttr = Object.assign(Object.assign({}, this.attrs.getAttr(attr.id)), attr);
1071
1129
  pendingAttrs.push(fullAttr);
1072
1130
  }
1073
1131
  }
1074
- const attrsWithoutDeleted = [
1075
- ...Object.values(this.attrs || {}),
1076
- ...pendingAttrs,
1077
- ].filter((a) => !deletedAttrIds.has(a.id));
1078
- const attrsRecord = Object.fromEntries(attrsWithoutDeleted.map((a) => [a.id, a]));
1079
- return attrsRecord;
1132
+ if (!deletedAttrIds.size && !pendingAttrs.length) {
1133
+ return this.attrs || new sts.AttrsStoreClass({}, this._linkIndex);
1134
+ }
1135
+ const attrs = Object.assign({}, (((_b = this.attrs) === null || _b === void 0 ? void 0 : _b.attrs) || {}));
1136
+ for (const attr of pendingAttrs) {
1137
+ attrs[attr.id] = attr;
1138
+ }
1139
+ for (const id of deletedAttrIds) {
1140
+ delete attrs[id];
1141
+ }
1142
+ return new sts.AttrsStoreClass(attrs, this._linkIndex);
1080
1143
  }
1081
1144
  /** Runs instaql on a query and a store */
1082
1145
  dataForQuery(hash) {
@@ -1101,19 +1164,21 @@ export default class Reactor {
1101
1164
  pendingMutationsVersion === cached.pendingMutationsVersion) {
1102
1165
  return cached;
1103
1166
  }
1104
- const { store, pageInfo, aggregate, processedTxId } = result;
1105
- const mutations = this._rewriteMutationsSorted(store.attrs, pendingMutations);
1106
- const newStore = this._applyOptimisticUpdates(store, mutations, processedTxId);
1107
- const resp = instaql({ store: newStore, pageInfo, aggregate }, q);
1167
+ const { store, attrsStore, pageInfo, aggregate, processedTxId } = result;
1168
+ const mutations = this._rewriteMutationsSorted(attrsStore, pendingMutations);
1169
+ const { store: newStore, attrsStore: newAttrsStore } = this._applyOptimisticUpdates(store, attrsStore, mutations, processedTxId);
1170
+ const resp = instaql({ store: newStore, attrsStore: newAttrsStore, pageInfo, aggregate }, q);
1108
1171
  return { data: resp, querySubVersion, pendingMutationsVersion };
1109
1172
  }
1110
- _applyOptimisticUpdates(store, mutations, processedTxId) {
1173
+ _applyOptimisticUpdates(store, attrsStore, mutations, processedTxId) {
1111
1174
  for (const [_, mut] of mutations) {
1112
1175
  if (!mut['tx-id'] || (processedTxId && mut['tx-id'] > processedTxId)) {
1113
- store = s.transact(store, mut['tx-steps']);
1176
+ const result = sts.transact(store, attrsStore, mut['tx-steps']);
1177
+ store = result.store;
1178
+ attrsStore = result.attrsStore;
1114
1179
  }
1115
1180
  }
1116
- return store;
1181
+ return { store, attrsStore };
1117
1182
  }
1118
1183
  /** Re-compute all subscriptions */
1119
1184
  notifyAll() {
@@ -1193,7 +1258,7 @@ export default class Reactor {
1193
1258
  .forEach(({ eventId, q }) => {
1194
1259
  this._trySendAuthed(eventId, { op: 'add-query', q });
1195
1260
  });
1196
- const muts = this._rewriteMutationsSorted(this.attrs, this._pendingMutations());
1261
+ const muts = this._rewriteMutationsSorted(this.ensureAttrs(), this._pendingMutations());
1197
1262
  muts.forEach(([eventId, mut]) => {
1198
1263
  if (!mut['tx-id']) {
1199
1264
  this._sendMutation(eventId, mut);
@@ -1480,7 +1545,7 @@ export default class Reactor {
1480
1545
  subscribeAttrs(cb) {
1481
1546
  this.attrsCbs.push(cb);
1482
1547
  if (this.attrs) {
1483
- cb(this.attrs);
1548
+ cb(this.attrs.attrs);
1484
1549
  }
1485
1550
  return () => {
1486
1551
  this.attrsCbs = this.attrsCbs.filter((x) => x !== cb);