@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.
- package/dist/commonjs/Connection.js +50 -51
- package/dist/commonjs/Connection.js.map +1 -1
- package/dist/commonjs/InMemoryStorage.js +13 -32
- package/dist/commonjs/InMemoryStorage.js.map +1 -1
- package/dist/commonjs/IndexedDBStorage.js +193 -217
- package/dist/commonjs/IndexedDBStorage.js.map +1 -1
- package/dist/commonjs/InstantError.js +1 -0
- package/dist/commonjs/InstantError.js.map +1 -1
- package/dist/commonjs/Reactor.js +566 -610
- package/dist/commonjs/Reactor.js.map +1 -1
- package/dist/commonjs/StorageAPI.js +51 -70
- package/dist/commonjs/StorageAPI.js.map +1 -1
- package/dist/commonjs/SyncTable.js +68 -81
- package/dist/commonjs/SyncTable.js.map +1 -1
- package/dist/commonjs/WindowNetworkListener.js +2 -13
- package/dist/commonjs/WindowNetworkListener.js.map +1 -1
- package/dist/commonjs/__types__/fieldsTypeTest.js +8 -16
- package/dist/commonjs/__types__/fieldsTypeTest.js.map +1 -1
- package/dist/commonjs/__types__/useDatesTypeTest.js +3 -6
- package/dist/commonjs/__types__/useDatesTypeTest.js.map +1 -1
- package/dist/commonjs/authAPI.js +62 -79
- package/dist/commonjs/authAPI.js.map +1 -1
- package/dist/commonjs/createRouteHandler.js +5 -15
- package/dist/commonjs/createRouteHandler.js.map +1 -1
- package/dist/commonjs/datalog.js +1 -1
- package/dist/commonjs/datalog.js.map +1 -1
- package/dist/commonjs/devtool.js +26 -8
- package/dist/commonjs/devtool.js.map +1 -1
- package/dist/commonjs/framework.d.ts.map +1 -1
- package/dist/commonjs/framework.js +142 -152
- package/dist/commonjs/framework.js.map +1 -1
- package/dist/commonjs/index.js +204 -190
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/instaml.js +44 -30
- package/dist/commonjs/instaml.js.map +1 -1
- package/dist/commonjs/instaql.js +25 -33
- package/dist/commonjs/instaql.js.map +1 -1
- package/dist/commonjs/parseSchemaFromJSON.js +6 -7
- package/dist/commonjs/parseSchemaFromJSON.js.map +1 -1
- package/dist/commonjs/presence.js +7 -8
- package/dist/commonjs/presence.js.map +1 -1
- package/dist/commonjs/queryValidation.js +1 -2
- package/dist/commonjs/queryValidation.js.map +1 -1
- package/dist/commonjs/schema.js +8 -6
- package/dist/commonjs/schema.js.map +1 -1
- package/dist/commonjs/schemaTypes.js +22 -3
- package/dist/commonjs/schemaTypes.js.map +1 -1
- package/dist/commonjs/store.js +29 -38
- package/dist/commonjs/store.js.map +1 -1
- package/dist/commonjs/transactionValidation.js +1 -2
- package/dist/commonjs/transactionValidation.js.map +1 -1
- package/dist/commonjs/utils/Deferred.js +3 -0
- package/dist/commonjs/utils/Deferred.js.map +1 -1
- package/dist/commonjs/utils/PersistedObject.js +216 -233
- package/dist/commonjs/utils/PersistedObject.js.map +1 -1
- package/dist/commonjs/utils/fetch.js +9 -19
- package/dist/commonjs/utils/fetch.js.map +1 -1
- package/dist/commonjs/utils/linkIndex.js +2 -4
- package/dist/commonjs/utils/linkIndex.js.map +1 -1
- package/dist/commonjs/utils/object.js +1 -1
- package/dist/commonjs/utils/object.js.map +1 -1
- package/dist/esm/Connection.js +50 -51
- package/dist/esm/Connection.js.map +1 -1
- package/dist/esm/InMemoryStorage.js +13 -32
- package/dist/esm/InMemoryStorage.js.map +1 -1
- package/dist/esm/IndexedDBStorage.js +193 -217
- package/dist/esm/IndexedDBStorage.js.map +1 -1
- package/dist/esm/InstantError.js +1 -0
- package/dist/esm/InstantError.js.map +1 -1
- package/dist/esm/Reactor.js +566 -610
- package/dist/esm/Reactor.js.map +1 -1
- package/dist/esm/StorageAPI.js +51 -70
- package/dist/esm/StorageAPI.js.map +1 -1
- package/dist/esm/SyncTable.js +68 -81
- package/dist/esm/SyncTable.js.map +1 -1
- package/dist/esm/WindowNetworkListener.js +2 -13
- package/dist/esm/WindowNetworkListener.js.map +1 -1
- package/dist/esm/__types__/fieldsTypeTest.js +8 -16
- package/dist/esm/__types__/fieldsTypeTest.js.map +1 -1
- package/dist/esm/__types__/useDatesTypeTest.js +3 -6
- package/dist/esm/__types__/useDatesTypeTest.js.map +1 -1
- package/dist/esm/authAPI.js +62 -79
- package/dist/esm/authAPI.js.map +1 -1
- package/dist/esm/createRouteHandler.js +5 -15
- package/dist/esm/createRouteHandler.js.map +1 -1
- package/dist/esm/datalog.js +1 -1
- package/dist/esm/datalog.js.map +1 -1
- package/dist/esm/devtool.js +26 -8
- package/dist/esm/devtool.js.map +1 -1
- package/dist/esm/framework.d.ts.map +1 -1
- package/dist/esm/framework.js +142 -152
- package/dist/esm/framework.js.map +1 -1
- package/dist/esm/index.js +204 -190
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instaml.js +44 -30
- package/dist/esm/instaml.js.map +1 -1
- package/dist/esm/instaql.js +25 -33
- package/dist/esm/instaql.js.map +1 -1
- package/dist/esm/parseSchemaFromJSON.js +6 -7
- package/dist/esm/parseSchemaFromJSON.js.map +1 -1
- package/dist/esm/presence.js +7 -8
- package/dist/esm/presence.js.map +1 -1
- package/dist/esm/queryValidation.js +1 -2
- package/dist/esm/queryValidation.js.map +1 -1
- package/dist/esm/schema.js +8 -6
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/schemaTypes.js +22 -3
- package/dist/esm/schemaTypes.js.map +1 -1
- package/dist/esm/store.js +29 -38
- package/dist/esm/store.js.map +1 -1
- package/dist/esm/transactionValidation.js +1 -2
- package/dist/esm/transactionValidation.js.map +1 -1
- package/dist/esm/utils/Deferred.js +3 -0
- package/dist/esm/utils/Deferred.js.map +1 -1
- package/dist/esm/utils/PersistedObject.js +216 -233
- package/dist/esm/utils/PersistedObject.js.map +1 -1
- package/dist/esm/utils/fetch.js +9 -19
- package/dist/esm/utils/fetch.js.map +1 -1
- package/dist/esm/utils/linkIndex.js +2 -4
- package/dist/esm/utils/linkIndex.js.map +1 -1
- package/dist/esm/utils/object.js +1 -1
- package/dist/esm/utils/object.js.map +1 -1
- package/dist/standalone/index.js +2610 -2367
- package/dist/standalone/index.umd.cjs +3 -3
- package/package.json +2 -2
- package/src/framework.ts +0 -1
package/dist/commonjs/Reactor.js
CHANGED
|
@@ -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 =
|
|
100
|
-
const PENDING_TX_CLEANUP_TIMEOUT =
|
|
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 =
|
|
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 (
|
|
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,
|
|
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
|
|
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 =
|
|
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
|
|
197
|
-
const memoryResult = inMemorySub
|
|
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 =
|
|
447
|
-
this.queryCacheLimit =
|
|
262
|
+
this.config = { ...defaultConfig, ...config };
|
|
263
|
+
this.queryCacheLimit = this.config.queryCacheLimit ?? 10;
|
|
448
264
|
this._pendingTxCleanupTimeout =
|
|
449
|
-
|
|
265
|
+
this.config.pendingTxCleanupTimeout ?? PENDING_TX_CLEANUP_TIMEOUT;
|
|
450
266
|
this._pendingMutationCleanupThreshold =
|
|
451
|
-
|
|
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 =
|
|
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) =>
|
|
471
|
-
var _a;
|
|
287
|
+
this._broadcastChannel.addEventListener('message', async (e) => {
|
|
472
288
|
try {
|
|
473
|
-
if (
|
|
474
|
-
const res =
|
|
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(() =>
|
|
495
|
-
const currentUser =
|
|
310
|
+
setInterval(async () => {
|
|
311
|
+
const currentUser = await this.getCurrentUser();
|
|
496
312
|
this.syncUserToEndpoint(currentUser.user);
|
|
497
|
-
}
|
|
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 =
|
|
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) =>
|
|
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:
|
|
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',
|
|
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
|
|
617
|
-
const { 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
|
|
441
|
+
status: status ?? 0,
|
|
622
442
|
}));
|
|
623
443
|
}
|
|
624
444
|
else {
|
|
625
|
-
dfd.reject(new InstantError_ts_1.InstantError(
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
716
|
-
const 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 =
|
|
782
|
-
const 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,
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
949
|
-
|
|
950
|
-
const 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 =
|
|
794
|
+
const isInitError = msg['original-event']?.op === 'init';
|
|
957
795
|
if (isInitError) {
|
|
958
796
|
if (msg.type === 'record-not-found' &&
|
|
959
|
-
|
|
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 (
|
|
807
|
+
if (msg['original-event']?.op === 'resync-table') {
|
|
970
808
|
this._syncTable.onResyncError(msg);
|
|
971
809
|
return;
|
|
972
810
|
}
|
|
973
|
-
if (
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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] =
|
|
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 =
|
|
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] =
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
1204
|
-
const fullAttr =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
1358
|
-
minProcessedTxId = Math.min(minProcessedTxId, result
|
|
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(
|
|
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
|
|
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
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
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
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
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
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
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
|
|
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
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
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
|
-
|
|
1653
|
-
|
|
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
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
}
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
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
|
-
|
|
1693
|
-
|
|
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
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
this.
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
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
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
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 =
|
|
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(
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
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
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
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
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
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(
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
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(
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
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
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
1961
|
+
this._presence[roomId]?.handlers?.filter((x) => x !== handler) ?? [];
|
|
1996
1962
|
leaveRoom();
|
|
1997
1963
|
};
|
|
1998
1964
|
}
|
|
1999
1965
|
_notifyPresenceSubs(roomId) {
|
|
2000
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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] =
|
|
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
|
-
|
|
2090
|
-
|
|
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
|
-
?
|
|
2095
|
-
:
|
|
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
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
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
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
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
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
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
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
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;
|