@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
@@ -1,23 +1,3 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __rest = (this && this.__rest) || function (s, e) {
11
- var t = {};
12
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
- t[p] = s[p];
14
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
- t[p[i]] = s[p[i]];
18
- }
19
- return t;
20
- };
21
1
  // @ts-check
22
2
  import weakHash from "./utils/weakHash.js";
23
3
  import instaql from "./instaql.js";
@@ -58,10 +38,10 @@ const STATUS = {
58
38
  CLOSED: 'closed',
59
39
  ERRORED: 'errored',
60
40
  };
61
- const QUERY_ONCE_TIMEOUT = 30000;
62
- const PENDING_TX_CLEANUP_TIMEOUT = 30000;
41
+ const QUERY_ONCE_TIMEOUT = 30_000;
42
+ const PENDING_TX_CLEANUP_TIMEOUT = 30_000;
63
43
  const PENDING_MUTATION_CLEANUP_THRESHOLD = 200;
64
- const ONE_MIN_MS = 1000 * 60;
44
+ const ONE_MIN_MS = 1_000 * 60;
65
45
  const defaultConfig = {
66
46
  apiURI: 'https://api.instantdb.com',
67
47
  websocketURI: 'wss://api.instantdb.com/runtime/session',
@@ -110,13 +90,15 @@ const ignoreLogging = {
110
90
  * @returns {QuerySub}
111
91
  */
112
92
  function querySubFromStorage(x, useDateObjects) {
113
- var _a;
114
93
  const v = typeof x === 'string' ? JSON.parse(x) : x;
115
- if ((_a = v === null || v === void 0 ? void 0 : v.result) === null || _a === void 0 ? void 0 : _a.store) {
94
+ if (v?.result?.store) {
116
95
  const attrsStore = s.attrsStoreFromJSON(v.result.attrsStore, v.result.store);
117
96
  if (attrsStore) {
118
97
  const storeJSON = v.result.store;
119
- v.result.store = s.fromJSON(attrsStore, Object.assign(Object.assign({}, storeJSON), { useDateObjects: useDateObjects }));
98
+ v.result.store = s.fromJSON(attrsStore, {
99
+ ...storeJSON,
100
+ useDateObjects: useDateObjects,
101
+ });
120
102
  v.result.attrsStore = attrsStore;
121
103
  }
122
104
  }
@@ -129,11 +111,15 @@ function querySubFromStorage(x, useDateObjects) {
129
111
  * @returns QuerySubInStorage
130
112
  */
131
113
  function querySubToStorage(_key, sub) {
132
- const { result } = sub, rest = __rest(sub, ["result"]);
114
+ const { result, ...rest } = sub;
133
115
  const jsonSub = /** @type {import('./reactorTypes.ts').QuerySubInStorage} */ (rest);
134
116
  if (result) {
135
117
  /** @type {import('./reactorTypes.ts').QuerySubResultInStorage} */
136
- const jsonResult = Object.assign(Object.assign({}, result), { store: s.toJSON(result.store), attrsStore: result.attrsStore.toJSON() });
118
+ const jsonResult = {
119
+ ...result,
120
+ store: s.toJSON(result.store),
121
+ attrsStore: result.attrsStore.toJSON(),
122
+ };
137
123
  jsonSub.result = jsonResult;
138
124
  }
139
125
  return jsonSub;
@@ -155,8 +141,8 @@ function kvToStorage(key, x) {
155
141
  }
156
142
  }
157
143
  function onMergeQuerySub(_k, storageSub, inMemorySub) {
158
- const storageResult = storageSub === null || storageSub === void 0 ? void 0 : storageSub.result;
159
- const memoryResult = inMemorySub === null || inMemorySub === void 0 ? void 0 : inMemorySub.result;
144
+ const storageResult = storageSub?.result;
145
+ const memoryResult = inMemorySub?.result;
160
146
  if (storageResult && !memoryResult && inMemorySub) {
161
147
  inMemorySub.result = storageResult;
162
148
  }
@@ -178,241 +164,72 @@ function sortedMutationEntries(entries) {
178
164
  * @template {import('./presence.ts').RoomSchemaShape} [RoomSchema = {}]
179
165
  */
180
166
  export default class Reactor {
167
+ /** @type {s.AttrsStore | undefined} */
168
+ attrs;
169
+ _isOnline = true;
170
+ _isShutdown = false;
171
+ status = STATUS.CONNECTING;
172
+ /** @type {PersistedObject<string, QuerySub, QuerySubInStorage>} */
173
+ querySubs;
174
+ /** @type {PersistedObject} */
175
+ kv;
176
+ /** @type {SyncTable} */
177
+ _syncTable;
178
+ /** @type {Record<string, Array<{ q: any, cb: (data: any) => any }>>} */
179
+ queryCbs = {};
180
+ /** @type {Record<string, Array<{ q: any, eventId: string, dfd: Deferred }>>} */
181
+ queryOnceDfds = {};
182
+ authCbs = [];
183
+ attrsCbs = [];
184
+ mutationErrorCbs = [];
185
+ connectionStatusCbs = [];
186
+ config;
187
+ mutationDeferredStore = new Map();
188
+ _reconnectTimeoutId = null;
189
+ _reconnectTimeoutMs = 0;
190
+ /** @type {Connection} */
191
+ _transport;
192
+ /** @type {TransportType} */
193
+ _transportType = 'ws';
194
+ /** @type {EventSourceConstructor} */
195
+ _EventSource;
196
+ /** @type {boolean | null} */
197
+ _wsOk = null;
198
+ _localIdPromises = {};
199
+ _errorMessage = null;
200
+ /** @type {Promise<null | {error: {message: string}}> | null}**/
201
+ _oauthCallbackResponse = null;
202
+ /** @type {null | import('./utils/linkIndex.ts').LinkIndex}} */
203
+ _linkIndex = null;
204
+ /** @type BroadcastChannel | undefined */
205
+ _broadcastChannel;
206
+ /** @type {Record<string, {isConnected: boolean; error: any}>} */
207
+ _rooms = {};
208
+ /** @type {Record<string, boolean>} */
209
+ _roomsPendingLeave = {};
210
+ _presence = {};
211
+ _broadcastQueue = [];
212
+ _broadcastSubs = {};
213
+ /** @type {{isLoading: boolean; error: any | undefined, user: any | undefined}} */
214
+ _currentUserCached = { isLoading: true, error: undefined, user: undefined };
215
+ _beforeUnloadCbs = [];
216
+ _dataForQueryCache = {};
217
+ /** @type {Logger} */
218
+ _log;
219
+ _pendingTxCleanupTimeout;
220
+ _pendingMutationCleanupThreshold;
221
+ _inFlightMutationEventIds = new Set();
181
222
  constructor(config, Storage = IndexedDBStorage, NetworkListener = WindowNetworkListener, versions, EventSourceConstructor) {
182
- var _a, _b, _c;
183
- this._isOnline = true;
184
- this._isShutdown = false;
185
- this.status = STATUS.CONNECTING;
186
- /** @type {Record<string, Array<{ q: any, cb: (data: any) => any }>>} */
187
- this.queryCbs = {};
188
- /** @type {Record<string, Array<{ q: any, eventId: string, dfd: Deferred }>>} */
189
- this.queryOnceDfds = {};
190
- this.authCbs = [];
191
- this.attrsCbs = [];
192
- this.mutationErrorCbs = [];
193
- this.connectionStatusCbs = [];
194
- this.mutationDeferredStore = new Map();
195
- this._reconnectTimeoutId = null;
196
- this._reconnectTimeoutMs = 0;
197
- /** @type {TransportType} */
198
- this._transportType = 'ws';
199
- /** @type {boolean | null} */
200
- this._wsOk = null;
201
- this._localIdPromises = {};
202
- this._errorMessage = null;
203
- /** @type {Promise<null | {error: {message: string}}> | null}**/
204
- this._oauthCallbackResponse = null;
205
- /** @type {null | import('./utils/linkIndex.ts').LinkIndex}} */
206
- this._linkIndex = null;
207
- /** @type {Record<string, {isConnected: boolean; error: any}>} */
208
- this._rooms = {};
209
- /** @type {Record<string, boolean>} */
210
- this._roomsPendingLeave = {};
211
- this._presence = {};
212
- this._broadcastQueue = [];
213
- this._broadcastSubs = {};
214
- /** @type {{isLoading: boolean; error: any | undefined, user: any | undefined}} */
215
- this._currentUserCached = { isLoading: true, error: undefined, user: undefined };
216
- this._beforeUnloadCbs = [];
217
- this._dataForQueryCache = {};
218
- this._inFlightMutationEventIds = new Set();
219
- this._onMergeKv = (key, storageV, inMemoryV) => {
220
- var _a, _b;
221
- switch (key) {
222
- case 'pendingMutations': {
223
- const storageEntries = (_a = storageV === null || storageV === void 0 ? void 0 : storageV.entries()) !== null && _a !== void 0 ? _a : [];
224
- const inMemoryEntries = (_b = inMemoryV === null || inMemoryV === void 0 ? void 0 : inMemoryV.entries()) !== null && _b !== void 0 ? _b : [];
225
- const muts = new Map([...storageEntries, ...inMemoryEntries]);
226
- const rewrittenStorageMuts = storageV
227
- ? this._rewriteMutationsSorted(this.attrs, storageV)
228
- : [];
229
- rewrittenStorageMuts.forEach(([k, mut]) => {
230
- var _a;
231
- if (!((_a = inMemoryV === null || inMemoryV === void 0 ? void 0 : inMemoryV.pendingMutations) === null || _a === void 0 ? void 0 : _a.has(k)) && !mut['tx-id']) {
232
- this._sendMutation(k, mut);
233
- }
234
- });
235
- return muts;
236
- }
237
- default:
238
- return inMemoryV || storageV;
239
- }
240
- };
241
- // ---------------------------
242
- // Queries
243
- this.getPreviousResult = (q) => {
244
- var _a;
245
- const hash = weakHash(q);
246
- return (_a = this.dataForQuery(hash)) === null || _a === void 0 ? void 0 : _a.data;
247
- };
248
- /** Re-run instaql and call all callbacks with new data */
249
- this.notifyOne = (hash) => {
250
- var _a, _b;
251
- const cbs = (_a = this.queryCbs[hash]) !== null && _a !== void 0 ? _a : [];
252
- const prevData = (_b = this._dataForQueryCache[hash]) === null || _b === void 0 ? void 0 : _b.data;
253
- const resp = this.dataForQuery(hash);
254
- if (!(resp === null || resp === void 0 ? void 0 : resp.data))
255
- return;
256
- this._dataForQueryCache[hash] = resp;
257
- if (areObjectsDeepEqual(resp.data, prevData))
258
- return;
259
- cbs.forEach((r) => r.cb(resp.data));
260
- };
261
- this.notifyOneQueryOnce = (hash) => {
262
- var _a, _b;
263
- const dfds = (_a = this.queryOnceDfds[hash]) !== null && _a !== void 0 ? _a : [];
264
- const data = (_b = this.dataForQuery(hash)) === null || _b === void 0 ? void 0 : _b.data;
265
- dfds.forEach((r) => {
266
- this._completeQueryOnce(r.q, hash, r.dfd);
267
- r.dfd.resolve(data);
268
- });
269
- };
270
- this.notifyQueryError = (hash, error) => {
271
- const cbs = this.queryCbs[hash] || [];
272
- cbs.forEach((r) => r.cb({ error }));
273
- };
274
- /** Applies transactions locally and sends transact message to server */
275
- this.pushTx = (chunks) => {
276
- // Throws if transactions are invalid
277
- if (!this.config.disableValidation) {
278
- validateTransactions(chunks, this.config.schema);
279
- }
280
- try {
281
- const txSteps = instaml.transform({
282
- attrsStore: this.optimisticAttrs(),
283
- schema: this.config.schema,
284
- 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; }),
285
- useDateObjects: this.config.useDateObjects,
286
- }, chunks);
287
- return this.pushOps(txSteps);
288
- }
289
- catch (e) {
290
- return this.pushOps([], e);
291
- }
292
- };
293
- /**
294
- * @param {*} txSteps
295
- * @param {*} [error]
296
- * @returns
297
- */
298
- this.pushOps = (txSteps, error) => {
299
- const eventId = uuid();
300
- const mutations = [...this._pendingMutations().values()];
301
- const order = Math.max(0, ...mutations.map((mut) => mut.order || 0)) + 1;
302
- const mutation = {
303
- op: 'transact',
304
- 'tx-steps': txSteps,
305
- created: Date.now(),
306
- error,
307
- order,
308
- };
309
- this._updatePendingMutations((prev) => {
310
- prev.set(eventId, mutation);
311
- });
312
- const dfd = new Deferred();
313
- this.mutationDeferredStore.set(eventId, dfd);
314
- this._sendMutation(eventId, mutation);
315
- this.notifyAll();
316
- return dfd.promise;
317
- };
318
- this._transportOnOpen = (e) => {
319
- const targetTransport = e.target;
320
- if (this._transport !== targetTransport) {
321
- this._log.info('[socket][open]', targetTransport.id, 'skip; this is no longer the current transport');
322
- return;
323
- }
324
- this._log.info('[socket][open]', this._transport.id);
325
- this._setStatus(STATUS.OPENED);
326
- this.getCurrentUser()
327
- .then((resp) => {
328
- var _a;
329
- this._trySend(uuid(), {
330
- op: 'init',
331
- 'app-id': this.config.appId,
332
- 'refresh-token': (_a = resp.user) === null || _a === void 0 ? void 0 : _a['refresh_token'],
333
- versions: this.versions,
334
- // If an admin token is provided for an app, we will
335
- // skip all permission checks. This is an advanced feature,
336
- // to let users write internal tools
337
- // This option is not exposed in `Config`, as it's
338
- // not ready for prime time
339
- '__admin-token': this.config.__adminToken,
340
- });
341
- })
342
- .catch((e) => {
343
- this._log.error('[socket][error]', targetTransport.id, e);
344
- });
345
- };
346
- this._transportOnMessage = (e) => {
347
- const targetTransport = e.target;
348
- const m = e.message;
349
- if (this._transport !== targetTransport) {
350
- this._log.info('[socket][message]', targetTransport.id, m, 'skip; this is no longer the current transport');
351
- return;
352
- }
353
- if (!this._wsOk && targetTransport.type === 'ws') {
354
- this._wsOk = true;
355
- }
356
- // Try to reconnect via websocket the next time we connect
357
- this._transportType = 'ws';
358
- if (Array.isArray(e.message)) {
359
- for (const msg of e.message) {
360
- this._handleReceive(targetTransport.id, msg);
361
- }
362
- }
363
- else {
364
- this._handleReceive(targetTransport.id, e.message);
365
- }
366
- };
367
- this._transportOnError = (e) => {
368
- const targetTransport = e.target;
369
- if (this._transport !== targetTransport) {
370
- this._log.info('[socket][error]', targetTransport.id, 'skip; this is no longer the current transport');
371
- return;
372
- }
373
- this._log.error('[socket][error]', targetTransport.id, e);
374
- };
375
- this._scheduleReconnect = () => {
376
- // If we couldn't connect with a websocket last time, try sse
377
- if (!this._wsOk && this._transportType !== 'sse') {
378
- this._transportType = 'sse';
379
- this._reconnectTimeoutMs = 0;
380
- }
381
- setTimeout(() => {
382
- this._reconnectTimeoutMs = Math.min(this._reconnectTimeoutMs + 1000, 10000);
383
- if (!this._isOnline) {
384
- this._log.info('[socket][close]', this._transport.id, 'we are offline, no need to start socket');
385
- return;
386
- }
387
- this._startSocket();
388
- }, this._reconnectTimeoutMs);
389
- };
390
- this._transportOnClose = (e) => {
391
- const targetTransport = e.target;
392
- if (this._transport !== targetTransport) {
393
- this._log.info('[socket][close]', targetTransport.id, 'skip; this is no longer the current transport');
394
- return;
395
- }
396
- this._setStatus(STATUS.CLOSED);
397
- for (const room of Object.values(this._rooms)) {
398
- room.isConnected = false;
399
- }
400
- if (this._isShutdown) {
401
- this._log.info('[socket][close]', targetTransport.id, 'Reactor has been shut down and will not reconnect');
402
- return;
403
- }
404
- this._log.info('[socket][close]', targetTransport.id, 'schedule reconnect, ms =', this._reconnectTimeoutMs);
405
- this._scheduleReconnect();
406
- };
407
223
  this._EventSource = EventSourceConstructor;
408
- this.config = Object.assign(Object.assign({}, defaultConfig), config);
409
- this.queryCacheLimit = (_a = this.config.queryCacheLimit) !== null && _a !== void 0 ? _a : 10;
224
+ this.config = { ...defaultConfig, ...config };
225
+ this.queryCacheLimit = this.config.queryCacheLimit ?? 10;
410
226
  this._pendingTxCleanupTimeout =
411
- (_b = this.config.pendingTxCleanupTimeout) !== null && _b !== void 0 ? _b : PENDING_TX_CLEANUP_TIMEOUT;
227
+ this.config.pendingTxCleanupTimeout ?? PENDING_TX_CLEANUP_TIMEOUT;
412
228
  this._pendingMutationCleanupThreshold =
413
- (_c = this.config.pendingMutationCleanupThreshold) !== null && _c !== void 0 ? _c : PENDING_MUTATION_CLEANUP_THRESHOLD;
229
+ this.config.pendingMutationCleanupThreshold ??
230
+ PENDING_MUTATION_CLEANUP_THRESHOLD;
414
231
  this._log = createLogger(config.verbose || flags.devBackend || flags.instantLogs, () => this._reactorStats());
415
- this.versions = Object.assign(Object.assign({}, (versions || {})), { '@instantdb/core': version });
232
+ this.versions = { ...(versions || {}), '@instantdb/core': version };
416
233
  if (this.config.schema) {
417
234
  this._linkIndex = createLinkIndex(this.config.schema);
418
235
  }
@@ -429,18 +246,17 @@ export default class Reactor {
429
246
  }
430
247
  if (typeof BroadcastChannel === 'function') {
431
248
  this._broadcastChannel = new BroadcastChannel('@instantdb');
432
- this._broadcastChannel.addEventListener('message', (e) => __awaiter(this, void 0, void 0, function* () {
433
- var _a;
249
+ this._broadcastChannel.addEventListener('message', async (e) => {
434
250
  try {
435
- if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === 'auth') {
436
- const res = yield this.getCurrentUser();
251
+ if (e.data?.type === 'auth') {
252
+ const res = await this.getCurrentUser();
437
253
  this.updateUser(res.user);
438
254
  }
439
255
  }
440
256
  catch (e) {
441
257
  this._log.error('[error] handle broadcast channel', e);
442
258
  }
443
- }));
259
+ });
444
260
  }
445
261
  this._initStorage(Storage);
446
262
  this._syncTable = new SyncTable(this._trySendAuthed.bind(this), new Storage(this.config.appId, 'syncSubs'), {
@@ -453,10 +269,10 @@ export default class Reactor {
453
269
  this.getCurrentUser().then((userInfo) => {
454
270
  this.syncUserToEndpoint(userInfo.user);
455
271
  });
456
- setInterval(() => __awaiter(this, void 0, void 0, function* () {
457
- const currentUser = yield this.getCurrentUser();
272
+ setInterval(async () => {
273
+ const currentUser = await this.getCurrentUser();
458
274
  this.syncUserToEndpoint(currentUser.user);
459
- }), ONE_MIN_MS);
275
+ }, ONE_MIN_MS);
460
276
  NetworkListener.getIsOnline().then((isOnline) => {
461
277
  this._isOnline = isOnline;
462
278
  this._startSocket();
@@ -490,7 +306,11 @@ export default class Reactor {
490
306
  return this.attrs;
491
307
  }
492
308
  updateSchema(schema) {
493
- this.config = Object.assign(Object.assign({}, this.config), { schema: schema, cardinalityInference: Boolean(schema) });
309
+ this.config = {
310
+ ...this.config,
311
+ schema: schema,
312
+ cardinalityInference: Boolean(schema),
313
+ };
494
314
  this._linkIndex = schema ? createLinkIndex(this.config.schema) : null;
495
315
  }
496
316
  _reactorStats() {
@@ -512,14 +332,14 @@ export default class Reactor {
512
332
  serialize: querySubToStorage,
513
333
  parse: (_key, x) => querySubFromStorage(x, this.config.useDateObjects),
514
334
  // objectSize
515
- 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; },
335
+ objectSize: (x) => x?.result?.store?.triples?.length ?? 0,
516
336
  logger: this._log,
517
337
  preloadEntryCount: 10,
518
338
  gc: {
519
339
  maxAgeMs: 1000 * 60 * 60 * 24 * 7 * 52, // 1 year
520
340
  maxEntries: 1000,
521
341
  // Size of each query is the number of triples
522
- maxSize: 1000000, // 1 million triples
342
+ maxSize: 1_000_000, // 1 million triples
523
343
  },
524
344
  });
525
345
  this.querySubs.onKeyLoaded = (k) => this._onQuerySubLoaded(k);
@@ -565,7 +385,7 @@ export default class Reactor {
565
385
  const ok = status !== 'error' && status !== 'timeout';
566
386
  if (!dfd && !ok) {
567
387
  // console.erroring here, as there are no listeners to let know
568
- console.error('Mutation failed', Object.assign({ status, eventId }, errorMsg));
388
+ console.error('Mutation failed', { status, eventId, ...errorMsg });
569
389
  }
570
390
  if (!dfd) {
571
391
  return;
@@ -575,16 +395,16 @@ export default class Reactor {
575
395
  }
576
396
  else {
577
397
  // Check if error comes from server or client
578
- if (errorMsg === null || errorMsg === void 0 ? void 0 : errorMsg.type) {
579
- const { status } = errorMsg, body = __rest(errorMsg, ["status"]);
398
+ if (errorMsg?.type) {
399
+ const { status, ...body } = errorMsg;
580
400
  dfd.reject(new InstantAPIError({
581
401
  // @ts-expect-error body.type is not constant typed
582
402
  body,
583
- status: status !== null && status !== void 0 ? status : 0,
403
+ status: status ?? 0,
584
404
  }));
585
405
  }
586
406
  else {
587
- dfd.reject(new InstantError((errorMsg === null || errorMsg === void 0 ? void 0 : errorMsg.message) || 'Unknown error', errorMsg === null || errorMsg === void 0 ? void 0 : errorMsg.hint));
407
+ dfd.reject(new InstantError(errorMsg?.message || 'Unknown error', errorMsg?.hint));
588
408
  }
589
409
  }
590
410
  }
@@ -593,9 +413,28 @@ export default class Reactor {
593
413
  this._errorMessage = err;
594
414
  this.notifyConnectionStatusSubs(status);
595
415
  }
416
+ _onMergeKv = (key, storageV, inMemoryV) => {
417
+ switch (key) {
418
+ case 'pendingMutations': {
419
+ const storageEntries = storageV?.entries() ?? [];
420
+ const inMemoryEntries = inMemoryV?.entries() ?? [];
421
+ const muts = new Map([...storageEntries, ...inMemoryEntries]);
422
+ const rewrittenStorageMuts = storageV
423
+ ? this._rewriteMutationsSorted(this.attrs, storageV)
424
+ : [];
425
+ rewrittenStorageMuts.forEach(([k, mut]) => {
426
+ if (!inMemoryV?.pendingMutations?.has(k) && !mut['tx-id']) {
427
+ this._sendMutation(k, mut);
428
+ }
429
+ });
430
+ return muts;
431
+ }
432
+ default:
433
+ return inMemoryV || storageV;
434
+ }
435
+ };
596
436
  _flushEnqueuedRoomData(roomId) {
597
- var _a, _b;
598
- const enqueuedUserPresence = (_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.user;
437
+ const enqueuedUserPresence = this._presence[roomId]?.result?.user;
599
438
  const enqueuedBroadcasts = this._broadcastQueue[roomId];
600
439
  this._broadcastQueue[roomId] = [];
601
440
  if (enqueuedUserPresence) {
@@ -640,7 +479,6 @@ export default class Reactor {
640
479
  this._cleanupPendingMutationsTimeout();
641
480
  }
642
481
  _handleReceive(connId, msg) {
643
- var _a, _b, _c, _d, _e, _f;
644
482
  // opt-out, enabled by default if schema
645
483
  const enableCardinalityInference = Boolean(this.config.schema) &&
646
484
  ('cardinalityInference' in this.config
@@ -659,7 +497,7 @@ export default class Reactor {
659
497
  // which item is us
660
498
  this._sessionId = msg['session-id'];
661
499
  for (const roomId of Object.keys(this._rooms)) {
662
- const enqueuedUserPresence = (_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.user;
500
+ const enqueuedUserPresence = this._presence[roomId]?.result?.user;
663
501
  this._tryJoinRoom(roomId, enqueuedUserPresence);
664
502
  }
665
503
  break;
@@ -674,8 +512,8 @@ export default class Reactor {
674
512
  if (!this._hasQueryListeners() && !this.querySubs.currentValue[hash]) {
675
513
  break;
676
514
  }
677
- 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'];
678
- 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'];
515
+ const pageInfo = result?.[0]?.data?.['page-info'];
516
+ const aggregate = result?.[0]?.data?.['aggregate'];
679
517
  const triples = extractTriples(result);
680
518
  const attrsStore = this.ensureAttrs();
681
519
  const store = s.createStore(attrsStore, triples, enableCardinalityInference, this.config.useDateObjects);
@@ -732,7 +570,6 @@ export default class Reactor {
732
570
  }
733
571
  const mutations = sortedMutationEntries(rewrittenMutations.entries());
734
572
  const updates = computations.map((x) => {
735
- var _a, _b, _c, _d;
736
573
  const q = x['instaql-query'];
737
574
  const result = x['instaql-result'];
738
575
  const hash = weakHash(q);
@@ -740,8 +577,8 @@ export default class Reactor {
740
577
  const attrsStore = this.ensureAttrs();
741
578
  const store = s.createStore(attrsStore, triples, enableCardinalityInference, this.config.useDateObjects);
742
579
  const { store: newStore, attrsStore: newAttrsStore } = this._applyOptimisticUpdates(store, attrsStore, mutations, processedTxId);
743
- 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'];
744
- 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'];
580
+ const pageInfo = result?.[0]?.data?.['page-info'];
581
+ const aggregate = result?.[0]?.data?.['aggregate'];
745
582
  return {
746
583
  q,
747
584
  hash,
@@ -782,7 +619,11 @@ export default class Reactor {
782
619
  }
783
620
  // update pendingMutation with server-side tx-id
784
621
  this._updatePendingMutations((prev) => {
785
- prev.set(eventId, Object.assign(Object.assign({}, prev.get(eventId)), { 'tx-id': txId, confirmed: Date.now() }));
622
+ prev.set(eventId, {
623
+ ...prev.get(eventId),
624
+ 'tx-id': txId,
625
+ confirmed: Date.now(),
626
+ });
786
627
  });
787
628
  const newAttrs = [];
788
629
  for (const step of prevMutation['tx-steps']) {
@@ -856,13 +697,11 @@ export default class Reactor {
856
697
  }
857
698
  }
858
699
  _pendingMutations() {
859
- var _a;
860
- return (_a = this.kv.currentValue.pendingMutations) !== null && _a !== void 0 ? _a : new Map();
700
+ return this.kv.currentValue.pendingMutations ?? new Map();
861
701
  }
862
702
  _updatePendingMutations(f) {
863
703
  this.kv.updateInPlace((prev) => {
864
- var _a;
865
- const muts = (_a = prev.pendingMutations) !== null && _a !== void 0 ? _a : new Map();
704
+ const muts = prev.pendingMutations ?? new Map();
866
705
  prev.pendingMutations = muts;
867
706
  f(muts);
868
707
  });
@@ -891,7 +730,6 @@ export default class Reactor {
891
730
  }
892
731
  }
893
732
  _handleReceiveError(msg) {
894
- var _a, _b, _c, _d, _e, _f, _g;
895
733
  console.log('error', msg);
896
734
  const eventId = msg['client-event-id'];
897
735
  // This might not be a mutation, but it can't hurt to delete it
@@ -907,18 +745,18 @@ export default class Reactor {
907
745
  this._handleMutationError('error', eventId, msg);
908
746
  return;
909
747
  }
910
- if (((_a = msg['original-event']) === null || _a === void 0 ? void 0 : _a.hasOwnProperty('q')) &&
911
- ((_b = msg['original-event']) === null || _b === void 0 ? void 0 : _b.op) === 'add-query') {
912
- const q = (_c = msg['original-event']) === null || _c === void 0 ? void 0 : _c.q;
748
+ if (msg['original-event']?.hasOwnProperty('q') &&
749
+ msg['original-event']?.op === 'add-query') {
750
+ const q = msg['original-event']?.q;
913
751
  const hash = weakHash(q);
914
752
  this.notifyQueryError(weakHash(q), errorMessage);
915
753
  this.notifyQueryOnceError(q, hash, eventId, errorMessage);
916
754
  return;
917
755
  }
918
- const isInitError = ((_d = msg['original-event']) === null || _d === void 0 ? void 0 : _d.op) === 'init';
756
+ const isInitError = msg['original-event']?.op === 'init';
919
757
  if (isInitError) {
920
758
  if (msg.type === 'record-not-found' &&
921
- ((_e = msg.hint) === null || _e === void 0 ? void 0 : _e['record-type']) === 'app-user') {
759
+ msg.hint?.['record-type'] === 'app-user') {
922
760
  // User has been logged out
923
761
  this.changeCurrentUser(null);
924
762
  return;
@@ -928,17 +766,17 @@ export default class Reactor {
928
766
  this.notifyAll();
929
767
  return;
930
768
  }
931
- if (((_f = msg['original-event']) === null || _f === void 0 ? void 0 : _f.op) === 'resync-table') {
769
+ if (msg['original-event']?.op === 'resync-table') {
932
770
  this._syncTable.onResyncError(msg);
933
771
  return;
934
772
  }
935
- if (((_g = msg['original-event']) === null || _g === void 0 ? void 0 : _g.op) === 'start-sync') {
773
+ if (msg['original-event']?.op === 'start-sync') {
936
774
  this._syncTable.onStartSyncError(msg);
937
775
  return;
938
776
  }
939
777
  // We've caught some error which has no corresponding listener.
940
778
  // Let's console.error to let the user know.
941
- const errorObj = Object.assign({}, msg);
779
+ const errorObj = { ...msg };
942
780
  delete errorObj.message;
943
781
  delete errorObj.hint;
944
782
  console.error(msg.message, errorObj);
@@ -947,8 +785,7 @@ export default class Reactor {
947
785
  }
948
786
  }
949
787
  notifyQueryOnceError(q, hash, eventId, e) {
950
- var _a;
951
- const r = (_a = this.queryOnceDfds[hash]) === null || _a === void 0 ? void 0 : _a.find((r) => r.eventId === eventId);
788
+ const r = this.queryOnceDfds[hash]?.find((r) => r.eventId === eventId);
952
789
  if (!r)
953
790
  return;
954
791
  r.dfd.reject(e);
@@ -961,6 +798,12 @@ export default class Reactor {
961
798
  }, {}), this._linkIndex);
962
799
  this.notifyAttrsSubs();
963
800
  }
801
+ // ---------------------------
802
+ // Queries
803
+ getPreviousResult = (q) => {
804
+ const hash = weakHash(q);
805
+ return this.dataForQuery(hash)?.data;
806
+ };
964
807
  _startQuerySub(q, hash) {
965
808
  const eventId = uuid();
966
809
  this.querySubs.updateInPlace((prev) => {
@@ -984,19 +827,18 @@ export default class Reactor {
984
827
  * Returns an unsubscribe function
985
828
  */
986
829
  subscribeQuery(q, cb, opts) {
987
- var _a;
988
830
  if (!this.config.disableValidation) {
989
831
  validateQuery(q, this.config.schema);
990
832
  }
991
833
  if (opts && 'ruleParams' in opts) {
992
- q = Object.assign({ $$ruleParams: opts['ruleParams'] }, q);
834
+ q = { $$ruleParams: opts['ruleParams'], ...q };
993
835
  }
994
836
  const hash = weakHash(q);
995
837
  const prevResult = this.getPreviousResult(q);
996
838
  if (prevResult) {
997
839
  cb(prevResult);
998
840
  }
999
- this.queryCbs[hash] = (_a = this.queryCbs[hash]) !== null && _a !== void 0 ? _a : [];
841
+ this.queryCbs[hash] = this.queryCbs[hash] ?? [];
1000
842
  this.queryCbs[hash].push({ q, cb });
1001
843
  this._startQuerySub(q, hash);
1002
844
  return () => {
@@ -1004,12 +846,11 @@ export default class Reactor {
1004
846
  };
1005
847
  }
1006
848
  queryOnce(q, opts) {
1007
- var _a;
1008
849
  if (!this.config.disableValidation) {
1009
850
  validateQuery(q, this.config.schema);
1010
851
  }
1011
852
  if (opts && 'ruleParams' in opts) {
1012
- q = Object.assign({ $$ruleParams: opts['ruleParams'] }, q);
853
+ q = { $$ruleParams: opts['ruleParams'], ...q };
1013
854
  }
1014
855
  const dfd = new Deferred();
1015
856
  if (!this._isOnline) {
@@ -1022,7 +863,7 @@ export default class Reactor {
1022
863
  }
1023
864
  const hash = weakHash(q);
1024
865
  const eventId = this._startQuerySub(q, hash);
1025
- this.queryOnceDfds[hash] = (_a = this.queryOnceDfds[hash]) !== null && _a !== void 0 ? _a : [];
866
+ this.queryOnceDfds[hash] = this.queryOnceDfds[hash] ?? [];
1026
867
  this.queryOnceDfds[hash].push({ q, dfd, eventId });
1027
868
  setTimeout(() => dfd.reject(new Error('Query timed out')), QUERY_ONCE_TIMEOUT);
1028
869
  return dfd.promise;
@@ -1040,8 +881,7 @@ export default class Reactor {
1040
881
  this._cleanupQuery(q, hash);
1041
882
  }
1042
883
  _hasQueryListeners(hash) {
1043
- var _a, _b;
1044
- 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));
884
+ return !!(this.queryCbs[hash]?.length || this.queryOnceDfds[hash]?.length);
1045
885
  }
1046
886
  _cleanupQuery(q, hash) {
1047
887
  const hasListeners = this._hasQueryListeners(hash);
@@ -1133,7 +973,10 @@ export default class Reactor {
1133
973
  };
1134
974
  const rewritten = new Map();
1135
975
  for (const [k, mut] of muts.entries()) {
1136
- rewritten.set(k, Object.assign(Object.assign({}, mut), { 'tx-steps': rewriteTxSteps(mut['tx-steps'], mut['tx-id']) }));
976
+ rewritten.set(k, {
977
+ ...mut,
978
+ 'tx-steps': rewriteTxSteps(mut['tx-steps'], mut['tx-id']),
979
+ });
1137
980
  }
1138
981
  if (!mappingChanged) {
1139
982
  return muts;
@@ -1149,7 +992,6 @@ export default class Reactor {
1149
992
  * @returns {s.AttrsStore}
1150
993
  */
1151
994
  optimisticAttrs() {
1152
- var _a, _b;
1153
995
  const pendingMutationSteps = [...this._pendingMutations().values()] // hack due to Map()
1154
996
  .flatMap((x) => x['tx-steps']);
1155
997
  const deletedAttrIds = new Set(pendingMutationSteps
@@ -1162,15 +1004,15 @@ export default class Reactor {
1162
1004
  }
1163
1005
  else if (_action === 'update-attr' &&
1164
1006
  attr.id &&
1165
- ((_a = this.attrs) === null || _a === void 0 ? void 0 : _a.getAttr(attr.id))) {
1166
- const fullAttr = Object.assign(Object.assign({}, this.attrs.getAttr(attr.id)), attr);
1007
+ this.attrs?.getAttr(attr.id)) {
1008
+ const fullAttr = { ...this.attrs.getAttr(attr.id), ...attr };
1167
1009
  pendingAttrs.push(fullAttr);
1168
1010
  }
1169
1011
  }
1170
1012
  if (!deletedAttrIds.size && !pendingAttrs.length) {
1171
1013
  return this.attrs || new s.AttrsStoreClass({}, this._linkIndex);
1172
1014
  }
1173
- const attrs = Object.assign({}, (((_b = this.attrs) === null || _b === void 0 ? void 0 : _b.attrs) || {}));
1015
+ const attrs = { ...(this.attrs?.attrs || {}) };
1174
1016
  for (const attr of pendingAttrs) {
1175
1017
  attrs[attr.id] = attr;
1176
1018
  }
@@ -1224,6 +1066,30 @@ export default class Reactor {
1224
1066
  }
1225
1067
  return { store, attrsStore };
1226
1068
  }
1069
+ /** Re-run instaql and call all callbacks with new data */
1070
+ notifyOne = (hash) => {
1071
+ const cbs = this.queryCbs[hash] ?? [];
1072
+ const prevData = this._dataForQueryCache[hash]?.data;
1073
+ const resp = this.dataForQuery(hash);
1074
+ if (!resp?.data)
1075
+ return;
1076
+ this._dataForQueryCache[hash] = resp;
1077
+ if (areObjectsDeepEqual(resp.data, prevData))
1078
+ return;
1079
+ cbs.forEach((r) => r.cb(resp.data));
1080
+ };
1081
+ notifyOneQueryOnce = (hash) => {
1082
+ const dfds = this.queryOnceDfds[hash] ?? [];
1083
+ const data = this.dataForQuery(hash)?.data;
1084
+ dfds.forEach((r) => {
1085
+ this._completeQueryOnce(r.q, hash, r.dfd);
1086
+ r.dfd.resolve(data);
1087
+ });
1088
+ };
1089
+ notifyQueryError = (hash, error) => {
1090
+ const cbs = this.queryCbs[hash] || [];
1091
+ cbs.forEach((r) => r.cb({ error }));
1092
+ };
1227
1093
  /** Re-compute all subscriptions */
1228
1094
  notifyAll() {
1229
1095
  Object.keys(this.queryCbs).forEach((hash) => {
@@ -1239,11 +1105,54 @@ export default class Reactor {
1239
1105
  .then(() => this.notifyAll())
1240
1106
  .catch(() => this.notifyAll());
1241
1107
  }
1108
+ /** Applies transactions locally and sends transact message to server */
1109
+ pushTx = (chunks) => {
1110
+ // Throws if transactions are invalid
1111
+ if (!this.config.disableValidation) {
1112
+ validateTransactions(chunks, this.config.schema);
1113
+ }
1114
+ try {
1115
+ const txSteps = instaml.transform({
1116
+ attrsStore: this.optimisticAttrs(),
1117
+ schema: this.config.schema,
1118
+ stores: Object.values(this.querySubs.currentValue).map((sub) => sub?.result?.store),
1119
+ useDateObjects: this.config.useDateObjects,
1120
+ }, chunks);
1121
+ return this.pushOps(txSteps);
1122
+ }
1123
+ catch (e) {
1124
+ return this.pushOps([], e);
1125
+ }
1126
+ };
1127
+ /**
1128
+ * @param {*} txSteps
1129
+ * @param {*} [error]
1130
+ * @returns
1131
+ */
1132
+ pushOps = (txSteps, error) => {
1133
+ const eventId = uuid();
1134
+ const mutations = [...this._pendingMutations().values()];
1135
+ const order = Math.max(0, ...mutations.map((mut) => mut.order || 0)) + 1;
1136
+ const mutation = {
1137
+ op: 'transact',
1138
+ 'tx-steps': txSteps,
1139
+ created: Date.now(),
1140
+ error,
1141
+ order,
1142
+ };
1143
+ this._updatePendingMutations((prev) => {
1144
+ prev.set(eventId, mutation);
1145
+ });
1146
+ const dfd = new Deferred();
1147
+ this.mutationDeferredStore.set(eventId, dfd);
1148
+ this._sendMutation(eventId, mutation);
1149
+ this.notifyAll();
1150
+ return dfd.promise;
1151
+ };
1242
1152
  shutdown() {
1243
- var _a;
1244
1153
  this._log.info('[shutdown]', this.config.appId);
1245
1154
  this._isShutdown = true;
1246
- (_a = this._transport) === null || _a === void 0 ? void 0 : _a.close();
1155
+ this._transport?.close();
1247
1156
  }
1248
1157
  /**
1249
1158
  * Sends mutation to server and schedules a timeout to cancel it if
@@ -1316,8 +1225,8 @@ export default class Reactor {
1316
1225
  _cleanupPendingMutationsQueries() {
1317
1226
  let minProcessedTxId = Number.MAX_SAFE_INTEGER;
1318
1227
  for (const { result } of Object.values(this.querySubs.currentValue)) {
1319
- if (result === null || result === void 0 ? void 0 : result.processedTxId) {
1320
- minProcessedTxId = Math.min(minProcessedTxId, result === null || result === void 0 ? void 0 : result.processedTxId);
1228
+ if (result?.processedTxId) {
1229
+ minProcessedTxId = Math.min(minProcessedTxId, result?.processedTxId);
1321
1230
  }
1322
1231
  }
1323
1232
  this._updatePendingMutations((prev) => {
@@ -1370,8 +1279,96 @@ export default class Reactor {
1370
1279
  this._inFlightMutationEventIds.clear();
1371
1280
  }
1372
1281
  }
1373
- this._transport.send(Object.assign({ 'client-event-id': eventId }, msg));
1282
+ this._transport.send({ 'client-event-id': eventId, ...msg });
1374
1283
  }
1284
+ _transportOnOpen = (e) => {
1285
+ const targetTransport = e.target;
1286
+ if (this._transport !== targetTransport) {
1287
+ this._log.info('[socket][open]', targetTransport.id, 'skip; this is no longer the current transport');
1288
+ return;
1289
+ }
1290
+ this._log.info('[socket][open]', this._transport.id);
1291
+ this._setStatus(STATUS.OPENED);
1292
+ this.getCurrentUser()
1293
+ .then((resp) => {
1294
+ this._trySend(uuid(), {
1295
+ op: 'init',
1296
+ 'app-id': this.config.appId,
1297
+ 'refresh-token': resp.user?.['refresh_token'],
1298
+ versions: this.versions,
1299
+ // If an admin token is provided for an app, we will
1300
+ // skip all permission checks. This is an advanced feature,
1301
+ // to let users write internal tools
1302
+ // This option is not exposed in `Config`, as it's
1303
+ // not ready for prime time
1304
+ '__admin-token': this.config.__adminToken,
1305
+ });
1306
+ })
1307
+ .catch((e) => {
1308
+ this._log.error('[socket][error]', targetTransport.id, e);
1309
+ });
1310
+ };
1311
+ _transportOnMessage = (e) => {
1312
+ const targetTransport = e.target;
1313
+ const m = e.message;
1314
+ if (this._transport !== targetTransport) {
1315
+ this._log.info('[socket][message]', targetTransport.id, m, 'skip; this is no longer the current transport');
1316
+ return;
1317
+ }
1318
+ if (!this._wsOk && targetTransport.type === 'ws') {
1319
+ this._wsOk = true;
1320
+ }
1321
+ // Try to reconnect via websocket the next time we connect
1322
+ this._transportType = 'ws';
1323
+ if (Array.isArray(e.message)) {
1324
+ for (const msg of e.message) {
1325
+ this._handleReceive(targetTransport.id, msg);
1326
+ }
1327
+ }
1328
+ else {
1329
+ this._handleReceive(targetTransport.id, e.message);
1330
+ }
1331
+ };
1332
+ _transportOnError = (e) => {
1333
+ const targetTransport = e.target;
1334
+ if (this._transport !== targetTransport) {
1335
+ this._log.info('[socket][error]', targetTransport.id, 'skip; this is no longer the current transport');
1336
+ return;
1337
+ }
1338
+ this._log.error('[socket][error]', targetTransport.id, e);
1339
+ };
1340
+ _scheduleReconnect = () => {
1341
+ // If we couldn't connect with a websocket last time, try sse
1342
+ if (!this._wsOk && this._transportType !== 'sse') {
1343
+ this._transportType = 'sse';
1344
+ this._reconnectTimeoutMs = 0;
1345
+ }
1346
+ setTimeout(() => {
1347
+ this._reconnectTimeoutMs = Math.min(this._reconnectTimeoutMs + 1000, 10000);
1348
+ if (!this._isOnline) {
1349
+ this._log.info('[socket][close]', this._transport.id, 'we are offline, no need to start socket');
1350
+ return;
1351
+ }
1352
+ this._startSocket();
1353
+ }, this._reconnectTimeoutMs);
1354
+ };
1355
+ _transportOnClose = (e) => {
1356
+ const targetTransport = e.target;
1357
+ if (this._transport !== targetTransport) {
1358
+ this._log.info('[socket][close]', targetTransport.id, 'skip; this is no longer the current transport');
1359
+ return;
1360
+ }
1361
+ this._setStatus(STATUS.CLOSED);
1362
+ for (const room of Object.values(this._rooms)) {
1363
+ room.isConnected = false;
1364
+ }
1365
+ if (this._isShutdown) {
1366
+ this._log.info('[socket][close]', targetTransport.id, 'Reactor has been shut down and will not reconnect');
1367
+ return;
1368
+ }
1369
+ this._log.info('[socket][close]', targetTransport.id, 'schedule reconnect, ms =', this._reconnectTimeoutMs);
1370
+ this._scheduleReconnect();
1371
+ };
1375
1372
  _startSocket() {
1376
1373
  // Reset whether we support websockets each time we connect
1377
1374
  // new networks may not support websockets
@@ -1400,7 +1397,7 @@ export default class Reactor {
1400
1397
  this._transport.onclose = this._transportOnClose;
1401
1398
  this._transport.onerror = this._transportOnError;
1402
1399
  this._log.info('[socket][start]', this._transport.id);
1403
- if (prevTransport === null || prevTransport === void 0 ? void 0 : prevTransport.isOpen()) {
1400
+ if (prevTransport?.isOpen()) {
1404
1401
  // When the network dies, it doesn't always mean that our
1405
1402
  // socket connection will fire a close event.
1406
1403
  //
@@ -1421,24 +1418,22 @@ export default class Reactor {
1421
1418
  * Note: If the user deletes their local storage, this id will change.
1422
1419
  *
1423
1420
  */
1424
- getLocalId(name) {
1425
- return __awaiter(this, void 0, void 0, function* () {
1426
- const k = `localToken_${name}`;
1427
- if (this.kv.currentValue[k]) {
1428
- return this.kv.currentValue[k];
1429
- }
1430
- const current = yield this.kv.waitForKeyToLoad(k);
1431
- if (current) {
1432
- return current;
1433
- }
1434
- const newId = uuid();
1435
- this.kv.updateInPlace((prev) => {
1436
- if (prev[k])
1437
- return;
1438
- prev[k] = newId;
1439
- });
1440
- return yield this.kv.waitForKeyToLoad(k);
1421
+ async getLocalId(name) {
1422
+ const k = `localToken_${name}`;
1423
+ if (this.kv.currentValue[k]) {
1424
+ return this.kv.currentValue[k];
1425
+ }
1426
+ const current = await this.kv.waitForKeyToLoad(k);
1427
+ if (current) {
1428
+ return current;
1429
+ }
1430
+ const newId = uuid();
1431
+ this.kv.updateInPlace((prev) => {
1432
+ if (prev[k])
1433
+ return;
1434
+ prev[k] = newId;
1441
1435
  });
1436
+ return await this.kv.waitForKeyToLoad(k);
1442
1437
  }
1443
1438
  // ----
1444
1439
  // Auth
@@ -1473,14 +1468,13 @@ export default class Reactor {
1473
1468
  // The next.js app router will reset the URL when the router loads.
1474
1469
  // This puts it back after the router loads.
1475
1470
  const listener = (e) => {
1476
- var _a;
1477
1471
  if (!ran) {
1478
1472
  ran = true;
1479
1473
  // @ts-ignore (waiting for ts support)
1480
1474
  navigation.removeEventListener('navigate', listener);
1481
1475
  if (!e.userInitiated &&
1482
1476
  e.navigationType === 'replace' &&
1483
- ((_a = e.destination) === null || _a === void 0 ? void 0 : _a.url) === startUrl) {
1477
+ e.destination?.url === startUrl) {
1484
1478
  history.replaceState(history.state, '', newPath);
1485
1479
  }
1486
1480
  }
@@ -1494,57 +1488,52 @@ export default class Reactor {
1494
1488
  *
1495
1489
  * @returns Promise<null | {error: {message: string}}>
1496
1490
  */
1497
- _oauthLoginInit() {
1498
- return __awaiter(this, void 0, void 0, function* () {
1499
- var _a, _b, _c, _d;
1500
- if (typeof window === 'undefined' ||
1501
- typeof window.location === 'undefined' ||
1502
- typeof URLSearchParams === 'undefined') {
1503
- return null;
1504
- }
1505
- const params = new URLSearchParams(window.location.search);
1506
- if (!params.get(OAUTH_REDIRECT_PARAM)) {
1507
- return null;
1508
- }
1509
- const error = params.get('error');
1510
- if (error) {
1511
- this._replaceUrlAfterOAuth();
1512
- return { error: { message: error } };
1513
- }
1514
- const code = params.get('code');
1515
- if (!code) {
1516
- return null;
1517
- }
1491
+ async _oauthLoginInit() {
1492
+ if (typeof window === 'undefined' ||
1493
+ typeof window.location === 'undefined' ||
1494
+ typeof URLSearchParams === 'undefined') {
1495
+ return null;
1496
+ }
1497
+ const params = new URLSearchParams(window.location.search);
1498
+ if (!params.get(OAUTH_REDIRECT_PARAM)) {
1499
+ return null;
1500
+ }
1501
+ const error = params.get('error');
1502
+ if (error) {
1518
1503
  this._replaceUrlAfterOAuth();
1519
- try {
1520
- const currentUser = yield this._getCurrentUser();
1521
- const isGuest = (currentUser === null || currentUser === void 0 ? void 0 : currentUser.type) === 'guest';
1522
- const { user } = yield authAPI.exchangeCodeForToken({
1523
- apiURI: this.config.apiURI,
1524
- appId: this.config.appId,
1525
- code,
1526
- refreshToken: isGuest ? currentUser.refresh_token : undefined,
1527
- });
1528
- this.setCurrentUser(user);
1504
+ return { error: { message: error } };
1505
+ }
1506
+ const code = params.get('code');
1507
+ if (!code) {
1508
+ return null;
1509
+ }
1510
+ this._replaceUrlAfterOAuth();
1511
+ try {
1512
+ const currentUser = await this._getCurrentUser();
1513
+ const isGuest = currentUser?.type === 'guest';
1514
+ const { user } = await authAPI.exchangeCodeForToken({
1515
+ apiURI: this.config.apiURI,
1516
+ appId: this.config.appId,
1517
+ code,
1518
+ refreshToken: isGuest ? currentUser.refresh_token : undefined,
1519
+ });
1520
+ this.setCurrentUser(user);
1521
+ return null;
1522
+ }
1523
+ catch (e) {
1524
+ if (e?.body?.type === 'record-not-found' &&
1525
+ e?.body?.hint?.['record-type'] === 'app-oauth-code' &&
1526
+ (await this._hasCurrentUser())) {
1527
+ // We probably just weren't able to clean up the URL, so
1528
+ // let's just ignore this error
1529
1529
  return null;
1530
1530
  }
1531
- catch (e) {
1532
- if (((_a = e === null || e === void 0 ? void 0 : e.body) === null || _a === void 0 ? void 0 : _a.type) === 'record-not-found' &&
1533
- ((_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' &&
1534
- (yield this._hasCurrentUser())) {
1535
- // We probably just weren't able to clean up the URL, so
1536
- // let's just ignore this error
1537
- return null;
1538
- }
1539
- const message = ((_d = e === null || e === void 0 ? void 0 : e.body) === null || _d === void 0 ? void 0 : _d.message) || 'Error logging in.';
1540
- return { error: { message } };
1541
- }
1542
- });
1531
+ const message = e?.body?.message || 'Error logging in.';
1532
+ return { error: { message } };
1533
+ }
1543
1534
  }
1544
- _waitForOAuthCallbackResponse() {
1545
- return __awaiter(this, void 0, void 0, function* () {
1546
- return yield this._oauthCallbackResponse;
1547
- });
1535
+ async _waitForOAuthCallbackResponse() {
1536
+ return await this._oauthCallbackResponse;
1548
1537
  }
1549
1538
  __subscribeMutationErrors(cb) {
1550
1539
  this.mutationErrorCbs.push(cb);
@@ -1571,14 +1560,12 @@ export default class Reactor {
1571
1560
  this.authCbs = this.authCbs.filter((x) => x !== cb);
1572
1561
  };
1573
1562
  }
1574
- getAuth() {
1575
- return __awaiter(this, void 0, void 0, function* () {
1576
- const { user, error } = yield this.getCurrentUser();
1577
- if (error) {
1578
- throw new InstantError('Could not get current user: ' + error.message);
1579
- }
1580
- return user;
1581
- });
1563
+ async getAuth() {
1564
+ const { user, error } = await this.getCurrentUser();
1565
+ if (error) {
1566
+ throw new InstantError('Could not get current user: ' + error.message);
1567
+ }
1568
+ return user;
1582
1569
  }
1583
1570
  subscribeConnectionStatus(cb) {
1584
1571
  this.connectionStatusCbs.push(cb);
@@ -1610,99 +1597,89 @@ export default class Reactor {
1610
1597
  notifyConnectionStatusSubs(status) {
1611
1598
  this.connectionStatusCbs.forEach((cb) => cb(status));
1612
1599
  }
1613
- setCurrentUser(user) {
1614
- return __awaiter(this, void 0, void 0, function* () {
1615
- this.kv.updateInPlace((prev) => {
1616
- prev[currentUserKey] = user;
1617
- });
1618
- yield this.kv.waitForKeyToLoad(currentUserKey);
1600
+ async setCurrentUser(user) {
1601
+ this.kv.updateInPlace((prev) => {
1602
+ prev[currentUserKey] = user;
1619
1603
  });
1604
+ await this.kv.waitForKeyToLoad(currentUserKey);
1620
1605
  }
1621
1606
  getCurrentUserCached() {
1622
1607
  return this._currentUserCached;
1623
1608
  }
1624
- _getCurrentUser() {
1625
- return __awaiter(this, void 0, void 0, function* () {
1626
- const user = yield this.kv.waitForKeyToLoad(currentUserKey);
1627
- return typeof user === 'string' ? JSON.parse(user) : user;
1628
- });
1629
- }
1630
- getCurrentUser() {
1631
- return __awaiter(this, void 0, void 0, function* () {
1632
- const oauthResp = yield this._waitForOAuthCallbackResponse();
1633
- if (oauthResp === null || oauthResp === void 0 ? void 0 : oauthResp.error) {
1634
- const errorV = { error: oauthResp.error, user: undefined };
1635
- this._currentUserCached = Object.assign({ isLoading: false }, errorV);
1636
- return errorV;
1637
- }
1638
- try {
1639
- const user = yield this._getCurrentUser();
1640
- const userV = { user: user, error: undefined };
1641
- this._currentUserCached = Object.assign({ isLoading: false }, userV);
1642
- return userV;
1643
- }
1644
- catch (e) {
1645
- return {
1646
- user: undefined,
1647
- isLoading: false,
1648
- error: { message: (e === null || e === void 0 ? void 0 : e.message) || 'Error loading user' },
1649
- };
1650
- }
1651
- });
1609
+ async _getCurrentUser() {
1610
+ const user = await this.kv.waitForKeyToLoad(currentUserKey);
1611
+ return typeof user === 'string' ? JSON.parse(user) : user;
1612
+ }
1613
+ async getCurrentUser() {
1614
+ const oauthResp = await this._waitForOAuthCallbackResponse();
1615
+ if (oauthResp?.error) {
1616
+ const errorV = { error: oauthResp.error, user: undefined };
1617
+ this._currentUserCached = { isLoading: false, ...errorV };
1618
+ return errorV;
1619
+ }
1620
+ try {
1621
+ const user = await this._getCurrentUser();
1622
+ const userV = { user: user, error: undefined };
1623
+ this._currentUserCached = {
1624
+ isLoading: false,
1625
+ ...userV,
1626
+ };
1627
+ return userV;
1628
+ }
1629
+ catch (e) {
1630
+ return {
1631
+ user: undefined,
1632
+ isLoading: false,
1633
+ error: { message: e?.message || 'Error loading user' },
1634
+ };
1635
+ }
1652
1636
  }
1653
- _hasCurrentUser() {
1654
- return __awaiter(this, void 0, void 0, function* () {
1655
- const user = yield this.kv.waitForKeyToLoad(currentUserKey);
1656
- return typeof user === 'string' ? JSON.parse(user) != null : user != null;
1657
- });
1637
+ async _hasCurrentUser() {
1638
+ const user = await this.kv.waitForKeyToLoad(currentUserKey);
1639
+ return typeof user === 'string' ? JSON.parse(user) != null : user != null;
1658
1640
  }
1659
- changeCurrentUser(newUser) {
1660
- return __awaiter(this, void 0, void 0, function* () {
1661
- var _a;
1662
- const { user: oldUser } = yield this.getCurrentUser();
1663
- if (areObjectsDeepEqual(oldUser, newUser)) {
1664
- // We were already logged in as the newUser, don't
1665
- // bother updating
1666
- return;
1667
- }
1668
- yield this.setCurrentUser(newUser);
1669
- // We need to remove all `result` from querySubs,
1670
- // as they are no longer valid for the new user
1671
- this.updateUser(newUser);
1672
- try {
1673
- (_a = this._broadcastChannel) === null || _a === void 0 ? void 0 : _a.postMessage({ type: 'auth' });
1674
- }
1675
- catch (error) {
1676
- console.error('Error posting message to broadcast channel', error);
1677
- }
1678
- });
1641
+ async changeCurrentUser(newUser) {
1642
+ const { user: oldUser } = await this.getCurrentUser();
1643
+ if (areObjectsDeepEqual(oldUser, newUser)) {
1644
+ // We were already logged in as the newUser, don't
1645
+ // bother updating
1646
+ return;
1647
+ }
1648
+ await this.setCurrentUser(newUser);
1649
+ // We need to remove all `result` from querySubs,
1650
+ // as they are no longer valid for the new user
1651
+ this.updateUser(newUser);
1652
+ try {
1653
+ this._broadcastChannel?.postMessage({ type: 'auth' });
1654
+ }
1655
+ catch (error) {
1656
+ console.error('Error posting message to broadcast channel', error);
1657
+ }
1679
1658
  }
1680
- syncUserToEndpoint(user) {
1681
- return __awaiter(this, void 0, void 0, function* () {
1682
- if (!this.config.firstPartyPath)
1683
- return;
1684
- try {
1685
- fetch(this.config.firstPartyPath + '/', {
1686
- method: 'POST',
1687
- body: JSON.stringify({
1688
- type: 'sync-user',
1689
- appId: this.config.appId,
1690
- user: user,
1691
- }),
1692
- headers: {
1693
- 'Content-Type': 'application/json',
1694
- },
1695
- });
1696
- }
1697
- catch (error) {
1698
- this._log.error('Error syncing user with external endpoint', error);
1699
- }
1700
- });
1659
+ async syncUserToEndpoint(user) {
1660
+ if (!this.config.firstPartyPath)
1661
+ return;
1662
+ try {
1663
+ fetch(this.config.firstPartyPath + '/', {
1664
+ method: 'POST',
1665
+ body: JSON.stringify({
1666
+ type: 'sync-user',
1667
+ appId: this.config.appId,
1668
+ user: user,
1669
+ }),
1670
+ headers: {
1671
+ 'Content-Type': 'application/json',
1672
+ },
1673
+ });
1674
+ }
1675
+ catch (error) {
1676
+ this._log.error('Error syncing user with external endpoint', error);
1677
+ }
1701
1678
  }
1702
1679
  updateUser(newUser) {
1703
1680
  this.syncUserToEndpoint(newUser);
1704
1681
  const newV = { error: undefined, user: newUser };
1705
- this._currentUserCached = Object.assign({ isLoading: false }, newV);
1682
+ this._currentUserCached = { isLoading: false, ...newV };
1706
1683
  this._dataForQueryCache = {};
1707
1684
  this.querySubs.updateInPlace((prev) => {
1708
1685
  Object.keys(prev).forEach((k) => {
@@ -1721,46 +1698,38 @@ export default class Reactor {
1721
1698
  email: email,
1722
1699
  });
1723
1700
  }
1724
- signInWithMagicCode(_a) {
1725
- return __awaiter(this, arguments, void 0, function* ({ email, code }) {
1726
- var _b;
1727
- const currentUser = yield this.getCurrentUser();
1728
- const isGuest = ((_b = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _b === void 0 ? void 0 : _b.type) === 'guest';
1729
- const res = yield authAPI.verifyMagicCode({
1730
- apiURI: this.config.apiURI,
1731
- appId: this.config.appId,
1732
- email,
1733
- code,
1734
- refreshToken: isGuest ? currentUser.user.refresh_token : undefined,
1735
- });
1736
- yield this.changeCurrentUser(res.user);
1737
- return res;
1701
+ async signInWithMagicCode({ email, code }) {
1702
+ const currentUser = await this.getCurrentUser();
1703
+ const isGuest = currentUser?.user?.type === 'guest';
1704
+ const res = await authAPI.verifyMagicCode({
1705
+ apiURI: this.config.apiURI,
1706
+ appId: this.config.appId,
1707
+ email,
1708
+ code,
1709
+ refreshToken: isGuest ? currentUser.user.refresh_token : undefined,
1738
1710
  });
1711
+ await this.changeCurrentUser(res.user);
1712
+ return res;
1739
1713
  }
1740
- signInWithCustomToken(authToken) {
1741
- return __awaiter(this, void 0, void 0, function* () {
1742
- const res = yield authAPI.verifyRefreshToken({
1743
- apiURI: this.config.apiURI,
1744
- appId: this.config.appId,
1745
- refreshToken: authToken,
1746
- });
1747
- yield this.changeCurrentUser(res.user);
1748
- return res;
1714
+ async signInWithCustomToken(authToken) {
1715
+ const res = await authAPI.verifyRefreshToken({
1716
+ apiURI: this.config.apiURI,
1717
+ appId: this.config.appId,
1718
+ refreshToken: authToken,
1749
1719
  });
1720
+ await this.changeCurrentUser(res.user);
1721
+ return res;
1750
1722
  }
1751
- signInAsGuest() {
1752
- return __awaiter(this, void 0, void 0, function* () {
1753
- const res = yield authAPI.signInAsGuest({
1754
- apiURI: this.config.apiURI,
1755
- appId: this.config.appId,
1756
- });
1757
- yield this.changeCurrentUser(res.user);
1758
- return res;
1723
+ async signInAsGuest() {
1724
+ const res = await authAPI.signInAsGuest({
1725
+ apiURI: this.config.apiURI,
1726
+ appId: this.config.appId,
1759
1727
  });
1728
+ await this.changeCurrentUser(res.user);
1729
+ return res;
1760
1730
  }
1761
1731
  potentiallyInvalidateToken(currentUser, opts) {
1762
- var _a;
1763
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
1732
+ const refreshToken = currentUser?.user?.refresh_token;
1764
1733
  if (!refreshToken) {
1765
1734
  return;
1766
1735
  }
@@ -1780,12 +1749,10 @@ export default class Reactor {
1780
1749
  })
1781
1750
  .catch((e) => { });
1782
1751
  }
1783
- signOut(opts) {
1784
- return __awaiter(this, void 0, void 0, function* () {
1785
- const currentUser = yield this.getCurrentUser();
1786
- this.potentiallyInvalidateToken(currentUser, opts);
1787
- yield this.changeCurrentUser(null);
1788
- });
1752
+ async signOut(opts) {
1753
+ const currentUser = await this.getCurrentUser();
1754
+ this.potentiallyInvalidateToken(currentUser, opts);
1755
+ await this.changeCurrentUser(null);
1789
1756
  }
1790
1757
  /**
1791
1758
  * Creates an OAuth authorization URL.
@@ -1804,21 +1771,18 @@ export default class Reactor {
1804
1771
  * @param {string} params.code - The code received from the OAuth service.
1805
1772
  * @param {string} [params.codeVerifier] - The code verifier used to generate the code challenge.
1806
1773
  */
1807
- exchangeCodeForToken(_a) {
1808
- return __awaiter(this, arguments, void 0, function* ({ code, codeVerifier }) {
1809
- var _b;
1810
- const currentUser = yield this.getCurrentUser();
1811
- const isGuest = ((_b = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _b === void 0 ? void 0 : _b.type) === 'guest';
1812
- const res = yield authAPI.exchangeCodeForToken({
1813
- apiURI: this.config.apiURI,
1814
- appId: this.config.appId,
1815
- code: code,
1816
- codeVerifier,
1817
- refreshToken: isGuest ? currentUser.user.refresh_token : undefined,
1818
- });
1819
- yield this.changeCurrentUser(res.user);
1820
- return res;
1774
+ async exchangeCodeForToken({ code, codeVerifier }) {
1775
+ const currentUser = await this.getCurrentUser();
1776
+ const isGuest = currentUser?.user?.type === 'guest';
1777
+ const res = await authAPI.exchangeCodeForToken({
1778
+ apiURI: this.config.apiURI,
1779
+ appId: this.config.appId,
1780
+ code: code,
1781
+ codeVerifier,
1782
+ refreshToken: isGuest ? currentUser.user.refresh_token : undefined,
1821
1783
  });
1784
+ await this.changeCurrentUser(res.user);
1785
+ return res;
1822
1786
  }
1823
1787
  issuerURI() {
1824
1788
  const { apiURI, appId } = this.config;
@@ -1830,22 +1794,19 @@ export default class Reactor {
1830
1794
  * @param {string} params.idToken - The id_token from the external service
1831
1795
  * @param {string | null | undefined} [params.nonce] - The nonce used when requesting the id_token from the external service
1832
1796
  */
1833
- signInWithIdToken(_a) {
1834
- return __awaiter(this, arguments, void 0, function* ({ idToken, clientName, nonce }) {
1835
- var _b;
1836
- const currentUser = yield this.getCurrentUser();
1837
- const refreshToken = (_b = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _b === void 0 ? void 0 : _b.refresh_token;
1838
- const res = yield authAPI.signInWithIdToken({
1839
- apiURI: this.config.apiURI,
1840
- appId: this.config.appId,
1841
- idToken,
1842
- clientName,
1843
- nonce,
1844
- refreshToken,
1845
- });
1846
- yield this.changeCurrentUser(res.user);
1847
- return res;
1797
+ async signInWithIdToken({ idToken, clientName, nonce }) {
1798
+ const currentUser = await this.getCurrentUser();
1799
+ const refreshToken = currentUser?.user?.refresh_token;
1800
+ const res = await authAPI.signInWithIdToken({
1801
+ apiURI: this.config.apiURI,
1802
+ appId: this.config.appId,
1803
+ idToken,
1804
+ clientName,
1805
+ nonce,
1806
+ refreshToken,
1848
1807
  });
1808
+ await this.changeCurrentUser(res.user);
1809
+ return res;
1849
1810
  }
1850
1811
  // --------
1851
1812
  // Rooms
@@ -1878,10 +1839,9 @@ export default class Reactor {
1878
1839
  };
1879
1840
  }
1880
1841
  _cleanupRoom(roomId) {
1881
- var _a, _b, _c, _d;
1882
- if (!((_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.handlers) === null || _b === void 0 ? void 0 : _b.length) &&
1883
- !Object.keys((_c = this._broadcastSubs[roomId]) !== null && _c !== void 0 ? _c : {}).length) {
1884
- const isConnected = (_d = this._rooms[roomId]) === null || _d === void 0 ? void 0 : _d.isConnected;
1842
+ if (!this._presence[roomId]?.handlers?.length &&
1843
+ !Object.keys(this._broadcastSubs[roomId] ?? {}).length) {
1844
+ const isConnected = this._rooms[roomId]?.isConnected;
1885
1845
  delete this._rooms[roomId];
1886
1846
  delete this._presence[roomId];
1887
1847
  delete this._broadcastSubs[roomId];
@@ -1901,7 +1861,11 @@ export default class Reactor {
1901
1861
  const presence = this._presence[roomId];
1902
1862
  if (!room || !presence || !presence.result)
1903
1863
  return null;
1904
- return Object.assign(Object.assign({}, buildPresenceSlice(presence.result, opts, this._sessionId)), { isLoading: !room.isConnected, error: room.error });
1864
+ return {
1865
+ ...buildPresenceSlice(presence.result, opts, this._sessionId),
1866
+ isLoading: !room.isConnected,
1867
+ error: room.error,
1868
+ };
1905
1869
  }
1906
1870
  // TODO: look into typing again
1907
1871
  publishPresence(roomType, roomId, partialData) {
@@ -1911,7 +1875,10 @@ export default class Reactor {
1911
1875
  return;
1912
1876
  }
1913
1877
  presence.result = presence.result || {};
1914
- const data = Object.assign(Object.assign({}, presence.result.user), partialData);
1878
+ const data = {
1879
+ ...presence.result.user,
1880
+ ...partialData,
1881
+ };
1915
1882
  presence.result.user = data;
1916
1883
  if (!room.isConnected) {
1917
1884
  return;
@@ -1946,21 +1913,19 @@ export default class Reactor {
1946
1913
  // Note: initialData is deprecated.
1947
1914
  // Keeping here for backwards compatibility
1948
1915
  opts.initialPresence || opts.initialData);
1949
- const handler = Object.assign(Object.assign({}, opts), { roomId, cb, prev: null });
1916
+ const handler = { ...opts, roomId, cb, prev: null };
1950
1917
  this._presence[roomId] = this._presence[roomId] || {};
1951
1918
  this._presence[roomId].handlers = this._presence[roomId].handlers || [];
1952
1919
  this._presence[roomId].handlers.push(handler);
1953
1920
  this._notifyPresenceSub(roomId, handler);
1954
1921
  return () => {
1955
- var _a, _b, _c;
1956
1922
  this._presence[roomId].handlers =
1957
- (_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 : [];
1923
+ this._presence[roomId]?.handlers?.filter((x) => x !== handler) ?? [];
1958
1924
  leaveRoom();
1959
1925
  };
1960
1926
  }
1961
1927
  _notifyPresenceSubs(roomId) {
1962
- var _a, _b;
1963
- (_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.handlers) === null || _b === void 0 ? void 0 : _b.forEach((handler) => {
1928
+ this._presence[roomId]?.handlers?.forEach((handler) => {
1964
1929
  this._notifyPresenceSub(roomId, handler);
1965
1930
  });
1966
1931
  }
@@ -1976,10 +1941,9 @@ export default class Reactor {
1976
1941
  handler.cb(slice);
1977
1942
  }
1978
1943
  _patchPresencePeers(roomId, edits) {
1979
- var _a, _b, _c;
1980
- const peers = ((_b = (_a = this._presence[roomId]) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.peers) || {};
1944
+ const peers = this._presence[roomId]?.result?.peers || {};
1981
1945
  let sessions = Object.fromEntries(Object.entries(peers).map(([k, v]) => [k, { data: v }]));
1982
- const myPresence = (_c = this._presence[roomId]) === null || _c === void 0 ? void 0 : _c.result;
1946
+ const myPresence = this._presence[roomId]?.result;
1983
1947
  const newSessions = create(sessions, (draft) => {
1984
1948
  for (let [path, op, value] of edits) {
1985
1949
  switch (op) {
@@ -2000,7 +1964,7 @@ export default class Reactor {
2000
1964
  this._setPresencePeers(roomId, newSessions);
2001
1965
  }
2002
1966
  _setPresencePeers(roomId, data) {
2003
- const sessions = Object.assign({}, data);
1967
+ const sessions = { ...data };
2004
1968
  // no need to keep track of `user`
2005
1969
  delete sessions[this._sessionId];
2006
1970
  const peers = Object.fromEntries(Object.entries(sessions).map(([k, v]) => [k, v.data]));
@@ -2011,13 +1975,12 @@ export default class Reactor {
2011
1975
  // --------
2012
1976
  // Broadcast
2013
1977
  publishTopic({ roomType, roomId, topic, data }) {
2014
- var _a;
2015
1978
  const room = this._rooms[roomId];
2016
1979
  if (!room) {
2017
1980
  return;
2018
1981
  }
2019
1982
  if (!room.isConnected) {
2020
- this._broadcastQueue[roomId] = (_a = this._broadcastQueue[roomId]) !== null && _a !== void 0 ? _a : [];
1983
+ this._broadcastQueue[roomId] = this._broadcastQueue[roomId] ?? [];
2021
1984
  this._broadcastQueue[roomId].push({ topic, roomType, data });
2022
1985
  return;
2023
1986
  }
@@ -2048,71 +2011,64 @@ export default class Reactor {
2048
2011
  };
2049
2012
  }
2050
2013
  _notifyBroadcastSubs(room, topic, msg) {
2051
- var _a, _b, _c;
2052
- (_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) => {
2053
- var _a, _b, _c, _d, _e, _f;
2054
- const data = (_a = msg.data) === null || _a === void 0 ? void 0 : _a.data;
2014
+ this._broadcastSubs?.[room]?.[topic]?.forEach((cb) => {
2015
+ const data = msg.data?.data;
2055
2016
  const peer = msg.data['peer-id'] === this._sessionId
2056
- ? (_c = (_b = this._presence[room]) === null || _b === void 0 ? void 0 : _b.result) === null || _c === void 0 ? void 0 : _c.user
2057
- : (_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']];
2017
+ ? this._presence[room]?.result?.user
2018
+ : this._presence[room]?.result?.peers?.[msg.data['peer-id']];
2058
2019
  return cb(data, peer);
2059
2020
  });
2060
2021
  }
2061
2022
  // --------
2062
2023
  // Storage
2063
- uploadFile(path, file, opts) {
2064
- return __awaiter(this, void 0, void 0, function* () {
2065
- var _a;
2066
- const currentUser = yield this.getCurrentUser();
2067
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
2068
- return StorageApi.uploadFile(Object.assign(Object.assign({}, opts), { apiURI: this.config.apiURI, appId: this.config.appId, path: path, file, refreshToken: refreshToken }));
2024
+ async uploadFile(path, file, opts) {
2025
+ const currentUser = await this.getCurrentUser();
2026
+ const refreshToken = currentUser?.user?.refresh_token;
2027
+ return StorageApi.uploadFile({
2028
+ ...opts,
2029
+ apiURI: this.config.apiURI,
2030
+ appId: this.config.appId,
2031
+ path: path,
2032
+ file,
2033
+ refreshToken: refreshToken,
2069
2034
  });
2070
2035
  }
2071
- deleteFile(path) {
2072
- return __awaiter(this, void 0, void 0, function* () {
2073
- var _a;
2074
- const currentUser = yield this.getCurrentUser();
2075
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
2076
- const result = yield StorageApi.deleteFile({
2077
- apiURI: this.config.apiURI,
2078
- appId: this.config.appId,
2079
- path,
2080
- refreshToken: refreshToken,
2081
- });
2082
- return result;
2036
+ async deleteFile(path) {
2037
+ const currentUser = await this.getCurrentUser();
2038
+ const refreshToken = currentUser?.user?.refresh_token;
2039
+ const result = await StorageApi.deleteFile({
2040
+ apiURI: this.config.apiURI,
2041
+ appId: this.config.appId,
2042
+ path,
2043
+ refreshToken: refreshToken,
2083
2044
  });
2045
+ return result;
2084
2046
  }
2085
2047
  // Deprecated Storage API (Jan 2025)
2086
2048
  // ---------------------------------
2087
- upload(path, file) {
2088
- return __awaiter(this, void 0, void 0, function* () {
2089
- var _a;
2090
- const currentUser = yield this.getCurrentUser();
2091
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
2092
- const fileName = path || file.name;
2093
- const url = yield StorageApi.getSignedUploadUrl({
2094
- apiURI: this.config.apiURI,
2095
- appId: this.config.appId,
2096
- fileName: fileName,
2097
- refreshToken: refreshToken,
2098
- });
2099
- const isSuccess = yield StorageApi.upload(url, file);
2100
- return isSuccess;
2049
+ async upload(path, file) {
2050
+ const currentUser = await this.getCurrentUser();
2051
+ const refreshToken = currentUser?.user?.refresh_token;
2052
+ const fileName = path || file.name;
2053
+ const url = await StorageApi.getSignedUploadUrl({
2054
+ apiURI: this.config.apiURI,
2055
+ appId: this.config.appId,
2056
+ fileName: fileName,
2057
+ refreshToken: refreshToken,
2101
2058
  });
2059
+ const isSuccess = await StorageApi.upload(url, file);
2060
+ return isSuccess;
2102
2061
  }
2103
- getDownloadUrl(path) {
2104
- return __awaiter(this, void 0, void 0, function* () {
2105
- var _a;
2106
- const currentUser = yield this.getCurrentUser();
2107
- const refreshToken = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.user) === null || _a === void 0 ? void 0 : _a.refresh_token;
2108
- const url = yield StorageApi.getDownloadUrl({
2109
- apiURI: this.config.apiURI,
2110
- appId: this.config.appId,
2111
- path: path,
2112
- refreshToken: refreshToken,
2113
- });
2114
- return url;
2062
+ async getDownloadUrl(path) {
2063
+ const currentUser = await this.getCurrentUser();
2064
+ const refreshToken = currentUser?.user?.refresh_token;
2065
+ const url = await StorageApi.getDownloadUrl({
2066
+ apiURI: this.config.apiURI,
2067
+ appId: this.config.appId,
2068
+ path: path,
2069
+ refreshToken: refreshToken,
2115
2070
  });
2071
+ return url;
2116
2072
  }
2117
2073
  }
2118
2074
  //# sourceMappingURL=Reactor.js.map