@instantdb/core 0.22.97 → 0.22.98-experimental.drewh-ts-target.20762041587.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 (126) hide show
  1. package/dist/commonjs/Connection.js +50 -51
  2. package/dist/commonjs/Connection.js.map +1 -1
  3. package/dist/commonjs/InMemoryStorage.js +13 -32
  4. package/dist/commonjs/InMemoryStorage.js.map +1 -1
  5. package/dist/commonjs/IndexedDBStorage.js +193 -217
  6. package/dist/commonjs/IndexedDBStorage.js.map +1 -1
  7. package/dist/commonjs/InstantError.js +1 -0
  8. package/dist/commonjs/InstantError.js.map +1 -1
  9. package/dist/commonjs/Reactor.js +566 -610
  10. package/dist/commonjs/Reactor.js.map +1 -1
  11. package/dist/commonjs/StorageAPI.js +51 -70
  12. package/dist/commonjs/StorageAPI.js.map +1 -1
  13. package/dist/commonjs/SyncTable.js +68 -81
  14. package/dist/commonjs/SyncTable.js.map +1 -1
  15. package/dist/commonjs/WindowNetworkListener.js +2 -13
  16. package/dist/commonjs/WindowNetworkListener.js.map +1 -1
  17. package/dist/commonjs/__types__/fieldsTypeTest.js +8 -16
  18. package/dist/commonjs/__types__/fieldsTypeTest.js.map +1 -1
  19. package/dist/commonjs/__types__/useDatesTypeTest.js +3 -6
  20. package/dist/commonjs/__types__/useDatesTypeTest.js.map +1 -1
  21. package/dist/commonjs/authAPI.js +62 -79
  22. package/dist/commonjs/authAPI.js.map +1 -1
  23. package/dist/commonjs/createRouteHandler.js +5 -15
  24. package/dist/commonjs/createRouteHandler.js.map +1 -1
  25. package/dist/commonjs/datalog.js +1 -1
  26. package/dist/commonjs/datalog.js.map +1 -1
  27. package/dist/commonjs/devtool.js +26 -8
  28. package/dist/commonjs/devtool.js.map +1 -1
  29. package/dist/commonjs/framework.d.ts.map +1 -1
  30. package/dist/commonjs/framework.js +142 -152
  31. package/dist/commonjs/framework.js.map +1 -1
  32. package/dist/commonjs/index.js +204 -190
  33. package/dist/commonjs/index.js.map +1 -1
  34. package/dist/commonjs/instaml.js +44 -30
  35. package/dist/commonjs/instaml.js.map +1 -1
  36. package/dist/commonjs/instaql.js +25 -33
  37. package/dist/commonjs/instaql.js.map +1 -1
  38. package/dist/commonjs/parseSchemaFromJSON.js +6 -7
  39. package/dist/commonjs/parseSchemaFromJSON.js.map +1 -1
  40. package/dist/commonjs/presence.js +7 -8
  41. package/dist/commonjs/presence.js.map +1 -1
  42. package/dist/commonjs/queryValidation.js +1 -2
  43. package/dist/commonjs/queryValidation.js.map +1 -1
  44. package/dist/commonjs/schema.js +8 -6
  45. package/dist/commonjs/schema.js.map +1 -1
  46. package/dist/commonjs/schemaTypes.js +22 -3
  47. package/dist/commonjs/schemaTypes.js.map +1 -1
  48. package/dist/commonjs/store.js +29 -38
  49. package/dist/commonjs/store.js.map +1 -1
  50. package/dist/commonjs/transactionValidation.js +1 -2
  51. package/dist/commonjs/transactionValidation.js.map +1 -1
  52. package/dist/commonjs/utils/Deferred.js +3 -0
  53. package/dist/commonjs/utils/Deferred.js.map +1 -1
  54. package/dist/commonjs/utils/PersistedObject.js +216 -233
  55. package/dist/commonjs/utils/PersistedObject.js.map +1 -1
  56. package/dist/commonjs/utils/fetch.js +9 -19
  57. package/dist/commonjs/utils/fetch.js.map +1 -1
  58. package/dist/commonjs/utils/linkIndex.js +2 -4
  59. package/dist/commonjs/utils/linkIndex.js.map +1 -1
  60. package/dist/commonjs/utils/object.js +1 -1
  61. package/dist/commonjs/utils/object.js.map +1 -1
  62. package/dist/esm/Connection.js +50 -51
  63. package/dist/esm/Connection.js.map +1 -1
  64. package/dist/esm/InMemoryStorage.js +13 -32
  65. package/dist/esm/InMemoryStorage.js.map +1 -1
  66. package/dist/esm/IndexedDBStorage.js +193 -217
  67. package/dist/esm/IndexedDBStorage.js.map +1 -1
  68. package/dist/esm/InstantError.js +1 -0
  69. package/dist/esm/InstantError.js.map +1 -1
  70. package/dist/esm/Reactor.js +566 -610
  71. package/dist/esm/Reactor.js.map +1 -1
  72. package/dist/esm/StorageAPI.js +51 -70
  73. package/dist/esm/StorageAPI.js.map +1 -1
  74. package/dist/esm/SyncTable.js +68 -81
  75. package/dist/esm/SyncTable.js.map +1 -1
  76. package/dist/esm/WindowNetworkListener.js +2 -13
  77. package/dist/esm/WindowNetworkListener.js.map +1 -1
  78. package/dist/esm/__types__/fieldsTypeTest.js +8 -16
  79. package/dist/esm/__types__/fieldsTypeTest.js.map +1 -1
  80. package/dist/esm/__types__/useDatesTypeTest.js +3 -6
  81. package/dist/esm/__types__/useDatesTypeTest.js.map +1 -1
  82. package/dist/esm/authAPI.js +62 -79
  83. package/dist/esm/authAPI.js.map +1 -1
  84. package/dist/esm/createRouteHandler.js +5 -15
  85. package/dist/esm/createRouteHandler.js.map +1 -1
  86. package/dist/esm/datalog.js +1 -1
  87. package/dist/esm/datalog.js.map +1 -1
  88. package/dist/esm/devtool.js +26 -8
  89. package/dist/esm/devtool.js.map +1 -1
  90. package/dist/esm/framework.d.ts.map +1 -1
  91. package/dist/esm/framework.js +142 -152
  92. package/dist/esm/framework.js.map +1 -1
  93. package/dist/esm/index.js +204 -190
  94. package/dist/esm/index.js.map +1 -1
  95. package/dist/esm/instaml.js +44 -30
  96. package/dist/esm/instaml.js.map +1 -1
  97. package/dist/esm/instaql.js +25 -33
  98. package/dist/esm/instaql.js.map +1 -1
  99. package/dist/esm/parseSchemaFromJSON.js +6 -7
  100. package/dist/esm/parseSchemaFromJSON.js.map +1 -1
  101. package/dist/esm/presence.js +7 -8
  102. package/dist/esm/presence.js.map +1 -1
  103. package/dist/esm/queryValidation.js +1 -2
  104. package/dist/esm/queryValidation.js.map +1 -1
  105. package/dist/esm/schema.js +8 -6
  106. package/dist/esm/schema.js.map +1 -1
  107. package/dist/esm/schemaTypes.js +22 -3
  108. package/dist/esm/schemaTypes.js.map +1 -1
  109. package/dist/esm/store.js +29 -38
  110. package/dist/esm/store.js.map +1 -1
  111. package/dist/esm/transactionValidation.js +1 -2
  112. package/dist/esm/transactionValidation.js.map +1 -1
  113. package/dist/esm/utils/Deferred.js +3 -0
  114. package/dist/esm/utils/Deferred.js.map +1 -1
  115. package/dist/esm/utils/PersistedObject.js +216 -233
  116. package/dist/esm/utils/PersistedObject.js.map +1 -1
  117. package/dist/esm/utils/fetch.js +9 -19
  118. package/dist/esm/utils/fetch.js.map +1 -1
  119. package/dist/esm/utils/linkIndex.js +2 -4
  120. package/dist/esm/utils/linkIndex.js.map +1 -1
  121. package/dist/esm/utils/object.js +1 -1
  122. package/dist/esm/utils/object.js.map +1 -1
  123. package/dist/standalone/index.js +2610 -2367
  124. package/dist/standalone/index.umd.cjs +3 -3
  125. package/package.json +2 -2
  126. package/src/framework.ts +0 -1
@@ -32,26 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
- return new (P || (P = Promise))(function (resolve, reject) {
38
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
- step((generator = generator.apply(thisArg, _arguments || [])).next());
42
- });
43
- };
44
- var __rest = (this && this.__rest) || function (s, e) {
45
- var t = {};
46
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
47
- t[p] = s[p];
48
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
49
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
50
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
51
- t[p[i]] = s[p[i]];
52
- }
53
- return t;
54
- };
55
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
56
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
57
37
  };
@@ -96,10 +76,10 @@ const STATUS = {
96
76
  CLOSED: 'closed',
97
77
  ERRORED: 'errored',
98
78
  };
99
- const QUERY_ONCE_TIMEOUT = 30000;
100
- const PENDING_TX_CLEANUP_TIMEOUT = 30000;
79
+ const QUERY_ONCE_TIMEOUT = 30_000;
80
+ const PENDING_TX_CLEANUP_TIMEOUT = 30_000;
101
81
  const PENDING_MUTATION_CLEANUP_THRESHOLD = 200;
102
- const ONE_MIN_MS = 1000 * 60;
82
+ const ONE_MIN_MS = 1_000 * 60;
103
83
  const defaultConfig = {
104
84
  apiURI: 'https://api.instantdb.com',
105
85
  websocketURI: 'wss://api.instantdb.com/runtime/session',
@@ -148,13 +128,15 @@ const ignoreLogging = {
148
128
  * @returns {QuerySub}
149
129
  */
150
130
  function querySubFromStorage(x, useDateObjects) {
151
- var _a;
152
131
  const v = typeof x === 'string' ? JSON.parse(x) : x;
153
- if ((_a = v === null || v === void 0 ? void 0 : v.result) === null || _a === void 0 ? void 0 : _a.store) {
132
+ if (v?.result?.store) {
154
133
  const attrsStore = s.attrsStoreFromJSON(v.result.attrsStore, v.result.store);
155
134
  if (attrsStore) {
156
135
  const storeJSON = v.result.store;
157
- v.result.store = s.fromJSON(attrsStore, Object.assign(Object.assign({}, storeJSON), { useDateObjects: useDateObjects }));
136
+ v.result.store = s.fromJSON(attrsStore, {
137
+ ...storeJSON,
138
+ useDateObjects: useDateObjects,
139
+ });
158
140
  v.result.attrsStore = attrsStore;
159
141
  }
160
142
  }
@@ -167,11 +149,15 @@ function querySubFromStorage(x, useDateObjects) {
167
149
  * @returns QuerySubInStorage
168
150
  */
169
151
  function querySubToStorage(_key, sub) {
170
- const { result } = sub, rest = __rest(sub, ["result"]);
152
+ const { result, ...rest } = sub;
171
153
  const jsonSub = /** @type {import('./reactorTypes.ts').QuerySubInStorage} */ (rest);
172
154
  if (result) {
173
155
  /** @type {import('./reactorTypes.ts').QuerySubResultInStorage} */
174
- const jsonResult = Object.assign(Object.assign({}, result), { store: s.toJSON(result.store), attrsStore: result.attrsStore.toJSON() });
156
+ const jsonResult = {
157
+ ...result,
158
+ store: s.toJSON(result.store),
159
+ attrsStore: result.attrsStore.toJSON(),
160
+ };
175
161
  jsonSub.result = jsonResult;
176
162
  }
177
163
  return jsonSub;
@@ -193,8 +179,8 @@ function kvToStorage(key, x) {
193
179
  }
194
180
  }
195
181
  function onMergeQuerySub(_k, storageSub, inMemorySub) {
196
- const storageResult = storageSub === null || storageSub === void 0 ? void 0 : storageSub.result;
197
- const memoryResult = inMemorySub === null || inMemorySub === void 0 ? void 0 : inMemorySub.result;
182
+ const storageResult = storageSub?.result;
183
+ const memoryResult = inMemorySub?.result;
198
184
  if (storageResult && !memoryResult && inMemorySub) {
199
185
  inMemorySub.result = storageResult;
200
186
  }
@@ -216,241 +202,72 @@ function sortedMutationEntries(entries) {
216
202
  * @template {import('./presence.ts').RoomSchemaShape} [RoomSchema = {}]
217
203
  */
218
204
  class Reactor {
205
+ /** @type {s.AttrsStore | undefined} */
206
+ attrs;
207
+ _isOnline = true;
208
+ _isShutdown = false;
209
+ status = STATUS.CONNECTING;
210
+ /** @type {PersistedObject<string, QuerySub, QuerySubInStorage>} */
211
+ querySubs;
212
+ /** @type {PersistedObject} */
213
+ kv;
214
+ /** @type {SyncTable} */
215
+ _syncTable;
216
+ /** @type {Record<string, Array<{ q: any, cb: (data: any) => any }>>} */
217
+ queryCbs = {};
218
+ /** @type {Record<string, Array<{ q: any, eventId: string, dfd: Deferred }>>} */
219
+ queryOnceDfds = {};
220
+ authCbs = [];
221
+ attrsCbs = [];
222
+ mutationErrorCbs = [];
223
+ connectionStatusCbs = [];
224
+ config;
225
+ mutationDeferredStore = new Map();
226
+ _reconnectTimeoutId = null;
227
+ _reconnectTimeoutMs = 0;
228
+ /** @type {Connection} */
229
+ _transport;
230
+ /** @type {TransportType} */
231
+ _transportType = 'ws';
232
+ /** @type {EventSourceConstructor} */
233
+ _EventSource;
234
+ /** @type {boolean | null} */
235
+ _wsOk = null;
236
+ _localIdPromises = {};
237
+ _errorMessage = null;
238
+ /** @type {Promise<null | {error: {message: string}}> | null}**/
239
+ _oauthCallbackResponse = null;
240
+ /** @type {null | import('./utils/linkIndex.ts').LinkIndex}} */
241
+ _linkIndex = null;
242
+ /** @type BroadcastChannel | undefined */
243
+ _broadcastChannel;
244
+ /** @type {Record<string, {isConnected: boolean; error: any}>} */
245
+ _rooms = {};
246
+ /** @type {Record<string, boolean>} */
247
+ _roomsPendingLeave = {};
248
+ _presence = {};
249
+ _broadcastQueue = [];
250
+ _broadcastSubs = {};
251
+ /** @type {{isLoading: boolean; error: any | undefined, user: any | undefined}} */
252
+ _currentUserCached = { isLoading: true, error: undefined, user: undefined };
253
+ _beforeUnloadCbs = [];
254
+ _dataForQueryCache = {};
255
+ /** @type {Logger} */
256
+ _log;
257
+ _pendingTxCleanupTimeout;
258
+ _pendingMutationCleanupThreshold;
259
+ _inFlightMutationEventIds = new Set();
219
260
  constructor(config, Storage = IndexedDBStorage_ts_1.default, NetworkListener = WindowNetworkListener_js_1.default, versions, EventSourceConstructor) {
220
- var _a, _b, _c;
221
- this._isOnline = true;
222
- this._isShutdown = false;
223
- this.status = STATUS.CONNECTING;
224
- /** @type {Record<string, Array<{ q: any, cb: (data: any) => any }>>} */
225
- this.queryCbs = {};
226
- /** @type {Record<string, Array<{ q: any, eventId: string, dfd: Deferred }>>} */
227
- this.queryOnceDfds = {};
228
- this.authCbs = [];
229
- this.attrsCbs = [];
230
- this.mutationErrorCbs = [];
231
- this.connectionStatusCbs = [];
232
- this.mutationDeferredStore = new Map();
233
- this._reconnectTimeoutId = null;
234
- this._reconnectTimeoutMs = 0;
235
- /** @type {TransportType} */
236
- this._transportType = 'ws';
237
- /** @type {boolean | null} */
238
- this._wsOk = null;
239
- this._localIdPromises = {};
240
- this._errorMessage = null;
241
- /** @type {Promise<null | {error: {message: string}}> | null}**/
242
- this._oauthCallbackResponse = null;
243
- /** @type {null | import('./utils/linkIndex.ts').LinkIndex}} */
244
- this._linkIndex = null;
245
- /** @type {Record<string, {isConnected: boolean; error: any}>} */
246
- this._rooms = {};
247
- /** @type {Record<string, boolean>} */
248
- this._roomsPendingLeave = {};
249
- this._presence = {};
250
- this._broadcastQueue = [];
251
- this._broadcastSubs = {};
252
- /** @type {{isLoading: boolean; error: any | undefined, user: any | undefined}} */
253
- this._currentUserCached = { isLoading: true, error: undefined, user: undefined };
254
- this._beforeUnloadCbs = [];
255
- this._dataForQueryCache = {};
256
- this._inFlightMutationEventIds = new Set();
257
- this._onMergeKv = (key, storageV, inMemoryV) => {
258
- var _a, _b;
259
- switch (key) {
260
- case 'pendingMutations': {
261
- const storageEntries = (_a = storageV === null || storageV === void 0 ? void 0 : storageV.entries()) !== null && _a !== void 0 ? _a : [];
262
- const inMemoryEntries = (_b = inMemoryV === null || inMemoryV === void 0 ? void 0 : inMemoryV.entries()) !== null && _b !== void 0 ? _b : [];
263
- const muts = new Map([...storageEntries, ...inMemoryEntries]);
264
- const rewrittenStorageMuts = storageV
265
- ? this._rewriteMutationsSorted(this.attrs, storageV)
266
- : [];
267
- rewrittenStorageMuts.forEach(([k, mut]) => {
268
- var _a;
269
- if (!((_a = inMemoryV === null || inMemoryV === void 0 ? void 0 : inMemoryV.pendingMutations) === null || _a === void 0 ? void 0 : _a.has(k)) && !mut['tx-id']) {
270
- this._sendMutation(k, mut);
271
- }
272
- });
273
- return muts;
274
- }
275
- default:
276
- return inMemoryV || storageV;
277
- }
278
- };
279
- // ---------------------------
280
- // Queries
281
- this.getPreviousResult = (q) => {
282
- var _a;
283
- const hash = (0, weakHash_ts_1.default)(q);
284
- return (_a = this.dataForQuery(hash)) === null || _a === void 0 ? void 0 : _a.data;
285
- };
286
- /** Re-run instaql and call all callbacks with new data */
287
- this.notifyOne = (hash) => {
288
- var _a, _b;
289
- const cbs = (_a = this.queryCbs[hash]) !== null && _a !== void 0 ? _a : [];
290
- const prevData = (_b = this._dataForQueryCache[hash]) === null || _b === void 0 ? void 0 : _b.data;
291
- const resp = this.dataForQuery(hash);
292
- if (!(resp === null || resp === void 0 ? void 0 : resp.data))
293
- return;
294
- this._dataForQueryCache[hash] = resp;
295
- if ((0, object_js_1.areObjectsDeepEqual)(resp.data, prevData))
296
- return;
297
- cbs.forEach((r) => r.cb(resp.data));
298
- };
299
- this.notifyOneQueryOnce = (hash) => {
300
- var _a, _b;
301
- const dfds = (_a = this.queryOnceDfds[hash]) !== null && _a !== void 0 ? _a : [];
302
- const data = (_b = this.dataForQuery(hash)) === null || _b === void 0 ? void 0 : _b.data;
303
- dfds.forEach((r) => {
304
- this._completeQueryOnce(r.q, hash, r.dfd);
305
- r.dfd.resolve(data);
306
- });
307
- };
308
- this.notifyQueryError = (hash, error) => {
309
- const cbs = this.queryCbs[hash] || [];
310
- cbs.forEach((r) => r.cb({ error }));
311
- };
312
- /** Applies transactions locally and sends transact message to server */
313
- this.pushTx = (chunks) => {
314
- // Throws if transactions are invalid
315
- if (!this.config.disableValidation) {
316
- (0, transactionValidation_ts_1.validateTransactions)(chunks, this.config.schema);
317
- }
318
- try {
319
- const txSteps = instaml.transform({
320
- attrsStore: this.optimisticAttrs(),
321
- schema: this.config.schema,
322
- 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; }),
323
- useDateObjects: this.config.useDateObjects,
324
- }, chunks);
325
- return this.pushOps(txSteps);
326
- }
327
- catch (e) {
328
- return this.pushOps([], e);
329
- }
330
- };
331
- /**
332
- * @param {*} txSteps
333
- * @param {*} [error]
334
- * @returns
335
- */
336
- this.pushOps = (txSteps, error) => {
337
- const eventId = (0, id_ts_1.default)();
338
- const mutations = [...this._pendingMutations().values()];
339
- const order = Math.max(0, ...mutations.map((mut) => mut.order || 0)) + 1;
340
- const mutation = {
341
- op: 'transact',
342
- 'tx-steps': txSteps,
343
- created: Date.now(),
344
- error,
345
- order,
346
- };
347
- this._updatePendingMutations((prev) => {
348
- prev.set(eventId, mutation);
349
- });
350
- const dfd = new Deferred_js_1.Deferred();
351
- this.mutationDeferredStore.set(eventId, dfd);
352
- this._sendMutation(eventId, mutation);
353
- this.notifyAll();
354
- return dfd.promise;
355
- };
356
- this._transportOnOpen = (e) => {
357
- const targetTransport = e.target;
358
- if (this._transport !== targetTransport) {
359
- this._log.info('[socket][open]', targetTransport.id, 'skip; this is no longer the current transport');
360
- return;
361
- }
362
- this._log.info('[socket][open]', this._transport.id);
363
- this._setStatus(STATUS.OPENED);
364
- this.getCurrentUser()
365
- .then((resp) => {
366
- var _a;
367
- this._trySend((0, id_ts_1.default)(), {
368
- op: 'init',
369
- 'app-id': this.config.appId,
370
- 'refresh-token': (_a = resp.user) === null || _a === void 0 ? void 0 : _a['refresh_token'],
371
- versions: this.versions,
372
- // If an admin token is provided for an app, we will
373
- // skip all permission checks. This is an advanced feature,
374
- // to let users write internal tools
375
- // This option is not exposed in `Config`, as it's
376
- // not ready for prime time
377
- '__admin-token': this.config.__adminToken,
378
- });
379
- })
380
- .catch((e) => {
381
- this._log.error('[socket][error]', targetTransport.id, e);
382
- });
383
- };
384
- this._transportOnMessage = (e) => {
385
- const targetTransport = e.target;
386
- const m = e.message;
387
- if (this._transport !== targetTransport) {
388
- this._log.info('[socket][message]', targetTransport.id, m, 'skip; this is no longer the current transport');
389
- return;
390
- }
391
- if (!this._wsOk && targetTransport.type === 'ws') {
392
- this._wsOk = true;
393
- }
394
- // Try to reconnect via websocket the next time we connect
395
- this._transportType = 'ws';
396
- if (Array.isArray(e.message)) {
397
- for (const msg of e.message) {
398
- this._handleReceive(targetTransport.id, msg);
399
- }
400
- }
401
- else {
402
- this._handleReceive(targetTransport.id, e.message);
403
- }
404
- };
405
- this._transportOnError = (e) => {
406
- const targetTransport = e.target;
407
- if (this._transport !== targetTransport) {
408
- this._log.info('[socket][error]', targetTransport.id, 'skip; this is no longer the current transport');
409
- return;
410
- }
411
- this._log.error('[socket][error]', targetTransport.id, e);
412
- };
413
- this._scheduleReconnect = () => {
414
- // If we couldn't connect with a websocket last time, try sse
415
- if (!this._wsOk && this._transportType !== 'sse') {
416
- this._transportType = 'sse';
417
- this._reconnectTimeoutMs = 0;
418
- }
419
- setTimeout(() => {
420
- this._reconnectTimeoutMs = Math.min(this._reconnectTimeoutMs + 1000, 10000);
421
- if (!this._isOnline) {
422
- this._log.info('[socket][close]', this._transport.id, 'we are offline, no need to start socket');
423
- return;
424
- }
425
- this._startSocket();
426
- }, this._reconnectTimeoutMs);
427
- };
428
- this._transportOnClose = (e) => {
429
- const targetTransport = e.target;
430
- if (this._transport !== targetTransport) {
431
- this._log.info('[socket][close]', targetTransport.id, 'skip; this is no longer the current transport');
432
- return;
433
- }
434
- this._setStatus(STATUS.CLOSED);
435
- for (const room of Object.values(this._rooms)) {
436
- room.isConnected = false;
437
- }
438
- if (this._isShutdown) {
439
- this._log.info('[socket][close]', targetTransport.id, 'Reactor has been shut down and will not reconnect');
440
- return;
441
- }
442
- this._log.info('[socket][close]', targetTransport.id, 'schedule reconnect, ms =', this._reconnectTimeoutMs);
443
- this._scheduleReconnect();
444
- };
445
261
  this._EventSource = EventSourceConstructor;
446
- this.config = Object.assign(Object.assign({}, defaultConfig), config);
447
- this.queryCacheLimit = (_a = this.config.queryCacheLimit) !== null && _a !== void 0 ? _a : 10;
262
+ this.config = { ...defaultConfig, ...config };
263
+ this.queryCacheLimit = this.config.queryCacheLimit ?? 10;
448
264
  this._pendingTxCleanupTimeout =
449
- (_b = this.config.pendingTxCleanupTimeout) !== null && _b !== void 0 ? _b : PENDING_TX_CLEANUP_TIMEOUT;
265
+ this.config.pendingTxCleanupTimeout ?? PENDING_TX_CLEANUP_TIMEOUT;
450
266
  this._pendingMutationCleanupThreshold =
451
- (_c = this.config.pendingMutationCleanupThreshold) !== null && _c !== void 0 ? _c : PENDING_MUTATION_CLEANUP_THRESHOLD;
267
+ this.config.pendingMutationCleanupThreshold ??
268
+ PENDING_MUTATION_CLEANUP_THRESHOLD;
452
269
  this._log = (0, log_ts_1.default)(config.verbose || flags.devBackend || flags.instantLogs, () => this._reactorStats());
453
- this.versions = Object.assign(Object.assign({}, (versions || {})), { '@instantdb/core': version_ts_1.default });
270
+ this.versions = { ...(versions || {}), '@instantdb/core': version_ts_1.default };
454
271
  if (this.config.schema) {
455
272
  this._linkIndex = (0, linkIndex_ts_1.createLinkIndex)(this.config.schema);
456
273
  }
@@ -467,18 +284,17 @@ class Reactor {
467
284
  }
468
285
  if (typeof BroadcastChannel === 'function') {
469
286
  this._broadcastChannel = new BroadcastChannel('@instantdb');
470
- this._broadcastChannel.addEventListener('message', (e) => __awaiter(this, void 0, void 0, function* () {
471
- var _a;
287
+ this._broadcastChannel.addEventListener('message', async (e) => {
472
288
  try {
473
- if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === 'auth') {
474
- const res = yield this.getCurrentUser();
289
+ if (e.data?.type === 'auth') {
290
+ const res = await this.getCurrentUser();
475
291
  this.updateUser(res.user);
476
292
  }
477
293
  }
478
294
  catch (e) {
479
295
  this._log.error('[error] handle broadcast channel', e);
480
296
  }
481
- }));
297
+ });
482
298
  }
483
299
  this._initStorage(Storage);
484
300
  this._syncTable = new SyncTable_ts_1.SyncTable(this._trySendAuthed.bind(this), new Storage(this.config.appId, 'syncSubs'), {
@@ -491,10 +307,10 @@ class Reactor {
491
307
  this.getCurrentUser().then((userInfo) => {
492
308
  this.syncUserToEndpoint(userInfo.user);
493
309
  });
494
- setInterval(() => __awaiter(this, void 0, void 0, function* () {
495
- const currentUser = yield this.getCurrentUser();
310
+ setInterval(async () => {
311
+ const currentUser = await this.getCurrentUser();
496
312
  this.syncUserToEndpoint(currentUser.user);
497
- }), ONE_MIN_MS);
313
+ }, ONE_MIN_MS);
498
314
  NetworkListener.getIsOnline().then((isOnline) => {
499
315
  this._isOnline = isOnline;
500
316
  this._startSocket();
@@ -528,7 +344,11 @@ class Reactor {
528
344
  return this.attrs;
529
345
  }
530
346
  updateSchema(schema) {
531
- this.config = Object.assign(Object.assign({}, this.config), { schema: schema, cardinalityInference: Boolean(schema) });
347
+ this.config = {
348
+ ...this.config,
349
+ schema: schema,
350
+ cardinalityInference: Boolean(schema),
351
+ };
532
352
  this._linkIndex = schema ? (0, linkIndex_ts_1.createLinkIndex)(this.config.schema) : null;
533
353
  }
534
354
  _reactorStats() {
@@ -550,14 +370,14 @@ class Reactor {
550
370
  serialize: querySubToStorage,
551
371
  parse: (_key, x) => querySubFromStorage(x, this.config.useDateObjects),
552
372
  // objectSize
553
- 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; },
373
+ objectSize: (x) => x?.result?.store?.triples?.length ?? 0,
554
374
  logger: this._log,
555
375
  preloadEntryCount: 10,
556
376
  gc: {
557
377
  maxAgeMs: 1000 * 60 * 60 * 24 * 7 * 52, // 1 year
558
378
  maxEntries: 1000,
559
379
  // Size of each query is the number of triples
560
- maxSize: 1000000, // 1 million triples
380
+ maxSize: 1_000_000, // 1 million triples
561
381
  },
562
382
  });
563
383
  this.querySubs.onKeyLoaded = (k) => this._onQuerySubLoaded(k);
@@ -603,7 +423,7 @@ class Reactor {
603
423
  const ok = status !== 'error' && status !== 'timeout';
604
424
  if (!dfd && !ok) {
605
425
  // console.erroring here, as there are no listeners to let know
606
- console.error('Mutation failed', Object.assign({ status, eventId }, errorMsg));
426
+ console.error('Mutation failed', { status, eventId, ...errorMsg });
607
427
  }
608
428
  if (!dfd) {
609
429
  return;
@@ -613,16 +433,16 @@ class Reactor {
613
433
  }
614
434
  else {
615
435
  // Check if error comes from server or client
616
- if (errorMsg === null || errorMsg === void 0 ? void 0 : errorMsg.type) {
617
- const { status } = errorMsg, body = __rest(errorMsg, ["status"]);
436
+ if (errorMsg?.type) {
437
+ const { status, ...body } = errorMsg;
618
438
  dfd.reject(new fetch_ts_1.InstantAPIError({
619
439
  // @ts-expect-error body.type is not constant typed
620
440
  body,
621
- status: status !== null && status !== void 0 ? status : 0,
441
+ status: status ?? 0,
622
442
  }));
623
443
  }
624
444
  else {
625
- dfd.reject(new InstantError_ts_1.InstantError((errorMsg === null || errorMsg === void 0 ? void 0 : errorMsg.message) || 'Unknown error', errorMsg === null || errorMsg === void 0 ? void 0 : errorMsg.hint));
445
+ dfd.reject(new InstantError_ts_1.InstantError(errorMsg?.message || 'Unknown error', errorMsg?.hint));
626
446
  }
627
447
  }
628
448
  }
@@ -631,9 +451,28 @@ class Reactor {
631
451
  this._errorMessage = err;
632
452
  this.notifyConnectionStatusSubs(status);
633
453
  }
454
+ _onMergeKv = (key, storageV, inMemoryV) => {
455
+ switch (key) {
456
+ case 'pendingMutations': {
457
+ const storageEntries = storageV?.entries() ?? [];
458
+ const inMemoryEntries = inMemoryV?.entries() ?? [];
459
+ const muts = new Map([...storageEntries, ...inMemoryEntries]);
460
+ const rewrittenStorageMuts = storageV
461
+ ? this._rewriteMutationsSorted(this.attrs, storageV)
462
+ : [];
463
+ rewrittenStorageMuts.forEach(([k, mut]) => {
464
+ if (!inMemoryV?.pendingMutations?.has(k) && !mut['tx-id']) {
465
+ this._sendMutation(k, mut);
466
+ }
467
+ });
468
+ return muts;
469
+ }
470
+ default:
471
+ return inMemoryV || storageV;
472
+ }
473
+ };
634
474
  _flushEnqueuedRoomData(roomId) {
635
- var _a, _b;
636
- const enqueuedUserPresence = (_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.user;
475
+ const enqueuedUserPresence = this._presence[roomId]?.result?.user;
637
476
  const enqueuedBroadcasts = this._broadcastQueue[roomId];
638
477
  this._broadcastQueue[roomId] = [];
639
478
  if (enqueuedUserPresence) {
@@ -678,7 +517,6 @@ class Reactor {
678
517
  this._cleanupPendingMutationsTimeout();
679
518
  }
680
519
  _handleReceive(connId, msg) {
681
- var _a, _b, _c, _d, _e, _f;
682
520
  // opt-out, enabled by default if schema
683
521
  const enableCardinalityInference = Boolean(this.config.schema) &&
684
522
  ('cardinalityInference' in this.config
@@ -697,7 +535,7 @@ class Reactor {
697
535
  // which item is us
698
536
  this._sessionId = msg['session-id'];
699
537
  for (const roomId of Object.keys(this._rooms)) {
700
- const enqueuedUserPresence = (_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.user;
538
+ const enqueuedUserPresence = this._presence[roomId]?.result?.user;
701
539
  this._tryJoinRoom(roomId, enqueuedUserPresence);
702
540
  }
703
541
  break;
@@ -712,8 +550,8 @@ class Reactor {
712
550
  if (!this._hasQueryListeners() && !this.querySubs.currentValue[hash]) {
713
551
  break;
714
552
  }
715
- 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'];
716
- 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'];
553
+ const pageInfo = result?.[0]?.data?.['page-info'];
554
+ const aggregate = result?.[0]?.data?.['aggregate'];
717
555
  const triples = (0, instaqlResult_js_1.extractTriples)(result);
718
556
  const attrsStore = this.ensureAttrs();
719
557
  const store = s.createStore(attrsStore, triples, enableCardinalityInference, this.config.useDateObjects);
@@ -770,7 +608,6 @@ class Reactor {
770
608
  }
771
609
  const mutations = sortedMutationEntries(rewrittenMutations.entries());
772
610
  const updates = computations.map((x) => {
773
- var _a, _b, _c, _d;
774
611
  const q = x['instaql-query'];
775
612
  const result = x['instaql-result'];
776
613
  const hash = (0, weakHash_ts_1.default)(q);
@@ -778,8 +615,8 @@ class Reactor {
778
615
  const attrsStore = this.ensureAttrs();
779
616
  const store = s.createStore(attrsStore, triples, enableCardinalityInference, this.config.useDateObjects);
780
617
  const { store: newStore, attrsStore: newAttrsStore } = this._applyOptimisticUpdates(store, attrsStore, mutations, processedTxId);
781
- 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'];
782
- 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'];
618
+ const pageInfo = result?.[0]?.data?.['page-info'];
619
+ const aggregate = result?.[0]?.data?.['aggregate'];
783
620
  return {
784
621
  q,
785
622
  hash,
@@ -820,7 +657,11 @@ class Reactor {
820
657
  }
821
658
  // update pendingMutation with server-side tx-id
822
659
  this._updatePendingMutations((prev) => {
823
- prev.set(eventId, Object.assign(Object.assign({}, prev.get(eventId)), { 'tx-id': txId, confirmed: Date.now() }));
660
+ prev.set(eventId, {
661
+ ...prev.get(eventId),
662
+ 'tx-id': txId,
663
+ confirmed: Date.now(),
664
+ });
824
665
  });
825
666
  const newAttrs = [];
826
667
  for (const step of prevMutation['tx-steps']) {
@@ -894,13 +735,11 @@ class Reactor {
894
735
  }
895
736
  }
896
737
  _pendingMutations() {
897
- var _a;
898
- return (_a = this.kv.currentValue.pendingMutations) !== null && _a !== void 0 ? _a : new Map();
738
+ return this.kv.currentValue.pendingMutations ?? new Map();
899
739
  }
900
740
  _updatePendingMutations(f) {
901
741
  this.kv.updateInPlace((prev) => {
902
- var _a;
903
- const muts = (_a = prev.pendingMutations) !== null && _a !== void 0 ? _a : new Map();
742
+ const muts = prev.pendingMutations ?? new Map();
904
743
  prev.pendingMutations = muts;
905
744
  f(muts);
906
745
  });
@@ -929,7 +768,6 @@ class Reactor {
929
768
  }
930
769
  }
931
770
  _handleReceiveError(msg) {
932
- var _a, _b, _c, _d, _e, _f, _g;
933
771
  console.log('error', msg);
934
772
  const eventId = msg['client-event-id'];
935
773
  // This might not be a mutation, but it can't hurt to delete it
@@ -945,18 +783,18 @@ class Reactor {
945
783
  this._handleMutationError('error', eventId, msg);
946
784
  return;
947
785
  }
948
- if (((_a = msg['original-event']) === null || _a === void 0 ? void 0 : _a.hasOwnProperty('q')) &&
949
- ((_b = msg['original-event']) === null || _b === void 0 ? void 0 : _b.op) === 'add-query') {
950
- const q = (_c = msg['original-event']) === null || _c === void 0 ? void 0 : _c.q;
786
+ if (msg['original-event']?.hasOwnProperty('q') &&
787
+ msg['original-event']?.op === 'add-query') {
788
+ const q = msg['original-event']?.q;
951
789
  const hash = (0, weakHash_ts_1.default)(q);
952
790
  this.notifyQueryError((0, weakHash_ts_1.default)(q), errorMessage);
953
791
  this.notifyQueryOnceError(q, hash, eventId, errorMessage);
954
792
  return;
955
793
  }
956
- const isInitError = ((_d = msg['original-event']) === null || _d === void 0 ? void 0 : _d.op) === 'init';
794
+ const isInitError = msg['original-event']?.op === 'init';
957
795
  if (isInitError) {
958
796
  if (msg.type === 'record-not-found' &&
959
- ((_e = msg.hint) === null || _e === void 0 ? void 0 : _e['record-type']) === 'app-user') {
797
+ msg.hint?.['record-type'] === 'app-user') {
960
798
  // User has been logged out
961
799
  this.changeCurrentUser(null);
962
800
  return;
@@ -966,17 +804,17 @@ class Reactor {
966
804
  this.notifyAll();
967
805
  return;
968
806
  }
969
- if (((_f = msg['original-event']) === null || _f === void 0 ? void 0 : _f.op) === 'resync-table') {
807
+ if (msg['original-event']?.op === 'resync-table') {
970
808
  this._syncTable.onResyncError(msg);
971
809
  return;
972
810
  }
973
- if (((_g = msg['original-event']) === null || _g === void 0 ? void 0 : _g.op) === 'start-sync') {
811
+ if (msg['original-event']?.op === 'start-sync') {
974
812
  this._syncTable.onStartSyncError(msg);
975
813
  return;
976
814
  }
977
815
  // We've caught some error which has no corresponding listener.
978
816
  // Let's console.error to let the user know.
979
- const errorObj = Object.assign({}, msg);
817
+ const errorObj = { ...msg };
980
818
  delete errorObj.message;
981
819
  delete errorObj.hint;
982
820
  console.error(msg.message, errorObj);
@@ -985,8 +823,7 @@ class Reactor {
985
823
  }
986
824
  }
987
825
  notifyQueryOnceError(q, hash, eventId, e) {
988
- var _a;
989
- const r = (_a = this.queryOnceDfds[hash]) === null || _a === void 0 ? void 0 : _a.find((r) => r.eventId === eventId);
826
+ const r = this.queryOnceDfds[hash]?.find((r) => r.eventId === eventId);
990
827
  if (!r)
991
828
  return;
992
829
  r.dfd.reject(e);
@@ -999,6 +836,12 @@ class Reactor {
999
836
  }, {}), this._linkIndex);
1000
837
  this.notifyAttrsSubs();
1001
838
  }
839
+ // ---------------------------
840
+ // Queries
841
+ getPreviousResult = (q) => {
842
+ const hash = (0, weakHash_ts_1.default)(q);
843
+ return this.dataForQuery(hash)?.data;
844
+ };
1002
845
  _startQuerySub(q, hash) {
1003
846
  const eventId = (0, id_ts_1.default)();
1004
847
  this.querySubs.updateInPlace((prev) => {
@@ -1022,19 +865,18 @@ class Reactor {
1022
865
  * Returns an unsubscribe function
1023
866
  */
1024
867
  subscribeQuery(q, cb, opts) {
1025
- var _a;
1026
868
  if (!this.config.disableValidation) {
1027
869
  (0, queryValidation_ts_1.validateQuery)(q, this.config.schema);
1028
870
  }
1029
871
  if (opts && 'ruleParams' in opts) {
1030
- q = Object.assign({ $$ruleParams: opts['ruleParams'] }, q);
872
+ q = { $$ruleParams: opts['ruleParams'], ...q };
1031
873
  }
1032
874
  const hash = (0, weakHash_ts_1.default)(q);
1033
875
  const prevResult = this.getPreviousResult(q);
1034
876
  if (prevResult) {
1035
877
  cb(prevResult);
1036
878
  }
1037
- this.queryCbs[hash] = (_a = this.queryCbs[hash]) !== null && _a !== void 0 ? _a : [];
879
+ this.queryCbs[hash] = this.queryCbs[hash] ?? [];
1038
880
  this.queryCbs[hash].push({ q, cb });
1039
881
  this._startQuerySub(q, hash);
1040
882
  return () => {
@@ -1042,12 +884,11 @@ class Reactor {
1042
884
  };
1043
885
  }
1044
886
  queryOnce(q, opts) {
1045
- var _a;
1046
887
  if (!this.config.disableValidation) {
1047
888
  (0, queryValidation_ts_1.validateQuery)(q, this.config.schema);
1048
889
  }
1049
890
  if (opts && 'ruleParams' in opts) {
1050
- q = Object.assign({ $$ruleParams: opts['ruleParams'] }, q);
891
+ q = { $$ruleParams: opts['ruleParams'], ...q };
1051
892
  }
1052
893
  const dfd = new Deferred_js_1.Deferred();
1053
894
  if (!this._isOnline) {
@@ -1060,7 +901,7 @@ class Reactor {
1060
901
  }
1061
902
  const hash = (0, weakHash_ts_1.default)(q);
1062
903
  const eventId = this._startQuerySub(q, hash);
1063
- this.queryOnceDfds[hash] = (_a = this.queryOnceDfds[hash]) !== null && _a !== void 0 ? _a : [];
904
+ this.queryOnceDfds[hash] = this.queryOnceDfds[hash] ?? [];
1064
905
  this.queryOnceDfds[hash].push({ q, dfd, eventId });
1065
906
  setTimeout(() => dfd.reject(new Error('Query timed out')), QUERY_ONCE_TIMEOUT);
1066
907
  return dfd.promise;
@@ -1078,8 +919,7 @@ class Reactor {
1078
919
  this._cleanupQuery(q, hash);
1079
920
  }
1080
921
  _hasQueryListeners(hash) {
1081
- var _a, _b;
1082
- return !!(((_a = this.queryCbs[hash]) === null || _a === void 0 ? void 0 : _a.length) || ((_b = this.queryOnceDfds[hash]) === null || _b === void 0 ? void 0 : _b.length));
922
+ return !!(this.queryCbs[hash]?.length || this.queryOnceDfds[hash]?.length);
1083
923
  }
1084
924
  _cleanupQuery(q, hash) {
1085
925
  const hasListeners = this._hasQueryListeners(hash);
@@ -1171,7 +1011,10 @@ class Reactor {
1171
1011
  };
1172
1012
  const rewritten = new Map();
1173
1013
  for (const [k, mut] of muts.entries()) {
1174
- rewritten.set(k, Object.assign(Object.assign({}, mut), { 'tx-steps': rewriteTxSteps(mut['tx-steps'], mut['tx-id']) }));
1014
+ rewritten.set(k, {
1015
+ ...mut,
1016
+ 'tx-steps': rewriteTxSteps(mut['tx-steps'], mut['tx-id']),
1017
+ });
1175
1018
  }
1176
1019
  if (!mappingChanged) {
1177
1020
  return muts;
@@ -1187,7 +1030,6 @@ class Reactor {
1187
1030
  * @returns {s.AttrsStore}
1188
1031
  */
1189
1032
  optimisticAttrs() {
1190
- var _a, _b;
1191
1033
  const pendingMutationSteps = [...this._pendingMutations().values()] // hack due to Map()
1192
1034
  .flatMap((x) => x['tx-steps']);
1193
1035
  const deletedAttrIds = new Set(pendingMutationSteps
@@ -1200,15 +1042,15 @@ class Reactor {
1200
1042
  }
1201
1043
  else if (_action === 'update-attr' &&
1202
1044
  attr.id &&
1203
- ((_a = this.attrs) === null || _a === void 0 ? void 0 : _a.getAttr(attr.id))) {
1204
- const fullAttr = Object.assign(Object.assign({}, this.attrs.getAttr(attr.id)), attr);
1045
+ this.attrs?.getAttr(attr.id)) {
1046
+ const fullAttr = { ...this.attrs.getAttr(attr.id), ...attr };
1205
1047
  pendingAttrs.push(fullAttr);
1206
1048
  }
1207
1049
  }
1208
1050
  if (!deletedAttrIds.size && !pendingAttrs.length) {
1209
1051
  return this.attrs || new s.AttrsStoreClass({}, this._linkIndex);
1210
1052
  }
1211
- const attrs = Object.assign({}, (((_b = this.attrs) === null || _b === void 0 ? void 0 : _b.attrs) || {}));
1053
+ const attrs = { ...(this.attrs?.attrs || {}) };
1212
1054
  for (const attr of pendingAttrs) {
1213
1055
  attrs[attr.id] = attr;
1214
1056
  }
@@ -1262,6 +1104,30 @@ class Reactor {
1262
1104
  }
1263
1105
  return { store, attrsStore };
1264
1106
  }
1107
+ /** Re-run instaql and call all callbacks with new data */
1108
+ notifyOne = (hash) => {
1109
+ const cbs = this.queryCbs[hash] ?? [];
1110
+ const prevData = this._dataForQueryCache[hash]?.data;
1111
+ const resp = this.dataForQuery(hash);
1112
+ if (!resp?.data)
1113
+ return;
1114
+ this._dataForQueryCache[hash] = resp;
1115
+ if ((0, object_js_1.areObjectsDeepEqual)(resp.data, prevData))
1116
+ return;
1117
+ cbs.forEach((r) => r.cb(resp.data));
1118
+ };
1119
+ notifyOneQueryOnce = (hash) => {
1120
+ const dfds = this.queryOnceDfds[hash] ?? [];
1121
+ const data = this.dataForQuery(hash)?.data;
1122
+ dfds.forEach((r) => {
1123
+ this._completeQueryOnce(r.q, hash, r.dfd);
1124
+ r.dfd.resolve(data);
1125
+ });
1126
+ };
1127
+ notifyQueryError = (hash, error) => {
1128
+ const cbs = this.queryCbs[hash] || [];
1129
+ cbs.forEach((r) => r.cb({ error }));
1130
+ };
1265
1131
  /** Re-compute all subscriptions */
1266
1132
  notifyAll() {
1267
1133
  Object.keys(this.queryCbs).forEach((hash) => {
@@ -1277,11 +1143,54 @@ class Reactor {
1277
1143
  .then(() => this.notifyAll())
1278
1144
  .catch(() => this.notifyAll());
1279
1145
  }
1146
+ /** Applies transactions locally and sends transact message to server */
1147
+ pushTx = (chunks) => {
1148
+ // Throws if transactions are invalid
1149
+ if (!this.config.disableValidation) {
1150
+ (0, transactionValidation_ts_1.validateTransactions)(chunks, this.config.schema);
1151
+ }
1152
+ try {
1153
+ const txSteps = instaml.transform({
1154
+ attrsStore: this.optimisticAttrs(),
1155
+ schema: this.config.schema,
1156
+ stores: Object.values(this.querySubs.currentValue).map((sub) => sub?.result?.store),
1157
+ useDateObjects: this.config.useDateObjects,
1158
+ }, chunks);
1159
+ return this.pushOps(txSteps);
1160
+ }
1161
+ catch (e) {
1162
+ return this.pushOps([], e);
1163
+ }
1164
+ };
1165
+ /**
1166
+ * @param {*} txSteps
1167
+ * @param {*} [error]
1168
+ * @returns
1169
+ */
1170
+ pushOps = (txSteps, error) => {
1171
+ const eventId = (0, id_ts_1.default)();
1172
+ const mutations = [...this._pendingMutations().values()];
1173
+ const order = Math.max(0, ...mutations.map((mut) => mut.order || 0)) + 1;
1174
+ const mutation = {
1175
+ op: 'transact',
1176
+ 'tx-steps': txSteps,
1177
+ created: Date.now(),
1178
+ error,
1179
+ order,
1180
+ };
1181
+ this._updatePendingMutations((prev) => {
1182
+ prev.set(eventId, mutation);
1183
+ });
1184
+ const dfd = new Deferred_js_1.Deferred();
1185
+ this.mutationDeferredStore.set(eventId, dfd);
1186
+ this._sendMutation(eventId, mutation);
1187
+ this.notifyAll();
1188
+ return dfd.promise;
1189
+ };
1280
1190
  shutdown() {
1281
- var _a;
1282
1191
  this._log.info('[shutdown]', this.config.appId);
1283
1192
  this._isShutdown = true;
1284
- (_a = this._transport) === null || _a === void 0 ? void 0 : _a.close();
1193
+ this._transport?.close();
1285
1194
  }
1286
1195
  /**
1287
1196
  * Sends mutation to server and schedules a timeout to cancel it if
@@ -1354,8 +1263,8 @@ class Reactor {
1354
1263
  _cleanupPendingMutationsQueries() {
1355
1264
  let minProcessedTxId = Number.MAX_SAFE_INTEGER;
1356
1265
  for (const { result } of Object.values(this.querySubs.currentValue)) {
1357
- if (result === null || result === void 0 ? void 0 : result.processedTxId) {
1358
- minProcessedTxId = Math.min(minProcessedTxId, result === null || result === void 0 ? void 0 : result.processedTxId);
1266
+ if (result?.processedTxId) {
1267
+ minProcessedTxId = Math.min(minProcessedTxId, result?.processedTxId);
1359
1268
  }
1360
1269
  }
1361
1270
  this._updatePendingMutations((prev) => {
@@ -1408,8 +1317,96 @@ class Reactor {
1408
1317
  this._inFlightMutationEventIds.clear();
1409
1318
  }
1410
1319
  }
1411
- this._transport.send(Object.assign({ 'client-event-id': eventId }, msg));
1320
+ this._transport.send({ 'client-event-id': eventId, ...msg });
1412
1321
  }
1322
+ _transportOnOpen = (e) => {
1323
+ const targetTransport = e.target;
1324
+ if (this._transport !== targetTransport) {
1325
+ this._log.info('[socket][open]', targetTransport.id, 'skip; this is no longer the current transport');
1326
+ return;
1327
+ }
1328
+ this._log.info('[socket][open]', this._transport.id);
1329
+ this._setStatus(STATUS.OPENED);
1330
+ this.getCurrentUser()
1331
+ .then((resp) => {
1332
+ this._trySend((0, id_ts_1.default)(), {
1333
+ op: 'init',
1334
+ 'app-id': this.config.appId,
1335
+ 'refresh-token': resp.user?.['refresh_token'],
1336
+ versions: this.versions,
1337
+ // If an admin token is provided for an app, we will
1338
+ // skip all permission checks. This is an advanced feature,
1339
+ // to let users write internal tools
1340
+ // This option is not exposed in `Config`, as it's
1341
+ // not ready for prime time
1342
+ '__admin-token': this.config.__adminToken,
1343
+ });
1344
+ })
1345
+ .catch((e) => {
1346
+ this._log.error('[socket][error]', targetTransport.id, e);
1347
+ });
1348
+ };
1349
+ _transportOnMessage = (e) => {
1350
+ const targetTransport = e.target;
1351
+ const m = e.message;
1352
+ if (this._transport !== targetTransport) {
1353
+ this._log.info('[socket][message]', targetTransport.id, m, 'skip; this is no longer the current transport');
1354
+ return;
1355
+ }
1356
+ if (!this._wsOk && targetTransport.type === 'ws') {
1357
+ this._wsOk = true;
1358
+ }
1359
+ // Try to reconnect via websocket the next time we connect
1360
+ this._transportType = 'ws';
1361
+ if (Array.isArray(e.message)) {
1362
+ for (const msg of e.message) {
1363
+ this._handleReceive(targetTransport.id, msg);
1364
+ }
1365
+ }
1366
+ else {
1367
+ this._handleReceive(targetTransport.id, e.message);
1368
+ }
1369
+ };
1370
+ _transportOnError = (e) => {
1371
+ const targetTransport = e.target;
1372
+ if (this._transport !== targetTransport) {
1373
+ this._log.info('[socket][error]', targetTransport.id, 'skip; this is no longer the current transport');
1374
+ return;
1375
+ }
1376
+ this._log.error('[socket][error]', targetTransport.id, e);
1377
+ };
1378
+ _scheduleReconnect = () => {
1379
+ // If we couldn't connect with a websocket last time, try sse
1380
+ if (!this._wsOk && this._transportType !== 'sse') {
1381
+ this._transportType = 'sse';
1382
+ this._reconnectTimeoutMs = 0;
1383
+ }
1384
+ setTimeout(() => {
1385
+ this._reconnectTimeoutMs = Math.min(this._reconnectTimeoutMs + 1000, 10000);
1386
+ if (!this._isOnline) {
1387
+ this._log.info('[socket][close]', this._transport.id, 'we are offline, no need to start socket');
1388
+ return;
1389
+ }
1390
+ this._startSocket();
1391
+ }, this._reconnectTimeoutMs);
1392
+ };
1393
+ _transportOnClose = (e) => {
1394
+ const targetTransport = e.target;
1395
+ if (this._transport !== targetTransport) {
1396
+ this._log.info('[socket][close]', targetTransport.id, 'skip; this is no longer the current transport');
1397
+ return;
1398
+ }
1399
+ this._setStatus(STATUS.CLOSED);
1400
+ for (const room of Object.values(this._rooms)) {
1401
+ room.isConnected = false;
1402
+ }
1403
+ if (this._isShutdown) {
1404
+ this._log.info('[socket][close]', targetTransport.id, 'Reactor has been shut down and will not reconnect');
1405
+ return;
1406
+ }
1407
+ this._log.info('[socket][close]', targetTransport.id, 'schedule reconnect, ms =', this._reconnectTimeoutMs);
1408
+ this._scheduleReconnect();
1409
+ };
1413
1410
  _startSocket() {
1414
1411
  // Reset whether we support websockets each time we connect
1415
1412
  // new networks may not support websockets
@@ -1438,7 +1435,7 @@ class Reactor {
1438
1435
  this._transport.onclose = this._transportOnClose;
1439
1436
  this._transport.onerror = this._transportOnError;
1440
1437
  this._log.info('[socket][start]', this._transport.id);
1441
- if (prevTransport === null || prevTransport === void 0 ? void 0 : prevTransport.isOpen()) {
1438
+ if (prevTransport?.isOpen()) {
1442
1439
  // When the network dies, it doesn't always mean that our
1443
1440
  // socket connection will fire a close event.
1444
1441
  //
@@ -1459,24 +1456,22 @@ class Reactor {
1459
1456
  * Note: If the user deletes their local storage, this id will change.
1460
1457
  *
1461
1458
  */
1462
- getLocalId(name) {
1463
- return __awaiter(this, void 0, void 0, function* () {
1464
- const k = `localToken_${name}`;
1465
- if (this.kv.currentValue[k]) {
1466
- return this.kv.currentValue[k];
1467
- }
1468
- const current = yield this.kv.waitForKeyToLoad(k);
1469
- if (current) {
1470
- return current;
1471
- }
1472
- const newId = (0, id_ts_1.default)();
1473
- this.kv.updateInPlace((prev) => {
1474
- if (prev[k])
1475
- return;
1476
- prev[k] = newId;
1477
- });
1478
- return yield this.kv.waitForKeyToLoad(k);
1459
+ async getLocalId(name) {
1460
+ const k = `localToken_${name}`;
1461
+ if (this.kv.currentValue[k]) {
1462
+ return this.kv.currentValue[k];
1463
+ }
1464
+ const current = await this.kv.waitForKeyToLoad(k);
1465
+ if (current) {
1466
+ return current;
1467
+ }
1468
+ const newId = (0, id_ts_1.default)();
1469
+ this.kv.updateInPlace((prev) => {
1470
+ if (prev[k])
1471
+ return;
1472
+ prev[k] = newId;
1479
1473
  });
1474
+ return await this.kv.waitForKeyToLoad(k);
1480
1475
  }
1481
1476
  // ----
1482
1477
  // Auth
@@ -1511,14 +1506,13 @@ class Reactor {
1511
1506
  // The next.js app router will reset the URL when the router loads.
1512
1507
  // This puts it back after the router loads.
1513
1508
  const listener = (e) => {
1514
- var _a;
1515
1509
  if (!ran) {
1516
1510
  ran = true;
1517
1511
  // @ts-ignore (waiting for ts support)
1518
1512
  navigation.removeEventListener('navigate', listener);
1519
1513
  if (!e.userInitiated &&
1520
1514
  e.navigationType === 'replace' &&
1521
- ((_a = e.destination) === null || _a === void 0 ? void 0 : _a.url) === startUrl) {
1515
+ e.destination?.url === startUrl) {
1522
1516
  history.replaceState(history.state, '', newPath);
1523
1517
  }
1524
1518
  }
@@ -1532,57 +1526,52 @@ class Reactor {
1532
1526
  *
1533
1527
  * @returns Promise<null | {error: {message: string}}>
1534
1528
  */
1535
- _oauthLoginInit() {
1536
- return __awaiter(this, void 0, void 0, function* () {
1537
- var _a, _b, _c, _d;
1538
- if (typeof window === 'undefined' ||
1539
- typeof window.location === 'undefined' ||
1540
- typeof URLSearchParams === 'undefined') {
1541
- return null;
1542
- }
1543
- const params = new URLSearchParams(window.location.search);
1544
- if (!params.get(OAUTH_REDIRECT_PARAM)) {
1545
- return null;
1546
- }
1547
- const error = params.get('error');
1548
- if (error) {
1549
- this._replaceUrlAfterOAuth();
1550
- return { error: { message: error } };
1551
- }
1552
- const code = params.get('code');
1553
- if (!code) {
1554
- return null;
1555
- }
1529
+ async _oauthLoginInit() {
1530
+ if (typeof window === 'undefined' ||
1531
+ typeof window.location === 'undefined' ||
1532
+ typeof URLSearchParams === 'undefined') {
1533
+ return null;
1534
+ }
1535
+ const params = new URLSearchParams(window.location.search);
1536
+ if (!params.get(OAUTH_REDIRECT_PARAM)) {
1537
+ return null;
1538
+ }
1539
+ const error = params.get('error');
1540
+ if (error) {
1556
1541
  this._replaceUrlAfterOAuth();
1557
- try {
1558
- const currentUser = yield this._getCurrentUser();
1559
- const isGuest = (currentUser === null || currentUser === void 0 ? void 0 : currentUser.type) === 'guest';
1560
- const { user } = yield authAPI.exchangeCodeForToken({
1561
- apiURI: this.config.apiURI,
1562
- appId: this.config.appId,
1563
- code,
1564
- refreshToken: isGuest ? currentUser.refresh_token : undefined,
1565
- });
1566
- this.setCurrentUser(user);
1542
+ return { error: { message: error } };
1543
+ }
1544
+ const code = params.get('code');
1545
+ if (!code) {
1546
+ return null;
1547
+ }
1548
+ this._replaceUrlAfterOAuth();
1549
+ try {
1550
+ const currentUser = await this._getCurrentUser();
1551
+ const isGuest = currentUser?.type === 'guest';
1552
+ const { user } = await authAPI.exchangeCodeForToken({
1553
+ apiURI: this.config.apiURI,
1554
+ appId: this.config.appId,
1555
+ code,
1556
+ refreshToken: isGuest ? currentUser.refresh_token : undefined,
1557
+ });
1558
+ this.setCurrentUser(user);
1559
+ return null;
1560
+ }
1561
+ catch (e) {
1562
+ if (e?.body?.type === 'record-not-found' &&
1563
+ e?.body?.hint?.['record-type'] === 'app-oauth-code' &&
1564
+ (await this._hasCurrentUser())) {
1565
+ // We probably just weren't able to clean up the URL, so
1566
+ // let's just ignore this error
1567
1567
  return null;
1568
1568
  }
1569
- catch (e) {
1570
- if (((_a = e === null || e === void 0 ? void 0 : e.body) === null || _a === void 0 ? void 0 : _a.type) === 'record-not-found' &&
1571
- ((_c = (_b = e === null || e === void 0 ? void 0 : e.body) === null || _b === void 0 ? void 0 : _b.hint) === null || _c === void 0 ? void 0 : _c['record-type']) === 'app-oauth-code' &&
1572
- (yield this._hasCurrentUser())) {
1573
- // We probably just weren't able to clean up the URL, so
1574
- // let's just ignore this error
1575
- return null;
1576
- }
1577
- const message = ((_d = e === null || e === void 0 ? void 0 : e.body) === null || _d === void 0 ? void 0 : _d.message) || 'Error logging in.';
1578
- return { error: { message } };
1579
- }
1580
- });
1569
+ const message = e?.body?.message || 'Error logging in.';
1570
+ return { error: { message } };
1571
+ }
1581
1572
  }
1582
- _waitForOAuthCallbackResponse() {
1583
- return __awaiter(this, void 0, void 0, function* () {
1584
- return yield this._oauthCallbackResponse;
1585
- });
1573
+ async _waitForOAuthCallbackResponse() {
1574
+ return await this._oauthCallbackResponse;
1586
1575
  }
1587
1576
  __subscribeMutationErrors(cb) {
1588
1577
  this.mutationErrorCbs.push(cb);
@@ -1609,14 +1598,12 @@ class Reactor {
1609
1598
  this.authCbs = this.authCbs.filter((x) => x !== cb);
1610
1599
  };
1611
1600
  }
1612
- getAuth() {
1613
- return __awaiter(this, void 0, void 0, function* () {
1614
- const { user, error } = yield this.getCurrentUser();
1615
- if (error) {
1616
- throw new InstantError_ts_1.InstantError('Could not get current user: ' + error.message);
1617
- }
1618
- return user;
1619
- });
1601
+ async getAuth() {
1602
+ const { user, error } = await this.getCurrentUser();
1603
+ if (error) {
1604
+ throw new InstantError_ts_1.InstantError('Could not get current user: ' + error.message);
1605
+ }
1606
+ return user;
1620
1607
  }
1621
1608
  subscribeConnectionStatus(cb) {
1622
1609
  this.connectionStatusCbs.push(cb);
@@ -1648,99 +1635,89 @@ class Reactor {
1648
1635
  notifyConnectionStatusSubs(status) {
1649
1636
  this.connectionStatusCbs.forEach((cb) => cb(status));
1650
1637
  }
1651
- setCurrentUser(user) {
1652
- return __awaiter(this, void 0, void 0, function* () {
1653
- this.kv.updateInPlace((prev) => {
1654
- prev[currentUserKey] = user;
1655
- });
1656
- yield this.kv.waitForKeyToLoad(currentUserKey);
1638
+ async setCurrentUser(user) {
1639
+ this.kv.updateInPlace((prev) => {
1640
+ prev[currentUserKey] = user;
1657
1641
  });
1642
+ await this.kv.waitForKeyToLoad(currentUserKey);
1658
1643
  }
1659
1644
  getCurrentUserCached() {
1660
1645
  return this._currentUserCached;
1661
1646
  }
1662
- _getCurrentUser() {
1663
- return __awaiter(this, void 0, void 0, function* () {
1664
- const user = yield this.kv.waitForKeyToLoad(currentUserKey);
1665
- return typeof user === 'string' ? JSON.parse(user) : user;
1666
- });
1667
- }
1668
- getCurrentUser() {
1669
- return __awaiter(this, void 0, void 0, function* () {
1670
- const oauthResp = yield this._waitForOAuthCallbackResponse();
1671
- if (oauthResp === null || oauthResp === void 0 ? void 0 : oauthResp.error) {
1672
- const errorV = { error: oauthResp.error, user: undefined };
1673
- this._currentUserCached = Object.assign({ isLoading: false }, errorV);
1674
- return errorV;
1675
- }
1676
- try {
1677
- const user = yield this._getCurrentUser();
1678
- const userV = { user: user, error: undefined };
1679
- this._currentUserCached = Object.assign({ isLoading: false }, userV);
1680
- return userV;
1681
- }
1682
- catch (e) {
1683
- return {
1684
- user: undefined,
1685
- isLoading: false,
1686
- error: { message: (e === null || e === void 0 ? void 0 : e.message) || 'Error loading user' },
1687
- };
1688
- }
1689
- });
1647
+ async _getCurrentUser() {
1648
+ const user = await this.kv.waitForKeyToLoad(currentUserKey);
1649
+ return typeof user === 'string' ? JSON.parse(user) : user;
1650
+ }
1651
+ async getCurrentUser() {
1652
+ const oauthResp = await this._waitForOAuthCallbackResponse();
1653
+ if (oauthResp?.error) {
1654
+ const errorV = { error: oauthResp.error, user: undefined };
1655
+ this._currentUserCached = { isLoading: false, ...errorV };
1656
+ return errorV;
1657
+ }
1658
+ try {
1659
+ const user = await this._getCurrentUser();
1660
+ const userV = { user: user, error: undefined };
1661
+ this._currentUserCached = {
1662
+ isLoading: false,
1663
+ ...userV,
1664
+ };
1665
+ return userV;
1666
+ }
1667
+ catch (e) {
1668
+ return {
1669
+ user: undefined,
1670
+ isLoading: false,
1671
+ error: { message: e?.message || 'Error loading user' },
1672
+ };
1673
+ }
1690
1674
  }
1691
- _hasCurrentUser() {
1692
- return __awaiter(this, void 0, void 0, function* () {
1693
- const user = yield this.kv.waitForKeyToLoad(currentUserKey);
1694
- return typeof user === 'string' ? JSON.parse(user) != null : user != null;
1695
- });
1675
+ async _hasCurrentUser() {
1676
+ const user = await this.kv.waitForKeyToLoad(currentUserKey);
1677
+ return typeof user === 'string' ? JSON.parse(user) != null : user != null;
1696
1678
  }
1697
- changeCurrentUser(newUser) {
1698
- return __awaiter(this, void 0, void 0, function* () {
1699
- var _a;
1700
- const { user: oldUser } = yield this.getCurrentUser();
1701
- if ((0, object_js_1.areObjectsDeepEqual)(oldUser, newUser)) {
1702
- // We were already logged in as the newUser, don't
1703
- // bother updating
1704
- return;
1705
- }
1706
- yield this.setCurrentUser(newUser);
1707
- // We need to remove all `result` from querySubs,
1708
- // as they are no longer valid for the new user
1709
- this.updateUser(newUser);
1710
- try {
1711
- (_a = this._broadcastChannel) === null || _a === void 0 ? void 0 : _a.postMessage({ type: 'auth' });
1712
- }
1713
- catch (error) {
1714
- console.error('Error posting message to broadcast channel', error);
1715
- }
1716
- });
1679
+ async changeCurrentUser(newUser) {
1680
+ const { user: oldUser } = await this.getCurrentUser();
1681
+ if ((0, object_js_1.areObjectsDeepEqual)(oldUser, newUser)) {
1682
+ // We were already logged in as the newUser, don't
1683
+ // bother updating
1684
+ return;
1685
+ }
1686
+ await this.setCurrentUser(newUser);
1687
+ // We need to remove all `result` from querySubs,
1688
+ // as they are no longer valid for the new user
1689
+ this.updateUser(newUser);
1690
+ try {
1691
+ this._broadcastChannel?.postMessage({ type: 'auth' });
1692
+ }
1693
+ catch (error) {
1694
+ console.error('Error posting message to broadcast channel', error);
1695
+ }
1717
1696
  }
1718
- syncUserToEndpoint(user) {
1719
- return __awaiter(this, void 0, void 0, function* () {
1720
- if (!this.config.firstPartyPath)
1721
- return;
1722
- try {
1723
- fetch(this.config.firstPartyPath + '/', {
1724
- method: 'POST',
1725
- body: JSON.stringify({
1726
- type: 'sync-user',
1727
- appId: this.config.appId,
1728
- user: user,
1729
- }),
1730
- headers: {
1731
- 'Content-Type': 'application/json',
1732
- },
1733
- });
1734
- }
1735
- catch (error) {
1736
- this._log.error('Error syncing user with external endpoint', error);
1737
- }
1738
- });
1697
+ async syncUserToEndpoint(user) {
1698
+ if (!this.config.firstPartyPath)
1699
+ return;
1700
+ try {
1701
+ fetch(this.config.firstPartyPath + '/', {
1702
+ method: 'POST',
1703
+ body: JSON.stringify({
1704
+ type: 'sync-user',
1705
+ appId: this.config.appId,
1706
+ user: user,
1707
+ }),
1708
+ headers: {
1709
+ 'Content-Type': 'application/json',
1710
+ },
1711
+ });
1712
+ }
1713
+ catch (error) {
1714
+ this._log.error('Error syncing user with external endpoint', error);
1715
+ }
1739
1716
  }
1740
1717
  updateUser(newUser) {
1741
1718
  this.syncUserToEndpoint(newUser);
1742
1719
  const newV = { error: undefined, user: newUser };
1743
- this._currentUserCached = Object.assign({ isLoading: false }, newV);
1720
+ this._currentUserCached = { isLoading: false, ...newV };
1744
1721
  this._dataForQueryCache = {};
1745
1722
  this.querySubs.updateInPlace((prev) => {
1746
1723
  Object.keys(prev).forEach((k) => {
@@ -1759,46 +1736,38 @@ class Reactor {
1759
1736
  email: email,
1760
1737
  });
1761
1738
  }
1762
- signInWithMagicCode(_a) {
1763
- return __awaiter(this, arguments, void 0, function* ({ email, code }) {
1764
- var _b;
1765
- const currentUser = yield this.getCurrentUser();
1766
- const isGuest = ((_b = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _b === void 0 ? void 0 : _b.type) === 'guest';
1767
- const res = yield authAPI.verifyMagicCode({
1768
- apiURI: this.config.apiURI,
1769
- appId: this.config.appId,
1770
- email,
1771
- code,
1772
- refreshToken: isGuest ? currentUser.user.refresh_token : undefined,
1773
- });
1774
- yield this.changeCurrentUser(res.user);
1775
- return res;
1739
+ async signInWithMagicCode({ email, code }) {
1740
+ const currentUser = await this.getCurrentUser();
1741
+ const isGuest = currentUser?.user?.type === 'guest';
1742
+ const res = await authAPI.verifyMagicCode({
1743
+ apiURI: this.config.apiURI,
1744
+ appId: this.config.appId,
1745
+ email,
1746
+ code,
1747
+ refreshToken: isGuest ? currentUser.user.refresh_token : undefined,
1776
1748
  });
1749
+ await this.changeCurrentUser(res.user);
1750
+ return res;
1777
1751
  }
1778
- signInWithCustomToken(authToken) {
1779
- return __awaiter(this, void 0, void 0, function* () {
1780
- const res = yield authAPI.verifyRefreshToken({
1781
- apiURI: this.config.apiURI,
1782
- appId: this.config.appId,
1783
- refreshToken: authToken,
1784
- });
1785
- yield this.changeCurrentUser(res.user);
1786
- return res;
1752
+ async signInWithCustomToken(authToken) {
1753
+ const res = await authAPI.verifyRefreshToken({
1754
+ apiURI: this.config.apiURI,
1755
+ appId: this.config.appId,
1756
+ refreshToken: authToken,
1787
1757
  });
1758
+ await this.changeCurrentUser(res.user);
1759
+ return res;
1788
1760
  }
1789
- signInAsGuest() {
1790
- return __awaiter(this, void 0, void 0, function* () {
1791
- const res = yield authAPI.signInAsGuest({
1792
- apiURI: this.config.apiURI,
1793
- appId: this.config.appId,
1794
- });
1795
- yield this.changeCurrentUser(res.user);
1796
- return res;
1761
+ async signInAsGuest() {
1762
+ const res = await authAPI.signInAsGuest({
1763
+ apiURI: this.config.apiURI,
1764
+ appId: this.config.appId,
1797
1765
  });
1766
+ await this.changeCurrentUser(res.user);
1767
+ return res;
1798
1768
  }
1799
1769
  potentiallyInvalidateToken(currentUser, opts) {
1800
- var _a;
1801
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
1770
+ const refreshToken = currentUser?.user?.refresh_token;
1802
1771
  if (!refreshToken) {
1803
1772
  return;
1804
1773
  }
@@ -1818,12 +1787,10 @@ class Reactor {
1818
1787
  })
1819
1788
  .catch((e) => { });
1820
1789
  }
1821
- signOut(opts) {
1822
- return __awaiter(this, void 0, void 0, function* () {
1823
- const currentUser = yield this.getCurrentUser();
1824
- this.potentiallyInvalidateToken(currentUser, opts);
1825
- yield this.changeCurrentUser(null);
1826
- });
1790
+ async signOut(opts) {
1791
+ const currentUser = await this.getCurrentUser();
1792
+ this.potentiallyInvalidateToken(currentUser, opts);
1793
+ await this.changeCurrentUser(null);
1827
1794
  }
1828
1795
  /**
1829
1796
  * Creates an OAuth authorization URL.
@@ -1842,21 +1809,18 @@ class Reactor {
1842
1809
  * @param {string} params.code - The code received from the OAuth service.
1843
1810
  * @param {string} [params.codeVerifier] - The code verifier used to generate the code challenge.
1844
1811
  */
1845
- exchangeCodeForToken(_a) {
1846
- return __awaiter(this, arguments, void 0, function* ({ code, codeVerifier }) {
1847
- var _b;
1848
- const currentUser = yield this.getCurrentUser();
1849
- const isGuest = ((_b = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _b === void 0 ? void 0 : _b.type) === 'guest';
1850
- const res = yield authAPI.exchangeCodeForToken({
1851
- apiURI: this.config.apiURI,
1852
- appId: this.config.appId,
1853
- code: code,
1854
- codeVerifier,
1855
- refreshToken: isGuest ? currentUser.user.refresh_token : undefined,
1856
- });
1857
- yield this.changeCurrentUser(res.user);
1858
- return res;
1812
+ async exchangeCodeForToken({ code, codeVerifier }) {
1813
+ const currentUser = await this.getCurrentUser();
1814
+ const isGuest = currentUser?.user?.type === 'guest';
1815
+ const res = await authAPI.exchangeCodeForToken({
1816
+ apiURI: this.config.apiURI,
1817
+ appId: this.config.appId,
1818
+ code: code,
1819
+ codeVerifier,
1820
+ refreshToken: isGuest ? currentUser.user.refresh_token : undefined,
1859
1821
  });
1822
+ await this.changeCurrentUser(res.user);
1823
+ return res;
1860
1824
  }
1861
1825
  issuerURI() {
1862
1826
  const { apiURI, appId } = this.config;
@@ -1868,22 +1832,19 @@ class Reactor {
1868
1832
  * @param {string} params.idToken - The id_token from the external service
1869
1833
  * @param {string | null | undefined} [params.nonce] - The nonce used when requesting the id_token from the external service
1870
1834
  */
1871
- signInWithIdToken(_a) {
1872
- return __awaiter(this, arguments, void 0, function* ({ idToken, clientName, nonce }) {
1873
- var _b;
1874
- const currentUser = yield this.getCurrentUser();
1875
- const refreshToken = (_b = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _b === void 0 ? void 0 : _b.refresh_token;
1876
- const res = yield authAPI.signInWithIdToken({
1877
- apiURI: this.config.apiURI,
1878
- appId: this.config.appId,
1879
- idToken,
1880
- clientName,
1881
- nonce,
1882
- refreshToken,
1883
- });
1884
- yield this.changeCurrentUser(res.user);
1885
- return res;
1835
+ async signInWithIdToken({ idToken, clientName, nonce }) {
1836
+ const currentUser = await this.getCurrentUser();
1837
+ const refreshToken = currentUser?.user?.refresh_token;
1838
+ const res = await authAPI.signInWithIdToken({
1839
+ apiURI: this.config.apiURI,
1840
+ appId: this.config.appId,
1841
+ idToken,
1842
+ clientName,
1843
+ nonce,
1844
+ refreshToken,
1886
1845
  });
1846
+ await this.changeCurrentUser(res.user);
1847
+ return res;
1887
1848
  }
1888
1849
  // --------
1889
1850
  // Rooms
@@ -1916,10 +1877,9 @@ class Reactor {
1916
1877
  };
1917
1878
  }
1918
1879
  _cleanupRoom(roomId) {
1919
- var _a, _b, _c, _d;
1920
- if (!((_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.handlers) === null || _b === void 0 ? void 0 : _b.length) &&
1921
- !Object.keys((_c = this._broadcastSubs[roomId]) !== null && _c !== void 0 ? _c : {}).length) {
1922
- const isConnected = (_d = this._rooms[roomId]) === null || _d === void 0 ? void 0 : _d.isConnected;
1880
+ if (!this._presence[roomId]?.handlers?.length &&
1881
+ !Object.keys(this._broadcastSubs[roomId] ?? {}).length) {
1882
+ const isConnected = this._rooms[roomId]?.isConnected;
1923
1883
  delete this._rooms[roomId];
1924
1884
  delete this._presence[roomId];
1925
1885
  delete this._broadcastSubs[roomId];
@@ -1939,7 +1899,11 @@ class Reactor {
1939
1899
  const presence = this._presence[roomId];
1940
1900
  if (!room || !presence || !presence.result)
1941
1901
  return null;
1942
- return Object.assign(Object.assign({}, (0, presence_ts_1.buildPresenceSlice)(presence.result, opts, this._sessionId)), { isLoading: !room.isConnected, error: room.error });
1902
+ return {
1903
+ ...(0, presence_ts_1.buildPresenceSlice)(presence.result, opts, this._sessionId),
1904
+ isLoading: !room.isConnected,
1905
+ error: room.error,
1906
+ };
1943
1907
  }
1944
1908
  // TODO: look into typing again
1945
1909
  publishPresence(roomType, roomId, partialData) {
@@ -1949,7 +1913,10 @@ class Reactor {
1949
1913
  return;
1950
1914
  }
1951
1915
  presence.result = presence.result || {};
1952
- const data = Object.assign(Object.assign({}, presence.result.user), partialData);
1916
+ const data = {
1917
+ ...presence.result.user,
1918
+ ...partialData,
1919
+ };
1953
1920
  presence.result.user = data;
1954
1921
  if (!room.isConnected) {
1955
1922
  return;
@@ -1984,21 +1951,19 @@ class Reactor {
1984
1951
  // Note: initialData is deprecated.
1985
1952
  // Keeping here for backwards compatibility
1986
1953
  opts.initialPresence || opts.initialData);
1987
- const handler = Object.assign(Object.assign({}, opts), { roomId, cb, prev: null });
1954
+ const handler = { ...opts, roomId, cb, prev: null };
1988
1955
  this._presence[roomId] = this._presence[roomId] || {};
1989
1956
  this._presence[roomId].handlers = this._presence[roomId].handlers || [];
1990
1957
  this._presence[roomId].handlers.push(handler);
1991
1958
  this._notifyPresenceSub(roomId, handler);
1992
1959
  return () => {
1993
- var _a, _b, _c;
1994
1960
  this._presence[roomId].handlers =
1995
- (_c = (_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.handlers) === null || _b === void 0 ? void 0 : _b.filter((x) => x !== handler)) !== null && _c !== void 0 ? _c : [];
1961
+ this._presence[roomId]?.handlers?.filter((x) => x !== handler) ?? [];
1996
1962
  leaveRoom();
1997
1963
  };
1998
1964
  }
1999
1965
  _notifyPresenceSubs(roomId) {
2000
- var _a, _b;
2001
- (_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.handlers) === null || _b === void 0 ? void 0 : _b.forEach((handler) => {
1966
+ this._presence[roomId]?.handlers?.forEach((handler) => {
2002
1967
  this._notifyPresenceSub(roomId, handler);
2003
1968
  });
2004
1969
  }
@@ -2014,10 +1979,9 @@ class Reactor {
2014
1979
  handler.cb(slice);
2015
1980
  }
2016
1981
  _patchPresencePeers(roomId, edits) {
2017
- var _a, _b, _c;
2018
- const peers = ((_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.peers) || {};
1982
+ const peers = this._presence[roomId]?.result?.peers || {};
2019
1983
  let sessions = Object.fromEntries(Object.entries(peers).map(([k, v]) => [k, { data: v }]));
2020
- const myPresence = (_c = this._presence[roomId]) === null || _c === void 0 ? void 0 : _c.result;
1984
+ const myPresence = this._presence[roomId]?.result;
2021
1985
  const newSessions = (0, mutative_1.create)(sessions, (draft) => {
2022
1986
  for (let [path, op, value] of edits) {
2023
1987
  switch (op) {
@@ -2038,7 +2002,7 @@ class Reactor {
2038
2002
  this._setPresencePeers(roomId, newSessions);
2039
2003
  }
2040
2004
  _setPresencePeers(roomId, data) {
2041
- const sessions = Object.assign({}, data);
2005
+ const sessions = { ...data };
2042
2006
  // no need to keep track of `user`
2043
2007
  delete sessions[this._sessionId];
2044
2008
  const peers = Object.fromEntries(Object.entries(sessions).map(([k, v]) => [k, v.data]));
@@ -2049,13 +2013,12 @@ class Reactor {
2049
2013
  // --------
2050
2014
  // Broadcast
2051
2015
  publishTopic({ roomType, roomId, topic, data }) {
2052
- var _a;
2053
2016
  const room = this._rooms[roomId];
2054
2017
  if (!room) {
2055
2018
  return;
2056
2019
  }
2057
2020
  if (!room.isConnected) {
2058
- this._broadcastQueue[roomId] = (_a = this._broadcastQueue[roomId]) !== null && _a !== void 0 ? _a : [];
2021
+ this._broadcastQueue[roomId] = this._broadcastQueue[roomId] ?? [];
2059
2022
  this._broadcastQueue[roomId].push({ topic, roomType, data });
2060
2023
  return;
2061
2024
  }
@@ -2086,71 +2049,64 @@ class Reactor {
2086
2049
  };
2087
2050
  }
2088
2051
  _notifyBroadcastSubs(room, topic, msg) {
2089
- var _a, _b, _c;
2090
- (_c = (_b = (_a = this._broadcastSubs) === null || _a === void 0 ? void 0 : _a[room]) === null || _b === void 0 ? void 0 : _b[topic]) === null || _c === void 0 ? void 0 : _c.forEach((cb) => {
2091
- var _a, _b, _c, _d, _e, _f;
2092
- const data = (_a = msg.data) === null || _a === void 0 ? void 0 : _a.data;
2052
+ this._broadcastSubs?.[room]?.[topic]?.forEach((cb) => {
2053
+ const data = msg.data?.data;
2093
2054
  const peer = msg.data['peer-id'] === this._sessionId
2094
- ? (_c = (_b = this._presence[room]) === null || _b === void 0 ? void 0 : _b.result) === null || _c === void 0 ? void 0 : _c.user
2095
- : (_f = (_e = (_d = this._presence[room]) === null || _d === void 0 ? void 0 : _d.result) === null || _e === void 0 ? void 0 : _e.peers) === null || _f === void 0 ? void 0 : _f[msg.data['peer-id']];
2055
+ ? this._presence[room]?.result?.user
2056
+ : this._presence[room]?.result?.peers?.[msg.data['peer-id']];
2096
2057
  return cb(data, peer);
2097
2058
  });
2098
2059
  }
2099
2060
  // --------
2100
2061
  // Storage
2101
- uploadFile(path, file, opts) {
2102
- return __awaiter(this, void 0, void 0, function* () {
2103
- var _a;
2104
- const currentUser = yield this.getCurrentUser();
2105
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
2106
- return StorageApi.uploadFile(Object.assign(Object.assign({}, opts), { apiURI: this.config.apiURI, appId: this.config.appId, path: path, file, refreshToken: refreshToken }));
2062
+ async uploadFile(path, file, opts) {
2063
+ const currentUser = await this.getCurrentUser();
2064
+ const refreshToken = currentUser?.user?.refresh_token;
2065
+ return StorageApi.uploadFile({
2066
+ ...opts,
2067
+ apiURI: this.config.apiURI,
2068
+ appId: this.config.appId,
2069
+ path: path,
2070
+ file,
2071
+ refreshToken: refreshToken,
2107
2072
  });
2108
2073
  }
2109
- deleteFile(path) {
2110
- return __awaiter(this, void 0, void 0, function* () {
2111
- var _a;
2112
- const currentUser = yield this.getCurrentUser();
2113
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
2114
- const result = yield StorageApi.deleteFile({
2115
- apiURI: this.config.apiURI,
2116
- appId: this.config.appId,
2117
- path,
2118
- refreshToken: refreshToken,
2119
- });
2120
- return result;
2074
+ async deleteFile(path) {
2075
+ const currentUser = await this.getCurrentUser();
2076
+ const refreshToken = currentUser?.user?.refresh_token;
2077
+ const result = await StorageApi.deleteFile({
2078
+ apiURI: this.config.apiURI,
2079
+ appId: this.config.appId,
2080
+ path,
2081
+ refreshToken: refreshToken,
2121
2082
  });
2083
+ return result;
2122
2084
  }
2123
2085
  // Deprecated Storage API (Jan 2025)
2124
2086
  // ---------------------------------
2125
- upload(path, file) {
2126
- return __awaiter(this, void 0, void 0, function* () {
2127
- var _a;
2128
- const currentUser = yield this.getCurrentUser();
2129
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
2130
- const fileName = path || file.name;
2131
- const url = yield StorageApi.getSignedUploadUrl({
2132
- apiURI: this.config.apiURI,
2133
- appId: this.config.appId,
2134
- fileName: fileName,
2135
- refreshToken: refreshToken,
2136
- });
2137
- const isSuccess = yield StorageApi.upload(url, file);
2138
- return isSuccess;
2087
+ async upload(path, file) {
2088
+ const currentUser = await this.getCurrentUser();
2089
+ const refreshToken = currentUser?.user?.refresh_token;
2090
+ const fileName = path || file.name;
2091
+ const url = await StorageApi.getSignedUploadUrl({
2092
+ apiURI: this.config.apiURI,
2093
+ appId: this.config.appId,
2094
+ fileName: fileName,
2095
+ refreshToken: refreshToken,
2139
2096
  });
2097
+ const isSuccess = await StorageApi.upload(url, file);
2098
+ return isSuccess;
2140
2099
  }
2141
- getDownloadUrl(path) {
2142
- return __awaiter(this, void 0, void 0, function* () {
2143
- var _a;
2144
- const currentUser = yield this.getCurrentUser();
2145
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
2146
- const url = yield StorageApi.getDownloadUrl({
2147
- apiURI: this.config.apiURI,
2148
- appId: this.config.appId,
2149
- path: path,
2150
- refreshToken: refreshToken,
2151
- });
2152
- return url;
2100
+ async getDownloadUrl(path) {
2101
+ const currentUser = await this.getCurrentUser();
2102
+ const refreshToken = currentUser?.user?.refresh_token;
2103
+ const url = await StorageApi.getDownloadUrl({
2104
+ apiURI: this.config.apiURI,
2105
+ appId: this.config.appId,
2106
+ path: path,
2107
+ refreshToken: refreshToken,
2153
2108
  });
2109
+ return url;
2154
2110
  }
2155
2111
  }
2156
2112
  exports.default = Reactor;