@instantdb/core 0.22.88 → 0.22.89-experimental.drewh-ssr.20277611943.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 (102) 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/serializeSchema.test.ts +123 -0
  8. package/__tests__/src/{store.test.js → store.test.ts} +215 -212
  9. package/dist/commonjs/Reactor.d.ts +36 -7
  10. package/dist/commonjs/Reactor.d.ts.map +1 -1
  11. package/dist/commonjs/Reactor.js +176 -47
  12. package/dist/commonjs/Reactor.js.map +1 -1
  13. package/dist/commonjs/SyncTable.d.ts +4 -1
  14. package/dist/commonjs/SyncTable.d.ts.map +1 -1
  15. package/dist/commonjs/SyncTable.js +35 -37
  16. package/dist/commonjs/SyncTable.js.map +1 -1
  17. package/dist/commonjs/createRouteHandler.d.ts +8 -0
  18. package/dist/commonjs/createRouteHandler.d.ts.map +1 -0
  19. package/dist/commonjs/createRouteHandler.js +57 -0
  20. package/dist/commonjs/createRouteHandler.js.map +1 -0
  21. package/dist/commonjs/framework.d.ts +77 -0
  22. package/dist/commonjs/framework.d.ts.map +1 -0
  23. package/dist/commonjs/framework.js +209 -0
  24. package/dist/commonjs/framework.js.map +1 -0
  25. package/dist/commonjs/index.d.ts +5 -1
  26. package/dist/commonjs/index.d.ts.map +1 -1
  27. package/dist/commonjs/index.js +7 -1
  28. package/dist/commonjs/index.js.map +1 -1
  29. package/dist/commonjs/instaml.d.ts +17 -4
  30. package/dist/commonjs/instaml.d.ts.map +1 -1
  31. package/dist/commonjs/instaml.js +115 -82
  32. package/dist/commonjs/instaml.js.map +1 -1
  33. package/dist/commonjs/instaql.d.ts +4 -3
  34. package/dist/commonjs/instaql.d.ts.map +1 -1
  35. package/dist/commonjs/instaql.js +65 -63
  36. package/dist/commonjs/instaql.js.map +1 -1
  37. package/dist/commonjs/parseSchemaFromJSON.d.ts +3 -0
  38. package/dist/commonjs/parseSchemaFromJSON.d.ts.map +1 -0
  39. package/dist/commonjs/parseSchemaFromJSON.js +148 -0
  40. package/dist/commonjs/parseSchemaFromJSON.js.map +1 -0
  41. package/dist/commonjs/reactorTypes.d.ts +30 -0
  42. package/dist/commonjs/reactorTypes.d.ts.map +1 -0
  43. package/dist/commonjs/reactorTypes.js +3 -0
  44. package/dist/commonjs/reactorTypes.js.map +1 -0
  45. package/dist/commonjs/store.d.ts +67 -25
  46. package/dist/commonjs/store.d.ts.map +1 -1
  47. package/dist/commonjs/store.js +177 -81
  48. package/dist/commonjs/store.js.map +1 -1
  49. package/dist/esm/Reactor.d.ts +36 -7
  50. package/dist/esm/Reactor.d.ts.map +1 -1
  51. package/dist/esm/Reactor.js +177 -48
  52. package/dist/esm/Reactor.js.map +1 -1
  53. package/dist/esm/SyncTable.d.ts +4 -1
  54. package/dist/esm/SyncTable.d.ts.map +1 -1
  55. package/dist/esm/SyncTable.js +35 -37
  56. package/dist/esm/SyncTable.js.map +1 -1
  57. package/dist/esm/createRouteHandler.d.ts +8 -0
  58. package/dist/esm/createRouteHandler.d.ts.map +1 -0
  59. package/dist/esm/createRouteHandler.js +53 -0
  60. package/dist/esm/createRouteHandler.js.map +1 -0
  61. package/dist/esm/framework.d.ts +77 -0
  62. package/dist/esm/framework.d.ts.map +1 -0
  63. package/dist/esm/framework.js +169 -0
  64. package/dist/esm/framework.js.map +1 -0
  65. package/dist/esm/index.d.ts +5 -1
  66. package/dist/esm/index.d.ts.map +1 -1
  67. package/dist/esm/index.js +5 -2
  68. package/dist/esm/index.js.map +1 -1
  69. package/dist/esm/instaml.d.ts +17 -4
  70. package/dist/esm/instaml.d.ts.map +1 -1
  71. package/dist/esm/instaml.js +112 -77
  72. package/dist/esm/instaml.js.map +1 -1
  73. package/dist/esm/instaql.d.ts +4 -3
  74. package/dist/esm/instaql.d.ts.map +1 -1
  75. package/dist/esm/instaql.js +65 -63
  76. package/dist/esm/instaql.js.map +1 -1
  77. package/dist/esm/parseSchemaFromJSON.d.ts +3 -0
  78. package/dist/esm/parseSchemaFromJSON.d.ts.map +1 -0
  79. package/dist/esm/parseSchemaFromJSON.js +144 -0
  80. package/dist/esm/parseSchemaFromJSON.js.map +1 -0
  81. package/dist/esm/reactorTypes.d.ts +30 -0
  82. package/dist/esm/reactorTypes.d.ts.map +1 -0
  83. package/dist/esm/reactorTypes.js +2 -0
  84. package/dist/esm/reactorTypes.js.map +1 -0
  85. package/dist/esm/store.d.ts +67 -25
  86. package/dist/esm/store.d.ts.map +1 -1
  87. package/dist/esm/store.js +174 -81
  88. package/dist/esm/store.js.map +1 -1
  89. package/dist/standalone/index.js +2899 -2389
  90. package/dist/standalone/index.umd.cjs +3 -3
  91. package/package.json +2 -2
  92. package/src/Reactor.js +232 -77
  93. package/src/SyncTable.ts +85 -45
  94. package/src/createRouteHandler.ts +44 -0
  95. package/src/framework.ts +294 -0
  96. package/src/index.ts +9 -0
  97. package/src/{instaml.js → instaml.ts} +201 -96
  98. package/src/instaql.ts +88 -62
  99. package/src/parseSchemaFromJSON.ts +176 -0
  100. package/src/reactorTypes.ts +33 -0
  101. package/src/store.ts +257 -101
  102. package/__tests__/src/instaql.bench.js +0 -29
@@ -21,7 +21,7 @@ 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';
24
+ import * as instaml from "./instaml.js";
25
25
  import * as s from "./store.js";
26
26
  import uuid from "./utils/uuid.js";
27
27
  import IndexedDBStorage from "./IndexedDBStorage.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 = s.attrsStoreFromJSON(v.result.attrsStore, v.result.store);
116
+ if (attrsStore) {
117
+ const storeJSON = v.result.store;
118
+ v.result.store = s.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: s.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,10 +444,18 @@ 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 s.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
- this.getCurrentUser();
452
+ this.getCurrentUser().then((userInfo) => {
453
+ this.syncUserToEndpoint(userInfo.user);
454
+ });
455
+ setInterval(() => __awaiter(this, void 0, void 0, function* () {
456
+ const currentUser = yield this.getCurrentUser();
457
+ this.syncUserToEndpoint(currentUser.user);
458
+ }), 1000 * 60 * 20);
432
459
  NetworkListener.getIsOnline().then((isOnline) => {
433
460
  this._isOnline = isOnline;
434
461
  this._startSocket();
@@ -455,6 +482,12 @@ export default class Reactor {
455
482
  addEventListener('beforeunload', this._beforeUnload);
456
483
  }
457
484
  }
485
+ ensureAttrs() {
486
+ if (!this.attrs) {
487
+ throw new Error('attrs have not loaded.');
488
+ }
489
+ return this.attrs;
490
+ }
458
491
  updateSchema(schema) {
459
492
  this.config = Object.assign(Object.assign({}, this.config), { schema: schema, cardinalityInference: Boolean(schema) });
460
493
  this._linkIndex = schema ? createLinkIndex(this.config.schema) : null;
@@ -478,7 +511,7 @@ export default class Reactor {
478
511
  serialize: querySubToStorage,
479
512
  parse: (_key, x) => querySubFromStorage(x, this.config.useDateObjects),
480
513
  // 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; },
514
+ 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
515
  logger: this._log,
483
516
  preloadEntryCount: 10,
484
517
  gc: {
@@ -574,6 +607,37 @@ export default class Reactor {
574
607
  }
575
608
  }
576
609
  }
610
+ /**
611
+ * Does the same thing as add-query-ok
612
+ * but called as a result of receiving query info from ssr
613
+ * @param {any} q
614
+ * @param {{ triples: any; pageInfo: any; }} result
615
+ * @param {boolean} enableCardinalityInference
616
+ */
617
+ _addQueryData(q, result, enableCardinalityInference) {
618
+ if (!this.attrs) {
619
+ throw new Error('Attrs in reactor have not been set');
620
+ }
621
+ const queryHash = weakHash(q);
622
+ const attrsStore = this.ensureAttrs();
623
+ const store = s.createStore(this.attrs, result.triples, enableCardinalityInference, this.config.useDateObjects);
624
+ this.querySubs.updateInPlace((prev) => {
625
+ prev[queryHash] = {
626
+ result: {
627
+ store,
628
+ attrsStore,
629
+ pageInfo: result.pageInfo,
630
+ processedTxId: undefined,
631
+ isExternal: true,
632
+ },
633
+ q,
634
+ };
635
+ });
636
+ this._cleanupPendingMutationsQueries();
637
+ this.notifyOne(queryHash);
638
+ this.notifyOneQueryOnce(queryHash);
639
+ this._cleanupPendingMutationsTimeout();
640
+ }
577
641
  _handleReceive(connId, msg) {
578
642
  var _a, _b, _c, _d, _e, _f;
579
643
  // opt-out, enabled by default if schema
@@ -612,7 +676,8 @@ export default class Reactor {
612
676
  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
677
  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
678
  const triples = extractTriples(result);
615
- const store = s.createStore(this.attrs, triples, enableCardinalityInference, this._linkIndex, this.config.useDateObjects);
679
+ const attrsStore = this.ensureAttrs();
680
+ const store = s.createStore(attrsStore, triples, enableCardinalityInference, this.config.useDateObjects);
616
681
  this.querySubs.updateInPlace((prev) => {
617
682
  if (!prev[hash]) {
618
683
  this._log.info('Missing value in querySubs', { hash, q });
@@ -620,6 +685,7 @@ export default class Reactor {
620
685
  }
621
686
  prev[hash].result = {
622
687
  store,
688
+ attrsStore,
623
689
  pageInfo,
624
690
  aggregate,
625
691
  processedTxId: msg['processed-tx-id'],
@@ -654,7 +720,7 @@ export default class Reactor {
654
720
  this._setAttrs(attrs);
655
721
  }
656
722
  this._cleanupPendingMutationsTimeout();
657
- const rewrittenMutations = this._rewriteMutations(this.attrs, this._pendingMutations(), processedTxId);
723
+ const rewrittenMutations = this._rewriteMutations(this.ensureAttrs(), this._pendingMutations(), processedTxId);
658
724
  if (rewrittenMutations !== this._pendingMutations()) {
659
725
  // We know we've changed the mutations to fix the attr ids and removed
660
726
  // processed attrs, so we'll persist those changes to prevent optimisticAttrs
@@ -670,19 +736,33 @@ export default class Reactor {
670
736
  const result = x['instaql-result'];
671
737
  const hash = weakHash(q);
672
738
  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);
739
+ const attrsStore = this.ensureAttrs();
740
+ const store = s.createStore(attrsStore, triples, enableCardinalityInference, this.config.useDateObjects);
741
+ const { store: newStore, attrsStore: newAttrsStore } = this._applyOptimisticUpdates(store, attrsStore, mutations, processedTxId);
675
742
  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
743
  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 };
744
+ return {
745
+ q,
746
+ hash,
747
+ store: newStore,
748
+ attrsStore: newAttrsStore,
749
+ pageInfo,
750
+ aggregate,
751
+ };
678
752
  });
679
- updates.forEach(({ hash, q, store, pageInfo, aggregate }) => {
753
+ updates.forEach(({ hash, q, store, attrsStore, pageInfo, aggregate }) => {
680
754
  this.querySubs.updateInPlace((prev) => {
681
755
  if (!prev[hash]) {
682
756
  this._log.error('Missing value in querySubs', { hash, q });
683
757
  return;
684
758
  }
685
- prev[hash].result = { store, pageInfo, aggregate, processedTxId };
759
+ prev[hash].result = {
760
+ store,
761
+ attrsStore,
762
+ pageInfo,
763
+ aggregate,
764
+ processedTxId,
765
+ };
686
766
  });
687
767
  });
688
768
  this._cleanupPendingMutationsQueries();
@@ -694,7 +774,7 @@ export default class Reactor {
694
774
  case 'transact-ok': {
695
775
  const { 'client-event-id': eventId, 'tx-id': txId } = msg;
696
776
  this._inFlightMutationEventIds.delete(eventId);
697
- const muts = this._rewriteMutations(this.attrs, this._pendingMutations());
777
+ const muts = this._rewriteMutations(this.ensureAttrs(), this._pendingMutations());
698
778
  const prevMutation = muts.get(eventId);
699
779
  if (!prevMutation) {
700
780
  break;
@@ -703,11 +783,17 @@ export default class Reactor {
703
783
  this._updatePendingMutations((prev) => {
704
784
  prev.set(eventId, Object.assign(Object.assign({}, prev.get(eventId)), { 'tx-id': txId, confirmed: Date.now() }));
705
785
  });
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);
786
+ const newAttrs = [];
787
+ for (const step of prevMutation['tx-steps']) {
788
+ if (step[0] === 'add-attr') {
789
+ const attr = step[1];
790
+ newAttrs.push(attr);
791
+ }
792
+ }
793
+ if (newAttrs.length) {
794
+ const existingAttrs = Object.values(this.ensureAttrs().attrs);
795
+ this._setAttrs([...existingAttrs, ...newAttrs]);
796
+ }
711
797
  this._finishTransaction('synced', eventId);
712
798
  this._cleanupPendingMutationsTimeout();
713
799
  break;
@@ -868,10 +954,10 @@ export default class Reactor {
868
954
  this._completeQueryOnce(q, hash, r.dfd);
869
955
  }
870
956
  _setAttrs(attrs) {
871
- this.attrs = attrs.reduce((acc, attr) => {
957
+ this.attrs = new s.AttrsStoreClass(attrs.reduce((acc, attr) => {
872
958
  acc[attr.id] = attr;
873
959
  return acc;
874
- }, {});
960
+ }, {}), this._linkIndex);
875
961
  this.notifyAttrsSubs();
876
962
  }
877
963
  _startQuerySub(q, hash) {
@@ -977,6 +1063,12 @@ export default class Reactor {
977
1063
  // We remove `add-attr` commands for attrs that already exist.
978
1064
  // We update `add-triple` and `retract-triple` commands to use the
979
1065
  // server attr-ids.
1066
+ /**
1067
+ *
1068
+ * @param {s.AttrsStore} attrs
1069
+ * @param {any} muts
1070
+ * @param {number} [processedTxId]
1071
+ */
980
1072
  _rewriteMutations(attrs, muts, processedTxId) {
981
1073
  if (!attrs)
982
1074
  return muts;
@@ -984,12 +1076,12 @@ export default class Reactor {
984
1076
  return new Map();
985
1077
  const findExistingAttr = (attr) => {
986
1078
  const [_, etype, label] = attr['forward-identity'];
987
- const existing = instaml.getAttrByFwdIdentName(attrs, etype, label);
1079
+ const existing = s.getAttrByFwdIdentName(attrs, etype, label);
988
1080
  return existing;
989
1081
  };
990
1082
  const findReverseAttr = (attr) => {
991
1083
  const [_, etype, label] = attr['forward-identity'];
992
- const revAttr = instaml.getAttrByReverseIdentName(attrs, etype, label);
1084
+ const revAttr = s.getAttrByReverseIdentName(attrs, etype, label);
993
1085
  return revAttr;
994
1086
  };
995
1087
  const mapping = { attrIdMap: {}, refSwapAttrIds: new Set() };
@@ -1052,8 +1144,11 @@ export default class Reactor {
1052
1144
  }
1053
1145
  // ---------------------------
1054
1146
  // Transact
1147
+ /**
1148
+ * @returns {s.AttrsStore}
1149
+ */
1055
1150
  optimisticAttrs() {
1056
- var _a;
1151
+ var _a, _b;
1057
1152
  const pendingMutationSteps = [...this._pendingMutations().values()] // hack due to Map()
1058
1153
  .flatMap((x) => x['tx-steps']);
1059
1154
  const deletedAttrIds = new Set(pendingMutationSteps
@@ -1066,20 +1161,25 @@ export default class Reactor {
1066
1161
  }
1067
1162
  else if (_action === 'update-attr' &&
1068
1163
  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);
1164
+ ((_a = this.attrs) === null || _a === void 0 ? void 0 : _a.getAttr(attr.id))) {
1165
+ const fullAttr = Object.assign(Object.assign({}, this.attrs.getAttr(attr.id)), attr);
1071
1166
  pendingAttrs.push(fullAttr);
1072
1167
  }
1073
1168
  }
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;
1169
+ if (!deletedAttrIds.size && !pendingAttrs.length) {
1170
+ return this.attrs || new s.AttrsStoreClass({}, this._linkIndex);
1171
+ }
1172
+ const attrs = Object.assign({}, (((_b = this.attrs) === null || _b === void 0 ? void 0 : _b.attrs) || {}));
1173
+ for (const attr of pendingAttrs) {
1174
+ attrs[attr.id] = attr;
1175
+ }
1176
+ for (const id of deletedAttrIds) {
1177
+ delete attrs[id];
1178
+ }
1179
+ return new s.AttrsStoreClass(attrs, this._linkIndex);
1080
1180
  }
1081
1181
  /** Runs instaql on a query and a store */
1082
- dataForQuery(hash) {
1182
+ dataForQuery(hash, applyOptimistic = true) {
1083
1183
  const errorMessage = this._errorMessage;
1084
1184
  if (errorMessage) {
1085
1185
  return { error: errorMessage };
@@ -1101,19 +1201,27 @@ export default class Reactor {
1101
1201
  pendingMutationsVersion === cached.pendingMutationsVersion) {
1102
1202
  return cached;
1103
1203
  }
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);
1204
+ let store = result.store;
1205
+ let attrsStore = result.attrsStore;
1206
+ const { pageInfo, aggregate, processedTxId } = result;
1207
+ const mutations = this._rewriteMutationsSorted(attrsStore, pendingMutations);
1208
+ if (applyOptimistic) {
1209
+ const optimisticResult = this._applyOptimisticUpdates(store, attrsStore, mutations, processedTxId);
1210
+ store = optimisticResult.store;
1211
+ attrsStore = optimisticResult.attrsStore;
1212
+ }
1213
+ const resp = instaql({ store: store, attrsStore: attrsStore, pageInfo, aggregate }, q);
1108
1214
  return { data: resp, querySubVersion, pendingMutationsVersion };
1109
1215
  }
1110
- _applyOptimisticUpdates(store, mutations, processedTxId) {
1216
+ _applyOptimisticUpdates(store, attrsStore, mutations, processedTxId) {
1111
1217
  for (const [_, mut] of mutations) {
1112
1218
  if (!mut['tx-id'] || (processedTxId && mut['tx-id'] > processedTxId)) {
1113
- store = s.transact(store, mut['tx-steps']);
1219
+ const result = s.transact(store, attrsStore, mut['tx-steps']);
1220
+ store = result.store;
1221
+ attrsStore = result.attrsStore;
1114
1222
  }
1115
1223
  }
1116
- return store;
1224
+ return { store, attrsStore };
1117
1225
  }
1118
1226
  /** Re-compute all subscriptions */
1119
1227
  notifyAll() {
@@ -1193,7 +1301,7 @@ export default class Reactor {
1193
1301
  .forEach(({ eventId, q }) => {
1194
1302
  this._trySendAuthed(eventId, { op: 'add-query', q });
1195
1303
  });
1196
- const muts = this._rewriteMutationsSorted(this.attrs, this._pendingMutations());
1304
+ const muts = this._rewriteMutationsSorted(this.ensureAttrs(), this._pendingMutations());
1197
1305
  muts.forEach(([eventId, mut]) => {
1198
1306
  if (!mut['tx-id']) {
1199
1307
  this._sendMutation(eventId, mut);
@@ -1480,7 +1588,7 @@ export default class Reactor {
1480
1588
  subscribeAttrs(cb) {
1481
1589
  this.attrsCbs.push(cb);
1482
1590
  if (this.attrs) {
1483
- cb(this.attrs);
1591
+ cb(this.attrs.attrs);
1484
1592
  }
1485
1593
  return () => {
1486
1594
  this.attrsCbs = this.attrsCbs.filter((x) => x !== cb);
@@ -1496,7 +1604,7 @@ export default class Reactor {
1496
1604
  if (!this.attrs)
1497
1605
  return;
1498
1606
  const oas = this.optimisticAttrs();
1499
- this.attrsCbs.forEach((cb) => cb(oas));
1607
+ this.attrsCbs.forEach((cb) => cb(oas.attrs));
1500
1608
  }
1501
1609
  notifyConnectionStatusSubs(status) {
1502
1610
  this.connectionStatusCbs.forEach((cb) => cb(status));
@@ -1568,7 +1676,28 @@ export default class Reactor {
1568
1676
  }
1569
1677
  });
1570
1678
  }
1679
+ syncUserToEndpoint(user) {
1680
+ return __awaiter(this, void 0, void 0, function* () {
1681
+ if (this.config.cookieEndpoint) {
1682
+ try {
1683
+ fetch(this.config.cookieEndpoint + '/sync-auth', {
1684
+ method: 'POST',
1685
+ body: JSON.stringify({
1686
+ user: user,
1687
+ }),
1688
+ headers: {
1689
+ 'Content-Type': 'application/json',
1690
+ },
1691
+ });
1692
+ }
1693
+ catch (error) {
1694
+ console.error('Error syncing user with external endpoint', error);
1695
+ }
1696
+ }
1697
+ });
1698
+ }
1571
1699
  updateUser(newUser) {
1700
+ this.syncUserToEndpoint(newUser);
1572
1701
  const newV = { error: undefined, user: newUser };
1573
1702
  this._currentUserCached = Object.assign({ isLoading: false }, newV);
1574
1703
  this._dataForQueryCache = {};