mosquito-transport-js 0.6.2 → 0.6.4
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/package.json +1 -1
- package/src/helpers/utils.js +23 -19
- package/src/index.d.ts +8 -0
- package/src/index.js +2 -7
- package/src/products/auth/accessor.js +15 -2
- package/src/products/auth/index.js +4 -1
- package/src/products/database/index.js +11 -18
- package/src/products/http_callable/index.js +9 -7
package/package.json
CHANGED
package/src/helpers/utils.js
CHANGED
|
@@ -179,18 +179,16 @@ export const awaitStore = () => new Promise(resolve => {
|
|
|
179
179
|
|
|
180
180
|
export const checkAreYouOk = (projectUrl) => {
|
|
181
181
|
if (!Scoped.AreYouOkPromise[projectUrl]) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const promise = fetch(engine_api._areYouOk(projectUrl), { credentials: 'omit', signal })
|
|
182
|
+
Scoped.IS_CONNECTED[projectUrl] = undefined;
|
|
183
|
+
ServerReachableListener.dispatchPersist(projectUrl, undefined);
|
|
184
|
+
|
|
185
|
+
const promise = fetch(engine_api._areYouOk(projectUrl), { credentials: 'omit' })
|
|
187
186
|
.then(async r => (await r.json()).status === 'yes')
|
|
188
187
|
.catch(() => false)
|
|
189
188
|
.then(async connected => {
|
|
190
189
|
Scoped.IS_CONNECTED[projectUrl] = connected;
|
|
191
190
|
ServerReachableListener.dispatchPersist(projectUrl, connected);
|
|
192
191
|
|
|
193
|
-
clearTimeout(timer);
|
|
194
192
|
delete Scoped.AreYouOkPromise[projectUrl];
|
|
195
193
|
return connected;
|
|
196
194
|
});
|
|
@@ -209,25 +207,31 @@ export const listenReachableServer = (callback, projectUrl) => {
|
|
|
209
207
|
});
|
|
210
208
|
};
|
|
211
209
|
|
|
212
|
-
export const awaitReachableServer = (projectUrl) =>
|
|
213
|
-
new Promise(
|
|
214
|
-
|
|
215
|
-
if (
|
|
210
|
+
export const awaitReachableServer = (projectUrl, pauseForRetry) =>
|
|
211
|
+
new Promise(resolve => {
|
|
212
|
+
const check = async () => {
|
|
213
|
+
if (!isScreenFocused()) {
|
|
214
|
+
if (await checkAreYouOk(projectUrl)) {
|
|
215
|
+
resolve();
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (Scoped.IS_CONNECTED[projectUrl]) {
|
|
216
221
|
resolve();
|
|
217
222
|
return;
|
|
218
223
|
}
|
|
219
|
-
}
|
|
220
224
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
225
|
+
const l = listenReachableServer(t => {
|
|
226
|
+
if (!t) return;
|
|
227
|
+
resolve();
|
|
228
|
+
l();
|
|
229
|
+
}, projectUrl);
|
|
224
230
|
}
|
|
225
231
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
l();
|
|
230
|
-
}, projectUrl);
|
|
232
|
+
if (pauseForRetry) {
|
|
233
|
+
setTimeout(check, Number.isInteger(pauseForRetry) ? pauseForRetry : 300);
|
|
234
|
+
} else check();
|
|
231
235
|
});
|
|
232
236
|
|
|
233
237
|
export const getReachableServer = (projectUrl) =>
|
package/src/index.d.ts
CHANGED
|
@@ -302,6 +302,14 @@ export interface FetchHttpConfig {
|
|
|
302
302
|
disableAuth?: boolean;
|
|
303
303
|
enableMinimizer?: boolean;
|
|
304
304
|
rawApproach?: boolean;
|
|
305
|
+
/**
|
|
306
|
+
* Wait for the server to come online if the response does not include a header with status 200.
|
|
307
|
+
*
|
|
308
|
+
* This ensures that the fetchHttp method only resolves when a response with status 200 is received; otherwise, it rejects if the server is online but continues returning a non-200 status
|
|
309
|
+
*
|
|
310
|
+
* @default false
|
|
311
|
+
*/
|
|
312
|
+
enforce200?: boolean;
|
|
305
313
|
}
|
|
306
314
|
|
|
307
315
|
type Delievery = 'default' | 'cache-no-await' | 'no-cache-no-await' | 'no-cache-await';
|
package/src/index.js
CHANGED
|
@@ -73,7 +73,6 @@ export class MosquitoTransport {
|
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
let connectionIte = 0;
|
|
76
|
-
let chainedPromise;
|
|
77
76
|
const setConnected = c => {
|
|
78
77
|
isConnected = c;
|
|
79
78
|
Scoped.IS_CONNECTED[projectUrl] = isConnected;
|
|
@@ -90,11 +89,9 @@ export class MosquitoTransport {
|
|
|
90
89
|
};
|
|
91
90
|
|
|
92
91
|
const manualCheckConnection = () => {
|
|
93
|
-
if (chainedPromise) return;
|
|
94
92
|
const ref = ++connectionIte;
|
|
95
93
|
|
|
96
94
|
checkAreYouOk(projectUrl).then(ok => {
|
|
97
|
-
chainedPromise = undefined;
|
|
98
95
|
if (ref !== connectionIte) return;
|
|
99
96
|
if (ok) {
|
|
100
97
|
onConnect();
|
|
@@ -363,9 +360,7 @@ export class MosquitoTransport {
|
|
|
363
360
|
}
|
|
364
361
|
|
|
365
362
|
if (isScreenFocused()) {
|
|
366
|
-
|
|
367
|
-
awaitReachableServer(projectUrl).then(reloadIntance);
|
|
368
|
-
}, timeout);
|
|
363
|
+
awaitReachableServer(projectUrl, timeout).then(reloadIntance);
|
|
369
364
|
} else {
|
|
370
365
|
foregroundListener = listenScreenVisible(visible => {
|
|
371
366
|
if (visible) {
|
|
@@ -396,7 +391,7 @@ export class MosquitoTransport {
|
|
|
396
391
|
clearSocket();
|
|
397
392
|
if (r === 'io client disconnect' || r === 'io server disconnect') {
|
|
398
393
|
resultant.destroy();
|
|
399
|
-
} else reconnect(
|
|
394
|
+
} else reconnect(true);
|
|
400
395
|
});
|
|
401
396
|
|
|
402
397
|
clientPrivateKey = privateKey;
|
|
@@ -2,7 +2,7 @@ import { doSignOut, revokeAuthIntance } from "./index.js";
|
|
|
2
2
|
import EngineApi from "../../helpers/engine_api";
|
|
3
3
|
import { AuthTokenListener, TokenRefreshListener } from "../../helpers/listeners";
|
|
4
4
|
import { decodeBinary, deserializeE2E } from "../../helpers/peripherals";
|
|
5
|
-
import { awaitReachableServer, awaitStore, buildFetchInterface, buildFetchResult, updateCacheStore } from "../../helpers/utils";
|
|
5
|
+
import { awaitReachableServer, awaitStore, buildFetchInterface, buildFetchResult, getReachableServer, updateCacheStore } from "../../helpers/utils";
|
|
6
6
|
import { CacheStore, Scoped } from "../../helpers/variables";
|
|
7
7
|
import { simplifyError } from "simplify-error";
|
|
8
8
|
import { Validator } from "guard-object";
|
|
@@ -75,6 +75,19 @@ export const awaitRefreshToken = (projectUrl) =>
|
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
+
export const ensureActiveToken = async (projectUrl) => {
|
|
79
|
+
if (await getReachableServer(projectUrl)) {
|
|
80
|
+
await awaitRefreshToken(projectUrl);
|
|
81
|
+
} else {
|
|
82
|
+
const emulatedURL = CacheStore.EmulatedAuth[projectUrl];
|
|
83
|
+
const { token } = CacheStore.AuthStore[emulatedURL || projectUrl] || {};
|
|
84
|
+
|
|
85
|
+
if (token && await hasTokenExpire(emulatedURL || projectUrl)) {
|
|
86
|
+
throw 'unable to refreshed expired token because of unreachable internet connection';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
78
91
|
export const listenTokenReady = (callback, projectUrl) => TokenRefreshListener.listenToPersist(projectUrl, callback);
|
|
79
92
|
|
|
80
93
|
export const initTokenRefresher = async ({ config, forceRefresh, justCheck }) => {
|
|
@@ -217,7 +230,7 @@ const refreshToken = (builder, remainRetries = 1, isForceRefresh) =>
|
|
|
217
230
|
);
|
|
218
231
|
console.error(`refreshToken retry limit exceeded err:`, e);
|
|
219
232
|
} else {
|
|
220
|
-
awaitReachableServer(projectUrl).then(() => {
|
|
233
|
+
awaitReachableServer(projectUrl, true).then(() => {
|
|
221
234
|
refreshToken(builder, remainRetries - 1, isForceRefresh).then(resolve, reject);
|
|
222
235
|
});
|
|
223
236
|
}
|
|
@@ -54,11 +54,13 @@ export default class MTAuth {
|
|
|
54
54
|
const processID = ++lastInitRef;
|
|
55
55
|
await awaitRefreshToken(projectUrl);
|
|
56
56
|
|
|
57
|
+
if (processID !== lastInitRef || hasCancelled) return;
|
|
58
|
+
|
|
57
59
|
if (!Scoped.AuthJWTToken[projectUrl]) {
|
|
58
60
|
onError?.(simplifyError('user_login_required', 'You must be signed-in to use this method').simpleError);
|
|
59
61
|
return;
|
|
60
62
|
}
|
|
61
|
-
|
|
63
|
+
|
|
62
64
|
const mtoken = Scoped.AuthJWTToken[projectUrl],
|
|
63
65
|
[reqBuilder, [privateKey]] = uglify ? await serializeE2E({ mtoken }, undefined, serverE2E_PublicKey) : [null, []];
|
|
64
66
|
|
|
@@ -251,6 +253,7 @@ const clearCacheForSignout = (builder, disposeEmulated) => {
|
|
|
251
253
|
purgeCache(projectUrl, true);
|
|
252
254
|
if (disposeEmulated) getEmulatedLinks(projectUrl).forEach(e => purgeCache(e));
|
|
253
255
|
|
|
256
|
+
clearInterval(Scoped.TokenRefreshTimer[projectUrl]);
|
|
254
257
|
setTimeout(() => {
|
|
255
258
|
initTokenRefresher({ config: builder });
|
|
256
259
|
}, 600);
|
|
@@ -6,7 +6,7 @@ import { awaitReachableServer, awaitStore, buildFetchInterface, buildFetchResult
|
|
|
6
6
|
import { CacheStore, Scoped } from "../../helpers/variables";
|
|
7
7
|
import { addPendingWrites, generateRecordID, getCountQuery, getRecord, insertCountQuery, insertRecord, listenQueryEntry, removePendingWrite, validateWriteValue } from "./accessor";
|
|
8
8
|
import { validateCollectionName, validateFilter, validateFindConfig, validateFindObject, validateListenFindConfig } from "./validator";
|
|
9
|
-
import { awaitRefreshToken, listenTokenReady } from "../auth/accessor";
|
|
9
|
+
import { awaitRefreshToken, ensureActiveToken, listenTokenReady } from "../auth/accessor";
|
|
10
10
|
import { DELIVERY, RETRIEVAL } from "../../helpers/values";
|
|
11
11
|
import { ObjectId } from "bson";
|
|
12
12
|
import { guardObject, Validator } from "guard-object";
|
|
@@ -261,9 +261,7 @@ const listenDocument = (callback, onError, builder, config) => {
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
if (isScreenFocused()) {
|
|
264
|
-
|
|
265
|
-
awaitReachableServer(projectUrl).then(reloadIntance);
|
|
266
|
-
}, timeout);
|
|
264
|
+
awaitReachableServer(projectUrl, timeout).then(reloadIntance);
|
|
267
265
|
} else {
|
|
268
266
|
foregroundListener = listenScreenVisible(visible => {
|
|
269
267
|
if (visible) {
|
|
@@ -288,7 +286,7 @@ const listenDocument = (callback, onError, builder, config) => {
|
|
|
288
286
|
clearSocket();
|
|
289
287
|
if (r === 'io client disconnect' || r === 'io server disconnect') {
|
|
290
288
|
canceller();
|
|
291
|
-
} else reconnect(
|
|
289
|
+
} else reconnect(true);
|
|
292
290
|
});
|
|
293
291
|
};
|
|
294
292
|
|
|
@@ -419,9 +417,7 @@ const initOnDisconnectionTask = ({ builder, connectData, disconnectData }) => {
|
|
|
419
417
|
}
|
|
420
418
|
|
|
421
419
|
if (isScreenFocused()) {
|
|
422
|
-
|
|
423
|
-
awaitReachableServer(projectUrl).then(reloadIntance);
|
|
424
|
-
}, timeout);
|
|
420
|
+
awaitReachableServer(projectUrl, timeout).then(reloadIntance);
|
|
425
421
|
} else {
|
|
426
422
|
foregroundListener = listenScreenVisible(visible => {
|
|
427
423
|
if (visible) {
|
|
@@ -446,7 +442,7 @@ const initOnDisconnectionTask = ({ builder, connectData, disconnectData }) => {
|
|
|
446
442
|
clearSocket();
|
|
447
443
|
if (r === 'io client disconnect' || r === 'io server disconnect') {
|
|
448
444
|
canceller();
|
|
449
|
-
} else reconnect(
|
|
445
|
+
} else reconnect(true);
|
|
450
446
|
});
|
|
451
447
|
};
|
|
452
448
|
|
|
@@ -525,8 +521,7 @@ const countCollection = async (builder, config) => {
|
|
|
525
521
|
};
|
|
526
522
|
|
|
527
523
|
try {
|
|
528
|
-
if (!disableAuth
|
|
529
|
-
await awaitRefreshToken(projectUrl);
|
|
524
|
+
if (!disableAuth) await ensureActiveToken(projectUrl);
|
|
530
525
|
|
|
531
526
|
const [reqBuilder, [privateKey]] = await buildFetchInterface({
|
|
532
527
|
body: {
|
|
@@ -558,7 +553,7 @@ const countCollection = async (builder, config) => {
|
|
|
558
553
|
} else if (retries > maxRetries) {
|
|
559
554
|
finalize(undefined, { error: 'retry_limit_exceeded', message: `retry exceed limit(${maxRetries})` });
|
|
560
555
|
} else {
|
|
561
|
-
awaitReachableServer(projectUrl).then(() => {
|
|
556
|
+
awaitReachableServer(projectUrl, true).then(() => {
|
|
562
557
|
readValue().then(
|
|
563
558
|
e => { finalize(e); },
|
|
564
559
|
e => { finalize(undefined, e); }
|
|
@@ -675,8 +670,7 @@ const findObject = async (builder, initConfig) => {
|
|
|
675
670
|
}
|
|
676
671
|
}
|
|
677
672
|
|
|
678
|
-
if (!disableAuth
|
|
679
|
-
await awaitRefreshToken(projectUrl);
|
|
673
|
+
if (!disableAuth) await ensureActiveToken(projectUrl);
|
|
680
674
|
|
|
681
675
|
const [reqBuilder, [privateKey]] = await buildFetchInterface({
|
|
682
676
|
body: {
|
|
@@ -733,7 +727,7 @@ const findObject = async (builder, initConfig) => {
|
|
|
733
727
|
} else if (retries > maxRetries) {
|
|
734
728
|
finalize(undefined, { error: 'retry_limit_exceeded', message: `retry exceed limit(${maxRetries})` });
|
|
735
729
|
} else {
|
|
736
|
-
awaitReachableServer(projectUrl).then(() => {
|
|
730
|
+
awaitReachableServer(projectUrl, true).then(() => {
|
|
737
731
|
if (intruder) {
|
|
738
732
|
intruder.resolve = undefined;
|
|
739
733
|
intruder.reject = undefined;
|
|
@@ -838,8 +832,7 @@ const commitData = async (builder, value, type, config) => {
|
|
|
838
832
|
};
|
|
839
833
|
|
|
840
834
|
try {
|
|
841
|
-
if (!disableAuth
|
|
842
|
-
await awaitRefreshToken(projectUrl);
|
|
835
|
+
if (!disableAuth) await ensureActiveToken(projectUrl);
|
|
843
836
|
|
|
844
837
|
const [reqBuilder, [privateKey]] = await buildFetchInterface({
|
|
845
838
|
body: {
|
|
@@ -880,7 +873,7 @@ const commitData = async (builder, value, type, config) => {
|
|
|
880
873
|
);
|
|
881
874
|
} else {
|
|
882
875
|
if (delivery === DELIVERY.NO_CACHE_AWAIT) {
|
|
883
|
-
awaitReachableServer(projectUrl).then(() => {
|
|
876
|
+
awaitReachableServer(projectUrl, true).then(() => {
|
|
884
877
|
sendValue().then(
|
|
885
878
|
e => { finalize(e.a, undefined, e.c); },
|
|
886
879
|
e => { finalize(undefined, e.b, e.c); }
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Buffer } from "buffer";
|
|
2
2
|
import { deserializeE2E, niceHash, normalizeRoute, serializeE2E } from "../../helpers/peripherals";
|
|
3
|
-
import { awaitReachableServer, awaitStore
|
|
3
|
+
import { awaitReachableServer, awaitStore } from "../../helpers/utils";
|
|
4
4
|
import { RETRIEVAL } from "../../helpers/values";
|
|
5
5
|
import { Scoped } from "../../helpers/variables";
|
|
6
|
-
import {
|
|
6
|
+
import { ensureActiveToken, parseToken } from "../auth/accessor";
|
|
7
7
|
import { simplifyCaughtError } from "simplify-error";
|
|
8
8
|
import { guardObject, Validator } from "guard-object";
|
|
9
9
|
import { serialize } from "entity-serializer";
|
|
@@ -42,10 +42,11 @@ export const mfetch = async (input = '', init, config) => {
|
|
|
42
42
|
enableMinimizer: t => t === undefined || Validator.BOOLEAN(t),
|
|
43
43
|
rawApproach: t => t === undefined || Validator.BOOLEAN(t),
|
|
44
44
|
disableAuth: t => t === undefined || Validator.BOOLEAN(t),
|
|
45
|
-
retrieval: t => t === undefined || Object.values(RETRIEVAL).includes(t)
|
|
45
|
+
retrieval: t => t === undefined || Object.values(RETRIEVAL).includes(t),
|
|
46
|
+
enforce200: t => t === undefined || Validator.BOOLEAN(t)
|
|
46
47
|
}).validate(method);
|
|
47
48
|
|
|
48
|
-
const { retrieval = RETRIEVAL.DEFAULT, enableMinimizer, rawApproach } = method || {};
|
|
49
|
+
const { retrieval = RETRIEVAL.DEFAULT, enableMinimizer, rawApproach, enforce200 } = method || {};
|
|
49
50
|
const isLink = Validator.LINK(input);
|
|
50
51
|
const isBaseUrl = isLink || rawApproach;
|
|
51
52
|
const disableAuth = method?.disableAuth === undefined ? isBaseUrl : method?.disableAuth;
|
|
@@ -138,8 +139,7 @@ export const mfetch = async (input = '', init, config) => {
|
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
|
|
141
|
-
if (!disableAuth
|
|
142
|
-
await awaitRefreshToken(projectUrl);
|
|
142
|
+
if (!disableAuth) await ensureActiveToken(projectUrl);
|
|
143
143
|
|
|
144
144
|
const mtoken = disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl];
|
|
145
145
|
const initType = rawHeader['content-type'];
|
|
@@ -168,6 +168,8 @@ export const mfetch = async (input = '', init, config) => {
|
|
|
168
168
|
const { ok, type, status, statusText, redirected, url, headers, size } = f;
|
|
169
169
|
const simple = headers.get('simple_error');
|
|
170
170
|
|
|
171
|
+
if (enforce200 && status !== 200)
|
|
172
|
+
throw `expected response status to be 200 but got ${status}`;
|
|
171
173
|
if (!isLink && simple) throw { simpleError: JSON.parse(simple) };
|
|
172
174
|
|
|
173
175
|
const buffer = uglified ?
|
|
@@ -220,7 +222,7 @@ export const mfetch = async (input = '', init, config) => {
|
|
|
220
222
|
} else if (retries > maxRetries) {
|
|
221
223
|
finalize(undefined, simplifyCaughtError(e).simpleError);
|
|
222
224
|
} else {
|
|
223
|
-
awaitReachableServer(projectUrl).then(() => {
|
|
225
|
+
awaitReachableServer(projectUrl, true).then(() => {
|
|
224
226
|
callFetch().then(
|
|
225
227
|
e => finalize(e),
|
|
226
228
|
e => finalize(undefined, e)
|