react-native-mosquito-transport 0.0.53 → 0.0.55

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mosquito-transport",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
4
4
  "description": "React native javascript sdk for mosquito-transport (https://github.com/brainbehindx/mosquito-transport)",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -157,18 +157,16 @@ export const awaitStore = () => new Promise(resolve => {
157
157
 
158
158
  export const checkAreYouOk = (projectUrl) => {
159
159
  if (!Scoped.AreYouOkPromise[projectUrl]) {
160
- const signal = new AbortController();
161
- const timer = setTimeout(() => {
162
- signal.abort();
163
- }, 9000);
164
- const promise = fetch(engine_api._areYouOk(projectUrl), { credentials: 'omit', signal })
160
+ Scoped.IS_CONNECTED[projectUrl] = undefined;
161
+ ServerReachableListener.dispatchPersist(projectUrl, undefined);
162
+
163
+ const promise = fetch(engine_api._areYouOk(projectUrl), { credentials: 'omit' })
165
164
  .then(async r => (await r.json()).status === 'yes')
166
165
  .catch(() => false)
167
166
  .then(async connected => {
168
167
  Scoped.IS_CONNECTED[projectUrl] = connected;
169
168
  ServerReachableListener.dispatchPersist(projectUrl, connected);
170
169
 
171
- clearTimeout(timer);
172
170
  delete Scoped.AreYouOkPromise[projectUrl];
173
171
  return connected;
174
172
  });
@@ -187,25 +185,31 @@ export const listenReachableServer = (callback, projectUrl) => {
187
185
  });
188
186
  };
189
187
 
190
- export const awaitReachableServer = (projectUrl) =>
191
- new Promise(async resolve => {
192
- if (AppState.currentState !== 'active') {
193
- if (await checkAreYouOk(projectUrl)) {
188
+ export const awaitReachableServer = (projectUrl, pauseForRetry) =>
189
+ new Promise(resolve => {
190
+ const check = async () => {
191
+ if (AppState.currentState !== 'active') {
192
+ if (await checkAreYouOk(projectUrl)) {
193
+ resolve();
194
+ return;
195
+ }
196
+ }
197
+
198
+ if (Scoped.IS_CONNECTED[projectUrl]) {
194
199
  resolve();
195
200
  return;
196
201
  }
197
- }
198
202
 
199
- if (Scoped.IS_CONNECTED[projectUrl]) {
200
- resolve();
201
- return;
203
+ const l = listenReachableServer(t => {
204
+ if (!t) return;
205
+ resolve();
206
+ l();
207
+ }, projectUrl);
202
208
  }
203
209
 
204
- const l = listenReachableServer(t => {
205
- if (!t) return;
206
- resolve();
207
- l();
208
- }, projectUrl);
210
+ if (pauseForRetry) {
211
+ setTimeout(check, Number.isInteger(pauseForRetry) ? pauseForRetry : 300);
212
+ } else check();
209
213
  });
210
214
 
211
215
  export const getReachableServer = (projectUrl) =>
package/src/index.d.ts CHANGED
@@ -297,6 +297,14 @@ export interface FetchHttpConfig {
297
297
  disableAuth?: boolean;
298
298
  enableMinimizer?: boolean;
299
299
  rawApproach?: boolean;
300
+ /**
301
+ * Wait for the server to come online if the response does not include a header with status 200.
302
+ *
303
+ * 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
304
+ *
305
+ * @default false
306
+ */
307
+ enforce200?: boolean;
300
308
  }
301
309
 
302
310
  type Delievery = 'default' | 'cache-no-await' | 'no-cache-no-await' | 'no-cache-await';
package/src/index.js CHANGED
@@ -74,7 +74,6 @@ class RNMT {
74
74
  });
75
75
 
76
76
  let connectionIte = 0;
77
- let chainedPromise;
78
77
  const setConnected = c => {
79
78
  isConnected = c;
80
79
  Scoped.IS_CONNECTED[projectUrl] = isConnected;
@@ -91,11 +90,9 @@ class RNMT {
91
90
  };
92
91
 
93
92
  const manualCheckConnection = () => {
94
- if (chainedPromise) return;
95
93
  const ref = ++connectionIte;
96
94
 
97
95
  checkAreYouOk(projectUrl).then(ok => {
98
- chainedPromise = undefined;
99
96
  if (ref !== connectionIte) return;
100
97
  if (ok) {
101
98
  onConnect();
@@ -345,9 +342,7 @@ class RNMT {
345
342
  }
346
343
 
347
344
  if (AppState.currentState === 'active') {
348
- setTimeout(() => {
349
- awaitReachableServer(projectUrl).then(reloadIntance);
350
- }, timeout);
345
+ awaitReachableServer(projectUrl, timeout).then(reloadIntance);
351
346
  } else {
352
347
  foregroundListener = AppState.addEventListener('change', s => {
353
348
  if (s === 'active') {
@@ -378,7 +373,7 @@ class RNMT {
378
373
  clearSocket();
379
374
  if (r === 'io client disconnect' || r === 'io server disconnect') {
380
375
  resultant.destroy();
381
- } else reconnect(0);
376
+ } else reconnect(true);
382
377
  });
383
378
 
384
379
  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";
@@ -76,6 +76,19 @@ export const awaitRefreshToken = (projectUrl) =>
76
76
  }
77
77
  });
78
78
 
79
+ export const ensureActiveToken = async (projectUrl) => {
80
+ if (await getReachableServer(projectUrl)) {
81
+ await awaitRefreshToken(projectUrl);
82
+ } else {
83
+ const emulatedURL = CacheStore.EmulatedAuth[projectUrl];
84
+ const { token } = CacheStore.AuthStore[emulatedURL || projectUrl] || {};
85
+
86
+ if (token && await hasTokenExpire(emulatedURL || projectUrl)) {
87
+ throw 'unable to refreshed expired token because of unreachable internet connection';
88
+ }
89
+ }
90
+ }
91
+
79
92
  export const listenTokenReady = (callback, projectUrl) => TokenRefreshListener.listenToPersist(projectUrl, callback);
80
93
 
81
94
  export const initTokenRefresher = async ({ config, forceRefresh, justCheck }) => {
@@ -208,7 +221,7 @@ const refreshToken = (builder, remainRetries = 1, isForceRefresh) =>
208
221
  );
209
222
  console.error(`refreshToken retry limit exceeded err:`, e);
210
223
  } else {
211
- awaitReachableServer(projectUrl).then(() => {
224
+ awaitReachableServer(projectUrl, true).then(() => {
212
225
  refreshToken(builder, remainRetries - 1, isForceRefresh).then(resolve, reject);
213
226
  });
214
227
  }
@@ -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
- if (processID !== lastInitRef || hasCancelled) return;
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 "../../vendor/bson";
12
12
  import { guardObject, Validator } from "guard-object";
@@ -262,9 +262,7 @@ const listenDocument = (callback, onError, builder, config) => {
262
262
  }
263
263
 
264
264
  if (AppState.currentState === 'active') {
265
- setTimeout(() => {
266
- awaitReachableServer(projectUrl).then(reloadIntance);
267
- }, timeout);
265
+ awaitReachableServer(projectUrl, timeout).then(reloadIntance);
268
266
  } else {
269
267
  foregroundListener = AppState.addEventListener('change', s => {
270
268
  if (s === 'active') {
@@ -289,7 +287,7 @@ const listenDocument = (callback, onError, builder, config) => {
289
287
  clearSocket();
290
288
  if (r === 'io client disconnect' || r === 'io server disconnect') {
291
289
  canceller();
292
- } else reconnect(0);
290
+ } else reconnect(true);
293
291
  });
294
292
  };
295
293
 
@@ -420,9 +418,7 @@ const initOnDisconnectionTask = ({ builder, connectData, disconnectData }) => {
420
418
  }
421
419
 
422
420
  if (AppState.currentState === 'active') {
423
- setTimeout(() => {
424
- awaitReachableServer(projectUrl).then(reloadIntance);
425
- }, timeout);
421
+ awaitReachableServer(projectUrl, timeout).then(reloadIntance);
426
422
  } else {
427
423
  foregroundListener = AppState.addEventListener('change', s => {
428
424
  if (s === 'active') {
@@ -447,7 +443,7 @@ const initOnDisconnectionTask = ({ builder, connectData, disconnectData }) => {
447
443
  clearSocket();
448
444
  if (r === 'io client disconnect' || r === 'io server disconnect') {
449
445
  canceller();
450
- } else reconnect(0);
446
+ } else reconnect(true);
451
447
  });
452
448
  };
453
449
 
@@ -526,8 +522,7 @@ const countCollection = async (builder, config) => {
526
522
  };
527
523
 
528
524
  try {
529
- if (!disableAuth && await getReachableServer(projectUrl))
530
- await awaitRefreshToken(projectUrl);
525
+ if (!disableAuth) await ensureActiveToken(projectUrl);
531
526
 
532
527
  const [reqBuilder, [privateKey]] = await buildFetchInterface({
533
528
  body: {
@@ -559,7 +554,7 @@ const countCollection = async (builder, config) => {
559
554
  } else if (retries > maxRetries) {
560
555
  finalize(undefined, { error: 'retry_limit_exceeded', message: `retry exceed limit(${maxRetries})` });
561
556
  } else {
562
- awaitReachableServer(projectUrl).then(() => {
557
+ awaitReachableServer(projectUrl, true).then(() => {
563
558
  readValue().then(
564
559
  e => { finalize(e); },
565
560
  e => { finalize(undefined, e); }
@@ -676,8 +671,7 @@ const findObject = async (builder, initConfig) => {
676
671
  }
677
672
  }
678
673
 
679
- if (!disableAuth && await getReachableServer(projectUrl))
680
- await awaitRefreshToken(projectUrl);
674
+ if (!disableAuth) await ensureActiveToken(projectUrl);
681
675
 
682
676
  const [reqBuilder, [privateKey]] = await buildFetchInterface({
683
677
  body: {
@@ -734,7 +728,7 @@ const findObject = async (builder, initConfig) => {
734
728
  } else if (retries > maxRetries) {
735
729
  finalize(undefined, { error: 'retry_limit_exceeded', message: `retry exceed limit(${maxRetries})` });
736
730
  } else {
737
- awaitReachableServer(projectUrl).then(() => {
731
+ awaitReachableServer(projectUrl, true).then(() => {
738
732
  if (intruder) {
739
733
  intruder.resolve = undefined;
740
734
  intruder.reject = undefined;
@@ -839,8 +833,7 @@ const commitData = async (builder, value, type, config) => {
839
833
  };
840
834
 
841
835
  try {
842
- if (!disableAuth && await getReachableServer(projectUrl))
843
- await awaitRefreshToken(projectUrl);
836
+ if (!disableAuth) await ensureActiveToken(projectUrl);
844
837
 
845
838
  const [reqBuilder, [privateKey]] = await buildFetchInterface({
846
839
  body: {
@@ -881,7 +874,7 @@ const commitData = async (builder, value, type, config) => {
881
874
  );
882
875
  } else {
883
876
  if (delivery === DELIVERY.NO_CACHE_AWAIT) {
884
- awaitReachableServer(projectUrl).then(() => {
877
+ awaitReachableServer(projectUrl, true).then(() => {
885
878
  sendValue().then(
886
879
  e => { finalize(e.a, undefined, e.c); },
887
880
  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, getReachableServer } from "../../helpers/utils";
3
+ import { awaitReachableServer, awaitStore } from "../../helpers/utils";
4
4
  import { RETRIEVAL } from "../../helpers/values";
5
5
  import { Scoped } from "../../helpers/variables";
6
- import { awaitRefreshToken, parseToken } from "../auth/accessor";
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;
@@ -134,8 +135,7 @@ export const mfetch = async (input = '', init, config) => {
134
135
  }
135
136
  }
136
137
 
137
- if (!disableAuth && await getReachableServer(projectUrl))
138
- await awaitRefreshToken(projectUrl);
138
+ if (!disableAuth) await ensureActiveToken(projectUrl);
139
139
 
140
140
  const mtoken = disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl];
141
141
  const initType = rawHeader['content-type'];
@@ -164,6 +164,8 @@ export const mfetch = async (input = '', init, config) => {
164
164
  const { ok, type, status, statusText, redirected, url, headers, size } = f;
165
165
  const simple = headers.get('simple_error');
166
166
 
167
+ if (enforce200 && status !== 200)
168
+ throw `expected response status to be 200 but got ${status}`;
167
169
  if (!isLink && simple) throw { simpleError: JSON.parse(simple) };
168
170
 
169
171
  const buffer = uglified ?
@@ -216,7 +218,7 @@ export const mfetch = async (input = '', init, config) => {
216
218
  } else if (retries > maxRetries) {
217
219
  finalize(undefined, simplifyCaughtError(e).simpleError);
218
220
  } else {
219
- awaitReachableServer(projectUrl).then(() => {
221
+ awaitReachableServer(projectUrl, true).then(() => {
220
222
  callFetch().then(
221
223
  e => finalize(e),
222
224
  e => finalize(undefined, e)